mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Compare commits
522 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a9bdfcde5 | |||
| 112120969d | |||
| 63956036e1 | |||
| cdf45438f0 | |||
| b6b9c57f24 | |||
| aa578c346d | |||
| ac8360003e | |||
| 233cb49903 | |||
| 9cdf439db5 | |||
| 95360a17f2 | |||
| 9dfe50f1d9 | |||
| c07f24cd18 | |||
| 03c2b8656b | |||
| ea6e1b003c | |||
| c2b37e76b3 | |||
| d40b922c98 | |||
| 28e793496a | |||
| 33c8d6af1e | |||
| 49ae2a69f2 | |||
| 2ffb77586a | |||
| dad99afae8 | |||
| f93dffb5ee | |||
| 742117e7a3 | |||
| 15ceb35e05 | |||
| f0bad600e0 | |||
| a8aeba89ef | |||
| 7f593893e8 | |||
| 5d5b1d1f3c | |||
| bb6846468a | |||
| 960c82e396 | |||
| 5be33b82c7 | |||
| 4cd858f93d | |||
| 2098acee7d | |||
| 3157efa57c | |||
| 613e0bee5e | |||
| 78c9c71bdf | |||
| aa30b13b36 | |||
| 6ba542cd53 | |||
| 106f4c4e9d | |||
| f1523d2404 | |||
| 00f6271e3b | |||
| b0e49ef79e | |||
| 81d340e042 | |||
| 4e40169ed6 | |||
| 49f1c0e94d | |||
| dcfebc6eed | |||
| f9d113f764 | |||
| 3d2d9f8a9b | |||
| 07129c76d9 | |||
| 6fe03f3b39 | |||
| 41f3456a28 | |||
| 7a420d4bba | |||
| d2b9c90f28 | |||
| ce12ef7e5c | |||
| 8bca11a64e | |||
| 14e325e45d | |||
| f85906b679 | |||
| 1fc9345b45 | |||
| 0a5983dd5e | |||
| aec40d10b8 | |||
| 89ceb3e7ba | |||
| fc80e4b651 | |||
| 52ab095ccf | |||
| d5cca2bdb2 | |||
| ebbb4fd7fb | |||
| b717cc7830 | |||
| a476c83caf | |||
| 15c63688e3 | |||
| 69c62415c0 | |||
| 690b2aa761 | |||
| 69311fa4c9 | |||
| ab9be1b48a | |||
| 5a682bfc7b | |||
| 53ea8abea6 | |||
| 6445e4683f | |||
| 6d49ec25a9 | |||
| a3ec6ede76 | |||
| 6803ddb8e2 | |||
| 4ce3997ca4 | |||
| 93e78fcde1 | |||
| 6f4c585bd7 | |||
| 47ea60814b | |||
| 86223b6eca | |||
| d79147fe5d | |||
| ac68c90800 | |||
| 82194c01ca | |||
| 69bc477b43 | |||
| 3655d4e0f4 | |||
| bc929656fb | |||
| 4aba93c969 | |||
| 49d97d6051 | |||
| 484577670f | |||
| d64c4d64e6 | |||
| 846af371c0 | |||
| 38b4483f9d | |||
| bb2512641f | |||
| bd60ad98eb | |||
| 7826af38ac | |||
| 84d842ea5c | |||
| f6c2662632 | |||
| e2aecacaeb | |||
| 8cdf6a87ed | |||
| 181f7b97d6 | |||
| 3491372a1d | |||
| 03b0741994 | |||
| a87f0b158d | |||
| 5e01674b72 | |||
| b652a4ff14 | |||
| 7dc0fe66c7 | |||
| 1cdcd00cc0 | |||
| 9f4b5227fe | |||
| d464fe5003 | |||
| 6b839b2319 | |||
| 45bd372755 | |||
| f5ee7df7f3 | |||
| e82b8b7bf8 | |||
| 91368c117c | |||
| 87576b819e | |||
| 48c473a0c4 | |||
| 87d77c13f5 | |||
| 4188219620 | |||
| fa8668c77d | |||
| 47f5f887e8 | |||
| c143d87e7c | |||
| 2fcdd3f8eb | |||
| 8c0dc55af8 | |||
| 8c04379a4c | |||
| a5bfe548d7 | |||
| e77e6e9d12 | |||
| a2b87c033a | |||
| b3c5d94bd1 | |||
| d029549c2f | |||
| 6e13467ce8 | |||
| 508ac2030e | |||
| 4b81bce48d | |||
| 3486675e00 | |||
| 84aad39940 | |||
| c89ca5ebb8 | |||
| 1a4b86233f | |||
| 69a487c407 | |||
| f32c73ad1f | |||
| a343439973 | |||
| aeb86d953e | |||
| 49bba6c997 | |||
| 49b2e8c3a9 | |||
| 9c1220e14d | |||
| e2ac2a82a5 | |||
| bb6290a5d5 | |||
| 312411dea0 | |||
| 7277682cfb | |||
| 0f229bfbbf | |||
| 28b23b44ec | |||
| 8627157298 | |||
| b87268f130 | |||
| a395f8e2c8 | |||
| 3ce459f23a | |||
| e51923778f | |||
| 468578113a | |||
| 2c32154115 | |||
| 47d99457d9 | |||
| 88b756b39f | |||
| 462ff4cc84 | |||
| 18274e717a | |||
| 7870f74c21 | |||
| 8dee2e3984 | |||
| 8e86e64d78 | |||
| e79e972255 | |||
| 682a31f92b | |||
| 17974aa285 | |||
| 0a7fd86d59 | |||
| d95d46dee6 | |||
| 81c8352179 | |||
| 6d80c9505d | |||
| 1b0cf6a91b | |||
| 954ce5379c | |||
| 8b5c19218d | |||
| f6408c7b11 | |||
| 095aae5e2c | |||
| 26eb29547b | |||
| d3a02a297f | |||
| ab508e1e7f | |||
| 87d1bbe947 | |||
| 2e661e82d1 | |||
| 61c6832b48 | |||
| ed0038fdf2 | |||
| c181d89c9d | |||
| c91c9e2429 | |||
| 7add524041 | |||
| 72928f201c | |||
| 81a9210091 | |||
| e9877bc72a | |||
| ea632ab8a4 | |||
| d0501c69b0 | |||
| 3c03385e2e | |||
| 191ccbf660 | |||
| d983269908 | |||
| 2ceab2d270 | |||
| 8ce3664305 | |||
| ccd8485111 | |||
| 70caf4ed6d | |||
| b7c8bf7781 | |||
| 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 | |||
| 6af555b394 | |||
| 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 | |||
| ad6c58972c | |||
| 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,106 @@
|
||||
name: Build & Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
Ubuntu-1604:
|
||||
runs-on: ubuntu-16.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: apt
|
||||
run: sudo apt install ruby gperf
|
||||
- name: build and test
|
||||
run: rake -m -j4 all test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
|
||||
Ubuntu-1804-gcc:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: apt
|
||||
run: sudo apt install ruby gperf gcc g++
|
||||
- name: build and test
|
||||
run: rake -m -j4 all test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
|
||||
Ubuntu-1804-clang:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: apt
|
||||
run: sudo apt install ruby gperf
|
||||
- name: build and test
|
||||
run: rake -m -j4 all test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
macOS:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: brew
|
||||
run: brew install ruby gperf
|
||||
- name: build and test
|
||||
run: rake -m -j4 all test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
|
||||
Windows-MinGW:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: chocolatey
|
||||
run: choco install -y ruby gperf
|
||||
- name: build and test
|
||||
run: rake -E '$stdout.sync=true' -j4 test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
CFLAGS: -g -O1 -Wall -Wundef
|
||||
|
||||
Windows-Cygwin:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
|
||||
key: ${{ runner.os }}-cygwin-chocolatey-${{ matrix.os }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cygwin-chocolatey-${{ matrix.os }}-
|
||||
${{ runner.os }}-cygwin-chocolatey-
|
||||
- name: chocolatey
|
||||
run: choco install -y cygwin
|
||||
- name: Install cygwin packages
|
||||
shell: cmd
|
||||
run: C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -l C:/tools/cygwin/package -s http://mirrors.kernel.org/sourceware/cygwin/ -P gcc-core,gcc-g++,make,gperf,ruby
|
||||
- name: Set ENV
|
||||
run: |
|
||||
echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin'
|
||||
- name: build and test
|
||||
shell: cmd
|
||||
run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -m -j4 -E 'STDOUT.sync=true' test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
|
||||
Windows-VC:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: chocolatey
|
||||
run: choco install -y ruby gperf
|
||||
- name: build and test
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
rake -E "STDOUT.sync=true" -m -j4 test
|
||||
env:
|
||||
MRUBY_CONFIG: appveyor_config.rb
|
||||
# TODO(take-cheeze): Re-enable /O2
|
||||
CFLAGS: "/c /nologo /W3 /we4013 /Zi /MD /D_CRT_SECURE_NO_WARNINGS"
|
||||
CXXFLAGS: "/c /nologo /W3 /Zi /MD /EHs /D_CRT_SECURE_NO_WARNINGS"
|
||||
@@ -0,0 +1,51 @@
|
||||
name: "Code scanning - action"
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 19 * * 4'
|
||||
|
||||
jobs:
|
||||
CodeQL-Build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -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
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
.svn
|
||||
.vscode
|
||||
.yardoc
|
||||
.ccls*
|
||||
compile_flags.txt
|
||||
compile_commands.json
|
||||
cscope.files
|
||||
cscope.out
|
||||
tags
|
||||
|
||||
+1601
-401
File diff suppressed because it is too large
Load Diff
+6
-14
@@ -1,19 +1,11 @@
|
||||
language: c
|
||||
|
||||
sudo: false
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
sudo: false
|
||||
- os: osx
|
||||
osx_image: xcode7.1
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gperf
|
||||
jobs:
|
||||
- os: linux
|
||||
- os: osx
|
||||
|
||||
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.2
|
||||
|
||||
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.2 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.1.2.zip](https://github.com/mruby/mruby/archive/2.1.2.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,11 @@ 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
|
||||
$ rake test
|
||||
|
||||
Or
|
||||
|
||||
$ ruby ./minirake test
|
||||
Note: `bison` bundled with MacOS is too old to compile `mruby`.
|
||||
Try `brew install bison` and follow the instuction shown to update
|
||||
the `$PATH` to compile `mruby`.
|
||||
|
||||
## 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
|
||||
|
||||
+9
-12
@@ -4,20 +4,23 @@ os: Visual Studio 2017
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
|
||||
cache:
|
||||
- win_flex_bison
|
||||
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
# 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
|
||||
@@ -30,13 +33,7 @@ init:
|
||||
- ruby --version
|
||||
|
||||
|
||||
install:
|
||||
- if not exist win_flex_bison (
|
||||
appveyor DownloadFile "https://github.com/lexxmark/winflexbison/releases/download/v.2.5.10/win_flex_bison-2.5.10.zip" &
|
||||
7z x -y -owin_flex_bison win_flex_bison-2.5.10.zip
|
||||
)
|
||||
|
||||
build_script:
|
||||
- set YACC=.\win_flex_bison\win_bison.exe
|
||||
- set MRUBY_CONFIG=appveyor_config.rb
|
||||
- rake -m
|
||||
- rake -E $stdout.sync=true test
|
||||
|
||||
+8
-12
@@ -1,14 +1,7 @@
|
||||
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
|
||||
def setup_option(conf)
|
||||
conf.cc.flags[0].delete("/Zi") unless ENV['CFLAGS']
|
||||
conf.cxx.flags[0].delete("/Zi") unless ENV['CFLAGS'] || ENV['CXXFLAGS']
|
||||
conf.linker.flags << "/DEBUG:NONE" unless ENV['LDFLAGS']
|
||||
end
|
||||
|
||||
MRuby::Build.new('full-debug') do |conf|
|
||||
@@ -17,7 +10,8 @@ MRuby::Build.new('full-debug') do |conf|
|
||||
|
||||
# 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)
|
||||
setup_option(conf)
|
||||
|
||||
conf.enable_test
|
||||
end
|
||||
@@ -30,6 +24,7 @@ MRuby::Build.new do |conf|
|
||||
conf.compilers.each do |c|
|
||||
c.defines += %w(MRB_GC_FIXED_ARENA)
|
||||
end
|
||||
setup_option(conf)
|
||||
conf.enable_bintest
|
||||
conf.enable_test
|
||||
end
|
||||
@@ -41,6 +36,7 @@ MRuby::Build.new('cxx_abi') do |conf|
|
||||
conf.compilers.each do |c|
|
||||
c.defines += %w(MRB_GC_FIXED_ARENA)
|
||||
end
|
||||
setup_option(conf)
|
||||
conf.enable_bintest
|
||||
conf.enable_test
|
||||
|
||||
|
||||
+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
|
||||
|
||||
+10
-6
@@ -6,12 +6,16 @@ binaries.
|
||||
## Prerequisites
|
||||
|
||||
To compile mruby out of the source code you need the following tools:
|
||||
* C Compiler (e.g. `gcc`)
|
||||
* Linker (e.g. `gcc`)
|
||||
* C Compiler (e.g. `gcc` or `clang`)
|
||||
* Linker (e.g. `gcc` or `clang`)
|
||||
* Archive utility (e.g. `ar`)
|
||||
* Parser generator (e.g. `bison`)
|
||||
* Ruby 2.0 or later (e.g. `ruby` or `jruby`)
|
||||
|
||||
Note that `bison` bundled with MacOS is too old to compile `mruby`.
|
||||
Try `brew install bison` and follow the instuction shown to update
|
||||
the `$PATH` to compile `mruby`.
|
||||
|
||||
Optional:
|
||||
* GIT (to update mruby source and integrate mrbgems easier)
|
||||
* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc)
|
||||
@@ -32,10 +36,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.2 (2020-08-06)
|
||||
```
|
||||
|
||||
## 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.2 (2020-08-06)]
|
||||
|
||||
```
|
||||
[1, 2, 3]
|
||||
@@ -61,7 +61,7 @@ end
|
||||
|
||||
`ZeroDivisionError` is raised.
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.2 (2020-08-06)]
|
||||
|
||||
No exception is raised.
|
||||
|
||||
@@ -89,7 +89,7 @@ p Liste.new "foobar"
|
||||
|
||||
` [] `
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.2 (2020-08-06)]
|
||||
|
||||
`ArgumentError` is raised.
|
||||
|
||||
@@ -119,7 +119,7 @@ false
|
||||
true
|
||||
```
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.2 (2020-08-06)]
|
||||
|
||||
```
|
||||
true
|
||||
@@ -156,7 +156,7 @@ p 'ok'
|
||||
ok
|
||||
```
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.2 (2020-08-06)]
|
||||
|
||||
```
|
||||
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.2 (2020-08-06)]
|
||||
|
||||
`NameError` is raised.
|
||||
|
||||
@@ -195,7 +195,7 @@ alias $a $__a__
|
||||
|
||||
` nil `
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.2 (2020-08-06)]
|
||||
|
||||
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.2 (2020-08-06)]
|
||||
|
||||
` '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.2 (2020-08-06)]
|
||||
|
||||
```
|
||||
$ ./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.2]
|
||||
|
||||
```
|
||||
$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
|
||||
|
||||
+108
-95
@@ -16,7 +16,6 @@ In the table.1 below, the second field describes the size (and
|
||||
sign) of operands.
|
||||
|
||||
* B: 8bit
|
||||
* sB: signed 8bit
|
||||
* S: 16bit
|
||||
* sS: signed 16bit
|
||||
* W: 24bit
|
||||
@@ -31,97 +30,111 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|
||||
|
||||
## table.1 Instruction Table
|
||||
|
||||
| Instruction Name | Operand type | Semantics |
|
||||
|:-----------------|--------------|---------------------|
|
||||
| OP_NOP | - | |
|
||||
| OP_MOVE" | BB | R(a) = R(b)
|
||||
| OP_LOADL" | BB | R(a) = Pool(b)
|
||||
| OP_LOADI" | BsB | R(a) = mrb_int(b)
|
||||
| OP_LOADI_0' | B | R(a) = 0
|
||||
| OP_LOADI_1' | B | R(a) = 1
|
||||
| OP_LOADI_2' | B | R(a) = 2
|
||||
| OP_LOADI_3' | B | R(a) = 3
|
||||
| OP_LOADSYM" | BB | R(a) = Syms(b)
|
||||
| OP_LOADNIL' | B | R(a) = nil
|
||||
| OP_LOADSELF' | B | R(a) = self
|
||||
| OP_LOADT' | B | R(a) = true
|
||||
| OP_LOADF' | B | R(a) = false
|
||||
| OP_GETGV" | BB | R(a) = getglobal(Syms(b))
|
||||
| OP_SETGV" | BB | setglobal(Syms(b), R(a))
|
||||
| OP_GETSV" | BB | R(a) = Special[b]
|
||||
| OP_SETSV" | BB | Special[b] = R(a)
|
||||
| OP_GETIV" | BB | R(a) = ivget(Syms(b))
|
||||
| OP_SETIV" | BB | ivset(Syms(b),R(a))
|
||||
| OP_GETCV" | BB | R(a) = cvget(Syms(b))
|
||||
| OP_SETCV" | BB | cvset(Syms(b),R(a))
|
||||
| OP_GETCONST" | BB | R(a) = constget(Syms(b))
|
||||
| OP_SETCONST" | BB | constset(Syms(b),R(a))
|
||||
| OP_GETMCNST" | BB | R(a) = R(a)::Syms(b)
|
||||
| OP_SETMCNST" | BB | R(a+1)::Syms(b) = R(a)
|
||||
| OP_GETUPVAR' | BBB | R(a) = uvget(b,c)
|
||||
| OP_SETUPVAR' | BBB | uvset(b,c,R(a))
|
||||
| OP_JMP | S | pc+=a
|
||||
| OP_JMPIF' | SB | if R(b) pc+=a
|
||||
| OP_JMPNOT' | SB | if !R(b) pc+=a
|
||||
| OP_ONERR | sS | rescue_push(pc+a)
|
||||
| OP_EXCEPT' | B | R(a) = exc
|
||||
| OP_RESCUE" | BB | R(b) = R(a).isa?(R(b))
|
||||
| OP_POPERR | B | a.times{rescue_pop()}
|
||||
| OP_RAISE' | B | raise(R(a))
|
||||
| OP_EPUSH' | B | ensure_push(SEQ[a])
|
||||
| OP_EPOP | B | A.times{ensure_pop().call}
|
||||
| OP_SENDV" | BB | R(a) = call(R(a),Syms(b),*R(a+1))
|
||||
| OP_SENDVB" | BB | R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
|
||||
| OP_SEND" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
|
||||
| OP_SENDB" | BBB | R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|
||||
| OP_CALL' | B | R(a) = self.call(frame.argc, frame.argv)
|
||||
| OP_SUPER' | BB | R(a) = super(R(a+1),... ,R(a+b+1))
|
||||
| OP_ARGARY' | BS | R(a) = argument array (16=5:1:5:1:4)
|
||||
| OP_ENTER | W | arg setup according to flags (23=5:5:1:5:5:1:1)
|
||||
| OP_KARG" | BB | R(a) = kdict[Syms(Bx)] # todo
|
||||
| OP_KARG2" | BB | R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|
||||
| OP_RETURN' | B | return R(a) (normal)
|
||||
| OP_RETURN_BLK' | B | return R(a) (in-block return)
|
||||
| OP_BREAK' | B | break R(a)
|
||||
| OP_BLKPUSH' | BS | R(a) = block (16=5:1:5:1:4)
|
||||
| OP_ADD" | BB | R(a) = R(a)+R(a+1)
|
||||
| OP_ADDI" | BBB | R(a) = R(a)+mrb_int(c)
|
||||
| OP_SUB" | BB | R(a) = R(a)-R(a+1)
|
||||
| OP_SUBI" | BB | R(a) = R(a)-C
|
||||
| OP_MUL" | BB | R(a) = R(a)*R(a+1)
|
||||
| OP_DIV" | BB | R(a) = R(a)/R(a+1)
|
||||
| OP_EQ" | BB | R(a) = R(a)==R(a+1)
|
||||
| OP_LT" | BB | R(a) = R(a)<R(a+1)
|
||||
| OP_LE" | BB | R(a) = R(a)<=R(a+1)
|
||||
| OP_GT" | BB | R(a) = R(a)>R(a+1)
|
||||
| OP_GE" | BB | R(a) = R(a)>=R(a+1)
|
||||
| OP_ARRAY' | BB | R(a) = ary_new(R(a),R(a+1)..R(a+b))
|
||||
| OP_ARRAY2" | BB | R(a) = ary_new(R(b),R(b+1)..R(b+c))
|
||||
| OP_ARYCAT' | B | ary_cat(R(a),R(a+1))
|
||||
| OP_ARYPUSH' | B | ary_push(R(a),R(a+1))
|
||||
| OP_AREF' | BB | R(a) = R(a)[b]
|
||||
| OP_ASET' | BB | R(a)[b] = R(a+1)
|
||||
| OP_APOST' | BB | *R(a),R(A+1)..R(A+C) = R(a)[B..]
|
||||
| OP_STRING" | BB | R(a) = str_dup(Lit(b))
|
||||
| OP_STRCAT' | B | str_cat(R(a),R(a+1))
|
||||
| OP_HASH' | BB | R(a) = hash_new(R(a),R(a+1)..R(a+b))
|
||||
| OP_HASHADD' | BB | R(a) = hash_push(R(a),R(a+1)..R(a+b))
|
||||
| OP_LAMBDA" | BB | R(a) = lambda(SEQ[b],OP_L_LAMBDA)
|
||||
| OP_BLOCK" | BB | R(a) = lambda(SEQ[b],OP_L_BLOCK)
|
||||
| OP_METHOD" | BB | R(a) = lambda(SEQ[b],OP_L_METHOD)
|
||||
| OP_RANGE_INC' | B | R(a) = range_new(R(a),R(a+1),FALSE)
|
||||
| OP_RANGE_EXC' | B | R(a) = range_new(R(a),R(a+1),TRUE)
|
||||
| OP_OCLASS' | B | R(a) = ::Object
|
||||
| OP_CLASS" | BB | R(a) = newclass(R(a),Syms(b),R(a+1))
|
||||
| OP_MODULE" | BB | R(a) = newmodule(R(a),Syms(b))
|
||||
| OP_EXEC" | BB | R(a) = blockexec(R(a),SEQ[b])
|
||||
| OP_DEF" | BB | R(a).newmethod(Syms(b),R(a+1))
|
||||
| OP_ALIAS' | B | alias_method(R(a),R(a+1),R(a+2))
|
||||
| OP_UNDEF" | BB | undef_method(R(a),Syms(b))
|
||||
| OP_SCLASS' | B | R(a) = R(a).singleton_class
|
||||
| OP_TCLASS' | B | R(a) = target_class
|
||||
| OP_ERR' | B | raise(RuntimeError, Lit(Bx))
|
||||
| OP_EXT1 | - | make 1st operand 16bit
|
||||
| OP_EXT2 | - | make 2nd operand 16bit
|
||||
| OP_EXT3 | - | make 1st and 2nd operands 16bit
|
||||
| OP_STOP | - | stop VM
|
||||
| Instruction Name | Operand type | Semantics |
|
||||
|------------------|--------------|--------------------------------------------------------|
|
||||
| OP_NOP | - | no operation |
|
||||
| OP_MOVE" | BB | R(a) = R(b) |
|
||||
| OP_LOADL" | BB | R(a) = Pool(b) |
|
||||
| OP_LOADI" | BB | R(a) = mrb_int(b) |
|
||||
| OP_LOADINEG" | BB | R(a) = mrb_int(-b) |
|
||||
| OP_LOADI__1' | B | R(a) = mrb_int(-1) |
|
||||
| OP_LOADI_0' | B | R(a) = mrb_int(0) |
|
||||
| OP_LOADI_1' | B | R(a) = mrb_int(1) |
|
||||
| OP_LOADI_2' | B | R(a) = mrb_int(2) |
|
||||
| OP_LOADI_3' | B | R(a) = mrb_int(3) |
|
||||
| OP_LOADI_4' | B | R(a) = mrb_int(4) |
|
||||
| OP_LOADI_5' | B | R(a) = mrb_int(5) |
|
||||
| OP_LOADI_6' | B | R(a) = mrb_int(6) |
|
||||
| OP_LOADI_7' | B | R(a) = mrb_int(7) |
|
||||
| OP_LOADI16' | BsS | R(a) = mrb_int(b) |
|
||||
| OP_LOADSYM" | BB | R(a) = Syms(b) |
|
||||
| OP_LOADNIL' | B | R(a) = nil |
|
||||
| OP_LOADSELF' | B | R(a) = self |
|
||||
| OP_LOADT' | B | R(a) = true |
|
||||
| OP_LOADF' | B | R(a) = false |
|
||||
| OP_GETGV" | BB | R(a) = getglobal(Syms(b)) |
|
||||
| OP_SETGV" | BB | setglobal(Syms(b), R(a)) |
|
||||
| OP_GETSV" | BB | R(a) = Special[Syms(b)] |
|
||||
| OP_SETSV" | BB | Special[Syms(b)] = R(a) |
|
||||
| OP_GETIV" | BB | R(a) = ivget(Syms(b)) |
|
||||
| OP_SETIV" | BB | ivset(Syms(b),R(a)) |
|
||||
| OP_GETCV" | BB | R(a) = cvget(Syms(b)) |
|
||||
| OP_SETCV" | BB | cvset(Syms(b),R(a)) |
|
||||
| OP_GETCONST" | BB | R(a) = constget(Syms(b)) |
|
||||
| OP_SETCONST" | BB | constset(Syms(b),R(a)) |
|
||||
| OP_GETMCNST" | BB | R(a) = R(a)::Syms(b) |
|
||||
| OP_SETMCNST" | BB | R(a+1)::Syms(b) = R(a) |
|
||||
| OP_GETUPVAR" | BBB | R(a) = uvget(b,c) |
|
||||
| OP_SETUPVAR" | BBB | uvset(b,c,R(a)) |
|
||||
| OP_JMP | S | pc=a |
|
||||
| OP_JMPIF' | BS | if R(a) pc=b |
|
||||
| OP_JMPNOT' | BS | if !R(a) pc=b |
|
||||
| OP_JMPNIL' | BS | if R(a)==nil pc=b |
|
||||
| OP_ONERR | S | rescue_push(a) |
|
||||
| OP_EXCEPT' | B | R(a) = exc |
|
||||
| OP_RESCUE" | BB | R(b) = R(a).isa?(R(b)) |
|
||||
| OP_POPERR' | B | a.times{rescue_pop()} |
|
||||
| OP_RAISE' | B | raise(R(a)) |
|
||||
| OP_EPUSH' | B | ensure_push(SEQ[a]) |
|
||||
| OP_EPOP' | B | A.times{ensure_pop().call} |
|
||||
| OP_SENDV" | BB | R(a) = call(R(a),Syms(b),*R(a+1)) |
|
||||
| OP_SENDVB" | BB | R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2)) |
|
||||
| OP_SEND" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) |
|
||||
| OP_SENDB" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c),&R(a+c+1)) |
|
||||
| OP_CALL | - | R(0) = self.call(frame.argc, frame.argv) |
|
||||
| OP_SUPER" | BB | R(a) = super(R(a+1),... ,R(a+b+1)) |
|
||||
| OP_ARGARY' | BS | R(a) = argument array (16=5:1:5:1:4) |
|
||||
| OP_ENTER | W | arg setup according to flags (23=5:5:1:5:5:1:1) |
|
||||
| OP_KEY_P" | BB | R(a) = kdict.key?(Syms(b)) |
|
||||
| OP_KEYEND | - | raise unless kdict.empty? |
|
||||
| OP_KARG" | BB | R(a) = kdict[Syms(b)]; kdict.delete(Syms(b)) |
|
||||
| OP_RETURN' | B | return R(a) (normal) |
|
||||
| OP_RETURN_BLK' | B | return R(a) (in-block return) |
|
||||
| OP_BREAK' | B | break R(a) |
|
||||
| OP_BLKPUSH' | BS | R(a) = block (16=5:1:5:1:4) |
|
||||
| OP_ADD' | B | R(a) = R(a)+R(a+1) |
|
||||
| OP_ADDI" | BB | R(a) = R(a)+mrb_int(b) |
|
||||
| OP_SUB' | B | R(a) = R(a)-R(a+1) |
|
||||
| OP_SUBI" | BB | R(a) = R(a)-mrb_int(b) |
|
||||
| OP_MUL' | B | R(a) = R(a)*R(a+1) |
|
||||
| OP_DIV' | B | R(a) = R(a)/R(a+1) |
|
||||
| OP_EQ' | B | R(a) = R(a)==R(a+1) |
|
||||
| OP_LT' | B | R(a) = R(a)<R(a+1) |
|
||||
| OP_LE' | B | R(a) = R(a)<=R(a+1) |
|
||||
| OP_GT' | B | R(a) = R(a)>R(a+1) |
|
||||
| OP_GE' | B | R(a) = R(a)>=R(a+1) |
|
||||
| OP_ARRAY" | BB | R(a) = ary_new(R(a),R(a+1)..R(a+b)) |
|
||||
| OP_ARRAY2" | BBB | R(a) = ary_new(R(b),R(b+1)..R(b+c)) |
|
||||
| OP_ARYCAT' | B | ary_cat(R(a),R(a+1)) |
|
||||
| OP_ARYPUSH' | B | ary_push(R(a),R(a+1)) |
|
||||
| OP_ARYDUP' | B | R(a) = ary_dup(R(a)) |
|
||||
| OP_AREF" | BBB | R(a) = R(b)[c] |
|
||||
| OP_ASET" | BBB | R(a)[c] = R(b) |
|
||||
| OP_APOST" | BBB | *R(a),R(a+1)..R(a+c) = R(a)[b..] |
|
||||
| OP_INTERN' | B | R(a) = intern(R(a)) |
|
||||
| OP_STRING" | BB | R(a) = str_dup(Lit(b)) |
|
||||
| OP_STRCAT' | B | str_cat(R(a),R(a+1)) |
|
||||
| OP_HASH" | BB | R(a) = hash_new(R(a),R(a+1)..R(a+b)) |
|
||||
| OP_HASHADD" | BB | R(a) = hash_push(R(a),R(a+1)..R(a+b)) |
|
||||
| OP_HASHCAT' | B | R(a) = hash_cat(R(a),R(a+1)) |
|
||||
| OP_LAMBDA" | BB | R(a) = lambda(SEQ[b],OP_L_LAMBDA) |
|
||||
| OP_BLOCK" | BB | R(a) = lambda(SEQ[b],OP_L_BLOCK) |
|
||||
| OP_METHOD" | BB | R(a) = lambda(SEQ[b],OP_L_METHOD) |
|
||||
| OP_RANGE_INC' | B | R(a) = range_new(R(a),R(a+1),FALSE) |
|
||||
| OP_RANGE_EXC' | B | R(a) = range_new(R(a),R(a+1),TRUE) |
|
||||
| OP_OCLASS' | B | R(a) = ::Object |
|
||||
| OP_CLASS" | BB | R(a) = newclass(R(a),Syms(b),R(a+1)) |
|
||||
| OP_MODULE" | BB | R(a) = newmodule(R(a),Syms(b)) |
|
||||
| OP_EXEC" | BB | R(a) = blockexec(R(a),SEQ[b]) |
|
||||
| OP_DEF" | BB | R(a).newmethod(Syms(b),R(a+1)) |
|
||||
| OP_ALIAS" | BB | alias_method(target_class,Syms(a),Syms(b)) |
|
||||
| OP_UNDEF' | B | undef_method(target_class,Syms(a)) |
|
||||
| OP_SCLASS' | B | R(a) = R(a).singleton_class |
|
||||
| OP_TCLASS' | B | R(a) = target_class |
|
||||
| OP_DEBUG" | BBB | print a,b,c |
|
||||
| OP_ERR' | B | raise(LocalJumpError, Lit(a)) |
|
||||
| OP_EXT1 | - | make 1st operand 16bit |
|
||||
| OP_EXT2 | - | make 2nd operand 16bit |
|
||||
| OP_EXT3 | - | make 1st and 2nd operands 16bit |
|
||||
| OP_STOP | - | stop VM |
|
||||
|------------------|--------------|--------------------------------------------------------|
|
||||
|
||||
@@ -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
|
||||
+10
-10
@@ -38,21 +38,24 @@
|
||||
|
||||
/* 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 at least on 32bit
|
||||
// Windows and 32bit Linux.
|
||||
# ifdef MRB_32BIT
|
||||
# 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 +65,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) || \
|
||||
|
||||
+25
-9
@@ -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,7 +70,13 @@
|
||||
|
||||
#include "mrbconf.h"
|
||||
|
||||
#include <mruby/common.h>
|
||||
#include <mruby/value.h>
|
||||
#include <mruby/gc.h>
|
||||
#include <mruby/version.h>
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
#include <float.h>
|
||||
#ifndef FLT_EPSILON
|
||||
#define FLT_EPSILON (1.19209290e-07f)
|
||||
#endif
|
||||
@@ -88,11 +94,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <mruby/common.h>
|
||||
#include <mruby/value.h>
|
||||
#include <mruby/gc.h>
|
||||
#include <mruby/version.h>
|
||||
|
||||
/**
|
||||
* MRuby C API entry point
|
||||
*/
|
||||
@@ -164,8 +165,8 @@ struct mrb_context {
|
||||
struct RProc **ensure; /* ensure handler stack */
|
||||
uint16_t esize, eidx;
|
||||
|
||||
enum mrb_fiber_state status;
|
||||
mrb_bool vmexec;
|
||||
enum mrb_fiber_state status : 4;
|
||||
mrb_bool vmexec : 1;
|
||||
struct RFiber *fib;
|
||||
};
|
||||
|
||||
@@ -317,7 +318,9 @@ MRB_API struct RClass *mrb_define_class(mrb_state *mrb, const char *name, struct
|
||||
* @return [struct RClass *] Reference to the newly defined module.
|
||||
*/
|
||||
MRB_API struct RClass *mrb_define_module(mrb_state *mrb, const char *name);
|
||||
|
||||
MRB_API mrb_value mrb_singleton_class(mrb_state *mrb, mrb_value val);
|
||||
MRB_API struct RClass *mrb_singleton_class_ptr(mrb_state *mrb, mrb_value val);
|
||||
|
||||
/**
|
||||
* Include a module in another class or module.
|
||||
@@ -956,8 +959,21 @@ mrb_get_mid(mrb_state *mrb) /* get method symbol */
|
||||
*/
|
||||
MRB_API mrb_int mrb_get_argc(mrb_state *mrb);
|
||||
|
||||
/**
|
||||
* Retrieve an array of arguments from mrb_state.
|
||||
*
|
||||
* Correctly handles *splat arguments.
|
||||
*/
|
||||
MRB_API mrb_value* mrb_get_argv(mrb_state *mrb);
|
||||
|
||||
/**
|
||||
* Retrieve the first and only argument from mrb_state.
|
||||
* Raises ArgumentError unless the number of arguments is exactly one.
|
||||
*
|
||||
* Correctly handles *splat arguments.
|
||||
*/
|
||||
MRB_API mrb_value mrb_get_arg1(mrb_state *mrb);
|
||||
|
||||
/* `strlen` for character string literals (use with caution or `strlen` instead)
|
||||
Adjacent string literals are concatenated in C/C++ in translation phase 6.
|
||||
If `lit` is not one, the compiler will report a syntax error:
|
||||
@@ -1148,7 +1164,6 @@ MRB_API void mrb_close(mrb_state *mrb);
|
||||
MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*);
|
||||
|
||||
MRB_API mrb_value mrb_top_self(mrb_state *mrb);
|
||||
MRB_API mrb_value mrb_run(mrb_state *mrb, struct RProc* proc, mrb_value self);
|
||||
MRB_API mrb_value mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep);
|
||||
MRB_API mrb_value mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep);
|
||||
MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *iseq);
|
||||
@@ -1232,6 +1247,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;
|
||||
@@ -239,6 +239,7 @@ MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
|
||||
* @param head Beginning position of a replacement subsequence.
|
||||
* @param len Length of a replacement subsequence.
|
||||
* @param rpl The array of replacement elements.
|
||||
* It is possible to pass `mrb_undef_value()` instead of an empty array.
|
||||
* @return The receiver array.
|
||||
*/
|
||||
MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value self, mrb_int head, mrb_int len, mrb_value rpl);
|
||||
@@ -291,6 +292,9 @@ MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep);
|
||||
*/
|
||||
MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len);
|
||||
|
||||
/* helper functions */
|
||||
mrb_value mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len);
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
#endif /* MRUBY_ARRAY_H */
|
||||
|
||||
@@ -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
|
||||
@@ -43,6 +44,9 @@ typedef struct mrb_value {
|
||||
};
|
||||
)
|
||||
};
|
||||
#ifdef MRB_64BIT
|
||||
struct RCptr *vp;
|
||||
#endif
|
||||
} value;
|
||||
};
|
||||
} mrb_value;
|
||||
@@ -53,13 +57,15 @@ typedef struct mrb_value {
|
||||
#define mrb_type(o) (enum mrb_vtype)((uint32_t)0xfff00000 < (o).value.ttt ? mrb_tt(o) : MRB_TT_FLOAT)
|
||||
#define mrb_ptr(o) ((void*)((((uintptr_t)0x3fffffffffff)&((uintptr_t)((o).value.p)))<<2))
|
||||
#define mrb_float(o) (o).f
|
||||
#define mrb_cptr(o) mrb_ptr(o)
|
||||
#define mrb_fixnum(o) (o).value.i
|
||||
#define mrb_symbol(o) (o).value.sym
|
||||
|
||||
#ifdef MRB_64BIT
|
||||
MRB_API mrb_value mrb_nan_boxing_cptr_value(struct mrb_state*, void*);
|
||||
#define mrb_cptr(o) (((struct RCptr*)mrb_ptr(o))->p)
|
||||
#define BOXNAN_SHIFT_LONG_POINTER(v) (((uintptr_t)(v)>>34)&0x3fff)
|
||||
#else
|
||||
#define mrb_cptr(o) ((o).value.p)
|
||||
#define BOXNAN_SHIFT_LONG_POINTER(v) 0
|
||||
#endif
|
||||
|
||||
@@ -89,7 +95,11 @@ typedef struct mrb_value {
|
||||
#define SET_INT_VALUE(r,n) BOXNAN_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
|
||||
#define SET_SYM_VALUE(r,v) BOXNAN_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
|
||||
#define SET_OBJ_VALUE(r,v) BOXNAN_SET_OBJ_VALUE(r, (((struct RObject*)(v))->tt), (v))
|
||||
#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_OBJ_VALUE(r, MRB_TT_CPTR, v)
|
||||
#ifdef MRB_64BIT
|
||||
#define SET_CPTR_VALUE(mrb,r,v) ((r) = mrb_nan_boxing_cptr_value(mrb, v))
|
||||
#else
|
||||
#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_VALUE(r, MRB_TT_CPTR, value.p, v)
|
||||
#endif
|
||||
#define SET_UNDEF_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0)
|
||||
|
||||
#endif /* MRUBY_BOXING_NAN_H */
|
||||
|
||||
@@ -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
-33
@@ -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
|
||||
@@ -22,11 +18,6 @@ struct RFloat {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct RCptr {
|
||||
MRB_OBJECT_HEADER;
|
||||
void *p;
|
||||
};
|
||||
|
||||
enum mrb_special_consts {
|
||||
MRB_Qnil = 0,
|
||||
MRB_Qfalse = 4,
|
||||
@@ -34,41 +25,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 +110,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
|
||||
@@ -141,7 +137,6 @@ MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
|
||||
#define mrb_sclass_p(o) BOXWORD_OBJ_TYPE_P(o, SCLASS)
|
||||
#define mrb_proc_p(o) BOXWORD_OBJ_TYPE_P(o, PROC)
|
||||
#define mrb_range_p(o) BOXWORD_OBJ_TYPE_P(o, RANGE)
|
||||
#define mrb_file_p(o) BOXWORD_OBJ_TYPE_P(o, FILE)
|
||||
#define mrb_env_p(o) BOXWORD_OBJ_TYPE_P(o, ENV)
|
||||
#define mrb_data_p(o) BOXWORD_OBJ_TYPE_P(o, DATA)
|
||||
#define mrb_fiber_p(o) BOXWORD_OBJ_TYPE_P(o, FIBER)
|
||||
@@ -159,7 +154,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 */
|
||||
|
||||
+12
-3
@@ -33,7 +33,7 @@ typedef struct mrbc_context {
|
||||
mrb_bool no_exec:1;
|
||||
mrb_bool keep_lv:1;
|
||||
mrb_bool no_optimize:1;
|
||||
mrb_bool on_eval:1;
|
||||
struct RProc *upper;
|
||||
|
||||
size_t parser_nerr;
|
||||
} mrbc_context;
|
||||
@@ -151,8 +151,8 @@ struct mrb_parser_state {
|
||||
mrb_ast_node *tree;
|
||||
|
||||
mrb_bool no_optimize:1;
|
||||
mrb_bool on_eval:1;
|
||||
mrb_bool capture_errors:1;
|
||||
struct RProc *upper;
|
||||
struct mrb_parser_message error_buffer[10];
|
||||
struct mrb_parser_message warn_buffer[10];
|
||||
|
||||
@@ -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*);
|
||||
@@ -179,7 +180,15 @@ MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t
|
||||
MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*);
|
||||
MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c);
|
||||
|
||||
/* program load functions */
|
||||
/** program load functions
|
||||
* Please note! Currently due to interactions with the GC calling these functions will
|
||||
* leak one RProc object per function call.
|
||||
* To prevent this save the current memory arena before calling and restore the arena
|
||||
* right after, like so
|
||||
* int ai = mrb_gc_arena_save(mrb);
|
||||
* mrb_value status = mrb_load_string(mrb, buffer);
|
||||
* mrb_gc_arena_restore(mrb, ai);
|
||||
*/
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
MRB_API mrb_value mrb_load_file(mrb_state*,FILE*);
|
||||
MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
|
||||
|
||||
+1
-17
@@ -17,10 +17,6 @@
|
||||
MRB_BEGIN_DECL
|
||||
|
||||
#define DUMP_DEBUG_INFO 1
|
||||
#define DUMP_ENDIAN_BIG 2
|
||||
#define DUMP_ENDIAN_LIL 4
|
||||
#define DUMP_ENDIAN_NAT 6
|
||||
#define DUMP_ENDIAN_MASK 6
|
||||
|
||||
int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
@@ -52,8 +48,7 @@ MRB_API mrb_irep *mrb_read_irep_buf(mrb_state*, const void*, size_t);
|
||||
|
||||
/* Rite Binary File header */
|
||||
#define RITE_BINARY_IDENT "RITE"
|
||||
#define RITE_BINARY_IDENT_LIL "ETIR"
|
||||
#define RITE_BINARY_FORMAT_VER "0006"
|
||||
#define RITE_BINARY_FORMAT_VER "0007"
|
||||
#define RITE_COMPILER_NAME "MATZ"
|
||||
#define RITE_COMPILER_VERSION "0000"
|
||||
|
||||
@@ -106,17 +101,6 @@ struct rite_binary_footer {
|
||||
RITE_SECTION_HEADER;
|
||||
};
|
||||
|
||||
static inline int
|
||||
bigendian_p()
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
i = 1;
|
||||
p = (char*)&i;
|
||||
return p[0]?0:1;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
uint8_to_bin(uint8_t s, uint8_t *bin)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -49,6 +49,16 @@ typedef struct mrb_irep {
|
||||
|
||||
MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb);
|
||||
|
||||
/** load mruby bytecode functions
|
||||
* Please note! Currently due to interactions with the GC calling these functions will
|
||||
* leak one RProc object per function call.
|
||||
* To prevent this save the current memory arena before calling and restore the arena
|
||||
* right after, like so
|
||||
* int ai = mrb_gc_arena_save(mrb);
|
||||
* mrb_value status = mrb_load_irep(mrb, buffer);
|
||||
* mrb_gc_arena_restore(mrb, ai);
|
||||
*/
|
||||
|
||||
/* @param [const uint8_t*] irep code, expected as a literal */
|
||||
MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*);
|
||||
|
||||
|
||||
@@ -21,7 +21,10 @@ MRB_BEGIN_DECL
|
||||
|
||||
struct RIStruct {
|
||||
MRB_OBJECT_HEADER;
|
||||
char inline_data[ISTRUCT_DATA_SIZE];
|
||||
union {
|
||||
intptr_t inline_alignment[3];
|
||||
char inline_data[ISTRUCT_DATA_SIZE];
|
||||
};
|
||||
};
|
||||
|
||||
#define RISTRUCT(obj) ((struct RIStruct*)(mrb_ptr(obj)))
|
||||
|
||||
+23
-5
@@ -73,6 +73,7 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0};
|
||||
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \
|
||||
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \
|
||||
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \
|
||||
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h); \
|
||||
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \
|
||||
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \
|
||||
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
|
||||
@@ -95,16 +96,25 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
|
||||
__hash_equal: hash comparation function
|
||||
*/
|
||||
#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
|
||||
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
|
||||
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb); \
|
||||
int kh_alloc_simple_##name(mrb_state *mrb, kh_##name##_t *h) \
|
||||
{ \
|
||||
khint_t sz = h->n_buckets; \
|
||||
size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \
|
||||
uint8_t *p = (uint8_t*)mrb_malloc(mrb, sizeof(uint8_t)*sz/4+len*sz); \
|
||||
uint8_t *p = (uint8_t*)mrb_malloc_simple(mrb, sizeof(uint8_t)*sz/4+len*sz); \
|
||||
if (!p) { return 1; } \
|
||||
h->size = h->n_occupied = 0; \
|
||||
h->keys = (khkey_t *)p; \
|
||||
h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \
|
||||
h->ed_flags = p+len*sz; \
|
||||
kh_fill_flags(h->ed_flags, 0xaa, sz/4); \
|
||||
return 0; \
|
||||
} \
|
||||
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
|
||||
{ \
|
||||
if (kh_alloc_simple_##name(mrb, h)) { \
|
||||
mrb_raise_nomemory(mrb); \
|
||||
} \
|
||||
} \
|
||||
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \
|
||||
kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
|
||||
@@ -112,7 +122,10 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
|
||||
size = KHASH_MIN_SIZE; \
|
||||
khash_power2(size); \
|
||||
h->n_buckets = size; \
|
||||
kh_alloc_##name(mrb, h); \
|
||||
if (kh_alloc_simple_##name(mrb, h)) { \
|
||||
mrb_free(mrb, h); \
|
||||
mrb_raise_nomemory(mrb); \
|
||||
} \
|
||||
return h; \
|
||||
} \
|
||||
kh_##name##_t *kh_init_##name(mrb_state *mrb) { \
|
||||
@@ -171,12 +184,16 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
|
||||
mrb_free(mrb, old_keys); \
|
||||
} \
|
||||
} \
|
||||
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
|
||||
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h) \
|
||||
{ \
|
||||
khint_t k, del_k, step = 0; \
|
||||
if (h->n_occupied >= khash_upper_bound(h)) { \
|
||||
kh_resize_##name(mrb, h, h->n_buckets*2); \
|
||||
} \
|
||||
} \
|
||||
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
|
||||
{ \
|
||||
khint_t k, del_k, step = 0; \
|
||||
kh_put_prepare_##name(mrb, h); \
|
||||
k = __hash_func(mrb,key) & khash_mask(h); \
|
||||
del_k = kh_end(h); \
|
||||
while (!__ac_isempty(h->ed_flags, k)) { \
|
||||
@@ -239,6 +256,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
|
||||
#define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h)
|
||||
#define kh_clear(name, mrb, h) kh_clear_##name(mrb, h)
|
||||
#define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s)
|
||||
#define kh_put_prepare(name, mrb, h) kh_put_prepare_##name(mrb, h)
|
||||
#define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL)
|
||||
#define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r)
|
||||
#define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k)
|
||||
|
||||
@@ -37,6 +37,7 @@ MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base);
|
||||
/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
|
||||
MRB_API int mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float f);
|
||||
MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
|
||||
MRB_API mrb_value mrb_int_value(mrb_state *mrb, mrb_float f);
|
||||
#endif
|
||||
|
||||
+3
-2
@@ -92,8 +92,8 @@ OPCODE(APOST, BBB) /* *R(a),R(a+1)..R(a+c) = R(a)[b..] */
|
||||
OPCODE(INTERN, B) /* R(a) = intern(R(a)) */
|
||||
OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */
|
||||
OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */
|
||||
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b)) */
|
||||
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b)) */
|
||||
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b*2-1)) */
|
||||
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b*2)) */
|
||||
OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */
|
||||
OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
|
||||
OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
|
||||
@@ -115,3 +115,4 @@ OPCODE(EXT1, Z) /* make 1st operand 16bit */
|
||||
OPCODE(EXT2, Z) /* make 2nd operand 16bit */
|
||||
OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */
|
||||
OPCODE(STOP, Z) /* stop VM */
|
||||
OPCODE(LOADI16, BS) /* R(a) = mrb_int(b) */
|
||||
|
||||
+13
-8
@@ -22,14 +22,19 @@ struct REnv {
|
||||
mrb_sym mid;
|
||||
};
|
||||
|
||||
/* flags (21bits): 1(shared flag):10(cioff/bidx):10(stack_len) */
|
||||
#define MRB_ENV_SET_STACK_LEN(e,len) ((e)->flags = (((e)->flags & ~0x3ff)|((unsigned int)(len) & 0x3ff)))
|
||||
#define MRB_ENV_STACK_LEN(e) ((mrb_int)((e)->flags & 0x3ff))
|
||||
#define MRB_ENV_STACK_UNSHARED (1<<20)
|
||||
#define MRB_ENV_UNSHARE_STACK(e) ((e)->flags |= MRB_ENV_STACK_UNSHARED)
|
||||
#define MRB_ENV_STACK_SHARED_P(e) (((e)->flags & MRB_ENV_STACK_UNSHARED) == 0)
|
||||
#define MRB_ENV_BIDX(e) (((e)->flags >> 10) & 0x3ff)
|
||||
#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0x3ff<<10))|((unsigned int)(idx) & 0x3ff)<<10))
|
||||
/* flags (21bits): 1(close):1(touched):1(heap):8(cioff/bidx):8(stack_len) */
|
||||
#define MRB_ENV_SET_LEN(e,len) ((e)->flags = (((e)->flags & ~0xff)|((unsigned int)(len) & 0xff)))
|
||||
#define MRB_ENV_LEN(e) ((mrb_int)((e)->flags & 0xff))
|
||||
#define MRB_ENV_CLOSED (1<<20)
|
||||
#define MRB_ENV_TOUCHED (1<<19)
|
||||
#define MRB_ENV_HEAPED (1<<18)
|
||||
#define MRB_ENV_CLOSE(e) ((e)->flags |= MRB_ENV_CLOSED)
|
||||
#define MRB_ENV_TOUCH(e) ((e)->flags |= MRB_ENV_TOUCHED)
|
||||
#define MRB_ENV_HEAP(e) ((e)->flags |= MRB_ENV_HEAPED)
|
||||
#define MRB_ENV_HEAP_P(e) ((e)->flags & MRB_ENV_HEAPED)
|
||||
#define MRB_ENV_ONSTACK_P(e) (((e)->flags & MRB_ENV_CLOSED) == 0)
|
||||
#define MRB_ENV_BIDX(e) (((e)->flags >> 8) & 0xff)
|
||||
#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0xff<<8))|((unsigned int)(idx) & 0xff)<<8))
|
||||
|
||||
void mrb_env_unshare(mrb_state*, struct REnv*);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+41
-44
@@ -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
|
||||
@@ -115,32 +103,31 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
|
||||
#endif
|
||||
|
||||
enum mrb_vtype {
|
||||
MRB_TT_FALSE = 0, /* 0 */
|
||||
MRB_TT_TRUE, /* 1 */
|
||||
MRB_TT_FLOAT, /* 2 */
|
||||
MRB_TT_FIXNUM, /* 3 */
|
||||
MRB_TT_SYMBOL, /* 4 */
|
||||
MRB_TT_UNDEF, /* 5 */
|
||||
MRB_TT_CPTR, /* 6 */
|
||||
MRB_TT_FREE, /* 7 */
|
||||
MRB_TT_OBJECT, /* 8 */
|
||||
MRB_TT_CLASS, /* 9 */
|
||||
MRB_TT_MODULE, /* 10 */
|
||||
MRB_TT_ICLASS, /* 11 */
|
||||
MRB_TT_SCLASS, /* 12 */
|
||||
MRB_TT_PROC, /* 13 */
|
||||
MRB_TT_ARRAY, /* 14 */
|
||||
MRB_TT_HASH, /* 15 */
|
||||
MRB_TT_STRING, /* 16 */
|
||||
MRB_TT_RANGE, /* 17 */
|
||||
MRB_TT_EXCEPTION, /* 18 */
|
||||
MRB_TT_FILE, /* 19 */
|
||||
MRB_TT_ENV, /* 20 */
|
||||
MRB_TT_DATA, /* 21 */
|
||||
MRB_TT_FIBER, /* 22 */
|
||||
MRB_TT_ISTRUCT, /* 23 */
|
||||
MRB_TT_BREAK, /* 24 */
|
||||
MRB_TT_MAXDEFINE /* 25 */
|
||||
MRB_TT_FALSE = 0,
|
||||
MRB_TT_TRUE,
|
||||
MRB_TT_FLOAT,
|
||||
MRB_TT_FIXNUM,
|
||||
MRB_TT_SYMBOL,
|
||||
MRB_TT_UNDEF,
|
||||
MRB_TT_CPTR,
|
||||
MRB_TT_FREE,
|
||||
MRB_TT_OBJECT,
|
||||
MRB_TT_CLASS,
|
||||
MRB_TT_MODULE,
|
||||
MRB_TT_ICLASS,
|
||||
MRB_TT_SCLASS,
|
||||
MRB_TT_PROC,
|
||||
MRB_TT_ARRAY,
|
||||
MRB_TT_HASH,
|
||||
MRB_TT_STRING,
|
||||
MRB_TT_RANGE,
|
||||
MRB_TT_EXCEPTION,
|
||||
MRB_TT_ENV,
|
||||
MRB_TT_DATA,
|
||||
MRB_TT_FIBER,
|
||||
MRB_TT_ISTRUCT,
|
||||
MRB_TT_BREAK,
|
||||
MRB_TT_MAXDEFINE
|
||||
};
|
||||
|
||||
#include <mruby/object.h>
|
||||
@@ -161,6 +148,13 @@ typedef void mrb_value;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT))
|
||||
struct RCptr {
|
||||
MRB_OBJECT_HEADER;
|
||||
void *p;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(MRB_NAN_BOXING)
|
||||
#include "boxing_nan.h"
|
||||
#elif defined(MRB_WORD_BOXING)
|
||||
@@ -169,9 +163,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
|
||||
@@ -239,9 +239,6 @@ typedef void mrb_value;
|
||||
#ifndef mrb_range_p
|
||||
#define mrb_range_p(o) (mrb_type(o) == MRB_TT_RANGE)
|
||||
#endif
|
||||
#ifndef mrb_file_p
|
||||
#define mrb_file_p(o) (mrb_type(o) == MRB_TT_FILE)
|
||||
#endif
|
||||
#ifndef mrb_env_p
|
||||
#define mrb_env_p(o) (mrb_type(o) == MRB_TT_ENV)
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,7 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Tiny release version number.
|
||||
*/
|
||||
#define MRUBY_RELEASE_TEENY 0
|
||||
#define MRUBY_RELEASE_TEENY 2
|
||||
|
||||
/*
|
||||
* 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 8
|
||||
|
||||
/*
|
||||
* Release day.
|
||||
*/
|
||||
#define MRUBY_RELEASE_DAY 18
|
||||
#define MRUBY_RELEASE_DAY 6
|
||||
|
||||
/*
|
||||
* 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"
|
||||
|
||||
+5
-33
@@ -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
|
||||
@@ -344,7 +336,8 @@ EOS
|
||||
puts " Binaries: #{@bins.join(', ')}" unless @bins.empty?
|
||||
unless @gems.empty?
|
||||
puts " Included Gems:"
|
||||
@gems.map do |gem|
|
||||
gems = @gems.sort_by { |gem| gem.name }
|
||||
gems.each do |gem|
|
||||
gem_version = " - #{gem.version}" if gem.version != '0.0.0'
|
||||
gem_summary = " - #{gem.summary}" if gem.summary
|
||||
puts " #{gem.name}#{gem_version}#{gem_summary}"
|
||||
@@ -386,7 +379,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."
|
||||
@@ -395,26 +388,5 @@ EOS
|
||||
@test_runner.run(mrbtest)
|
||||
end
|
||||
end
|
||||
|
||||
def big_endian
|
||||
if @endian
|
||||
puts "Endian has already specified as #{@endian}."
|
||||
return
|
||||
end
|
||||
@endian = :big
|
||||
@mrbc.compile_options += ' -E'
|
||||
compilers.each do |c|
|
||||
c.defines += %w(MRB_ENDIAN_BIG)
|
||||
end
|
||||
end
|
||||
|
||||
def little_endian
|
||||
if @endian
|
||||
puts "Endian has already specified as #{@endian}."
|
||||
return
|
||||
end
|
||||
@endian = :little
|
||||
@mrbc.compile_options += ' -e'
|
||||
end
|
||||
end # CrossBuild
|
||||
end # MRuby
|
||||
|
||||
+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
|
||||
|
||||
+3
-1
@@ -6,7 +6,9 @@ module MRuby
|
||||
ROOT = Pathname.new(File.expand_path('../../../',__FILE__))
|
||||
|
||||
# Reads a constant defined at version.h
|
||||
MRUBY_READ_VERSION_CONSTANT = Proc.new { |name| ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?$/)[1] }
|
||||
MRUBY_READ_VERSION_CONSTANT = Proc.new do |name|
|
||||
ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?\r?$/)[1]
|
||||
end
|
||||
|
||||
MRUBY_RUBY_VERSION = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_VERSION']
|
||||
MRUBY_RUBY_ENGINE = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_ENGINE']
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -71,6 +71,10 @@ MRuby::GemBox.new do |conf|
|
||||
# Use toplevel object (main) methods extension
|
||||
conf.gem :core => "mruby-toplevel-ext"
|
||||
|
||||
# Use Rational/Complex numbers
|
||||
conf.gem :core => "mruby-rational"
|
||||
conf.gem :core => "mruby-complex"
|
||||
|
||||
# Generate mirb command
|
||||
conf.gem :core => "mruby-bin-mirb"
|
||||
|
||||
@@ -89,6 +93,9 @@ MRuby::GemBox.new do |conf|
|
||||
# Use Method/UnboundMethod class
|
||||
conf.gem :core => "mruby-method"
|
||||
|
||||
# Use eval()
|
||||
conf.gem :core => "mruby-eval"
|
||||
|
||||
# Use mruby-compiler to build other mrbgems
|
||||
conf.gem :core => "mruby-compiler"
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -28,9 +28,8 @@ static mrb_value
|
||||
mrb_ary_assoc(mrb_state *mrb, mrb_value ary)
|
||||
{
|
||||
mrb_int i;
|
||||
mrb_value v, k;
|
||||
|
||||
mrb_get_args(mrb, "o", &k);
|
||||
mrb_value v;
|
||||
mrb_value k = mrb_get_arg1(mrb);
|
||||
|
||||
for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
||||
v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
|
||||
@@ -59,9 +58,8 @@ static mrb_value
|
||||
mrb_ary_rassoc(mrb_state *mrb, mrb_value ary)
|
||||
{
|
||||
mrb_int i;
|
||||
mrb_value v, value;
|
||||
|
||||
mrb_get_args(mrb, "o", &value);
|
||||
mrb_value v;
|
||||
mrb_value value = mrb_get_arg1(mrb);
|
||||
|
||||
for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
||||
v = RARRAY_PTR(ary)[i];
|
||||
@@ -140,9 +138,8 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
|
||||
mrb_ary_modify(mrb, a);
|
||||
|
||||
if (mrb_get_argc(mrb) == 1) {
|
||||
mrb_value index;
|
||||
mrb_value index = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o|i", &index, &len);
|
||||
switch (mrb_type(index)) {
|
||||
case MRB_TT_RANGE:
|
||||
if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -5,19 +5,22 @@ unless MRuby::Build.current.kind_of?(MRuby::CrossBuild)
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = "#{name} command"
|
||||
|
||||
mruby_config_dir = "#{build.build_dir}/bin"
|
||||
mruby_config = name + (ENV['OS'] == 'Windows_NT' ? '.bat' : '')
|
||||
mruby_config_path = "#{build.build_dir}/bin/#{mruby_config}"
|
||||
mruby_config_path = "#{mruby_config_dir}/#{mruby_config}"
|
||||
make_cfg = "#{build.build_dir}/lib/libmruby.flags.mak"
|
||||
tmplt_path = "#{__dir__}/#{mruby_config}"
|
||||
build.bins << mruby_config
|
||||
|
||||
file mruby_config_path => [make_cfg, tmplt_path] do |t|
|
||||
directory mruby_config_dir
|
||||
|
||||
file mruby_config_path => [mruby_config_dir, make_cfg, tmplt_path] do |t|
|
||||
config = Hash[File.readlines(make_cfg).map!(&:chomp).map! {|l|
|
||||
l.gsub('\\"', '"').split(' = ', 2).map! {|s| s.sub(/^(?=.)/, 'echo ')}
|
||||
}]
|
||||
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>
|
||||
@@ -645,8 +649,8 @@ main(int argc, char **argv)
|
||||
/* adjust stack length of toplevel environment */
|
||||
if (mrb->c->cibase->env) {
|
||||
struct REnv *e = mrb->c->cibase->env;
|
||||
if (e && MRB_ENV_STACK_LEN(e) < proc->body.irep->nlocals) {
|
||||
MRB_ENV_SET_STACK_LEN(e, proc->body.irep->nlocals);
|
||||
if (e && MRB_ENV_LEN(e) < proc->body.irep->nlocals) {
|
||||
MRB_ENV_SET_LEN(e, proc->body.irep->nlocals);
|
||||
}
|
||||
}
|
||||
/* pass a proc for evaluation */
|
||||
|
||||
@@ -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>
|
||||
@@ -32,8 +36,6 @@ usage(const char *name)
|
||||
"-v print version number, then turn on verbose mode",
|
||||
"-g produce debugging information",
|
||||
"-B<symbol> binary <symbol> output in C language format",
|
||||
"-e generate little endian iseq data",
|
||||
"-E generate big endian iseq data",
|
||||
"--remove-lv remove local variables",
|
||||
"--verbose run at verbose mode",
|
||||
"--version print the version",
|
||||
@@ -50,19 +52,26 @@ usage(const char *name)
|
||||
static char *
|
||||
get_outfilename(mrb_state *mrb, char *infile, const char *ext)
|
||||
{
|
||||
size_t infilelen;
|
||||
size_t extlen;
|
||||
size_t ilen, flen, elen;
|
||||
char *outfile;
|
||||
char *p;
|
||||
char *p = NULL;
|
||||
|
||||
infilelen = strlen(infile);
|
||||
extlen = strlen(ext);
|
||||
outfile = (char*)mrb_malloc(mrb, infilelen + extlen + 1);
|
||||
memcpy(outfile, infile, infilelen + 1);
|
||||
ilen = strlen(infile);
|
||||
flen = ilen;
|
||||
if (*ext) {
|
||||
if ((p = strrchr(outfile, '.')) == NULL)
|
||||
p = outfile + infilelen;
|
||||
memcpy(p, ext, extlen + 1);
|
||||
elen = strlen(ext);
|
||||
if ((p = strrchr(infile, '.'))) {
|
||||
ilen = p - infile;
|
||||
}
|
||||
flen += elen;
|
||||
}
|
||||
else {
|
||||
flen = ilen;
|
||||
}
|
||||
outfile = (char*)mrb_malloc(mrb, flen+1);
|
||||
strncpy(outfile, infile, ilen+1);
|
||||
if (p) {
|
||||
strncpy(outfile+ilen, ext, elen+1);
|
||||
}
|
||||
|
||||
return outfile;
|
||||
@@ -120,10 +129,8 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
|
||||
args->flags |= DUMP_DEBUG_INFO;
|
||||
break;
|
||||
case 'E':
|
||||
args->flags = DUMP_ENDIAN_BIG | (args->flags & ~DUMP_ENDIAN_MASK);
|
||||
break;
|
||||
case 'e':
|
||||
args->flags = DUMP_ENDIAN_LIL | (args->flags & ~DUMP_ENDIAN_MASK);
|
||||
fprintf(stderr, "%s: -e/-E option no longer needed.\n", args->prog);
|
||||
break;
|
||||
case 'h':
|
||||
return -1;
|
||||
@@ -156,10 +163,6 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (args->verbose && args->initname && (args->flags & DUMP_ENDIAN_MASK) == 0) {
|
||||
fprintf(stderr, "%s: generating %s endian C file. specify -e/-E for cross compiling.\n",
|
||||
args->prog, bigendian_p() ? "big" : "little");
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -183,7 +186,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 +213,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
|
||||
|
||||
@@ -4,7 +4,6 @@ MRuby::Gem::Specification.new('mruby-bin-mruby') do |spec|
|
||||
spec.summary = 'mruby command'
|
||||
spec.bins = %w(mruby)
|
||||
spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
|
||||
spec.add_dependency('mruby-error', :core => 'mruby-error')
|
||||
spec.add_test_dependency('mruby-print', :core => 'mruby-print')
|
||||
|
||||
if build.cxx_exception_enabled?
|
||||
|
||||
@@ -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
|
||||
@@ -39,10 +43,15 @@ mrb_mod_module_exec(mrb_state *mrb, mrb_value self)
|
||||
const mrb_value *argv;
|
||||
mrb_int argc;
|
||||
mrb_value blk;
|
||||
struct RClass *c;
|
||||
|
||||
mrb_get_args(mrb, "*&!", &argv, &argc, &blk);
|
||||
|
||||
mrb->c->ci->target_class = mrb_class_ptr(self);
|
||||
c = mrb_class_ptr(self);
|
||||
if (mrb->c->ci->acc < 0) {
|
||||
return mrb_yield_with_class(mrb, blk, argc, argv, self, c);
|
||||
}
|
||||
mrb->c->ci->target_class = c;
|
||||
return mrb_yield_cont(mrb, blk, self, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
@@ -281,15 +281,6 @@ no_optimize(codegen_scope *s)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
mrb_bool
|
||||
on_eval(codegen_scope *s)
|
||||
{
|
||||
if (s && s->parser && s->parser->on_eval)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
struct mrb_insn_data
|
||||
mrb_decode_insn(const mrb_code *pc)
|
||||
{
|
||||
@@ -407,9 +398,6 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
|
||||
if (no_peephole(s)) {
|
||||
normal:
|
||||
genop_2(s, OP_MOVE, dst, src);
|
||||
if (on_eval(s)) {
|
||||
genop_0(s, OP_NOP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
@@ -599,7 +587,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
|
||||
@@ -674,6 +662,43 @@ lv_idx(codegen_scope *s, mrb_sym id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
search_upvar(codegen_scope *s, mrb_sym id, int *idx)
|
||||
{
|
||||
struct RProc *u;
|
||||
int lv = 0;
|
||||
codegen_scope *up = s->prev;
|
||||
|
||||
while (up) {
|
||||
*idx = lv_idx(up, id);
|
||||
if (*idx > 0) {
|
||||
return lv;
|
||||
}
|
||||
lv ++;
|
||||
up = up->prev;
|
||||
}
|
||||
|
||||
if (lv < 1) lv = 1;
|
||||
u = s->parser->upper;
|
||||
while (u && !MRB_PROC_CFUNC_P(u)) {
|
||||
struct mrb_irep *ir = u->body.irep;
|
||||
uint_fast16_t n = ir->nlocals;
|
||||
const struct mrb_locals *v = ir->lv;
|
||||
for (; n > 1; n --, v ++) {
|
||||
if (v->name == id) {
|
||||
*idx = v->r;
|
||||
return lv - 1;
|
||||
}
|
||||
}
|
||||
if (MRB_PROC_SCOPE_P(u)) break;
|
||||
u = u->upper;
|
||||
lv ++;
|
||||
}
|
||||
|
||||
codegen_error(s, "Can't found local variables");
|
||||
return -1; /* not reached */
|
||||
}
|
||||
|
||||
static void
|
||||
for_body(codegen_scope *s, node *tree)
|
||||
{
|
||||
@@ -771,7 +796,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);
|
||||
@@ -786,12 +811,19 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
i = 0;
|
||||
while (opt) {
|
||||
int idx;
|
||||
mrb_sym id = nsym(opt->car->car);
|
||||
|
||||
dispatch(s, pos+i*3+1);
|
||||
codegen(s, opt->car->cdr, VAL);
|
||||
pop();
|
||||
idx = lv_idx(s, nsym(opt->car->car));
|
||||
gen_move(s, idx, cursp(), 0);
|
||||
idx = lv_idx(s, id);
|
||||
if (idx > 0) {
|
||||
gen_move(s, idx, cursp(), 0);
|
||||
}
|
||||
else {
|
||||
int lv = search_upvar(s, id, &idx);
|
||||
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
|
||||
}
|
||||
i++;
|
||||
opt = opt->cdr;
|
||||
}
|
||||
@@ -818,11 +850,19 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
mrb_assert(nint(kwd->car) == NODE_KW_ARG);
|
||||
|
||||
if (def_arg) {
|
||||
int idx;
|
||||
genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
|
||||
jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0);
|
||||
codegen(s, def_arg, VAL);
|
||||
pop();
|
||||
gen_move(s, lv_idx(s, kwd_sym), cursp(), 0);
|
||||
idx = lv_idx(s, kwd_sym);
|
||||
if (idx > 0) {
|
||||
gen_move(s, idx, cursp(), 0);
|
||||
}
|
||||
else {
|
||||
int lv = search_upvar(s, kwd_sym, &idx);
|
||||
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
|
||||
}
|
||||
jmp_def_set = genjmp(s, OP_JMP, 0);
|
||||
dispatch(s, jmpif_key_p);
|
||||
}
|
||||
@@ -1103,25 +1143,18 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
|
||||
if (idx > 0) {
|
||||
if (idx != sp) {
|
||||
gen_move(s, idx, sp, val);
|
||||
if (val && on_eval(s)) genop_0(s, OP_NOP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else { /* upvar */
|
||||
int lv = 0;
|
||||
codegen_scope *up = s->prev;
|
||||
|
||||
while (up) {
|
||||
idx = lv_idx(up, nsym(tree));
|
||||
if (idx > 0) {
|
||||
genop_3(s, OP_SETUPVAR, sp, idx, lv);
|
||||
break;
|
||||
}
|
||||
lv++;
|
||||
up = up->prev;
|
||||
}
|
||||
int lv = search_upvar(s, nsym(tree), &idx);
|
||||
genop_3(s, OP_SETUPVAR, sp, idx, lv);
|
||||
}
|
||||
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);
|
||||
@@ -1856,7 +1889,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
len++;
|
||||
}
|
||||
tree = tree->cdr;
|
||||
if (val && len == 255) {
|
||||
if (val && cursp() > 127) {
|
||||
pop_n(len*2);
|
||||
if (!update) {
|
||||
genop_2(s, OP_HASH, cursp(), len);
|
||||
@@ -2320,26 +2353,25 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
|
||||
if (idx > 0) {
|
||||
gen_move(s, cursp(), idx, val);
|
||||
if (val && on_eval(s)) genop_0(s, OP_NOP);
|
||||
}
|
||||
else {
|
||||
int lv = 0;
|
||||
codegen_scope *up = s->prev;
|
||||
|
||||
while (up) {
|
||||
idx = lv_idx(up, nsym(tree));
|
||||
if (idx > 0) {
|
||||
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
|
||||
break;
|
||||
}
|
||||
lv++;
|
||||
up = up->prev;
|
||||
}
|
||||
int lv = search_upvar(s, nsym(tree), &idx);
|
||||
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
|
||||
}
|
||||
push();
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_NVAR:
|
||||
if (val) {
|
||||
int idx = nint(tree);
|
||||
|
||||
gen_move(s, cursp(), idx, val);
|
||||
|
||||
push();
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_GVAR:
|
||||
{
|
||||
int sym = new_sym(s, nsym(tree));
|
||||
@@ -2425,12 +2457,20 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (i == -1) genop_1(s, OP_LOADI__1, cursp());
|
||||
else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
|
||||
if (i < 0) {
|
||||
if (i == -1) genop_1(s, OP_LOADI__1, cursp());
|
||||
else if (i >= -0xff) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
|
||||
else if (i >= -0x8000) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
|
||||
else goto lit_int;
|
||||
}
|
||||
else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp());
|
||||
else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
|
||||
else if (i <= 0xff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
|
||||
else if (i <= 0x7fff) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
|
||||
else {
|
||||
int off = new_lit(s, mrb_fixnum_value(i));
|
||||
int off;
|
||||
|
||||
lit_int:
|
||||
off = new_lit(s, mrb_fixnum_value(i));
|
||||
genop_2(s, OP_LOADL, cursp(), off);
|
||||
}
|
||||
}
|
||||
@@ -2486,9 +2526,12 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
else {
|
||||
#endif
|
||||
if (i == -1) genop_1(s, OP_LOADI__1, cursp());
|
||||
else if (i >= -0xffff) {
|
||||
else if (i >= -0xff) {
|
||||
genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
|
||||
}
|
||||
else if (i >= -0x8000) {
|
||||
genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
|
||||
}
|
||||
else {
|
||||
int off = new_lit(s, mrb_fixnum_value(i));
|
||||
genop_2(s, OP_LOADL, cursp(), off);
|
||||
|
||||
@@ -51,6 +51,7 @@ enum node_type {
|
||||
NODE_IVAR,
|
||||
NODE_CONST,
|
||||
NODE_CVAR,
|
||||
NODE_NVAR,
|
||||
NODE_NTH_REF,
|
||||
NODE_BACK_REF,
|
||||
NODE_MATCH,
|
||||
|
||||
+349
-175
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,35 +3,33 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = 'mruby compiler library'
|
||||
|
||||
current_dir = spec.dir
|
||||
current_build_dir = spec.build_dir
|
||||
|
||||
lex_def = "#{current_dir}/core/lex.def"
|
||||
core_objs = Dir.glob("#{current_dir}/core/*.c").map { |f|
|
||||
lex_def = "#{dir}/core/lex.def"
|
||||
core_objs = Dir.glob("#{dir}/core/*.c").map { |f|
|
||||
next nil if build.cxx_exception_enabled? and f =~ /(codegen).c$/
|
||||
objfile(f.pathmap("#{current_build_dir}/core/%n"))
|
||||
objfile(f.pathmap("#{build_dir}/core/%n"))
|
||||
}.compact
|
||||
|
||||
if build.cxx_exception_enabled?
|
||||
core_objs <<
|
||||
build.compile_as_cxx("#{current_build_dir}/core/y.tab.c", "#{current_build_dir}/core/y.tab.cxx",
|
||||
objfile("#{current_build_dir}/y.tab"), ["#{current_dir}/core"]) <<
|
||||
build.compile_as_cxx("#{current_dir}/core/codegen.c", "#{current_build_dir}/core/codegen.cxx")
|
||||
build.compile_as_cxx("#{dir}/core/y.tab.c", "#{build_dir}/core/y.tab.cxx",
|
||||
objfile("#{build_dir}/y.tab"), ["#{dir}/core"]) <<
|
||||
build.compile_as_cxx("#{dir}/core/codegen.c", "#{build_dir}/core/codegen.cxx")
|
||||
else
|
||||
core_objs << objfile("#{current_build_dir}/core/y.tab")
|
||||
file objfile("#{current_build_dir}/core/y.tab") => "#{current_build_dir}/core/y.tab.c" do |t|
|
||||
cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"]
|
||||
core_objs << objfile("#{build_dir}/core/y.tab")
|
||||
file objfile("#{build_dir}/core/y.tab") => "#{dir}/core/y.tab.c" do |t|
|
||||
cc.run t.name, t.prerequisites.first, [], ["#{dir}/core"]
|
||||
end
|
||||
end
|
||||
|
||||
# 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
|
||||
file "#{dir}/core/y.tab.c" => ["#{dir}/core/parse.y", lex_def] do |t|
|
||||
yacc.run t.name, t.prerequisites.first
|
||||
content = File.read(t.name).gsub(/^#line +\d+ +"\K.*$/){$&.relative_path}
|
||||
File.write(t.name, content)
|
||||
end
|
||||
|
||||
# Lexical analyzer
|
||||
file lex_def => "#{current_dir}/core/keywords" do |t|
|
||||
file lex_def => "#{dir}/core/keywords" do |t|
|
||||
gperf.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
|
||||
original_operator_name = "__original_operator_#{op}_complex"
|
||||
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
|
||||
|
||||
@@ -174,7 +174,7 @@ div_pair(struct float_pair *q, struct float_pair const *a,
|
||||
static mrb_value
|
||||
complex_div(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value rhs;
|
||||
mrb_value rhs = mrb_get_arg1(mrb);
|
||||
struct mrb_complex *a, *b;
|
||||
struct float_pair ar, ai, br, bi;
|
||||
struct float_pair br2, bi2;
|
||||
@@ -183,7 +183,6 @@ complex_div(mrb_state *mrb, mrb_value self)
|
||||
struct float_pair ai_br, ar_bi;
|
||||
struct float_pair zr, zi;
|
||||
|
||||
mrb_get_args(mrb, "o", &rhs);
|
||||
a = complex_ptr(mrb, self);
|
||||
b = complex_ptr(mrb, rhs);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -9,217 +9,6 @@
|
||||
mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p);
|
||||
mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self);
|
||||
|
||||
static struct mrb_irep *
|
||||
get_closure_irep(mrb_state *mrb, int level)
|
||||
{
|
||||
struct RProc *proc = mrb->c->ci[-1].proc;
|
||||
|
||||
while (level--) {
|
||||
if (!proc) return NULL;
|
||||
proc = proc->upper;
|
||||
}
|
||||
if (!proc) return NULL;
|
||||
if (MRB_PROC_CFUNC_P(proc)) {
|
||||
return NULL;
|
||||
}
|
||||
return proc->body.irep;
|
||||
}
|
||||
|
||||
/* search for irep lev above the bottom */
|
||||
static mrb_irep*
|
||||
search_irep(mrb_irep *top, int bnest, int lev, mrb_irep *bottom)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<top->rlen; i++) {
|
||||
mrb_irep* tmp = top->reps[i];
|
||||
|
||||
if (tmp == bottom) return top;
|
||||
tmp = search_irep(tmp, bnest-1, lev, bottom);
|
||||
if (tmp) {
|
||||
if (bnest == lev) return top;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
|
||||
{
|
||||
mrb_irep *virep;
|
||||
int level;
|
||||
int pos;
|
||||
|
||||
for (level = 0; (virep = get_closure_irep(mrb, level)); level++) {
|
||||
if (virep->lv == NULL) {
|
||||
continue;
|
||||
}
|
||||
for (pos = 0; pos < virep->nlocals - 1; pos++) {
|
||||
if (vsym == virep->lv[pos].name) {
|
||||
return (pos+1)<<8 | (level+bnest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
irep_argc(mrb_irep *irep)
|
||||
{
|
||||
mrb_code c;
|
||||
|
||||
c = irep->iseq[0];
|
||||
if (c == OP_ENTER) {
|
||||
mrb_aspec ax = PEEK_W(irep->iseq+1);
|
||||
/* extra 1 means a slot for block */
|
||||
return MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mrb_bool
|
||||
potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
|
||||
{
|
||||
if (v >= nlocals) return FALSE;
|
||||
/* skip arguments */
|
||||
if (v < argc+1) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern uint8_t mrb_insn_size[];
|
||||
extern uint8_t mrb_insn_size1[];
|
||||
extern uint8_t mrb_insn_size2[];
|
||||
extern uint8_t mrb_insn_size3[];
|
||||
|
||||
static void
|
||||
patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
|
||||
{
|
||||
int i;
|
||||
uint32_t a;
|
||||
uint16_t b;
|
||||
uint8_t c;
|
||||
mrb_code insn;
|
||||
int argc = irep_argc(irep);
|
||||
mrb_code *iseq = (mrb_code *)irep->iseq;
|
||||
|
||||
mrb_assert((irep->flags & MRB_ISEQ_NO_FREE) == 0);
|
||||
|
||||
for (i = 0; i < irep->ilen; ) {
|
||||
insn = iseq[i];
|
||||
switch(insn){
|
||||
case OP_EPUSH:
|
||||
b = PEEK_S(iseq+i+1);
|
||||
patch_irep(mrb, irep->reps[b], bnest + 1, top);
|
||||
break;
|
||||
|
||||
case OP_LAMBDA:
|
||||
case OP_BLOCK:
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
patch_irep(mrb, irep->reps[b], bnest + 1, top);
|
||||
break;
|
||||
|
||||
case OP_SEND:
|
||||
b = PEEK_B(iseq+i+2);
|
||||
c = PEEK_B(iseq+i+3);
|
||||
if (c != 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
uint16_t arg = search_variable(mrb, irep->syms[b], bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
iseq[i] = OP_GETUPVAR;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_MOVE:
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
/* src part */
|
||||
if (potential_upvar_p(irep->lv, b, argc, irep->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, irep->lv[b - 1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
iseq[i] = insn = OP_GETUPVAR;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
/* dst part */
|
||||
if (potential_upvar_p(irep->lv, a, argc, irep->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, irep->lv[a - 1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
iseq[i] = insn = OP_SETUPVAR;
|
||||
iseq[i+1] = (mrb_code)b;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_GETUPVAR:
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
c = PEEK_B(iseq+i+3);
|
||||
{
|
||||
int lev = c+1;
|
||||
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
|
||||
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
iseq[i] = OP_GETUPVAR;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_SETUPVAR:
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
c = PEEK_B(iseq+i+3);
|
||||
{
|
||||
int lev = c+1;
|
||||
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
|
||||
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
iseq[i] = OP_SETUPVAR;
|
||||
iseq[i+1] = a;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_EXT1:
|
||||
insn = PEEK_B(iseq+i+1);
|
||||
i += mrb_insn_size1[insn]+1;
|
||||
continue;
|
||||
case OP_EXT2:
|
||||
insn = PEEK_B(iseq+i+1);
|
||||
i += mrb_insn_size2[insn]+1;
|
||||
continue;
|
||||
case OP_EXT3:
|
||||
insn = PEEK_B(iseq+i+1);
|
||||
i += mrb_insn_size3[insn]+1;
|
||||
continue;
|
||||
}
|
||||
i+=mrb_insn_size[insn];
|
||||
}
|
||||
}
|
||||
|
||||
void mrb_codedump_all(mrb_state*, struct RProc*);
|
||||
|
||||
static struct RProc*
|
||||
@@ -243,7 +32,8 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
|
||||
mrbc_filename(mrb, cxt, file ? file : "(eval)");
|
||||
cxt->capture_errors = TRUE;
|
||||
cxt->no_optimize = TRUE;
|
||||
cxt->on_eval = TRUE;
|
||||
ci = (mrb->c->ci > mrb->c->cibase) ? mrb->c->ci - 1 : mrb->c->cibase;
|
||||
cxt->upper = ci->proc && MRB_PROC_CFUNC_P(ci->proc) ? NULL : ci->proc;
|
||||
|
||||
p = mrb_parse_nstring(mrb, s, len, cxt);
|
||||
|
||||
@@ -298,7 +88,7 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
|
||||
e->mid = ci->mid;
|
||||
e->stack = ci[1].stackent;
|
||||
e->cxt = mrb->c;
|
||||
MRB_ENV_SET_STACK_LEN(e, ci->proc->body.irep->nlocals);
|
||||
MRB_ENV_SET_LEN(e, ci->proc->body.irep->nlocals);
|
||||
bidx = ci->argc;
|
||||
if (ci->argc < 0) bidx = 2;
|
||||
else bidx += 1;
|
||||
@@ -311,7 +101,6 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
|
||||
}
|
||||
proc->upper = ci->proc;
|
||||
mrb->c->ci->target_class = target_class;
|
||||
patch_irep(mrb, proc->body.irep, 0, proc->body.irep);
|
||||
/* mrb_codedump_all(mrb, proc); */
|
||||
|
||||
mrb_parser_free(p);
|
||||
@@ -390,7 +179,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
|
||||
|
||||
@@ -130,3 +130,24 @@ Proc.new { foo }
|
||||
EOS
|
||||
}
|
||||
end
|
||||
|
||||
assert('Calling the same method as the variable name') do
|
||||
hoge = Object.new
|
||||
def hoge.fuga
|
||||
"Hit!"
|
||||
end
|
||||
assert_equal("Hit!") { fuga = "Miss!"; eval "hoge.fuga" }
|
||||
assert_equal("Hit!") { fuga = "Miss!"; -> { eval "hoge.fuga" }.call }
|
||||
assert_equal("Hit!") { -> { fuga = "Miss!"; eval "hoge.fuga" }.call }
|
||||
assert_equal("Hit!") { fuga = "Miss!"; eval("-> { hoge.fuga }").call }
|
||||
end
|
||||
|
||||
assert('Access numbered parameter from eval') do
|
||||
hoge = Object.new
|
||||
def hoge.fuga(a, &b)
|
||||
b.call(a)
|
||||
end
|
||||
assert_equal(6) {
|
||||
hoge.fuga(3) { _1 + eval("_1") }
|
||||
}
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -291,8 +291,7 @@ mrb_fiber_alive_p(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
fiber_eq(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
|
||||
if (!mrb_fiber_p(other)) {
|
||||
return mrb_false_value();
|
||||
@@ -409,7 +408,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
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@ istruct_test_initialize(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
char *string = (char*)mrb_istruct_ptr(self);
|
||||
mrb_int size = mrb_istruct_size();
|
||||
mrb_value object;
|
||||
mrb_get_args(mrb, "o", &object);
|
||||
mrb_value object = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_fixnum_p(object)) {
|
||||
strncpy(string, "fixnum", size-1);
|
||||
@@ -45,8 +44,8 @@ istruct_test_length(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
istruct_test_test_receive(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value object;
|
||||
mrb_get_args(mrb, "o", &object);
|
||||
mrb_value object = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_obj_class(mrb, object) != mrb_class_get(mrb, "InlineStructTest"))
|
||||
{
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "Expected InlineStructTest");
|
||||
|
||||
@@ -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__) || defined(__MACH__)
|
||||
# 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
|
||||
#define MRB_O_RSYNC 0x00010000
|
||||
|
||||
#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
|
||||
|
||||
+153
-14
@@ -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
|
||||
@@ -85,7 +89,7 @@ flock(int fd, int operation) {
|
||||
}
|
||||
#endif
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_file_s_umask(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
@@ -261,7 +265,7 @@ mrb_file_realpath(mrb_state *mrb, mrb_value klass)
|
||||
return result;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_file__getwd(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_value path;
|
||||
@@ -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,13 +395,13 @@ 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));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_file_flock(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
#if defined(sun)
|
||||
@@ -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,74 @@ 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, mrb_int 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;
|
||||
mrb_int length;
|
||||
mrb_value lenv = mrb_get_arg1(mrb);
|
||||
|
||||
fd = mrb_io_fileno(mrb, self);
|
||||
length = mrb_int(mrb, lenv);
|
||||
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 +593,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 +609,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 +626,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>
|
||||
|
||||
@@ -91,7 +85,7 @@ mrb_lstat(mrb_state *mrb, mrb_value obj, struct stat *st)
|
||||
* File.directory?(".")
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#ifndef S_ISDIR
|
||||
@@ -99,9 +93,7 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
|
||||
#endif
|
||||
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
@@ -118,7 +110,7 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
|
||||
* Returns <code>true</code> if the named file is a pipe.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
@@ -130,9 +122,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
|
||||
# endif
|
||||
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
@@ -151,7 +141,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
|
||||
* Returns <code>true</code> if the named file is a symbolic link.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
@@ -173,9 +163,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
|
||||
|
||||
#ifdef S_ISLNK
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_lstat(mrb, obj, &st) == -1)
|
||||
return mrb_false_value();
|
||||
@@ -194,7 +182,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
|
||||
* Returns <code>true</code> if the named file is a socket.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
@@ -216,9 +204,7 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
|
||||
|
||||
#ifdef S_ISSOCK
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
@@ -238,13 +224,12 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
|
||||
* Return <code>true</code> if the named file exists.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
|
||||
@@ -259,7 +244,7 @@ mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
|
||||
* regular file.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#ifndef S_ISREG
|
||||
@@ -267,9 +252,7 @@ mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
|
||||
#endif
|
||||
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
@@ -287,13 +270,11 @@ mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
|
||||
* a zero size.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_zero_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
@@ -312,13 +293,11 @@ mrb_filetest_s_zero_p(mrb_state *mrb, mrb_value klass)
|
||||
* _file_name_ can be an IO object.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
mrb_sys_fail(mrb, "mrb_stat");
|
||||
@@ -334,13 +313,11 @@ mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
|
||||
* file otherwise.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_size_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_nil_value();
|
||||
|
||||
+350
-157
@@ -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:
|
||||
@@ -304,7 +341,7 @@ option_to_fd(mrb_state *mrb, mrb_value obj, const char *key)
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_value cmd, io;
|
||||
@@ -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;
|
||||
@@ -402,14 +439,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
return io;
|
||||
}
|
||||
#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_raise(mrb, E_NOTIMP_ERROR, "IO#popen is not supported on the platform");
|
||||
return mrb_false_value();
|
||||
}
|
||||
#else
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_value cmd, io, result;
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -559,16 +596,15 @@ mrb_dup(mrb_state *mrb, int fd, mrb_bool *failed)
|
||||
return new_fd;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy)
|
||||
{
|
||||
mrb_value orig;
|
||||
mrb_value orig = mrb_get_arg1(mrb);
|
||||
mrb_value buf;
|
||||
struct mrb_io *fptr_copy;
|
||||
struct mrb_io *fptr_orig;
|
||||
mrb_bool failed = TRUE;
|
||||
|
||||
mrb_get_args(mrb, "o", &orig);
|
||||
fptr_orig = io_get_open_fptr(mrb, orig);
|
||||
fptr_copy = (struct mrb_io *)DATA_PTR(copy);
|
||||
if (fptr_orig == fptr_copy) return copy;
|
||||
@@ -608,7 +644,44 @@ mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy)
|
||||
return copy;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static void
|
||||
check_file_descriptor(mrb_state *mrb, mrb_int fd)
|
||||
{
|
||||
struct stat sb;
|
||||
int fdi = (int)fd;
|
||||
|
||||
#if MRB_INT_MIN < INT_MIN || MRB_INT_MAX > INT_MAX
|
||||
if (fdi != fd) {
|
||||
goto badfd;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
DWORD err;
|
||||
int len = sizeof(err);
|
||||
|
||||
if (getsockopt(fdi, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fdi < 0 || fdi > _getmaxstdio()) {
|
||||
goto badfd;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
if (fstat(fdi, &sb) != 0) {
|
||||
goto badfd;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
badfd:
|
||||
mrb_sys_fail(mrb, "bad file descriptor");
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_io_initialize(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -618,7 +691,8 @@ 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);
|
||||
check_file_descriptor(mrb, fd);
|
||||
if (mrb_nil_p(mode)) {
|
||||
mode = mrb_str_new_cstr(mrb, "r");
|
||||
}
|
||||
@@ -626,7 +700,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 +715,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;
|
||||
}
|
||||
@@ -710,7 +784,7 @@ fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet)
|
||||
}
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_check_readable(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr = io_get_open_fptr(mrb, self);
|
||||
@@ -720,7 +794,7 @@ mrb_io_check_readable(mrb_state *mrb, mrb_value self)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_isatty(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -731,7 +805,7 @@ mrb_io_isatty(mrb_state *mrb, mrb_value self)
|
||||
return mrb_true_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
struct RClass *c = mrb_class_ptr(klass);
|
||||
@@ -744,7 +818,7 @@ mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_io_initialize(mrb, obj);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_int fd;
|
||||
@@ -755,7 +829,7 @@ mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
mrb_cloexec_open(mrb_state *mrb, const char *pathname, mrb_int flags, mrb_int mode)
|
||||
{
|
||||
int fd, retry = FALSE;
|
||||
@@ -790,39 +864,55 @@ reopen:
|
||||
return fd;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_value path = mrb_nil_value();
|
||||
mrb_value mode = mrb_nil_value();
|
||||
mrb_int fd, 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);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
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);
|
||||
}
|
||||
|
||||
static 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 +926,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,29 +935,20 @@ 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;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_sysseek(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -894,11 +976,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 +989,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,7 +1002,23 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
|
||||
return mrb_fixnum_value(length);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
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);
|
||||
}
|
||||
|
||||
static 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);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_io_close(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -935,7 +1027,7 @@ mrb_io_close(mrb_state *mrb, mrb_value self)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_close_write(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -946,7 +1038,7 @@ mrb_io_close_write(mrb_state *mrb, mrb_value self)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_closed(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -958,7 +1050,7 @@ mrb_io_closed(mrb_state *mrb, mrb_value io)
|
||||
return mrb_true_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_pid(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -1063,7 +1155,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();
|
||||
@@ -1092,6 +1184,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
|
||||
for (i = 0; i < RARRAY_LEN(read); i++) {
|
||||
read_io = RARRAY_PTR(read)[i];
|
||||
fptr = io_get_open_fptr(mrb, read_io);
|
||||
if (fptr->fd >= FD_SETSIZE) continue;
|
||||
FD_SET(fptr->fd, rp);
|
||||
if (mrb_io_read_data_pending(mrb, read_io)) {
|
||||
pending++;
|
||||
@@ -1114,6 +1207,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
|
||||
FD_ZERO(wp);
|
||||
for (i = 0; i < RARRAY_LEN(write); i++) {
|
||||
fptr = io_get_open_fptr(mrb, RARRAY_PTR(write)[i]);
|
||||
if (fptr->fd >= FD_SETSIZE) continue;
|
||||
FD_SET(fptr->fd, wp);
|
||||
if (max < fptr->fd)
|
||||
max = fptr->fd;
|
||||
@@ -1133,6 +1227,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
|
||||
FD_ZERO(ep);
|
||||
for (i = 0; i < RARRAY_LEN(except); i++) {
|
||||
fptr = io_get_open_fptr(mrb, RARRAY_PTR(except)[i]);
|
||||
if (fptr->fd >= FD_SETSIZE) continue;
|
||||
FD_SET(fptr->fd, ep);
|
||||
if (max < fptr->fd)
|
||||
max = fptr->fd;
|
||||
@@ -1206,15 +1301,22 @@ 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;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
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);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_io_close_on_exec_p(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||
@@ -1238,7 +1340,7 @@ mrb_io_close_on_exec_p(mrb_state *mrb, mrb_value self)
|
||||
#endif
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_set_close_on_exec(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||
@@ -1274,7 +1376,7 @@ mrb_io_set_close_on_exec(mrb_state *mrb, mrb_value self)
|
||||
#endif
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_set_sync(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -1286,7 +1388,7 @@ mrb_io_set_sync(mrb_state *mrb, mrb_value self)
|
||||
return mrb_bool_value(b);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_sync(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -1294,15 +1396,55 @@ 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;
|
||||
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 +1457,54 @@ 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_LEN(buf) > 0);
|
||||
mrb_assert(RSTRING_PTR(buf) != NULL);
|
||||
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 +1514,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 +1538,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")
|
||||
@@ -94,18 +110,22 @@ assert('File.join') do
|
||||
end
|
||||
|
||||
assert('File.realpath') do
|
||||
if File::ALT_SEPARATOR
|
||||
readme_path = File._getwd + File::ALT_SEPARATOR + "README.md"
|
||||
assert_equal readme_path, File.realpath("README.md")
|
||||
else
|
||||
dir = MRubyIOTestUtil.mkdtemp("mruby-io-test.XXXXXX")
|
||||
begin
|
||||
dir1 = File.realpath($mrbtest_io_rfname)
|
||||
dir2 = File.realpath("./#{dir}//./../#{$mrbtest_io_symlinkname}")
|
||||
assert_equal dir1, dir2
|
||||
ensure
|
||||
MRubyIOTestUtil.rmdir dir
|
||||
dir = MRubyIOTestUtil.mkdtemp("mruby-io-test.XXXXXX")
|
||||
begin
|
||||
sep = File::ALT_SEPARATOR || File::SEPARATOR
|
||||
relative_path = "#{File.basename(dir)}#{sep}realpath_test"
|
||||
path = "#{File._getwd}#{sep}#{relative_path}"
|
||||
File.open(path, "w"){}
|
||||
assert_equal path, File.realpath(relative_path)
|
||||
|
||||
unless MRubyIOTestUtil.win?
|
||||
path1 = File.realpath($mrbtest_io_rfname)
|
||||
path2 = File.realpath($mrbtest_io_symlinkname)
|
||||
assert_equal path1, path2
|
||||
end
|
||||
ensure
|
||||
File.delete path rescue nil
|
||||
MRubyIOTestUtil.rmdir dir
|
||||
end
|
||||
|
||||
assert_raise(ArgumentError) { File.realpath("TO\0DO") }
|
||||
@@ -113,7 +133,9 @@ end
|
||||
|
||||
assert("File.readlink") do
|
||||
begin
|
||||
assert_equal $mrbtest_io_rfname, File.readlink($mrbtest_io_symlinkname)
|
||||
exp = File.basename($mrbtest_io_rfname)
|
||||
act = File.readlink($mrbtest_io_symlinkname)
|
||||
assert_equal exp, act
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
end
|
||||
|
||||
@@ -24,6 +24,10 @@ def assert_io_open(meth)
|
||||
end
|
||||
end
|
||||
io2.close unless meth == :open
|
||||
|
||||
assert_raise(RuntimeError) { IO.__send__(meth, 1023) } # For Windows
|
||||
assert_raise(RuntimeError) { IO.__send__(meth, 1 << 26) }
|
||||
assert_raise(RuntimeError) { IO.__send__(meth, 1 << 32) } if (1 << 32).kind_of?(Integer)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -564,6 +568,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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user