Compare commits

...

337 Commits

Author SHA1 Message Date
Hiroshi Mimaki f9d113f764 Update release date. 2020-06-04 17:20:46 +09:00
Yukihiro "Matz" Matsumoto 5e01674b72 Should not use assert with expressions with side-effect; ref #4981
`assert()` can be completely removed when `NDEBUG` is set.
2020-05-07 09:37:02 +09:00
Yukihiro "Matz" Matsumoto b652a4ff14 Fixed wrong condition in #4981. 2020-05-07 09:36:43 +09:00
Yukihiro "Matz" Matsumoto 7dc0fe66c7 Add #include <string.h> on all platforms for strncpy; #4981 2020-05-07 09:36:21 +09:00
Yukihiro "Matz" Matsumoto 1cdcd00cc0 Remove unused local variable if MRB_UTF8_STRING is not set.
Ref #4982 #4983
2020-05-07 09:35:47 +09:00
Yukihiro "Matz" Matsumoto 9f4b5227fe Avoid snprintf in mruby-io test; ref #4981 2020-05-07 09:33:44 +09:00
Yukihiro "Matz" Matsumoto d464fe5003 Remove the temporary file from the AF_UNIX socket test; #4981 2020-05-07 09:33:08 +09:00
Yukihiro "Matz" Matsumoto 6b839b2319 Fix IO#readchar to return broken UTF-8 rather than EOF error.
The behavior is different from CRuby, but we believe this is a right
behavior for mruby, which only supports either ASCII or UTF-8
exclusively; fix #4983, ref #4982

```
$ printf '\xe3\x81' | ruby -e 'p STDIN.readchar'
"\xE3\x81"
```

```
$ printf '\xe3\x81' | mruby -e 'p STDIN.readchar'
"\xE3"
```
2020-05-07 09:32:46 +09:00
Yukihiro "Matz" Matsumoto 45bd372755 Fix IO#readchar to support UTF-8 char reading; fix #4712
This fix only effective when `MRB_UTF8_STRING` is set.
2020-05-07 09:31:38 +09:00
Yukihiro "Matz" Matsumoto f5ee7df7f3 Rename (and expose) UTF-8 related functions; ref #4712
- mrb_utf8len() - returns the size of a UTF-8 char (in bytes)
- mrb_utf8_strlen() - returns the length of a UTF-8 string (in char)
2020-05-07 09:31:07 +09:00
Yukihiro "Matz" Matsumoto e77e6e9d12 Fix _read_buf to be more efficient; fix #4982
The bug was introduced by #4712. The `getc' problem resurrected.
It should be addressed soon.
2020-05-01 16:57:45 +09:00
Yukihiro "Matz" Matsumoto a2b87c033a Fix IO#sysread to update buffer string on EOF; ref #4982 2020-05-01 16:54:13 +09:00
Yukihiro "Matz" Matsumoto b3c5d94bd1 Update IO#ungetc to keep @buf string; ref #4982 2020-05-01 16:53:55 +09:00
Yukihiro "Matz" Matsumoto d029549c2f Fix UTF-8 boundary check; ref #4982 2020-05-01 16:53:25 +09:00
Uchio Kondo 6e13467ce8 Fix typo and include location 2020-05-01 16:52:11 +09:00
Uchio Kondo 508ac2030e Skip socket check on windows 2020-05-01 16:51:47 +09:00
Uchio Kondo 4b81bce48d Follow C90 style 2020-05-01 16:51:22 +09:00
Uchio Kondo 3486675e00 Test mruby-io in tmpdir when AF_UNIX cannot be created on cwd 2020-05-01 16:50:54 +09:00
Hiroshi Mimaki 3d46f1b620 Update version to 2.1.1. (mruby 2.1.1 RC) 2020-04-10 13:05:23 +09:00
Yukihiro "Matz" Matsumoto 63c7ff341a Merge pull request #4965 from mimaki/remove-cygwin_filename
Merged `cygwin_filename()` into `filename()`.
2020-04-08 22:40:49 +09:00
mimaki a8ab74a6dc Merged cygwin_filename() into filename() because Cygwin pathnames are in UNIX format. 2020-04-08 13:27:14 +09:00
Yukihiro "Matz" Matsumoto 7ab5353f80 Merge pull request #4960 from Reckordp/BuildAndroid
Validate windows by Dir testing
2020-04-05 14:17:09 +09:00
Reckordp d7df30bdd8 Unused library folder 2020-04-04 21:57:13 +07:00
Reckordp d317ee144b Correct naming file from Mingw 2020-04-04 21:56:40 +07:00
Yukihiro "Matz" Matsumoto 3cef380b20 Revert part of #4959
To prevent infinite loop on errors; reported by @shuujii
2020-04-04 11:50:59 +09:00
Reckordp 707933aa8e Helper for link window's library 2020-04-03 20:34:00 +07:00
Yukihiro "Matz" Matsumoto 068b16a352 Merge pull request #4959 from dsisnero/master
build when directories and files have spaces
2020-04-02 13:26:53 +09:00
dsisnero c7ab4cf616 fix for quoting visualcpp 2020-04-01 12:31:48 -06:00
Dominic Sisneros e3875ae8c5 build when directories and files have spaces
Modified the build to quote filenames so that it builds when files have spaces
2020-04-01 11:55:35 -06:00
Yukihiro "Matz" Matsumoto 226fcb4f2a Avoid unnecessary nextc() recursion. 2020-04-01 23:23:07 +09:00
Yukihiro "Matz" Matsumoto d22b72a7cc Merge pull request #4957 from dearblue/excessive-arena
Fix `mrb_funcall_with_block()` uses more GC arena
2020-04-01 15:40:25 +09:00
dearblue 15dec83832 Fix mrb_funcall_with_block() uses more GC arena
If `mrb->jmp` is `NULL` and the function `mrb_funcall_with_block()` is
called, GC Arena is returned from the function with over-used.

- A normal (no global exodus) return will consume two GC Arena's.
- In the event of an exception, five GC Arena are consumed.

This patch reduces consumption in both cases to one.
2020-03-31 23:24:53 +09:00
Yukihiro "Matz" Matsumoto 5acd802d2b Merge pull request #4956 from dearblue/null-local_variables
Fix NULL pointer dereferences in mrb_local_variables; fix #4955
2020-03-31 22:04:18 +09:00
dearblue 9b15860ddb Fix NULL pointer dereferences in mrb_local_variables; fix #4955
However, the behavior of `#call` on the method object of
`local_variables` is not corrected.
2020-03-30 23:52:59 +09:00
Yukihiro "Matz" Matsumoto 0dacc9a62a Merge pull request #4954 from dearblue/nostdio
Improve configuration guard
2020-03-08 22:37:22 +09:00
dearblue 67606170e3 Add configuration guard for MRB_DISABLE_STDIO
ref #4576 and ref #4947

* Need MRBAPI functions without `MRB_DISABLE_STDIO`:
  * mrbgems/mruby-bin-debugger
  * mrbgems/mruby-bin-mirb
  * mrbgems/mruby-bin-mrbc
  * mrbgems/mruby-bin-mruby
  * mrbgems/mruby-bin-strip
* Need `stdio.h`:
  * mrbgems/mruby-io
  * mrbgems/mruby-print
* Need `snprintf()` in `stdio.h`:
  * mrbgems/mruby-pack
  * mrbgems/mruby-sprintf
2020-03-08 21:57:17 +09:00
dearblue cc1db2d117 Remove unnecessary 'stdio.h'; ref #4947
'stdio.h' is included in 'mruby.h' ('mrbconf.h').

However, keep 'stdio.h' used by mruby-test.
2020-03-08 21:42:09 +09:00
dearblue b3d4ab0cd8 Improve conflict error message of mruby-bin-debugger; ref 87d1b2a91 2020-03-08 20:49:22 +09:00
Yukihiro "Matz" Matsumoto 5bf5a2cc6e Merge pull request #4953 from Reckordp/BuildAndroid
Some rule to CrossBuild Android
2020-03-08 19:07:32 +09:00
Yukihiro "Matz" Matsumoto e15e6e761e Merge branch 'master' into BuildAndroid 2020-03-08 19:01:29 +09:00
Yukihiro "Matz" Matsumoto 1cc270f0cc Small refactoring on #4952
Fix the argument of `mrb_file_is_absolute_path()`.
2020-03-08 18:57:49 +09:00
Yukihiro "Matz" Matsumoto 55f3202650 Merge pull request #4952 from Reckordp/master
Traditional, UNC, and Drive Path
2020-03-08 18:52:24 +09:00
Reckordp a8d508c567 Let me in Please 2020-03-08 14:41:38 +07:00
Reckordp 7c85a1ff07 Increase flexibility of CrossBuild 2020-03-08 14:23:55 +07:00
Reckordp dd6f5e4607 Let me in Please 2020-03-08 11:50:26 +07:00
Reckordp ab1465d9d5 Traditional, UNC, and Device Is Absolute? 2020-03-08 10:53:18 +07:00
Reckordp 66c44b8568 Commit from remote 2020-03-08 05:40:47 +07:00
Reckordp 6ee24fe1bc Evaluate all type path 2020-03-08 05:32:27 +07:00
Yukihiro "Matz" Matsumoto 4398bae56a Merge branch 'dearblue-io-pread-pwrite' 2020-03-07 19:07:13 +09:00
Yukihiro "Matz" Matsumoto 20f9128f73 Small refactoring on #4939 2020-03-07 19:06:46 +09:00
Yukihiro "Matz" Matsumoto 6901752723 Use in-house macro ISALPHA instead of isalpha; ref #4950 2020-03-07 19:03:45 +09:00
Yukihiro "Matz" Matsumoto 886355007c Merge branch 'io-pread-pwrite' of https://github.com/dearblue/mruby into dearblue-io-pread-pwrite 2020-03-07 19:00:30 +09:00
Yukihiro "Matz" Matsumoto f45549edbf Merge pull request #4951 from Reckordp/master
Fix unfinished changes
2020-03-07 17:58:26 +09:00
Reckordp 5a4b9fd877 Add absolute path for UNC 2020-03-07 15:50:14 +07:00
Reckordp f319c5fb26 Fix typo 2020-03-07 15:18:48 +07:00
Yukihiro "Matz" Matsumoto 4687f8790c Merge the update suggested by @mattn; ref #4950 2020-03-07 14:58:05 +09:00
Yukihiro "Matz" Matsumoto 30eaee30fa Merge pull request #4950 from Reckordp/master
Absolute path for windows
2020-03-07 14:53:37 +09:00
Reckordp 8df49ea955 Absolute path for windows 2020-03-07 09:09:28 +07:00
Yukihiro "Matz" Matsumoto 7905431fe9 Merge pull request #4948 from kou/32bit-windows-method-t-struct
Enable MRB_METHOD_T_STRUCT by default on 32bit Windows
2020-03-04 21:25:10 +09:00
Sutou Kouhei 96d727177e Enable MRB_METHOD_T_STRUCT by default on 32bit Windows
Because we can't use the highest 2 bits of function pointers.
2020-03-04 18:35:40 +09:00
Yukihiro "Matz" Matsumoto be86bd3c49 Merge pull request #4946 from sizious/sega-dreamcast-example
Improving comments in the cross-compiling sample for the Sega Dreamcast.
2020-02-23 18:01:05 +09:00
SiZiOUS 260dc6d741 Improving comments in the cross-compiling example for the Sega Dreamcast (sh-elf). 2020-02-22 23:44:13 +01:00
Yukihiro "Matz" Matsumoto 3ba32e80af Merge pull request #4945 from Leo-Neat/master
Add CIFuzz action
2020-02-22 14:09:23 +09:00
Yukihiro "Matz" Matsumoto ac5ec1a153 Merge pull request #4944 from sizious/sega-dreamcast-example
Added example for cross-compiling for Sega Dreamcast (sh-elf).
2020-02-22 14:07:46 +09:00
Yukihiro "Matz" Matsumoto 34be5acc99 Merge pull request #4942 from inobelar/patch-1
Updated README.md - Fixed link to github issues
2020-02-22 13:25:11 +09:00
Leo Neat 4713502083 CIFuzz action 2020-02-21 15:27:53 -08:00
SiZiOUS 2f6afb52a9 Added example for cross-compiling for Sega Dreamcast (sh-elf).
Thanks to @yujiyokoo for demonstrating mruby usage on Sega Dreamcast at RubyConf AU 2020!
See more here: https://youtu.be/ni-1x5Esa_o
2020-02-21 22:07:07 +01:00
Yurii Nakonechnyi 20597b6d36 Updated README.md - Fixed link to github issues 2020-02-21 16:57:19 +02:00
Yukihiro "Matz" Matsumoto 0301d8a89b Fix integer boundary check before float to time_t casting. 2020-02-12 11:54:32 +09:00
Yukihiro "Matz" Matsumoto 736ea1f5c7 Merge pull request #4941 from davidsiaw/mac-compat
Include time.h for ios
2020-02-05 23:11:45 +09:00
Yukihiro "Matz" Matsumoto ffb55e51f1 Add explicit type cast to return value from mrmchr; ref #4940
C++ is stricter in implicit type casting.
2020-02-03 12:59:29 +09:00
Yukihiro "Matz" Matsumoto 6d9109bf70 Use simple search for short strings in mrb_memsearch_qs; close #4940
Differences from the PR #4940:
* Use simple search for short strings only.
* "short" means `m+n` is shorter than `MRB_QS_SHORT_STRING_LENGTH`.
* The current default value for `MRB_QS_SHORT_STRING_LENGTH` is 2048.
2020-02-03 12:59:29 +09:00
dearblue 4c6d524c47 Implement IO#pread and IO#pwrite
It is available by default in environments where `__unix__` is defined.
Other environments are enabled by defining `MRB_WITH_IO_PREAD_PWRITE`
(requires an implementation of `pread()` and `pwrite()` functions).

In any case, you can disable it by defining
`MRB_WITHOUT_IO_PREAD_PWRITE`.
2020-02-02 21:20:25 +09:00
Yukihiro "Matz" Matsumoto 3c67d9b1c0 Merge pull request #4938 from dearblue/socket-mingw
Fix builds for old mingw in mruby-socket; ref #4914
2020-02-01 17:41:19 +09:00
dearblue 8020374d6b Fix builds for old mingw in mruby-socket; ref #4914 2020-02-01 15:58:32 +09:00
Yukihiro "Matz" Matsumoto db64bd42d3 Add explicit casting in file.c to silence warnings. 2020-01-31 09:26:45 +09:00
Yukihiro "Matz" Matsumoto 724c90f369 Avoid casting warning from mrb_int to int in io.c. 2020-01-31 09:26:05 +09:00
Yukihiro "Matz" Matsumoto c0a6439a69 Avoid implicit integer casting in backtrace.c and hash.c. 2020-01-31 09:25:10 +09:00
Yukihiro "Matz" Matsumoto 10c2b7ee1c Remove unnecessary use of uint16_t in symbol.c. 2020-01-31 09:22:27 +09:00
Yukihiro "Matz" Matsumoto f34623fb03 Fix arena index type from mrb_int to just int. 2020-01-30 17:35:50 +09:00
Yukihiro "Matz" Matsumoto c8f4d72302 Move fallback definitions of FLT_EPSILON etc. after #include <mruby/value.h>
that includes `float.h`. It allows definitions from native headers.
2020-01-30 17:16:12 +09:00
Yukihiro "Matz" Matsumoto 7771c215e4 Removed junk.
My cat stepped on the keyboard at the last moment before the commit.
2020-01-29 10:23:31 +09:00
Yukihiro "Matz" Matsumoto ff5d1914ab Remove unused local variable mid; ref #4936 2020-01-29 08:56:05 +09:00
Yukihiro "Matz" Matsumoto e7e999414c Merge pull request #4873 from dearblue/open-flags
Support bit flags for `IO.open`
2020-01-28 11:09:33 +09:00
David Siaw 36efc33650 include time.h for ios 2020-01-28 00:43:49 +08:00
Yukihiro "Matz" Matsumoto 364c47610f Fixed backtrace message for top-level blocks; fix #4936
In top-level, `mid` is `NULL`. We used to ignore 'mid` update for `NULL`.
2020-01-27 14:34:54 +09:00
Yukihiro "Matz" Matsumoto 59464f3528 Merge pull request #4935 from mimaki/delete-duplicated-Array-delete_if
Delete duplicated `Array#delete_if`.
2020-01-21 13:40:30 +09:00
Hiroshi Mimaki 7d9a49efab Delete duplicated Array#delete_if test. 2020-01-21 12:50:26 +09:00
Hiroshi Mimaki e24b4a1e19 Delete duplicated Array#delete_if. 2020-01-21 11:35:53 +09:00
Yukihiro "Matz" Matsumoto f7abda1437 Remove debug target from travis_config.rb. 2020-01-15 23:39:19 +09:00
Yukihiro "Matz" Matsumoto ff57c0278f Remove broken MRB_INT16 configuration option. 2020-01-15 21:32:00 +09:00
Yukihiro "Matz" Matsumoto 2742ded32f Fixed wrong condition in #4926 fix. 2020-01-10 23:05:27 +09:00
Yukihiro "Matz" Matsumoto 70e5746896 Fixed wrong condition for copying arguments on stack; fix #4926
This bug was introduced in 694089f to address #4832
2020-01-10 17:58:15 +09:00
Yukihiro "Matz" Matsumoto fc8fb41451 Small refactoring in hash_slice; ref #4926 2020-01-10 17:57:33 +09:00
Yukihiro "Matz" Matsumoto dc86e35cac Add MRB_WITHOUT_FLOAT guard to <math.h>. 2020-01-08 10:53:11 +09:00
Yukihiro "Matz" Matsumoto 2124b9b4c9 Fix buffer overflow in mrb_str_len_to_dbl.
Issue 19902: mruby:mruby_fuzzer: Stack-buffer-overflow in mrb_str_len_to_dbl
2020-01-08 10:52:24 +09:00
Yukihiro "Matz" Matsumoto dbba0ca517 p->locals may be NULL when error occurs before the point.
This is reported by oss-fuzz:
Issue 19886: mruby:mruby_fuzzer: Potential-null-reference in setup_numparams
2020-01-08 01:18:53 +09:00
Yukihiro "Matz" Matsumoto afad939173 Check memory boundary in mrb_str_len_to_dbl. 2020-01-07 08:58:06 +09:00
Yukihiro "Matz" Matsumoto 3e4e10ffb6 "0x10".to_f should be 0, not 16.0; fix #4924 2020-01-06 22:27:39 +09:00
Yukihiro "Matz" Matsumoto c60bccaa94 Check remaining string length before access to avoid OOB access. 2020-01-06 22:25:47 +09:00
Yukihiro "Matz" Matsumoto 59756aef14 Need to preserve the original input string in mrb_str_len_to_dbl. 2020-01-06 22:25:05 +09:00
Yukihiro "Matz" Matsumoto 874797f36f Merge branch 'dearblue-file-size-truncate' 2020-01-06 18:58:42 +09:00
Yukihiro "Matz" Matsumoto b545f62aeb Avoid Boxing/Unboxing of file descriptors; ref #4872 2020-01-06 18:57:43 +09:00
Yukihiro "Matz" Matsumoto ca71eb7eef Merge branch 'file-size-truncate' of https://github.com/dearblue/mruby into dearblue-file-size-truncate 2020-01-06 18:49:52 +09:00
Yukihiro "Matz" Matsumoto ccf28775b8 Fix mrb_str_len_to_dbl to support Hexadecimal like 0x10. 2020-01-06 15:52:39 +09:00
Yukihiro "Matz" Matsumoto 2532e625ed Refactor mrb_cstr_to_dbl; ref #4920 2020-01-06 15:52:39 +09:00
Yukihiro "Matz" Matsumoto 111045ecad Avoid creating temporary objects in read_irep_record_1; close #4920
The basic idea of this change is from @dearblue.

Note: the arguments of `mrb_str_pool()` have changed, but the function
is provided for internal use (No `MRB_API`). So basically you don't have
to worry about the change.
2020-01-06 15:52:39 +09:00
Yukihiro "Matz" Matsumoto 282f907f1b Merge pull request #4923 from dearblue/kwargs-block
Fix ainfo with keyword arguments; fix #4921
2020-01-05 20:59:18 +09:00
dearblue 541185ef14 Fix ainfo with keyword arguments; fix #4921 2020-01-05 16:48:34 +09:00
Yukihiro "Matz" Matsumoto d82e91898d Merge pull request #4917 from dearblue/va_end
Call `va_end()` before return
2020-01-02 09:26:15 +09:00
dearblue 00f5c92149 Call va_end() before return
The behavior when returning from a function without `va_end()` is
undefined.
2020-01-02 00:58:27 +09:00
Yukihiro "Matz" Matsumoto 9174b18f34 Rename mrb_num_args_error to mrb_argnum_error; ref #4863 2020-01-01 22:37:14 +09:00
Yukihiro "Matz" Matsumoto b9c78c3fcc Merge pull request #4863 from shuujii/add-mrb_num_args_error-for-wrong-number-of-arguments-error
Add `mrb_num_args_error()` for "wrong number of arguments" error
2020-01-01 22:34:22 +09:00
Yukihiro "Matz" Matsumoto 021f228f9d Merge pull request #4919 from shuujii/revert-SHARED-string-is-not-required-when-sharing-POOL-string
Revert "SHARED string is not required when sharing POOL string" (75949836)
2020-01-01 22:32:41 +09:00
KOBAYASHI Shuji 40b8490fa4 Revert "SHARED string is not required when sharing POOL string" (75949836)
Because literal pool may be released by GC.

#### Example:

  ```ruby
  s1 = eval('"abcdefghijklmnopqrstuvwxyz01"')
  GC.start
  p s1  #=> "\x00\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x90\x03\x00stuvwxyz01"
  ```
2020-01-01 19:16:05 +09:00
Yukihiro "Matz" Matsumoto 7247e4cf1b Merge pull request #4918 from dearblue/sync-vars
Integrate `i` and `arg_i` in `mrb_get_args()`
2020-01-01 15:31:16 +09:00
Yukihiro "Matz" Matsumoto b49bc17f48 Merge pull request #4916 from dearblue/stdint
Do not include `stdint.h` before `mruby.h`; ref #4750
2020-01-01 15:30:29 +09:00
dearblue 7ed26ead9b Integrate i and arg_i in mrb_get_args()
The behavior of these two variables is the same.
2020-01-01 15:07:16 +09:00
dearblue 20d3882469 Do not include stdint.h before mruby.h; ref #4750 2020-01-01 14:17:11 +09:00
Yukihiro "Matz" Matsumoto fd1cff7735 Fixed wrong usages of mrb_get_args in vformat.c. 2020-01-01 12:34:30 +09:00
Yukihiro "Matz" Matsumoto 943fbb2bea Allow here-doc in the middle of Hash expressions; fix #4815 2020-01-01 12:21:17 +09:00
Yukihiro "Matz" Matsumoto 28c8e29c4d Merge pull request #4915 from shuujii/silence-GCC-warning-in-time.c-on-Travis-CI
Silence GCC warning in `time.c` on Travis CI
2019-12-31 22:36:41 +09:00
KOBAYASHI Shuji b493229a23 Silence GCC warning in time.c on Travis CI
Silence the following warnings:

  ```
  /mruby/mrbgems/mruby-time/src/time.c:260:55: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    if ((MRB_INT_MAX > MRB_TIME_MAX && i > 0 && i > MRB_TIME_MAX) ||
                                                  ^
  ```
2019-12-31 21:52:20 +09:00
Yukihiro "Matz" Matsumoto 83e502b847 Merge pull request #4914 from dearblue/fix-4869
Fix builds for modern mingw; fix #4869
2019-12-31 09:42:47 +09:00
dearblue 93d0e5d9fb Fix builds for modern mingw; fix #4869
What I intended to fix in #4869 was a patch for an old MinGW.
Recent MinGWs have their own `mkstemp()` function.
I knew this after checking the patch #4903.
2019-12-31 00:11:40 +09:00
Yukihiro "Matz" Matsumoto 5e519cdbb5 Merge pull request #4913 from shuujii/use-rake-instead-of-minirake-in-.gitlab-ci.yml
Use `rake` instead of `minirake` in `.gitlab-ci.yml`
2019-12-30 22:24:08 +09:00
KOBAYASHI Shuji b96fa664b0 Use rake instead of minirake in .gitlab-ci.yml
There was an error in the `.gitlab-ci.yml` generation script, so it was also
fixed.
2019-12-30 17:46:22 +09:00
Yukihiro "Matz" Matsumoto 4327f36940 Merge pull request #4912 from shuujii/avoid-unneeded-directory-creation-during-rake--T-etc
Avoid unneeded directory creation during `rake -T`, etc.
2019-12-29 21:08:49 +09:00
KOBAYASHI Shuji b97ebf2aeb Avoid unneeded directory creation during rake -T, etc. 2019-12-29 17:46:55 +09:00
Yukihiro "Matz" Matsumoto e9de5a7a5c Merge pull request #4911 from shuujii/use-Rake.verbose-instead-of-verbose-and-pp_show
Use `Rake.verbose` instead of `$verbose` and `$pp_show` in build scripts
2019-12-28 17:43:54 +09:00
KOBAYASHI Shuji bb98fd78c3 Use Rake.verbose instead of $verbose and $pp_show in build scripts
The incompatibility that the commands of `FileUtils` origin output verbose
by default due to the changes in d8a5163b and 26e6e75b is also fixed.
2019-12-28 17:03:37 +09:00
Yukihiro "Matz" Matsumoto d2f34a8455 Merge pull request #4910 from shuujii/use-Rake-DSL-instead-of-commands-of-FileUtils
Use Rake DSL instead of commands of `FileUtils`
2019-12-27 18:35:19 +09:00
KOBAYASHI Shuji 26e6e75ba6 Use Rake DSL instead of commands of FileUtils
- Respect `--verbose(-v)` and `--dry-run(-n)` options.
- Silence warnings to keyword arguments on Ruby 2.7.
2019-12-27 16:49:32 +09:00
Yukihiro "Matz" Matsumoto 03244b52a0 Revert "Enable sanitizer in travis test"; ref #4864
`gcc` sanitizer does not work on some environment (namely my localhost).
Although it works on Travis, it is not convenient that tests fail on the
local host. We keep sanitizer tests on the local (using `clang`).

This reverts commit 9cde967321.
2019-12-27 11:16:37 +09:00
Yukihiro "Matz" Matsumoto d15e56dab0 Prohibit assignment to numbered parameters.
It is stricter than CRuby but confusing anyway.
2019-12-27 11:05:56 +09:00
Yukihiro "Matz" Matsumoto ff16331754 Allow non numbered-parameter identifier like _1 outside of blocks.
But it causes warnings as CRuby does; fix #4892 fix #489
2019-12-27 11:05:56 +09:00
Yukihiro "Matz" Matsumoto d8a5163b24 Support -v flag of rake; close #4887
The patch was originally written by @take-cheese. I have fixed the
conflict caused by `minirake` deletion - @matz.
2019-12-27 11:05:56 +09:00
Yukihiro "Matz" Matsumoto ed8491cde6 Numbered parameters: usually linked list uses cdr for links. 2019-12-27 11:05:56 +09:00
Yukihiro "Matz" Matsumoto 7e6355975e Prohibit numbered parameters as method arguments; fix #4892
As of CRuby2.7 it is only warned. `mruby` prohibits explicitly to
implement the future Ruby3 behavior.
2019-12-27 11:05:56 +09:00
KOBAYASHI Shuji 716102fff3 Enable MRB_GC_STRESS test on CI
The `debug` build target (`MRB_GC_STRESS` is enabled) on CI have been
compiled but not tested so far. However, I think testing with
`MRB_GC_STRESS` is effective (in fact, I found #4907 bug).

Therefore, I integrated `debug` and `full-debug` build targets to enable
`MRB_GC_STRESS` testing. Testing with `MRB_GC_STRESS` takes a little time,
but compiling takes more time, so CI execution time does not increase due to
decrease of build target.
2019-12-27 11:05:56 +09:00
Yukihiro "Matz" Matsumoto ef6805f599 Merge pull request #4864 from take-cheeze/enable_sanitizer_travis
Enable sanitizer in travis test
2019-12-27 10:58:24 +09:00
Yukihiro "Matz" Matsumoto d6b898685f Merge pull request #4907 from shuujii/fix-poteltially-use-of-wrong-method-cache
Fix potentially use of wrong method cache
2019-12-25 23:23:00 +09:00
KOBAYASHI Shuji 0b2d54f4f1 Fix potentially use of wrong method cache
#### Example (with `MRB_METHOD_CACHE`)

  ```ruby
  GC.start
  c = Class.new
  p c            #=> #<Class:0x7fd6a180e790>
  c.new          #=> cache `c.new`
  c = nil
  GC.start       #=> `c` is GCed
  r = Range.dup
  p r            #=> #<Class:0x7fd6a180e790>
                 #   [same pointer as `c`]
  r.new(2, 3)    #=> ArgumentError: 'initialize':
                 #   wrong number of arguments (2 for 0)
                 #   [`c.new` is called instead of `r.new`]
  ```

#### Cause

  An entry of method cache is identified by class pointer and method
  id. However, reusing memory after GC may create a class with the same
  pointer as the cached class.

#### Treatment

  Cleared method caches of the class when the class is GCed.
2019-12-25 21:31:10 +09:00
Yukihiro "Matz" Matsumoto d4cbe6271c Merge pull request #4906 from shuujii/refine-the-assertion-failure-message-in-mrdb-print-tests
Refine the assertion failure message in mrdb print tests
2019-12-25 10:58:04 +09:00
KOBAYASHI Shuji f92867a59e Refine the assertion failure message in mrdb print tests
#### Before this patch:

  ```console
  Fail: mruby-bin-debugger(print) error (mrbgems: mruby-bin-debugger)
   - Assertion[2]
      Expected true to be false.
  ```

#### After this patch:

  ```console
  Fail: mruby-bin-debugger(print) error (mrbgems: mruby-bin-debugger)
   - Assertion[2]
      Expected "$2 = undefined method 'bar' (NoMethodError)\n" to be start_with? "$2 = (eval):2: undefined method".
  ```
2019-12-24 23:20:20 +09:00
Yukihiro "Matz" Matsumoto d062528653 Merge pull request #4905 from kishima/cygwin_compile
Add double quotes for cygwin filenames #4904
2019-12-24 14:23:24 +09:00
kishima b63f1912df add double quotes for cygwin filenames #4904 2019-12-23 23:36:59 +09:00
Yukihiro "Matz" Matsumoto 18248cfd00 Merge pull request #4901 from take-cheeze/gnu_cxx
Use GNU extension in C++ for cygwin
2019-12-23 21:32:26 +09:00
Yukihiro "Matz" Matsumoto 0f89a91607 Merge pull request #4902 from take-cheeze/native_crlf
Handle CR LF newline natively in lexer
2019-12-23 21:31:51 +09:00
take-cheeze bb0aec1d94 Use binary mode in mrbc source code reading 2019-12-23 21:01:42 +09:00
take-cheeze 10e9f193ca Handle CR LF newline natively in lexer 2019-12-23 21:01:11 +09:00
take-cheeze 38fdca82c6 Use GNU extension in C++ for cygwin 2019-12-23 20:58:43 +09:00
Yukihiro "Matz" Matsumoto 49301ed785 Merge pull request #4900 from shuujii/parallelize-compilation-only-on-Travis-CI
Parallelize compilation only on Travis CI
2019-12-23 20:37:25 +09:00
KOBAYASHI Shuji 212d12f269 Parallelize compilation only on Travis CI
Parallel execution of tests makes log difficult to see due to mixing.
2019-12-23 20:04:11 +09:00
Yukihiro "Matz" Matsumoto a562a9aa93 Merge pull request #4899 from dearblue/build-git
Use `git checkout` instead of `git reset`
2019-12-22 22:31:33 +09:00
dearblue f08d9b288d Use git checkout instead of git reset
With this change, if the checkout fails, it will stop with an error.

The purpose is to avoid deleting working branch history when
developing gem.
2019-12-22 15:09:29 +09:00
dearblue dc15c2838f Display directory with git command 2019-12-22 14:26:00 +09:00
Yukihiro "Matz" Matsumoto 0bd3a67dea Merge pull request #4898 from shuujii/refine-.travis.yml
Refine `.travis.yml`
2019-12-22 13:13:49 +09:00
Yukihiro "Matz" Matsumoto 572958ece3 Merge pull request #4896 from shuujii/fix-undefined-method-Pathname
Fix "undefined method `Pathname'"; fix #4895
2019-12-22 13:12:59 +09:00
Yukihiro "Matz" Matsumoto fa90bcb9ab Merge pull request #4897 from shuujii/use-exec-instead-of-system-in-minirake-for-exit-status
Use `exec` instead of `system` in `minirake` for exit status
2019-12-22 13:11:23 +09:00
KOBAYASHI Shuji 5974d53ab0 Refine .travis.yml
* Use `rake` instead of `minirake`.
* Remove `gperf` configuration.

Execution time seems to be reduced by about 15%.
2019-12-22 11:48:04 +09:00
KOBAYASHI Shuji 66349bcef1 Use exec instead of system in minirake for exit status
#### Before this patch:

  ```console
  $ ./minirake --foo; echo $?
  invalid option: --foo
  0
  ```

#### After this patch:

  ```console
  $ ./minirake --foo; echo $?
  invalid option: --foo
  1
  ```
2019-12-21 23:44:33 +09:00
KOBAYASHI Shuji 9f1167f7c9 Fix "undefined method `Pathname'"; fix #4895 2019-12-21 23:31:17 +09:00
Yukihiro "Matz" Matsumoto 089bb6acad Merge pull request #4888 from dearblue/shellquote
Perform `shellquote` on referenced string
2019-12-21 22:46:27 +09:00
Yukihiro "Matz" Matsumoto 06e09fc7a9 Numbered parameters should not be available in the lambda bodies.
`mruby` does not warn like `CRuby` for cases like #4893.
Fix #4890, fix #4891, fix #4893.
2019-12-21 22:41:32 +09:00
Yukihiro "Matz" Matsumoto 2fe78a0c7c Add emulating minirake that calls real rake. 2019-12-21 22:11:08 +09:00
Yukihiro "Matz" Matsumoto de17f63b45 Abandon minirake. Use rake for compilation; fix #4884 2019-12-21 22:11:08 +09:00
Yukihiro "Matz" Matsumoto fee3c1c242 Merge pull request #4889 from shuujii/_0-is-not-numbered-parameter
`_0` is not numbered parameter
2019-12-21 22:10:42 +09:00
KOBAYASHI Shuji 74f564b0bb _0 is not numbered parameter
#### Before this patch:

  ```console
  $ bin/mruby rb -e '_0=:l; p ->{_0}.()'
  -e:1:13: _0 is not available
  -e:1:13: syntax error, unexpected $end, expecting '}'
  ```

#### After this patch (same as Ruby):

  ```console
  $ bin/mruby rb -e '_0=:l; p ->{_0}.()'
  :l
  ```
2019-12-21 18:54:15 +09:00
dearblue acef52c35e Perform shellquote on referenced string 2019-12-21 17:25:22 +09:00
Yukihiro "Matz" Matsumoto 5cc595cb2a Fix SEGV from numbered parameters outside of blocks; fix #4862 2019-12-21 01:24:56 +09:00
Yukihiro "Matz" Matsumoto ef8621cb61 Merge pull request #4885 from shuujii/fix-potentially-crash-in-%n-of-mrb_vformat-with-64-bit-int
Fix potentially crash in `%n` of `mrb_vformat()` with 64-bit `int`
2019-12-21 01:18:09 +09:00
KOBAYASHI Shuji e8299a89da Fix potentially crash in %n of mrb_vformat() with 64-bit int
If `mrb_sym` is smaller than `int`, it is promoted to `int`.
2019-12-20 23:04:46 +09:00
Yukihiro "Matz" Matsumoto 19fa77ddbb Merge pull request #4871 from dearblue/method-in-method
Avoid method in method
2019-12-20 19:29:48 +09:00
Yukihiro "Matz" Matsumoto adf358363c Merge pull request #4870 from dearblue/unnessesary-branch
Remove unnessesary branches
2019-12-20 19:24:45 +09:00
Yukihiro "Matz" Matsumoto 64e9f278b3 Merge pull request #4874 from dearblue/method-list
Fix for `#methods` to include methods that were `undef`
2019-12-20 19:23:13 +09:00
take-cheeze 9cde967321 Enable sanitizer in travis test 2019-12-19 14:21:49 +09:00
Yukihiro "Matz" Matsumoto 87809742f5 Fix mixed declarations in 429f6de 2019-12-19 10:00:33 +09:00
Yukihiro "Matz" Matsumoto fcde80a4d0 Merge pull request #4881 from shuujii/fix-mruby-bin-debugger-tests
Fix `mruby-bin-debugger` tests; ref d2f2f9db
2019-12-19 09:51:31 +09:00
Yukihiro "Matz" Matsumoto 868ba8464e Merge pull request #4882 from shuujii/simplify-print_backtrace
Simplify `print_backtrace()`
2019-12-19 09:50:22 +09:00
Yukihiro "Matz" Matsumoto 429f6defdd Reimplement vformat tests; close #4868
Avoid creating `Data` object that refers `mruby` objects.
Also close #4622 ref #4613
2019-12-19 09:35:51 +09:00
Yukihiro "Matz" Matsumoto 7f0e1fc90b Revert "%C value need not to be saved in TestVFormat::Native; close #4868"
This reverts commit f507ff4842.
It makes AppVeyor tests fail.
2019-12-19 00:07:08 +09:00
KOBAYASHI Shuji 6df6bd4ac7 Simplify print_backtrace() 2019-12-18 19:35:24 +09:00
KOBAYASHI Shuji f0b8c9ec06 Fix mruby-bin-debugger tests; ref d2f2f9db 2019-12-18 19:34:11 +09:00
Yukihiro "Matz" Matsumoto 815e0c400a Merge pull request #4875 from shuujii/remove-location-info-from-Exception-inspect
Remove location info from `Exception#inspect`
2019-12-18 01:55:23 +09:00
Yukihiro "Matz" Matsumoto 4c1667a5f6 Merge pull request #4879 from shuujii/refine-output-of-mrb_print_error
Refine output of `mrb_print_error()`
2019-12-18 01:54:28 +09:00
Yukihiro "Matz" Matsumoto f507ff4842 %C value need not to be saved in TestVFormat::Native; close #4868 2019-12-18 01:40:11 +09:00
KOBAYASHI Shuji 29ecc3840a Refine output of mrb_print_error()
The following improvements are made according to Ruby's behavior:

- Match location number to index.
- Remove duplicate most recent call output.
- Fix that first call is not output when array (unpacked) backtrace.

### Example

  ```ruby
  def a; raise "error!" end
  def b; a end
  begin
    b
  rescue => e
    e.backtrace if ARGV[0] == "unpack"  # unpack backtrace
    raise e
  end
  ```

#### Before this patch:

  ```
  $ bin/mruby example.rb unpack
  trace (most recent call last):
    [0] example.rb:2:in b
    [1] example.rb:1:in a
  example.rb:1: error! (RuntimeError)
  ```

#### After this patch:

  ```
  $ bin/mruby example.rb unpack
  trace (most recent call last):
    [2] example.rb:4
    [1] example.rb:2:in b
  example.rb:1:in a: error! (RuntimeError)
  ```
2019-12-17 23:16:20 +09:00
Yukihiro "Matz" Matsumoto 8bc9a79e65 Merge pull request #4869 from dearblue/mingw32-io-test
Fix mruby-io test for mingw32
2019-12-17 00:49:01 +09:00
Yukihiro "Matz" Matsumoto 6a22fa7f47 Merge pull request #4878 from shuujii/remove-unneeded-null-checks-to-struct-backtrace_locationfilename
Remove unneeded null checks to `struct backtrace_location::filename`
2019-12-17 00:48:27 +09:00
KOBAYASHI Shuji 854c61c3ab Remove unneeded null checks to struct backtrace_location::filename
`struct backtrace_location` is created only in `each_backtrace()`, and
the `filename` field will never be null (it will be `(unknown)` if null).
2019-12-16 18:57:53 +09:00
Yukihiro "Matz" Matsumoto 85b4ed623e Merge pull request #4876 from dearblue/class-methods
Remove module only methods from class
2019-12-16 13:53:55 +09:00
Yukihiro "Matz" Matsumoto fc5a9c2be2 Merge pull request #4877 from shuujii/drop-dependencies-from-mruby-complex-to-some-gems
Drop dependencies from `mruby-complex` to some gems
2019-12-16 13:51:48 +09:00
Yukihiro "Matz" Matsumoto cc6d17423b Merge pull request #4859 from dearblue/authors
Add "mruby developers" into some gems; Resolve #4709
2019-12-16 13:50:33 +09:00
KOBAYASHI Shuji 4bdb1eb5aa Drop dependencies from mruby-complex to some gems 2019-12-15 22:51:07 +09:00
KOBAYASHI Shuji d2f2f9db51 Remove location info from Exception#inspect
Because location info (file name and line number) is kept in the backtrace,
it should not be kept in the result of `inspect` (and the exception object
itself), I think.

### Example

  ```ruby
  # example.rb
  begin
    raise "err"
  rescue => e
    p e
  end
  ```

#### Before this patch:

  ```
  $ bin/mruby example.rb
  example.rb:2: err (RuntimeError)
  ```

#### After this patch:

  ```
  $ bin/mruby example.rb
  err (RuntimeError)
  ```
2019-12-14 22:29:37 +09:00
dearblue cc52fa66e8 Remove module only methods from class
The `#prepend_features` and `#module_function` methods are not haves for
class objects.
2019-12-14 22:12:32 +09:00
dearblue 184ad732df Fix for #methods to include methods that were undef
If `#methods` traverse the super class, it includes the methods that
were does `undef` in the subclass.

Before patched:
```terminal
% bin/mruby -e 'p Module.instance_methods - Class.instance_methods'
[]
```

After patched:
```terminal
% bin/mruby -e 'p Module.instance_methods - Class.instance_methods'
[:append_features, :extend_object]
```
2019-12-14 21:30:44 +09:00
dearblue 69619aeeb1 Support bit flags for IO.open
Note that this bit flags are not compatible with the native flags
defined in `#include <fcntl.h>`.
2019-12-14 15:19:13 +09:00
dearblue 6d9ac89f92 Implement File#size and File#truncate 2019-12-14 15:10:57 +09:00
dearblue 5b30f789e5 Avoid method in method
And rename `File.concat_path` to `File._concat_path`.
2019-12-14 15:04:56 +09:00
dearblue c18a8c53e8 Remove unnessesary branches 2019-12-14 15:01:42 +09:00
dearblue ec1ef925a9 Fix mruby-io test for mingw32
Need `mkstemp()` implements.
2019-12-14 14:57:10 +09:00
Yukihiro "Matz" Matsumoto 6c5ee8f79e Merge pull request #4866 from shuujii/fix-arguments-check-to-Array-each
Fix arguments check to `Array#each`
2019-12-14 01:14:26 +09:00
KOBAYASHI Shuji e18aa4d893 Fix arguments check to Array#each
#### Before this patch:

  ```
  $ mruby -e '[].each(1){}'  #=> no error
  ```

#### After this patch:

  ```
  $ mruby -e '[].each(1){}'  #=> ArgumentError: wrong number of arguments
  ```
2019-12-13 17:30:34 +09:00
KOBAYASHI Shuji 81de1f159c Add mrb_num_args_error() for "wrong number of arguments" error
To unify the style of messages.
2019-12-12 11:45:58 +09:00
Yukihiro "Matz" Matsumoto 9c4c82ed1c Merge pull request #4861 from shuujii/fix-behavior-of-Kernel-Integer-to-numbers-ending-with-_-and-spaces
Fix behavior of `Kernel#Integer` to numbers ending with `_` and spaces
2019-12-12 09:26:14 +09:00
KOBAYASHI Shuji 7192429e83 Fix behavior of Kernel#Integer to numbers ending with _ and spaces
#### Before this patch:

  ```ruby
  Integer("1_ ")  #=> 1
  ```

#### After this patch (same as Ruby):

  ```ruby
  Integer("1_ ")  #=> ArgumentError
  ```
2019-12-11 16:40:39 +09:00
Yukihiro "Matz" Matsumoto 994da0fd73 Merge pull request #4860 from shuujii/fix-behavior-of-String-to_i-Kernel-Integer-to-numbers-starting-with-_
Fix behavior of `String#to_i`/`Kernel#Integer` to numbers starting with `_`
2019-12-10 23:00:17 +09:00
KOBAYASHI Shuji bf431e77b8 Fix behavior of String#to_i/Kernel#Integer to numbers starting with _
#### Before this patch:

  ```ruby
  Integer("_1")  #=> 1
  "_1".to_i      #=> 1
  ```

#### After this patch (same as Ruby):

  ```ruby
  Integer("_1")  #=> ArgumentError
  "_1".to_i      #=> 0
  ```
2019-12-10 21:31:30 +09:00
Yukihiro "Matz" Matsumoto 543a9f84d1 Merge pull request #4858 from shuujii/fix-that-String-to_f-accepts-consecutive-_-as-a-numeric-expression
Fix that `String#to_f` accepts consecutive `_` as a numeric expression
2019-12-10 11:09:55 +09:00
dearblue 56de911b7a Add "mruby developers" into some gems; Resolve #4709
It is writing side by side with the original authors.
2019-12-09 23:49:03 +09:00
KOBAYASHI Shuji 0893ee492c Fix that String#to_f accepts consecutive _ as a numeric expression
Consecutive `_` is not allowed as a numeric expression:

  1_2__3             #=> SyntaxError
  Float("1_2__3")    #=> ArgumentError
  Integer("1_2__3")  #=> ArgumentError
  "1_2__3".to_i      #=> 12

But `String#to_f` accept it, so I fixed the issue.

Before this patch:

  "1_2__3".to_f      #=> 123

After this patch:

  "1_2__3".to_f      #=> 12
2019-12-09 21:47:59 +09:00
Yukihiro "Matz" Matsumoto 694089fafe Fix mrb_get_argv() to return array pointer every time; fix #4832 2019-12-09 20:50:41 +09:00
Yukihiro "Matz" Matsumoto fb9e92e828 Warnings for numbered parameters in nested blocks. 2019-12-09 20:50:41 +09:00
Yukihiro "Matz" Matsumoto f7a0f11c36 Parser refactoring on numbered parameters.
Now identifiers like `_1abc` are allowed.
2019-12-09 20:50:41 +09:00
Yukihiro "Matz" Matsumoto 0011652a28 Support new numbered parameter syntax _1 instead of @1. 2019-12-09 20:50:41 +09:00
Ukrainskiy Sergey 72d57ad094 Implement numbered parameters 2019-12-09 20:50:41 +09:00
Yukihiro "Matz" Matsumoto 8267993988 Merge pull request #4855 from dearblue/kwargs-uninit
Fix keyword arguments not be obtained with `mrb_get_args()`; Fix #4754
2019-12-09 17:31:53 +09:00
Yukihiro "Matz" Matsumoto ef644120e4 Merge pull request #4856 from shuujii/fix-the-error-message-of-Kernel-Float
Fix the error message of `Kernel#Float`
2019-12-08 21:31:14 +09:00
KOBAYASHI Shuji cf6ae0de6a Fix the error message of Kernel#Float
#### Before this patch:

  ```
  $ bin/mruby -e 'Float("1_a")'
  -e:1: invalid string for float(a) (ArgumentError)
  ```

#### After this patch:

  ```
  $ bin/mruby -e 'Float("1_a")'
  -e:1: invalid string for float("1_a") (ArgumentError)
  ```
2019-12-08 18:31:41 +09:00
Yukihiro "Matz" Matsumoto 2456d3abc0 Merge pull request #4854 from shuujii/add-tests-to-Math
Add tests to `Math`
2019-12-08 11:24:29 +09:00
dearblue 1ca4fdc4c7 Fix keyword arguments not be obtained with mrb_get_args(); Fix #4754
If ":" is after "|" and there is no "?" or "*", the keyword argument
could not be obtained and it was not initialized with `undef`.

For example: "|oo:"
2019-12-07 22:48:58 +09:00
KOBAYASHI Shuji d908a73b04 Add tests to Math 2019-12-07 20:50:56 +09:00
Yukihiro "Matz" Matsumoto 6e5c861fff Merge pull request #4852 from shuujii/auto-detect-MRB_TIME_T_UINT
Auto detect `MRB_TIME_T_UINT`
2019-12-06 08:00:53 +09:00
KOBAYASHI Shuji e6033e00fe Auto detect MRB_TIME_T_UINT 2019-12-05 21:40:15 +09:00
Yukihiro "Matz" Matsumoto 52318b3359 Merge pull request #4851 from shuujii/refine-mrb_alloca
Refine `mrb_alloca()`
2019-12-05 09:40:44 +09:00
KOBAYASHI Shuji a030446a94 Refine mrb_alloca()
* The allocated memory is guaranteed to be aligned for any data type (it was
  not guaranteed when string type is embed).
* Make allocation size exactly specified size (does not allocate space for a
  null byte).
2019-12-04 22:21:00 +09:00
Yukihiro "Matz" Matsumoto bc22991ac3 Merge pull request #4850 from shuujii/silence-Clang-warning-with-MRB_INT64-and-MRB_32BIT-in-time.c
Silence Clang warning with `MRB_INT64` and `MRB_32BIT` in `time.c`
2019-12-04 07:10:17 +09:00
KOBAYASHI Shuji ea1911d23f Silence Clang warning with MRB_INT64 and MRB_32BIT in time.c
Silence the following warnings:

  ```
  /mruby/mrbgems/mruby-time/src/time.c:871:15: warning: result of comparison of constant 9223372036854775807 with expression of type 'time_t' (aka 'long') is always false [-Wtautological-constant-out-of-range-compare]
    if (tm->sec > MRB_INT_MAX || tm->sec < MRB_INT_MIN) {
        ~~~~~~~ ^ ~~~~~~~~~~~
  /mruby/mrbgems/mruby-time/src/time.c:871:40: warning: result of comparison of constant -9223372036854775808 with expression of type 'time_t' (aka 'long') is always false [-Wtautological-constant-out-of-range-compare]
    if (tm->sec > MRB_INT_MAX || tm->sec < MRB_INT_MIN) {
                                 ~~~~~~~ ^ ~~~~~~~~~~~
  /mruby/mrbgems/mruby-time/src/time.c:887:16: warning: result of comparison of constant 9223372036854775807 with expression of type 'time_t' (aka 'long') is always false [-Wtautological-constant-out-of-range-compare]
    if (tm->usec > MRB_INT_MAX || tm->usec < MRB_INT_MIN) {
        ~~~~~~~~ ^ ~~~~~~~~~~~
  /mruby/mrbgems/mruby-time/src/time.c:887:42: warning: result of comparison of constant -9223372036854775808 with expression of type 'time_t' (aka 'long') is always false [-Wtautological-constant-out-of-range-compare]
    if (tm->usec > MRB_INT_MAX || tm->usec < MRB_INT_MIN) {
                                ~~~~~~~~ ^ ~~~~~~~~~~~
  ```
2019-12-03 22:50:50 +09:00
Yukihiro "Matz" Matsumoto 54f2ed6afd Merge pull request #4849 from shuujii/silence-Clang-warning-with-MRB_INT32-and-MRB_64BIT-in-time.c
Silence Clang warning with `MRB_INT32` and `MRB_64BIT` in `time.c`
2019-12-03 22:35:44 +09:00
KOBAYASHI Shuji 6973539005 Silence Clang warning with MRB_INT32 and MRB_64BIT in time.c
Silence the following warning:

  ```
  /mruby/mrbgems/mruby-time/src/time.c:258:60: warning: result of comparison of constant -9223372036854775808 with expression of type 'mrb_int' (aka 'int') is always false [-Wtautological-constant-out-of-range-compare]
        if ((mrb_time_int)i > MRB_TIME_MAX || MRB_TIME_MIN > i) {
                                              ~~~~~~~~~~~~ ^ ~
  ```
2019-12-02 20:00:36 +09:00
Yukihiro "Matz" Matsumoto 3c67872805 Merge pull request #4848 from shuujii/fix-MRB_FIXNUM_SHIFT-with-MRB_WORD_BOXING-MRB_INT32-and-MRB_64BIT
Fix `MRB_FIXNUM_SHIFT` with `MRB_WORD_BOXING`, `MRB_INT32` and `MRB_64BIT`
2019-12-02 13:42:16 +09:00
KOBAYASHI Shuji a53f28275e Fix MRB_FIXNUM_SHIFT with MRB_WORD_BOXING, MRB_INT32 and MRB_64BIT
### Example

  ```ruby
  # example.rb
  max32 = 2**30 - 1 + 2**30
  min32 = -max32-1
  [max32, max32+1, min32, min32-1].each{|n| p [n, n.class]}
  ```

#### Before this patch:

  ```
  $ bin/mruby example.rb
  [2147483647, Float]
  [2147483648, Float]
  [-2147483648, Float]
  [-2147483649, Float]
  ```

#### After this patch:

  ```
  $ bin/mruby example.rb
  [2147483647, Fixnum]
  [2147483648, Float]
  [-2147483648, Fixnum]
  [-2147483649, Float]
  ```
2019-12-01 22:09:38 +09:00
Yukihiro "Matz" Matsumoto ef95a9fa93 Use a string as a common regexp representation; ref #4847 2019-11-30 21:10:36 +09:00
Yukihiro "Matz" Matsumoto 25b5b79cc3 Merge pull request #4847 from shuujii/quit-mruby-v-immediately-if-no-program-is-given
Quit `mruby -v` immediately if no program is given for Ruby compatibility
2019-11-30 21:08:54 +09:00
KOBAYASHI Shuji 49653b81ea Quit mruby -v immediately if no program is given for Ruby compatibility 2019-11-30 19:52:22 +09:00
Yukihiro "Matz" Matsumoto 5eb08a0d1a Merge pull request #4846 from shuujii/fix-mruby---verbose-regression-by--4827
Fix `mruby --verbose` (regression by #4827)
2019-11-29 21:53:12 +09:00
KOBAYASHI Shuji df437eebcc Fix mruby --verbose (regression by #4827)
#### Before this patch:

  ```
  $ bin/mruby --verbose -e 'p 1'
  bin/mruby: Cannot open program file: --verbose
  ```

#### After this patch:

  ```
  $ bin/mruby --verbose -e 'p 1'
  00001 NODE_SCOPE:
  (snip)
  irep 0x7fe97041df30 nregs=4 nlocals=1 pools=0 syms=1 reps=0 iseq=11
  file: -e
      1 000 OP_LOADSELF R1
  (snip)

  1
  ```
2019-11-29 19:02:04 +09:00
Yukihiro "Matz" Matsumoto 75e96c6927 Merge pull request #4845 from shuujii/change-URL-of-mruby.org
Change the URL of `mruby.org` [ci skip]
2019-11-29 09:22:26 +09:00
KOBAYASHI Shuji 1680f2c95e Change the URL of mruby.org [ci skip]
- `http` -> `https`
- Remove `www.`
2019-11-28 17:54:52 +09:00
Yukihiro "Matz" Matsumoto 17ec885270 Merge pull request #4843 from shuujii/support-end-of-options-to-mruby-command
Support `--` (end of options) to `mruby` command
2019-11-27 22:41:36 +09:00
KOBAYASHI Shuji f4b528e07a Support -- (end of options) to mruby command
#### Before this patch:

  ```
  $ bin/mruby -e 'p ARGV' -- -x
  bin/mruby: invalid option -- (-h will show valid options)
  ```

#### After this patch:

  ```
  $ bin/mruby -e 'p ARGV' -- -x
  ["-x"]
  ```
2019-11-27 19:51:43 +09:00
Yukihiro "Matz" Matsumoto 190649e591 Merge pull request #4837 from shuujii/add-assertion-to-RVALUE-size
Add assertion to `RVALUE` size
2019-11-27 09:47:35 +09:00
Yukihiro "Matz" Matsumoto ec957ec5ee Merge pull request #4838 from shuujii/rename-BITSIZE-to-BIT-and-BIT-to-BIT_POS-for-consistency
Rename `BITSIZE` to `BIT` and `BIT` to `BIT_POS` for consistency
2019-11-26 06:31:48 +09:00
Yukihiro "Matz" Matsumoto ff15a586a0 Merge pull request #4841 from shuujii/fix-ARGV-value-in-mruby-command-regression-by-4827
Fix `ARGV` value in `mruby` command (regression by #4827)
2019-11-25 23:19:17 +09:00
KOBAYASHI Shuji f9bd414350 Fix ARGV value in mruby command (regression by #4827)
#### Before this patch:

  ```
  $ bin/mruby -e 'p ARGV' a b
  ["bin/mruby", "-e", "p ARGV", "a", "b"]
  ```

#### After this patch:

  ```
  $ bin/mruby -e 'p ARGV' a b
  ["a", "b"]
  ```
2019-11-25 21:56:27 +09:00
Yukihiro "Matz" Matsumoto a89d15cdde Merge pull request #4827 from shuujii/support-short-options-concatenation-to-mruby-command
Support short options concatenation to `mruby` command
2019-11-25 09:49:28 +09:00
Yukihiro "Matz" Matsumoto 1d1c81258e Merge pull request #4840 from shuujii/remove-unused-methods-of-MRubyIOTestUtil
Remove unused methods of `MRubyIOTestUtil`
2019-11-24 23:07:15 +09:00
KOBAYASHI Shuji ce553fa834 Remove unused methods of MRubyIOTestUtil 2019-11-24 21:40:22 +09:00
Yukihiro "Matz" Matsumoto b3e6a993a9 Merge pull request #4834 from shuujii/use-proper-PEEK-macro-for-OP_EPUSH-in-patch_irep
Use proper `PEEK` macro for `OP_EPUSH` in `patch_irep`; fix #4833
2019-11-24 07:52:17 +09:00
KOBAYASHI Shuji 375c1ebc41 Rename BITSIZE to BIT and BIT to BIT_POS for consistency
The bit width terminology is unified to `BIT` according to `MRB_INT_BIT`
and `CHAR_BIT`. Also the bit position terminology is unified to `BIT_POS`.
2019-11-23 20:40:23 +09:00
KOBAYASHI Shuji 6cf99d12ac Add assertion to RVALUE size 2019-11-23 17:36:46 +09:00
Yukihiro "Matz" Matsumoto 56f9106d94 Merge pull request #4836 from shuujii/allow-true-false-argument-to-Kernel-exit
Allow `true`/`false` argument to `Kernel#exit`
2019-11-23 06:25:02 +09:00
Yukihiro "Matz" Matsumoto 8bcf44669c Merge pull request #4835 from shuujii/introduce-mrb_ssize-type-for-buffer-size-on-memory
Introduce `mrb_ssize` type for buffer size on memory; ref #4483
2019-11-22 19:40:19 +09:00
KOBAYASHI Shuji d81e4d71c1 Allow true/false argument to Kernel#exit 2019-11-22 18:29:38 +09:00
KOBAYASHI Shuji a2df247063 Introduce mrb_ssize type for buffer size on memory; ref #4483
Previously, `mrb_int` was used as the type that represents the buffer size
on memory, but the sizes of `RString` and `RArray` exceed 6 words when
`MRB_INT64` is enabled on 32-bit CPU.

I don't think it is necessary to be able to represent the buffer size on
memory that exceeds the virtual address space. Therefore, for this purpose,
introduce `mrb_ssize` which doesn't exceed the sizes of `mrb_int` and
pointer.

I think all `mrb_int` used for this purpose should be changed to
`mrb_ssize`, but currently only the members of the structures (`RString`,
`mrb_shared_string`, `RArray` and `mrb_shared_array`) are changed.
2019-11-21 19:34:02 +09:00
KOBAYASHI Shuji 8596edba09 Use proper PEEK macro for OP_EPUSH in patch_irep; fix #4833 2019-11-20 16:00:58 +09:00
Yukihiro "Matz" Matsumoto 1bb1df19d8 Merge pull request #4831 from shuujii/always-enable-the-rational-and-complex-literals
Always enable the rational and complex literals
2019-11-19 23:32:16 +09:00
Yukihiro "Matz" Matsumoto 125c660974 Merge pull request #4830 from mruby/stable
Release `mruby 2.1.0`.
2019-11-19 23:30:37 +09:00
KOBAYASHI Shuji 351c9c80e7 Always enable the rational and complex literals
I think they can always be enabled because the regular expression literal is
always enabled.
2019-11-19 21:10:59 +09:00
Hiroshi Mimaki 57a56ddaa2 Release mruby 2.1.0. 2019-11-19 18:58:11 +09:00
Yukihiro "Matz" Matsumoto 79e73dd86a Merge pull request #4828 from shuujii/refactor-mrb_string_value_cstr
Refactor `mrb_string_value_cstr`
2019-11-19 02:52:39 +09:00
KOBAYASHI Shuji 3241a7e5a8 Refactor mrb_string_value_cstr
- Keep `MRB_STR_ASCII` flag.
- Avoid a string object creation.
2019-11-19 01:07:58 +09:00
Yukihiro "Matz" Matsumoto bd87799673 Merge pull request #4825 from shuujii/fix-argument-specs-to-Kernel
Fix argument specs to `Kernel`
2019-11-18 08:15:58 +09:00
KOBAYASHI Shuji 9de7130a9a Support short options concatenation to mruby command
#### Before this patch:

  ```
  $ bin/mruby -ce 1
  bin/mruby: Cannot open program file: 1
  ```

#### After this patch:

  ```
  $ bin/mruby -ce 1
  Syntax OK
  ```
2019-11-17 16:38:50 +09:00
Yukihiro "Matz" Matsumoto 74310f41d7 Merge pull request #4826 from shuujii/revert-Implement-Ruby2.7-frozen-strings-from-Symbol-to_s
Revert "Implement Ruby2.7's frozen strings from `Symbol#to_s`"
2019-11-17 04:38:46 +09:00
KOBAYASHI Shuji a367373fe3 Revert "Implement Ruby2.7's frozen strings from Symbol#to_s"
This feature was reverted from Ruby 2.7.
2019-11-16 19:47:31 +09:00
KOBAYASHI Shuji 04baaab311 Fix argument specs to Kernel 2019-11-15 19:07:42 +09:00
Yukihiro "Matz" Matsumoto c9f156ef0c Merge pull request #4823 from shuujii/fix-here-document-with-EOF
Fix here document with EOF
2019-11-15 08:16:33 +09:00
KOBAYASHI Shuji 455930fbc4 Fix here document with EOF
#### Before this patch:

  ```
  $ bin/mruby -e 'p <<EOS
1
EOS'
  -e:4:0: can't find heredoc delimiter "EOS" anywhere before EOF
  -e:4:0: syntax error, unexpected $end, expecting tHEREDOC_END or tHD_STRING_PART or tHD_STRING_MID
  ```

#### After this patch (same as Ruby):

  ```
  $ bin/mruby -e 'p <<EOS
1
EOS'
  "1\n"
  ```
2019-11-14 20:28:36 +09:00
Yukihiro "Matz" Matsumoto db43738397 Merge pull request #4821 from shuujii/use-mrb_intern_lit-if-possible-in-parse.y
Use `mrb_intern_lit` if possible in `parse.y`
2019-11-13 21:08:47 +09:00
Yukihiro "Matz" Matsumoto 079aff1779 Revert a76dc04 to resolve #4820 2019-11-13 21:06:26 +09:00
KOBAYASHI Shuji 29133b2fe2 Use mrb_intern_lit if possible in parse.y 2019-11-13 19:20:47 +09:00
Yukihiro "Matz" Matsumoto 37c8cbe76b Merge pull request #4819 from shuujii/use-intern-instead-of-intern_cstr-if-possible-in-parse.y
Use `intern` instead of `intern_cstr` if possible in `parse.y`
2019-11-13 08:10:50 +09:00
KOBAYASHI Shuji ac917983c5 Use intern instead of intern_cstr if possible in parse.y 2019-11-12 21:04:12 +09:00
Yukihiro "Matz" Matsumoto 1259564c01 Merge pull request #4818 from shuujii/fix-argument-specs-to-Integer
Fix argument specs to `Integer`
2019-11-12 08:33:21 +09:00
KOBAYASHI Shuji edbc6d8ab5 Fix argument specs to Integer 2019-11-11 20:48:52 +09:00
Yukihiro "Matz" Matsumoto c268e36e44 Require Regexp.escape before interpolating build_dir; fix #4817 2019-11-11 18:13:24 +09:00
Yukihiro "Matz" Matsumoto 067c11f65d Merge pull request #4816 from shuujii/defer-getting-caller_dir-until-needed-in-MRubyLoadGems-gem
Defer getting `caller_dir` until needed in `MRuby::LoadGems#gem`
2019-11-11 07:33:31 +09:00
KOBAYASHI Shuji b5946822af Defer getting caller_dir until needed in MRuby::LoadGems#gem 2019-11-10 19:40:07 +09:00
Yukihiro "Matz" Matsumoto cc54257de5 Merge pull request #4814 from shuujii/fix-argument-specs-to-IO
Fix argument specs to `IO`
2019-11-10 08:29:55 +09:00
KOBAYASHI Shuji a72917541f Fix argument specs to IO 2019-11-09 22:08:00 +09:00
Yukihiro "Matz" Matsumoto e50344b5da Avoid unnecessary Symbol#to_s call; fix #4812 2019-11-08 23:38:40 +09:00
Yukihiro "Matz" Matsumoto 1a0c799898 Merge pull request #4813 from shuujii/remove-unneeded-dependency-from-mruby-hash-ext
Remove unneeded dependency from `mruby-hash-ext`
2019-11-08 23:37:40 +09:00
KOBAYASHI Shuji ac213907d7 Remove unneeded dependency from mruby-hash-ext 2019-11-08 20:40:20 +09:00
Yukihiro "Matz" Matsumoto 7750c61e29 Fixed a bug in keyword arguments in block parameters; fix #4810
This is caused by incomplete fix in #4746
2019-11-08 14:06:46 +09:00
Yukihiro "Matz" Matsumoto 8ff001ef30 Avoid crashing of Array#unshift; fix #4808
On cases like `a.unshift(*a)`.
2019-11-08 10:57:18 +09:00
Yukihiro "Matz" Matsumoto 962776fe25 Allow here-doc before closing parentheses; ref #4796 2019-11-08 09:50:48 +09:00
Yukihiro "Matz" Matsumoto 0f64cb421e Merge pull request #4811 from shuujii/clear-MRB_STR_SHARED-flag-in-mrb_str_modify_keep_ascii
Clear `MRB_STR_SHARED` flag in `mrb_str_modify_keep_ascii`; close #4807
2019-11-08 08:12:23 +09:00
KOBAYASHI Shuji 45aa5081e4 Clear MRB_STR_SHARED flag in mrb_str_modify_keep_ascii; close #4807 2019-11-07 22:16:59 +09:00
Yukihiro "Matz" Matsumoto c10e191ac7 Merge pull request #4806 from shuujii/drop-test-dependency-from-mruby-hash-ext-to-mruby-enumerator
Drop test dependency from `mruby-hash-ext` to `mruby-enumerator`
2019-11-06 21:10:21 +09:00
KOBAYASHI Shuji ea2424d36d Drop test dependency from mruby-hash-ext to mruby-enumerator 2019-11-06 18:57:35 +09:00
Yukihiro "Matz" Matsumoto 1cc0180a81 Merge pull request #4805 from shuujii/remove-test-that-depend-on-mruby-enumerator-from-mruby-array-ext
Remove test that depend on `mruby-enumerator` from `mruby-array-ext`
2019-11-05 21:35:06 +09:00
KOBAYASHI Shuji b5bb981959 Remove test that depend on mruby-enumerator from mruby-array-ext
`Object.const_defined?(:Enumerator)` is always false because
`mruby-enumerator` is not specified in `test_dependency`. I don't
think this test is necessary.
2019-11-05 19:45:04 +09:00
Yukihiro "Matz" Matsumoto ee86721ef9 Merge pull request #4804 from shuujii/avoid-using-C++-style-comments-in-parse.y
Avoid using C++ style comments (`//`) in `parse.y` [ci skip]
2019-11-05 17:08:53 +09:00
KOBAYASHI Shuji 4841754aba Avoid using C++ style comments (//) in parse.y [ci skip] 2019-11-04 22:12:59 +09:00
Yukihiro "Matz" Matsumoto 2166cc2e80 Merge pull request #4803 from shuujii/remove-unused-enum-in-mrb_cstr_to_dbl
Remove unused enum in `mrb_cstr_to_dbl`
2019-11-03 22:31:35 +09:00
KOBAYASHI Shuji bf0b591b2f Remove unused enum in mrb_cstr_to_dbl 2019-11-03 19:39:25 +09:00
Yukihiro "Matz" Matsumoto 5812d05b71 Merge pull request #4802 from shuujii/fix-argument-specs-to-Hash
Fix argument specs to `Hash`
2019-11-02 19:40:48 +09:00
KOBAYASHI Shuji 7a06e49008 Fix argument specs to Hash 2019-11-02 17:37:43 +09:00
Yukihiro "Matz" Matsumoto 8cbee9695b Merge pull request #4801 from shuujii/fix-argument-specs-to-File
Fix argument specs to `File`
2019-11-02 08:40:22 +09:00
KOBAYASHI Shuji 7e03f47370 Fix argument specs to File 2019-11-01 22:02:18 +09:00
Yukihiro "Matz" Matsumoto ad7f9b3542 Merge pull request #4799 from shuujii/fix-argument-specs-to-Fiber
Fix argument specs to `Fiber`
2019-10-31 11:29:19 +09:00
KOBAYASHI Shuji e4d078b520 Fix argument specs to Fiber 2019-10-30 23:00:22 +09:00
Yukihiro "Matz" Matsumoto 1dc0da8218 Fix here-doc inside parens and brackets; fix #4796 2019-10-30 10:05:28 +09:00
mimaki a9e27933a9 Fix file/directory name parameter for git command. 2019-10-30 09:32:24 +09:00
Yukihiro "Matz" Matsumoto fdc0219db5 Merge pull request #4798 from mimaki/fix-git-params-for-windows
Fix `git` command parameter for Windows.
2019-10-30 00:40:58 +09:00
Yukihiro "Matz" Matsumoto ecdc6c6507 Merge pull request #4797 from shuujii/remove-unneeded-Array-creation-in-Struct-_inspect
Remove unneeded `Array` creation in `Struct#_inspect`
2019-10-30 00:39:44 +09:00
mimaki f68212cc7a Fix file/directory name parameter for git command. 2019-10-29 20:56:12 +09:00
KOBAYASHI Shuji e23840a3fc Remove unneeded Array creation in Struct#_inspect 2019-10-29 20:55:28 +09:00
Yukihiro "Matz" Matsumoto 34f68d0104 Merge pull request #4795 from shuujii/remove-documents-about-Regexp-argument-from-string
Remove documents about `Regexp` argument from `String#{[],[]=}` [ci skip]
2019-10-28 22:24:04 +09:00
KOBAYASHI Shuji 23cb78a0ff Remove documents about Regexp argument from String#{[],[]=} [ci skip] 2019-10-28 18:37:40 +09:00
Yukihiro "Matz" Matsumoto 552bd9daff Merge pull request #4792 from shuujii/refine-String-split-document
Refine `String#split` document
2019-10-27 22:52:50 +09:00
KOBAYASHI Shuji 799ad0e1c7 Refine String#split document 2019-10-27 19:14:12 +09:00
Yukihiro "Matz" Matsumoto 8710a22c31 Merge pull request #4791 from shuujii/optimize-chars2bytes-with-MRB_UTF8_STRING-to-ASCII-only-string
Optimize `chars2bytes` with `MRB_UTF8_STRING` to ASCII only string
2019-10-26 23:09:30 +09:00
KOBAYASHI Shuji db0a4d9045 Optimize chars2bytes with MRB_UTF8_STRING to ASCII only string
### Benchmark (with `MRB_UTF8_STRING`)

  ```
  $ mruby -e '
    COUNT = 150000
    SIZE = 10000
    strs = Array.new(COUNT) do
      s = "a" * SIZE
      s.size  # set `MRB_STR_ASCII` flag
      s
    end
    i = 0
    t = Time.now
    while i < COUNT
      strs[i][-2..-1] = ""
      i += 1
    end
    printf "%.2f sec\n", Time.now - t
  '

  1.10 sec  # before
  0.07 sec  # after
  ```
2019-10-26 22:19:04 +09:00
Yukihiro "Matz" Matsumoto 9c99451607 Merge pull request #4790 from shuujii/squeeze-redundant-spaces
Squeeze redundant spaces in `test/t/numeric.rb` [ci skip]
2019-10-25 22:14:18 +09:00
KOBAYASHI Shuji 4b14c4633a Squeeze redundant spaces in test/t/numeric.rb [ci skip] 2019-10-25 19:39:31 +09:00
Yukihiro "Matz" Matsumoto 39a0a25f20 Merge pull request #4788 from shuujii/fix-argument-specs-to-Exception
Fix argument specs to `Exception`
2019-10-25 08:21:53 +09:00
KOBAYASHI Shuji 85e34f1ca4 Fix argument specs to Exception 2019-10-24 22:24:40 +09:00
Yukihiro "Matz" Matsumoto b4262972dc Merge pull request #4787 from shuujii/optimize-str_subseq-with-MRB_UTF8_STRING-to-ASCII-only-string
Optimize `str_subseq` with `MRB_UTF8_STRING` to ASCII only string
2019-10-23 20:12:55 +09:00
KOBAYASHI Shuji 06bd4ffdaf Optimize str_subseq with MRB_UTF8_STRING to ASCII only string
### Benchmark (with `MRB_UTF8_STRING`)

  ```ruby
  # benchmark.rb
  COUNT = 300000
  SIZE = 10000
  s = "a" * SIZE
  s.size  # set `MRB_STR_ASCII` flag
  i = 0
  while i < COUNT
    s[-1]
    i += 1
  end
  ```

#### Before this patch:

  ```
  $ time mruby benchmark.rb
          2.06 real         2.05 user         0.00 sys
  ```

#### After this patch:

  ```
  $ time mruby benchmark.rb
          0.05 real         0.04 user         0.00 sys
  ```
2019-10-23 19:03:39 +09:00
Hiroshi Mimaki 4eb8fca140 Merge branch 'master' into stable 2019-10-23 15:44:21 +09:00
Yukihiro "Matz" Matsumoto fa85f91e0e Add type cast to avoid an error from int and enum mixture; fix #4786 2019-10-23 14:47:55 +09:00
Yukihiro "Matz" Matsumoto 9540a8309c Remove unnecessary mrb_funcall(). 2019-10-23 14:47:55 +09:00
Yukihiro "Matz" Matsumoto 11184e9186 Remove unnecessary mrb_string_p() check. 2019-10-23 14:47:55 +09:00
Yukihiro "Matz" Matsumoto 2f0bf1e110 Merge pull request #4785 from shuujii/fix-incorrect-MRB_STR_ASCII-flag-update-in-mrb_str_dump
Fix incorrect `MRB_STR_ASCII` flag update in `mrb_str_dump`
2019-10-23 09:55:47 +09:00
KOBAYASHI Shuji 41c43234a7 Fix incorrect MRB_STR_ASCII flag update in mrb_str_dump
### Example (with `MRB_UTF8_STRING`)

  ```ruby
  s = "\u3042"
  p s.size
  s.dump
  p s.size
  ```

#### Before this patch:

  ```
  1
  3
  ```

#### After this patch:

  ```
  1
  1
  ```
2019-10-22 21:56:40 +09:00
Yukihiro "Matz" Matsumoto 1aacde20fa Merge pull request #4784 from shuujii/remove-Kernel-getc
Remove `Kernel#getc`
2019-10-21 21:27:02 +09:00
KOBAYASHI Shuji 941b99955a Remove Kernel#getc
`Kernel#getc` has been removed since Ruby 1.9 and is not defined in ISO.
2019-10-21 18:50:52 +09:00
Yukihiro "Matz" Matsumoto 0701cc493c Merge pull request #4783 from shuujii/use-mrb_str_cat_str-instead-of-mrb_str_concat-if-possible
Use `mrb_str_cat_str` instead of `mrb_str_concat` if possible
2019-10-20 20:24:10 +09:00
KOBAYASHI Shuji 7047c52d7b Use mrb_str_cat_str instead of mrb_str_concat if possible 2019-10-20 16:26:10 +09:00
Yukihiro "Matz" Matsumoto fddefeb7ee Merge pull request #4781 from shuujii/fix-that-Module-to_s-may-return-frozen-string
Fix that `Module#to_s` may return frozen string; ref 08eafe2
2019-10-19 17:55:26 +09:00
KOBAYASHI Shuji 347729a7c0 Fix that Module#to_s may return frozen string; ref 08eafe2 2019-10-19 17:27:17 +09:00
Yukihiro "Matz" Matsumoto 7957f75bd8 Merge pull request #4779 from take-cheeze/print_mrbc_cmd
Print mrbc command on verbose mode
2019-10-19 11:12:03 +09:00
take-cheeze 4877dbf2a9 Print mrbc command on verbose mode 2019-10-19 01:42:34 +09:00
139 changed files with 4107 additions and 2748 deletions
+24
View File
@@ -0,0 +1,24 @@
name: CIFuzz
on: [pull_request]
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'mruby'
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'mruby'
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v1
if: failure()
with:
name: artifacts
path: ./out/artifacts
+1601 -401
View File
File diff suppressed because it is too large Load Diff
+1 -6
View File
@@ -9,11 +9,6 @@ matrix:
- os: osx
osx_image: xcode7.1
addons:
apt:
packages:
- gperf
env:
- MRUBY_CONFIG=travis_config.rb
script: "./minirake -j4 all test"
script: "rake -m && rake test"
+1
View File
@@ -42,3 +42,4 @@ of this list.
Masahiro Wakame
YAMAMOTO Masaya
KOBAYASHI Shuji
RIZAL Reckordp
+1 -1
View File
@@ -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
+1 -1
View File
@@ -6,7 +6,7 @@
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "mruby"
PROJECT_NUMBER = 2.1.0
PROJECT_NUMBER = 2.1.1
PROJECT_BRIEF = "mruby is the lightweight implementation of the Ruby language"
+1 -1
View File
@@ -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 -3
View File
@@ -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)
+4 -8
View File
@@ -17,7 +17,7 @@ of the Ministry of Economy, Trade and Industry of Japan.
## How to get mruby
The stable version 2.1.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.1.0.zip](https://github.com/mruby/mruby/archive/2.1.0.zip)
The stable version 2.1.1 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.1.1.zip](https://github.com/mruby/mruby/archive/2.1.1.zip)
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
@@ -30,11 +30,11 @@ You can also install and compile mruby using [ruby-install](https://github.com/p
## mruby home-page
The URL of the mruby home-page is: [http://www.mruby.org](http://www.mruby.org).
The URL of the mruby home-page is: https://mruby.org.
## Mailing list
We don't have a mailing list, but you can use [GitHub issues](https://github.com/mruby/mruby).
We don't have a mailing list, but you can use [GitHub issues](https://github.com/mruby/mruby/issues).
## How to compile and install (mruby and gems)
@@ -44,11 +44,7 @@ See the [compile.md](https://github.com/mruby/mruby/blob/master/doc/guides/compi
To run the tests, execute the following from the project's root directory.
$ make test
Or
$ ruby ./minirake test
$ rake test
## Building documentation
+9 -8
View File
@@ -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
+8
View File
@@ -14,10 +14,18 @@ environment:
# Visual Studio 2017 64bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat
# Visual Studio 2017 32bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat
machine: x86
# Visual Studio 2015 64bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
machine: amd64
# Visual Studio 2015 32bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
machine: x86
# Visual Studio 2013 64bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat
machine: amd64
+1 -14
View File
@@ -1,23 +1,10 @@
MRuby::Build.new('debug') do |conf|
toolchain :visualcpp
enable_debug
# include all core GEMs
conf.gembox 'full-core'
conf.compilers.each do |c|
c.defines += %w(MRB_GC_STRESS MRB_GC_FIXED_ARENA MRB_METHOD_CACHE)
end
build_mrbc_exec
end
MRuby::Build.new('full-debug') do |conf|
toolchain :visualcpp
enable_debug
# include all core GEMs
conf.gembox 'full-core'
conf.cc.defines += %w(MRB_ENABLE_DEBUG_HOOK)
conf.cc.defines += %w(MRB_GC_STRESS MRB_METHOD_CACHE MRB_ENABLE_DEBUG_HOOK)
conf.enable_test
end
+6 -6
View File
@@ -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
+4 -4
View File
@@ -32,10 +32,10 @@ All tools necessary to compile mruby can be set or modified here. In case
you want to maintain an additional *build_config.rb* you can define a
customized path using the *$MRUBY_CONFIG* environment variable.
To compile just call `./minirake` inside of the mruby source root. To
generate and execute the test tools call `./minirake test`. To clean
all build files call `./minirake clean`. To see full command line on
build, call `./minirake -v`.
To compile just call `rake` inside of the mruby source root. To
generate and execute the test tools call `rake test`. To clean
all build files call `rake clean`. To see full command line on
build, call `rake -v`.
## Build Configuration
+1 -1
View File
@@ -38,7 +38,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
```bash
$ mrdb --version
mruby 2.1.0 (2019-10-18)
mruby 2.1.1 (2020-06-04)
```
## 2.2 Basic Operation
+4 -8
View File
@@ -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.
+3 -3
View File
@@ -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
View File
@@ -38,7 +38,7 @@ puts [1,2,3]
3
```
#### mruby [2.1.0 (2019-10-18)]
#### mruby [2.1.1 (2020-06-04)]
```
[1, 2, 3]
@@ -61,7 +61,7 @@ end
`ZeroDivisionError` is raised.
#### mruby [2.1.0 (2019-10-18)]
#### mruby [2.1.1 (2020-06-04)]
No exception is raised.
@@ -89,7 +89,7 @@ p Liste.new "foobar"
` [] `
#### mruby [2.1.0 (2019-10-18)]
#### mruby [2.1.1 (2020-06-04)]
`ArgumentError` is raised.
@@ -119,7 +119,7 @@ false
true
```
#### mruby [2.1.0 (2019-10-18)]
#### mruby [2.1.1 (2020-06-04)]
```
true
@@ -156,7 +156,7 @@ p 'ok'
ok
```
#### mruby [2.1.0 (2019-10-18)]
#### mruby [2.1.1 (2020-06-04)]
```
test.rb:8: undefined method 'test_func' (NoMethodError)
@@ -178,7 +178,7 @@ defined?(Foo)
nil
```
#### mruby [2.1.0 (2019-10-18)]
#### mruby [2.1.1 (2020-06-04)]
`NameError` is raised.
@@ -195,7 +195,7 @@ alias $a $__a__
` nil `
#### mruby [2.1.0 (2019-10-18)]
#### mruby [2.1.1 (2020-06-04)]
Syntax error
@@ -217,7 +217,7 @@ end
`ArgumentError` is raised.
The re-defined `+` operator does not accept any arguments.
#### mruby [2.1.0 (2019-10-18)]
#### mruby [2.1.1 (2020-06-04)]
` 'ab' `
Behavior of the operator wasn't changed.
@@ -233,7 +233,7 @@ $ ruby -e 'puts Proc.new {}.binding'
#<Binding:0x00000e9deabb9950>
```
#### mruby [2.1.0 (2019-10-18)]
#### mruby [2.1.1 (2020-06-04)]
```
$ ./bin/mruby -e 'puts Proc.new {}.binding'
@@ -255,7 +255,7 @@ $ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
[[{"a"=>1}], {:b=>2}]
```
#### mruby [mruby 2.1.0]
#### mruby [mruby 2.1.1]
```
$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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|
+2 -2
View File
@@ -27,7 +27,7 @@ MRuby::CrossBuild.new("RX630") do |conf|
conf.cc do |cc|
cc.command = "#{BIN_PATH}/rx-elf-gcc"
cc.flags = "-Wall -g -O2 -flto -mcpu=rx600 -m64bit-doubles"
cc.compile_options = "%{flags} -o %{outfile} -c %{infile}"
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
#configuration for low memory environment
cc.defines << %w(MRB_USE_FLOAT)
@@ -53,7 +53,7 @@ MRuby::CrossBuild.new("RX630") do |conf|
conf.archiver do |archiver|
archiver.command = "#{BIN_PATH}/rx-elf-ar"
archiver.archive_options = 'rcs %{outfile} %{objs}'
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
#no executables
@@ -39,7 +39,7 @@ MRuby::CrossBuild.new("chipKITMax32") do |conf|
cc.flags = %w(-O2 -mno-smart-io -w -ffunction-sections -fdata-sections -g -mdebugger -Wcast-align
-fno-short-double -mprocessor=32MX795F512L -DF_CPU=80000000L -DARDUINO=23 -D_BOARD_MEGA_
-DMPIDEVER=0x01000202 -DMPIDE=23)
cc.compile_options = "%{flags} -o %{outfile} -c %{infile}"
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
#configuration for low memory environment
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
@@ -60,7 +60,7 @@ MRuby::CrossBuild.new("chipKITMax32") do |conf|
conf.archiver do |archiver|
archiver.command = "#{PIC32_PATH}/compiler/pic32-tools/bin/pic32-ar"
archiver.archive_options = 'rcs %{outfile} %{objs}'
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
#no executables
@@ -0,0 +1,108 @@
MRuby::Build.new do |conf|
# Gets set by the VS command prompts
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
# Include the default GEMs
conf.gembox 'default'
end
# Cross Compiling configuration for the Sega Dreamcast
# This configuration requires KallistiOS (KOS)
# https://dreamcast.wiki
#
# Tested on GNU/Linux, MinGW-w64/MSYS2, Cygwin, macOS and MinGW/MSYS (see below)
#
MRuby::CrossBuild.new("dreamcast") do |conf|
toolchain :gcc
# Support for DreamSDK (based on MinGW/MSYS)
# To compile mruby with DreamSDK, RubyInstaller for Windows should be installed
DREAMSDK_HOME = ENV["DREAMSDK_HOME"]
MSYS_ROOT = !(DREAMSDK_HOME.nil? || DREAMSDK_HOME.empty?) ? "#{DREAMSDK_HOME}/msys/1.0" : ""
# Setting paths
DREAMCAST_PATH = "#{MSYS_ROOT}/opt/toolchains/dc"
KOS_PATH = "#{DREAMCAST_PATH}/kos"
BIN_PATH = "#{DREAMCAST_PATH}/sh-elf/bin"
# C compiler
# Flags were extracted from KallistiOS environment files
conf.cc do |cc|
cc.command = "#{BIN_PATH}/sh-elf-gcc"
cc.include_paths << ["#{KOS_PATH}/include", "#{KOS_PATH}/kernel/arch/dreamcast/include", "#{KOS_PATH}/addons/include", "#{KOS_PATH}/../kos-ports/include"]
cc.flags << ["-O2", "-fomit-frame-pointer", "-ml", "-m4-single-only", "-ffunction-sections", "-fdata-sections", "-Wall", "-g", "-fno-builtin", "-ml", "-m4-single-only", "-Wl,-Ttext=0x8c010000", "-Wl,--gc-sections", "-T#{KOS_PATH}/utils/ldscripts/shlelf.xc", "-nodefaultlibs"]
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
cc.defines << %w(_arch_dreamcast)
cc.defines << %w(_arch_sub_pristine)
end
# C++ compiler
conf.cxx do |cxx|
cxx.command = conf.cc.command.dup
cxx.include_paths = conf.cc.include_paths.dup
cxx.flags = conf.cc.flags.dup
cxx.flags << %w(-fno-rtti -fno-exceptions)
cxx.defines = conf.cc.defines.dup
cxx.compile_options = conf.cc.compile_options.dup
end
# Linker
# There is an issue when making the mruby library with KallistiOS:
# 'newlib_kill.o' and 'newlib_getpid.o' aren't found so they are explicitly
# specified here at least for now.
conf.linker do |linker|
linker.command="#{BIN_PATH}/sh-elf-gcc"
linker.flags << ["#{MSYS_ROOT}/opt/toolchains/dc/kos/kernel/build/newlib_kill.o", "#{MSYS_ROOT}/opt/toolchains/dc/kos/kernel/build/newlib_getpid.o", "-Wl,--start-group -lkallisti -lc -lgcc -Wl,--end-group"]
linker.library_paths << ["#{KOS_PATH}/lib/dreamcast", "#{KOS_PATH}/addons/lib/dreamcast", "#{KOS_PATH}/../kos-ports/lib"]
end
# Archiver
conf.archiver do |archiver|
archiver.command = "#{BIN_PATH}/sh-elf-ar"
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
# No executables
conf.bins = []
# Do not build executable test
conf.build_mrbtest_lib_only
# Disable C++ exception
conf.disable_cxx_exception
# Gems from core
# removing mruby-io
conf.gem :core => "mruby-metaprog"
conf.gem :core => "mruby-pack"
conf.gem :core => "mruby-sprintf"
conf.gem :core => "mruby-print"
conf.gem :core => "mruby-math"
conf.gem :core => "mruby-time"
conf.gem :core => "mruby-struct"
conf.gem :core => "mruby-compar-ext"
conf.gem :core => "mruby-enum-ext"
conf.gem :core => "mruby-string-ext"
conf.gem :core => "mruby-numeric-ext"
conf.gem :core => "mruby-array-ext"
conf.gem :core => "mruby-hash-ext"
conf.gem :core => "mruby-range-ext"
conf.gem :core => "mruby-proc-ext"
conf.gem :core => "mruby-symbol-ext"
conf.gem :core => "mruby-random"
conf.gem :core => "mruby-object-ext"
conf.gem :core => "mruby-objectspace"
conf.gem :core => "mruby-fiber"
conf.gem :core => "mruby-enumerator"
conf.gem :core => "mruby-enum-lazy"
conf.gem :core => "mruby-toplevel-ext"
conf.gem :core => "mruby-kernel-ext"
conf.gem :core => "mruby-class-ext"
conf.gem :core => "mruby-compiler"
end
+9 -10
View File
@@ -38,21 +38,23 @@
/* add -DMRB_METHOD_T_STRUCT on machines that use higher bits of pointers */
/* no MRB_METHOD_T_STRUCT requires highest 2 bits of function pointers to be zero */
//#define MRB_METHOD_T_STRUCT
#ifndef MRB_METHOD_T_STRUCT
// can't use highest 2 bits of function pointers on 32bit Windows.
# if defined(_WIN32) && !defined(_WIN64)
# define MRB_METHOD_T_STRUCT
# endif
#endif
/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT32 and MRB_INT64 */
//#define MRB_INT16
/* add -DMRB_INT32 to use 32bit integer for mrb_int; conflict with MRB_INT16 and MRB_INT64;
/* add -DMRB_INT32 to use 32bit integer for mrb_int; conflict with MRB_INT64;
Default for 32-bit CPU mode. */
//#define MRB_INT32
/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 and MRB_INT32;
/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT32;
Default for 64-bit CPU mode. */
//#define MRB_INT64
/* if no specific integer type is chosen */
#if !defined(MRB_INT16) && !defined(MRB_INT32) && !defined(MRB_INT64)
#if !defined(MRB_INT32) && !defined(MRB_INT64)
# if defined(MRB_64BIT) && !defined(MRB_NAN_BOXING)
/* Use 64bit integers on 64bit architecture (without MRB_NAN_BOXING) */
# define MRB_INT64
@@ -62,9 +64,6 @@
# endif
#endif
#define MRB_COMPLEX_NUMBERS
#define MRB_RATIONAL_NUMBERS
/* define on big endian machines; used by MRB_NAN_BOXING, etc. */
#ifndef MRB_ENDIAN_BIG
# if (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \
+7 -6
View File
@@ -1,7 +1,7 @@
/*
** mruby - An embeddable Ruby implementation
**
** Copyright (c) mruby developers 2010-2019
** Copyright (c) mruby developers 2010-2020
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
@@ -70,6 +70,11 @@
#include "mrbconf.h"
#include <mruby/common.h>
#include <mruby/value.h>
#include <mruby/gc.h>
#include <mruby/version.h>
#ifndef MRB_WITHOUT_FLOAT
#ifndef FLT_EPSILON
#define FLT_EPSILON (1.19209290e-07f)
@@ -88,11 +93,6 @@
#endif
#endif
#include <mruby/common.h>
#include <mruby/value.h>
#include <mruby/gc.h>
#include <mruby/version.h>
/**
* MRuby C API entry point
*/
@@ -1232,6 +1232,7 @@ MRB_API mrb_noreturn void mrb_raise(mrb_state *mrb, struct RClass *c, const char
MRB_API mrb_noreturn void mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...);
MRB_API mrb_noreturn void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...);
MRB_API mrb_noreturn void mrb_frozen_error(mrb_state *mrb, void *frozen_obj);
MRB_API mrb_noreturn void mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max);
MRB_API void mrb_warn(mrb_state *mrb, const char *fmt, ...);
MRB_API mrb_noreturn void mrb_bug(mrb_state *mrb, const char *fmt, ...);
MRB_API void mrb_print_backtrace(mrb_state *mrb);
+3 -3
View File
@@ -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;
+1
View File
@@ -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
+1
View File
@@ -8,6 +8,7 @@
#define MRUBY_BOXING_NO_H
#define MRB_FIXNUM_SHIFT 0
#define MRB_SYMBOL_SHIFT 0
union mrb_value_union {
#ifndef MRB_WITHOUT_FLOAT
+28 -27
View File
@@ -7,10 +7,6 @@
#ifndef MRUBY_BOXING_WORD_H
#define MRUBY_BOXING_WORD_H
#if defined(MRB_INT16)
# error MRB_INT16 is too small for MRB_WORD_BOXING.
#endif
#if defined(MRB_INT64) && !defined(MRB_64BIT)
#error MRB_INT64 cannot be used with MRB_WORD_BOXING in 32-bit mode.
#endif
@@ -34,41 +30,46 @@ enum mrb_special_consts {
MRB_Qundef = 20,
};
#define MRB_FIXNUM_SHIFT 1
#define MRB_SYMBOL_SHIFT 2
#define MRB_FIXNUM_FLAG (1 << (MRB_FIXNUM_SHIFT - 1))
#define MRB_SYMBOL_FLAG (1 << (MRB_SYMBOL_SHIFT - 1))
#define MRB_FIXNUM_MASK ((1 << MRB_FIXNUM_SHIFT) - 1)
#define MRB_SYMBOL_MASK ((1 << MRB_SYMBOL_SHIFT) - 1)
#define MRB_IMMEDIATE_MASK 0x07
#ifdef MRB_64BIT
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT)
#define MRB_SYMBOL_MAX UINT32_MAX
#if defined(MRB_64BIT) && defined(MRB_INT32)
#define MRB_FIXNUM_SHIFT 0
#else
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT - MRB_SYMBOL_SHIFT)
#define MRB_SYMBOL_MAX (UINT32_MAX >> MRB_SYMBOL_SHIFT)
#define MRB_FIXNUM_SHIFT BOXWORD_FIXNUM_SHIFT
#endif
#define MRB_SYMBOL_SHIFT BOXWORD_SYMBOL_SHIFT
#define BOXWORD_FIXNUM_BIT_POS 1
#define BOXWORD_SYMBOL_BIT_POS 2
#define BOXWORD_FIXNUM_SHIFT BOXWORD_FIXNUM_BIT_POS
#ifdef MRB_64BIT
#define BOXWORD_SYMBOL_SHIFT 0
#else
#define BOXWORD_SYMBOL_SHIFT BOXWORD_SYMBOL_BIT_POS
#endif
#define BOXWORD_FIXNUM_FLAG (1 << (BOXWORD_FIXNUM_BIT_POS - 1))
#define BOXWORD_SYMBOL_FLAG (1 << (BOXWORD_SYMBOL_BIT_POS - 1))
#define BOXWORD_FIXNUM_MASK ((1 << BOXWORD_FIXNUM_BIT_POS) - 1)
#define BOXWORD_SYMBOL_MASK ((1 << BOXWORD_SYMBOL_BIT_POS) - 1)
#define BOXWORD_IMMEDIATE_MASK 0x07
#define BOXWORD_SHIFT_VALUE(o,n,t) \
((((t)(o).w)) >> MRB_##n##_SHIFT)
(t)(((long)(o).w) >> BOXWORD_##n##_SHIFT)
#define BOXWORD_SET_SHIFT_VALUE(o,n,v) \
((o).w = (((unsigned long)(v)) << MRB_##n##_SHIFT) | MRB_##n##_FLAG)
((o).w = (((unsigned long)(v)) << BOXWORD_##n##_SHIFT) | BOXWORD_##n##_FLAG)
#define BOXWORD_SHIFT_VALUE_P(o,n) \
(((o).w & MRB_##n##_MASK) == MRB_##n##_FLAG)
(((o).w & BOXWORD_##n##_MASK) == BOXWORD_##n##_FLAG)
#define BOXWORD_OBJ_TYPE_P(o,n) \
(!mrb_immediate_p(o) && (o).value.bp->tt == MRB_TT_##n)
/*
* mrb_value representation:
*
* nil : ...0000 0000 (all bits are zero)
* false : ...0000 0100
* nil : ...0000 0000 (all bits are 0)
* false : ...0000 0100 (mrb_fixnum(v) != 0)
* true : ...0000 1100
* undef : ...0001 0100
* fixnum: ...IIII III1
* symbol: ...SSSS SS10 (high-order 32-bit are symbol value in 64-bit mode)
* object: ...PPPP P000
* symbol: ...SSSS SS10 (use only upper 32-bit as symbol value on 64-bit CPU)
* object: ...PPPP P000 (any bits are 1)
*/
typedef union mrb_value {
union {
@@ -114,10 +115,10 @@ MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
#endif
#define mrb_bool(o) (((o).w & ~(unsigned long)MRB_Qfalse) != 0)
#define mrb_immediate_p(o) ((o).w & MRB_IMMEDIATE_MASK || (o).w == MRB_Qnil)
#define mrb_immediate_p(o) ((o).w & BOXWORD_IMMEDIATE_MASK || (o).w == MRB_Qnil)
#define mrb_fixnum_p(o) BOXWORD_SHIFT_VALUE_P(o, FIXNUM)
#ifdef MRB_64BIT
#define mrb_symbol_p(o) ((o).value.sym_flag == MRB_SYMBOL_FLAG)
#define mrb_symbol_p(o) ((o).value.sym_flag == BOXWORD_SYMBOL_FLAG)
#else
#define mrb_symbol_p(o) BOXWORD_SHIFT_VALUE_P(o, SYMBOL)
#endif
@@ -159,7 +160,7 @@ MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
#define SET_BOOL_VALUE(r,b) ((b) ? SET_TRUE_VALUE(r) : SET_FALSE_VALUE(r))
#define SET_INT_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, FIXNUM, n)
#ifdef MRB_64BIT
#define SET_SYM_VALUE(r,v) ((r).value.sym = v, (r).value.sym_flag = MRB_SYMBOL_FLAG)
#define SET_SYM_VALUE(r,v) ((r).value.sym = v, (r).value.sym_flag = BOXWORD_SYMBOL_FLAG)
#else
#define SET_SYM_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, SYMBOL, n)
#endif
+7
View File
@@ -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 */
+10
View File
@@ -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 */
+1
View File
@@ -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*);
+1 -1
View File
@@ -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
+8 -7
View File
@@ -23,9 +23,9 @@ struct RString {
MRB_OBJECT_HEADER;
union {
struct {
mrb_int len;
mrb_ssize len;
union {
mrb_int capa;
mrb_ssize capa;
struct mrb_shared_string *shared;
struct RString *fshared;
} aux;
@@ -54,7 +54,7 @@ struct RStringEmbed {
RSTR_SET_EMBED_LEN((s),(n));\
}\
else {\
(s)->as.heap.len = (mrb_int)(n);\
(s)->as.heap.len = (mrb_ssize)(n);\
}\
} while (0)
#define RSTR_EMBED_PTR(s) (((struct RStringEmbed*)(s))->ary)
@@ -115,8 +115,8 @@ MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
#define MRB_STR_POOL 16 /* status flags from here */
#define MRB_STR_ASCII 32
#define MRB_STR_EMBED_LEN_SHIFT 6
#define MRB_STR_EMBED_LEN_BITSIZE 5
#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BITSIZE) - 1) << MRB_STR_EMBED_LEN_SHIFT)
#define MRB_STR_EMBED_LEN_BIT 5
#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BIT) - 1) << MRB_STR_EMBED_LEN_SHIFT)
#define MRB_STR_TYPE_MASK (MRB_STR_POOL - 1)
@@ -447,7 +447,7 @@ MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
*/
MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_pool(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_pool(mrb_state *mrb, const char *s, mrb_int len, mrb_bool nofree);
uint32_t mrb_str_hash(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
@@ -465,7 +465,8 @@ mrb_bool mrb_str_beg_len(mrb_int str_len, mrb_int *begp, mrb_int *lenp);
mrb_value mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
#ifdef MRB_UTF8_STRING
mrb_int mrb_utf8_len(const char *str, mrb_int byte_len);
mrb_int mrb_utf8len(const char *str, const char *end);
mrb_int mrb_utf8_strlen(const char *str, mrb_int byte_len);
#endif
MRB_END_DECL
+9 -15
View File
@@ -34,10 +34,6 @@ typedef uint32_t mrb_sym;
typedef uint8_t mrb_bool;
struct mrb_state;
#if defined(MRB_INT16) && defined(MRB_INT64)
# error "You can't define MRB_INT16 and MRB_INT64 at the same time."
#endif
#if defined _MSC_VER && _MSC_VER < 1800
# define PRIo64 "llo"
# define PRId64 "lld"
@@ -63,14 +59,6 @@ struct mrb_state;
# define MRB_PRIo PRIo64
# define MRB_PRId PRId64
# define MRB_PRIx PRIx64
#elif defined(MRB_INT16)
typedef int16_t mrb_int;
# define MRB_INT_BIT 16
# define MRB_INT_MIN (INT16_MIN>>MRB_FIXNUM_SHIFT)
# define MRB_INT_MAX (INT16_MAX>>MRB_FIXNUM_SHIFT)
# define MRB_PRIo PRIo16
# define MRB_PRId PRId16
# define MRB_PRIx PRIx16
#else
typedef int32_t mrb_int;
# define MRB_INT_BIT 32
@@ -169,9 +157,15 @@ typedef void mrb_value;
#include "boxing_no.h"
#endif
#if !defined(MRB_SYMBOL_BITSIZE)
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT)
#define MRB_SYMBOL_MAX UINT32_MAX
#define MRB_SYMBOL_BIT (sizeof(mrb_sym) * CHAR_BIT - MRB_SYMBOL_SHIFT)
#define MRB_SYMBOL_MAX (UINT32_MAX >> MRB_SYMBOL_SHIFT)
#if INTPTR_MAX < MRB_INT_MAX
typedef intptr_t mrb_ssize;
# define MRB_SSIZE_MAX (INTPTR_MAX>>MRB_FIXNUM_SHIFT)
#else
typedef mrb_int mrb_ssize;
# define MRB_SSIZE_MAX MRB_INT_MAX
#endif
#ifndef mrb_immediate_p
+4 -4
View File
@@ -47,7 +47,7 @@ MRB_BEGIN_DECL
/*
* Tiny release version number.
*/
#define MRUBY_RELEASE_TEENY 0
#define MRUBY_RELEASE_TEENY 1
/*
* The mruby version.
@@ -62,17 +62,17 @@ MRB_BEGIN_DECL
/*
* Release year.
*/
#define MRUBY_RELEASE_YEAR 2019
#define MRUBY_RELEASE_YEAR 2020
/*
* Release month.
*/
#define MRUBY_RELEASE_MONTH 10
#define MRUBY_RELEASE_MONTH 6
/*
* Release day.
*/
#define MRUBY_RELEASE_DAY 18
#define MRUBY_RELEASE_DAY 4
/*
* Release date as a string.
+1 -20
View File
@@ -20,27 +20,8 @@ class String
end
end
$pp_show = true
if $verbose.nil?
if Rake.respond_to?(:verbose) && !Rake.verbose.nil?
if Rake.verbose.class == TrueClass
# verbose message logging
$pp_show = false
else
$pp_show = true
Rake.verbose(false)
end
else
# could not identify rake version
$pp_show = false
end
else
$pp_show = false if $verbose
end
def _pp(cmd, src, tgt=nil, options={})
return unless $pp_show
return if Rake.verbose
width = 5
template = options[:indent] ? "%#{width*options[:indent]}s %s %s" : "%-#{width}s %s %s"
+3 -11
View File
@@ -173,7 +173,7 @@ module MRuby
obj = objfile(cxx_src) if obj.nil?
file cxx_src => [src, __FILE__] do |t|
FileUtils.mkdir_p File.dirname t.name
mkdir_p File.dirname t.name
IO.write t.name, <<EOS
#define __STDC_CONSTANT_MACROS
#define __STDC_LIMIT_MACROS
@@ -276,14 +276,6 @@ EOS
end
end
def cygwin_filename(name)
if name.is_a?(Array)
name.flatten.map { |n| cygwin_filename(n) }
else
`cygpath -w "#{filename(name)}"`.strip
end
end
def exefile(name)
if name.is_a?(Array)
name.flatten.map { |n| exefile(n) }
@@ -320,7 +312,7 @@ EOS
end
def verbose_flag
$verbose ? ' -v' : ''
Rake.verbose ? ' -v' : ''
end
def run_test
@@ -386,7 +378,7 @@ EOS
end
def run_test
@test_runner.runner_options << ' -v' if $verbose
@test_runner.runner_options << verbose_flag
mrbtest = exefile("#{build_dir}/bin/mrbtest")
if (@test_runner.command == nil)
puts "You should run #{mrbtest} on target device."
+54 -63
View File
@@ -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
+9 -11
View 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
View File
@@ -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
+9 -1
View File
@@ -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
+2 -621
View File
@@ -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
-31
View File
@@ -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
-19
View File
@@ -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 }
+1 -1
View File
@@ -17,7 +17,7 @@ unless MRuby::Build.current.kind_of?(MRuby::CrossBuild)
}]
tmplt = File.read(tmplt_path)
File.write(t.name, tmplt.gsub(/(#{Regexp.union(*config.keys)})\b/, config))
FileUtils.chmod(0755, t.name)
chmod(0755, t.name)
end
end
end
+19 -17
View File
@@ -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: */
+5 -1
View File
@@ -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>
+8 -4
View File
@@ -1,7 +1,11 @@
#include <stdio.h>
#include <mruby.h>
#ifdef MRB_DISABLE_STDIO
# error mruby-bin-mrbc conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
#endif
#include <stdlib.h>
#include <string.h>
#include <mruby.h>
#include <mruby/compile.h>
#include <mruby/dump.h>
#include <mruby/proc.h>
@@ -183,7 +187,7 @@ partial_hook(struct mrb_parser_state *p)
return -1;
}
fn = args->argv[args->idx++];
p->f = fopen(fn, "r");
p->f = fopen(fn, "rb");
if (p->f == NULL) {
fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn);
return -1;
@@ -210,7 +214,7 @@ load_file(mrb_state *mrb, struct mrbc_args *args)
}
else {
need_close = TRUE;
if ((infile = fopen(input, "r")) == NULL) {
if ((infile = fopen(input, "rb")) == NULL) {
fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, input);
return mrb_nil_value();
}
+21 -4
View File
@@ -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
+131 -70
View File
@@ -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 -1
View File
@@ -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
+17 -2
View File
@@ -599,7 +599,7 @@ new_lit(codegen_scope *s, mrb_value val)
switch (mrb_type(val)) {
case MRB_TT_STRING:
*pv = mrb_str_pool(s->mrb, val);
*pv = mrb_str_pool(s->mrb, RSTRING_PTR(val), RSTRING_LEN(val), RSTR_NOFREE_P(RSTRING(val)));
break;
#ifndef MRB_WITHOUT_FLOAT
@@ -771,7 +771,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */
| ((ra & 0x1) << 6)
| ((pa & 0x1f) << 1)
| (kd & 0x1);
| ((ka | kd) != 0 ? 0x01 : 0x00);
genop_W(s, OP_ENTER, a);
/* generate jump table for optional arguments initializer */
pos = new_label(s);
@@ -1122,6 +1122,10 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
}
}
break;
case NODE_NVAR:
idx = nint(tree);
codegen_error(s, "Can't assign to numbered parameter");
break;
case NODE_IVAR:
idx = new_sym(s, nsym(tree));
genop_2(s, OP_SETIV, sp, idx);
@@ -2340,6 +2344,17 @@ codegen(codegen_scope *s, node *tree, int val)
}
break;
case NODE_NVAR:
if (val) {
int idx = nint(tree);
gen_move(s, cursp(), idx, val);
if (val && on_eval(s)) genop_0(s, OP_NOP);
push();
}
break;
case NODE_GVAR:
{
int sym = new_sym(s, nsym(tree));
+1
View File
@@ -51,6 +51,7 @@ enum node_type {
NODE_IVAR,
NODE_CONST,
NODE_CVAR,
NODE_NVAR,
NODE_NTH_REF,
NODE_BACK_REF,
NODE_MATCH,
+269 -160
View File
@@ -71,23 +71,8 @@ typedef unsigned int stack_type;
#define nint(x) ((node*)(intptr_t)(x))
#define intn(x) ((int)(intptr_t)(x))
#if defined(MRB_COMPLEX_NUMBERS) || defined(MRB_RATIONAL_NUMBERS)
#define MRB_SUFFIX_SUPPORT
#ifdef MRB_RATIONAL_NUMBERS
#define NUM_SUFFIX_R (1<<0)
#else
#define NUM_SUFFIX_R 0
#endif
#ifdef MRB_COMPLEX_NUMBERS
#define NUM_SUFFIX_I (1<<1)
#else
#define NUM_SUFFIX_I 0
#endif
#define NUM_SUFFIX_ALL (NUM_SUFFIX_R | NUM_SUFFIX_I)
#endif
#define NUM_SUFFIX_R (1<<0)
#define NUM_SUFFIX_I (1<<1)
static inline mrb_sym
intern_cstr_gen(parser_state *p, const char *s)
@@ -103,12 +88,7 @@ intern_gen(parser_state *p, const char *s, size_t len)
}
#define intern(s,len) intern_gen(p,(s),(len))
static inline mrb_sym
intern_gen_c(parser_state *p, const char c)
{
return mrb_intern(p->mrb, &c, 1);
}
#define intern_c(c) intern_gen_c(p,(c))
#define intern_lit(s) mrb_intern_lit(p->mrb, s)
static void
cons_free_gen(parser_state *p, node *cons)
@@ -335,6 +315,24 @@ locals_node(parser_state *p)
return p->locals ? p->locals->car : NULL;
}
static void
nvars_nest(parser_state *p)
{
p->nvars = cons(nint(0), p->nvars);
}
static void
nvars_block(parser_state *p)
{
p->nvars = cons(nint(-2), p->nvars);
}
static void
nvars_unnest(parser_state *p)
{
p->nvars = p->nvars->cdr;
}
/* (:scope (vars..) (prog...)) */
static node*
new_scope(parser_state *p, node *body)
@@ -669,6 +667,16 @@ new_cvar(parser_state *p, mrb_sym sym)
return cons((node*)NODE_CVAR, nsym(sym));
}
/* (:nvar . a) */
static node*
new_nvar(parser_state *p, int num)
{
int nvars = intn(p->nvars->car);
p->nvars->car = nint(nvars > num ? nvars : num);
return cons((node*)NODE_NVAR, nint(num));
}
/* (:const . a) */
static node*
new_const(parser_state *p, mrb_sym sym)
@@ -793,15 +801,15 @@ new_args_tail(parser_state *p, node *kws, node *kwrest, mrb_sym blk)
local_add_blk(p, blk);
// allocate register for keywords arguments
// order is for Proc#parameters
/* allocate register for keywords arguments */
/* order is for Proc#parameters */
for (k = kws; k; k = k->cdr) {
if (!k->car->cdr->cdr->car) { // allocate required keywords
if (!k->car->cdr->cdr->car) { /* allocate required keywords */
local_add_f(p, sym(k->car->cdr->car));
}
}
for (k = kws; k; k = k->cdr) {
if (k->car->cdr->cdr->car) { // allocate keywords with default
if (k->car->cdr->cdr->car) { /* allocate keywords with default */
local_add_lv(p, k->car->cdr->cdr->car->cdr);
k->car->cdr->cdr->car = k->car->cdr->cdr->car->car;
local_add_f(p, sym(k->car->cdr->car));
@@ -826,10 +834,41 @@ new_block_arg(parser_state *p, node *a)
return cons((node*)NODE_BLOCK_ARG, a);
}
static node*
setup_numparams(parser_state *p, node *a)
{
int nvars = intn(p->nvars->car);
if (nvars > 0) {
int i;
mrb_sym sym;
// m || opt || rest || tail
if (a && (a->car || (a->cdr && a->cdr->car) || (a->cdr->cdr && a->cdr->cdr->car) || (a->cdr->cdr->cdr->cdr && a->cdr->cdr->cdr->cdr->car))) {
yyerror(p, "ordinary parameter is defined");
}
else if (p->locals) {
/* p->locals should not be NULL unless error happens before the point */
node* args = 0;
for (i = nvars; i > 0; i--) {
char buf[3];
buf[0] = '_';
buf[1] = i+'0';
buf[2] = '\0';
sym = intern_cstr(buf);
args = cons(new_arg(p, sym), args);
p->locals->car = cons(nsym(sym), p->locals->car);
}
a = new_args(p, args, 0, 0, 0, 0);
}
}
return a;
}
/* (:block arg body) */
static node*
new_block(parser_state *p, node *a, node *b)
{
a = setup_numparams(p, a);
return list4((node*)NODE_BLOCK, locals_node(p), a, b);
}
@@ -871,37 +910,29 @@ new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
return list4((node*)NODE_OP_ASGN, a, nsym(op), b);
}
#ifdef MRB_COMPLEX_NUMBERS
static node*
new_imaginary(parser_state *p, node *imaginary)
{
return new_call(p, new_const(p, intern_cstr("Kernel")), intern_cstr("Complex"), list1(list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary)), 1);
return new_call(p, new_const(p, intern_lit("Kernel")), intern_lit("Complex"), list1(list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary)), 1);
}
#endif
#ifdef MRB_RATIONAL_NUMBERS
static node*
new_rational(parser_state *p, node *rational)
{
return new_call(p, new_const(p, intern_cstr("Kernel")), intern_cstr("Rational"), list1(list1(rational)), 1);
return new_call(p, new_const(p, intern_lit("Kernel")), intern_lit("Rational"), list1(list1(rational)), 1);
}
#endif
/* (:int . i) */
static node*
new_int(parser_state *p, const char *s, int base, int suffix)
{
node* result = list3((node*)NODE_INT, (node*)strdup(s), nint(base));
#ifdef MRB_RATIONAL_NUMBERS
if (suffix & NUM_SUFFIX_R) {
result = new_rational(p, result);
}
#endif
#ifdef MRB_COMPLEX_NUMBERS
if (suffix & NUM_SUFFIX_I) {
result = new_imaginary(p, result);
}
#endif
return result;
}
@@ -911,16 +942,12 @@ static node*
new_float(parser_state *p, const char *s, int suffix)
{
node* result = cons((node*)NODE_FLOAT, (node*)strdup(s));
#ifdef MRB_RATIONAL_NUMBERS
if (suffix & NUM_SUFFIX_R) {
result = new_rational(p, result);
}
#endif
#ifdef MRB_COMPLEX_NUMBERS
if (suffix & NUM_SUFFIX_I) {
result = new_imaginary(p, result);
}
#endif
return result;
}
#endif
@@ -1281,7 +1308,6 @@ heredoc_end(parser_state *p)
p->parsing_heredoc = p->parsing_heredoc->cdr;
if (p->parsing_heredoc == NULL) {
p->lstate = EXPR_BEG;
p->cmd_start = TRUE;
end_strterm(p);
p->lex_strterm = p->lex_strterm_before_heredoc;
p->lex_strterm_before_heredoc = NULL;
@@ -1366,6 +1392,7 @@ heredoc_end(parser_state *p)
%token <nd> tSTRING tSTRING_PART tSTRING_MID
%token <nd> tNTH_REF tBACK_REF
%token <num> tREGEXP_END
%token <num> tNUMPARAM
%type <nd> singleton string string_fragment string_rep string_interp xstring regexp
%type <nd> literal numeric cpath symbol
@@ -1498,11 +1525,13 @@ top_stmt : stmt
| keyword_BEGIN
{
$<nd>$ = local_switch(p);
nvars_block(p);
}
'{' top_compstmt '}'
{
yyerror(p, "BEGIN not supported");
local_resume(p, $<nd>2);
nvars_unnest(p);
$$ = 0;
}
;
@@ -1620,9 +1649,9 @@ command_asgn : lhs '=' command_rhs
{
$$ = new_op_asgn(p, $1, $2, $3);
}
| primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs
| primary_value '[' opt_call_args ']' tOP_ASGN command_rhs
{
$$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3, '.'), $5, $6);
$$ = new_op_asgn(p, new_call(p, $1, intern_lit("[]"), $3, '.'), $5, $6);
}
| primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
{
@@ -1700,6 +1729,7 @@ block_command : block_call
cmd_brace_block : tLBRACE_ARG
{
local_nest(p);
nvars_nest(p);
}
opt_block_param
compstmt
@@ -1707,6 +1737,7 @@ cmd_brace_block : tLBRACE_ARG
{
$$ = new_block(p, $3, $4);
local_unnest(p);
nvars_unnest(p);
}
;
@@ -1849,9 +1880,9 @@ mlhs_node : variable
{
assignable(p, $1);
}
| primary_value '[' opt_call_args rbracket
| primary_value '[' opt_call_args ']'
{
$$ = new_call(p, $1, intern("[]",2), $3, '.');
$$ = new_call(p, $1, intern_lit("[]"), $3, '.');
}
| primary_value call_op tIDENTIFIER
{
@@ -1888,9 +1919,9 @@ lhs : variable
{
assignable(p, $1);
}
| primary_value '[' opt_call_args rbracket
| primary_value '[' opt_call_args ']'
{
$$ = new_call(p, $1, intern("[]",2), $3, '.');
$$ = new_call(p, $1, intern_lit("[]"), $3, '.');
}
| primary_value call_op tIDENTIFIER
{
@@ -1921,6 +1952,10 @@ lhs : variable
backref_error(p, $1);
$$ = 0;
}
| tNUMPARAM
{
yyerror(p, "can't assign to numbered parameter");
}
;
cname : tIDENTIFIER
@@ -1974,36 +2009,36 @@ undef_list : fsym
}
;
op : '|' { $$ = intern_c('|'); }
| '^' { $$ = intern_c('^'); }
| '&' { $$ = intern_c('&'); }
| tCMP { $$ = intern("<=>",3); }
| tEQ { $$ = intern("==",2); }
| tEQQ { $$ = intern("===",3); }
| tMATCH { $$ = intern("=~",2); }
| tNMATCH { $$ = intern("!~",2); }
| '>' { $$ = intern_c('>'); }
| tGEQ { $$ = intern(">=",2); }
| '<' { $$ = intern_c('<'); }
| tLEQ { $$ = intern("<=",2); }
| tNEQ { $$ = intern("!=",2); }
| tLSHFT { $$ = intern("<<",2); }
| tRSHFT { $$ = intern(">>",2); }
| '+' { $$ = intern_c('+'); }
| '-' { $$ = intern_c('-'); }
| '*' { $$ = intern_c('*'); }
| tSTAR { $$ = intern_c('*'); }
| '/' { $$ = intern_c('/'); }
| '%' { $$ = intern_c('%'); }
| tPOW { $$ = intern("**",2); }
| tDSTAR { $$ = intern("**",2); }
| '!' { $$ = intern_c('!'); }
| '~' { $$ = intern_c('~'); }
| tUPLUS { $$ = intern("+@",2); }
| tUMINUS { $$ = intern("-@",2); }
| tAREF { $$ = intern("[]",2); }
| tASET { $$ = intern("[]=",3); }
| '`' { $$ = intern_c('`'); }
op : '|' { $$ = intern_lit("|"); }
| '^' { $$ = intern_lit("^"); }
| '&' { $$ = intern_lit("&"); }
| tCMP { $$ = intern_lit("<=>"); }
| tEQ { $$ = intern_lit("=="); }
| tEQQ { $$ = intern_lit("==="); }
| tMATCH { $$ = intern_lit("=~"); }
| tNMATCH { $$ = intern_lit("!~"); }
| '>' { $$ = intern_lit(">"); }
| tGEQ { $$ = intern_lit(">="); }
| '<' { $$ = intern_lit("<"); }
| tLEQ { $$ = intern_lit("<="); }
| tNEQ { $$ = intern_lit("!="); }
| tLSHFT { $$ = intern_lit("<<"); }
| tRSHFT { $$ = intern_lit(">>"); }
| '+' { $$ = intern_lit("+"); }
| '-' { $$ = intern_lit("-"); }
| '*' { $$ = intern_lit("*"); }
| tSTAR { $$ = intern_lit("*"); }
| '/' { $$ = intern_lit("/"); }
| '%' { $$ = intern_lit("%"); }
| tPOW { $$ = intern_lit("**"); }
| tDSTAR { $$ = intern_lit("**"); }
| '!' { $$ = intern_lit("!"); }
| '~' { $$ = intern_lit("~"); }
| tUPLUS { $$ = intern_lit("+@"); }
| tUMINUS { $$ = intern_lit("-@"); }
| tAREF { $$ = intern_lit("[]"); }
| tASET { $$ = intern_lit("[]="); }
| '`' { $$ = intern_lit("`"); }
;
reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
@@ -2028,9 +2063,9 @@ arg : lhs '=' arg_rhs
{
$$ = new_op_asgn(p, $1, $2, $3);
}
| primary_value '[' opt_call_args rbracket tOP_ASGN arg_rhs
| primary_value '[' opt_call_args ']' tOP_ASGN arg_rhs
{
$$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3, '.'), $5, $6);
$$ = new_op_asgn(p, new_call(p, $1, intern_lit("[]"), $3, '.'), $5, $6);
}
| primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
{
@@ -2226,7 +2261,7 @@ arg_rhs : arg %prec tOP_ASGN
}
;
paren_args : '(' opt_call_args rparen
paren_args : '(' opt_call_args ')'
{
$$ = $2;
}
@@ -2237,18 +2272,18 @@ opt_paren_args : none
;
opt_call_args : none
| call_args
| args ','
| call_args opt_terms
| args comma
{
$$ = cons($1,0);
NODE_LINENO($$, $1);
}
| args comma assocs ','
| args comma assocs comma
{
$$ = cons(push($1, new_kw_hash(p, $3)), 0);
NODE_LINENO($$, $1);
}
| assocs ','
| assocs comma
{
$$ = cons(list1(new_kw_hash(p, $1)), 0);
NODE_LINENO($$, $1);
@@ -2311,7 +2346,7 @@ opt_block_arg : comma block_arg
;
comma : ','
| ',' heredoc_bodies
| ',' opt_nl heredoc_bodies
;
args : arg
@@ -2362,6 +2397,10 @@ primary : literal
| heredoc
| var_ref
| backref
| tNUMPARAM
{
$$ = new_nvar(p, $1);
}
| tFID
{
$$ = new_fcall(p, $1, 0);
@@ -2514,6 +2553,7 @@ primary : literal
if (p->in_def || p->in_single)
yyerror(p, "class definition in method body");
$<nd>$ = local_switch(p);
nvars_block(p);
}
bodystmt
keyword_end
@@ -2521,6 +2561,7 @@ primary : literal
$$ = new_class(p, $2, $3, $5);
SET_LINENO($$, $1);
local_resume(p, $<nd>4);
nvars_unnest(p);
}
| keyword_class
tLSHFT expr
@@ -2531,6 +2572,7 @@ primary : literal
term
{
$<nd>$ = cons(local_switch(p), nint(p->in_single));
nvars_block(p);
p->in_single = 0;
}
bodystmt
@@ -2539,6 +2581,7 @@ primary : literal
$$ = new_sclass(p, $3, $7);
SET_LINENO($$, $1);
local_resume(p, $<nd>6->car);
nvars_unnest(p);
p->in_def = $<num>4;
p->in_single = intn($<nd>6->cdr);
}
@@ -2548,6 +2591,7 @@ primary : literal
if (p->in_def || p->in_single)
yyerror(p, "module definition in method body");
$<nd>$ = local_switch(p);
nvars_block(p);
}
bodystmt
keyword_end
@@ -2555,6 +2599,7 @@ primary : literal
$$ = new_module(p, $2, $4);
SET_LINENO($$, $1);
local_resume(p, $<nd>3);
nvars_unnest(p);
}
| keyword_def fname
{
@@ -2564,6 +2609,7 @@ primary : literal
{
p->in_def++;
$<nd>$ = local_switch(p);
nvars_block(p);
}
f_arglist
bodystmt
@@ -2572,6 +2618,7 @@ primary : literal
$$ = new_def(p, $2, $5, $6);
SET_LINENO($$, $1);
local_resume(p, $<nd>4);
nvars_unnest(p);
p->in_def--;
p->cmdarg_stack = $<stack>3;
}
@@ -2586,6 +2633,7 @@ primary : literal
p->in_single++;
p->lstate = EXPR_ENDFN; /* force for args */
$<nd>$ = local_switch(p);
nvars_block(p);
}
f_arglist
bodystmt
@@ -2594,6 +2642,7 @@ primary : literal
$$ = new_sdef(p, $2, $5, $7, $8);
SET_LINENO($$, $1);
local_resume(p, $<nd>6);
nvars_unnest(p);
p->in_single--;
p->cmdarg_stack = $<stack>4;
}
@@ -2861,6 +2910,7 @@ lambda_body : tLAMBEG compstmt '}'
do_block : keyword_do_block
{
local_nest(p);
nvars_nest(p);
}
opt_block_param
bodystmt
@@ -2868,6 +2918,7 @@ do_block : keyword_do_block
{
$$ = new_block(p,$3,$4);
local_unnest(p);
nvars_unnest(p);
}
;
@@ -2915,11 +2966,11 @@ method_call : operation paren_args
}
| primary_value call_op paren_args
{
$$ = new_call(p, $1, intern("call",4), $3, $2);
$$ = new_call(p, $1, intern_lit("call"), $3, $2);
}
| primary_value tCOLON2 paren_args
{
$$ = new_call(p, $1, intern("call",4), $3, tCOLON2);
$$ = new_call(p, $1, intern_lit("call"), $3, tCOLON2);
}
| keyword_super paren_args
{
@@ -2929,15 +2980,16 @@ method_call : operation paren_args
{
$$ = new_zsuper(p);
}
| primary_value '[' opt_call_args rbracket
| primary_value '[' opt_call_args ']'
{
$$ = new_call(p, $1, intern("[]",2), $3, '.');
$$ = new_call(p, $1, intern_lit("[]"), $3, '.');
}
;
brace_block : '{'
{
local_nest(p);
nvars_nest(p);
$<num>$ = p->lineno;
}
opt_block_param
@@ -2946,10 +2998,12 @@ brace_block : '{'
$$ = new_block(p,$3,$4);
SET_LINENO($$, $<num>2);
local_unnest(p);
nvars_unnest(p);
}
| keyword_do
{
local_nest(p);
nvars_nest(p);
$<num>$ = p->lineno;
}
opt_block_param
@@ -2958,6 +3012,7 @@ brace_block : '{'
$$ = new_block(p,$3,$4);
SET_LINENO($$, $<num>2);
local_unnest(p);
nvars_unnest(p);
}
;
@@ -3224,6 +3279,10 @@ var_lhs : variable
{
assignable(p, $1);
}
| tNUMPARAM
{
yyerror(p, "can't assign to numbered parameter");
}
;
var_ref : variable
@@ -3329,11 +3388,13 @@ f_kw : f_label arg
f_block_kw : f_label primary_value
{
$$ = new_kw_arg(p, $1, $2);
$$ = new_kw_arg(p, $1, cons($2, locals_node(p)));
local_unnest(p);
}
| f_label
{
$$ = new_kw_arg(p, $1, 0);
local_unnest(p);
}
;
@@ -3482,6 +3543,11 @@ f_bad_arg : tCONSTANT
yyerror(p, "formal argument cannot be a class variable");
$$ = 0;
}
| tNUMPARAM
{
yyerror(p, "formal argument cannot be a numbered parameter");
$$ = 0;
}
;
f_norm_arg : f_bad_arg
@@ -3643,24 +3709,28 @@ assocs : assoc
$$ = list1($1);
NODE_LINENO($$, $1);
}
| assocs ',' assoc
| assocs comma assoc
{
$$ = push($1, $3);
}
;
label_tag : tLABEL_TAG
| tLABEL_TAG heredoc_bodies
;
assoc : arg tASSOC arg
{
void_expr_error(p, $1);
void_expr_error(p, $3);
$$ = cons($1, $3);
}
| tIDENTIFIER tLABEL_TAG arg
| tIDENTIFIER label_tag arg
{
void_expr_error(p, $3);
$$ = cons(new_sym(p, $1), $3);
}
| string_fragment tLABEL_TAG arg
| string_fragment label_tag arg
{
void_expr_error(p, $3);
if ($1->car == (node*)NODE_DSTR) {
@@ -3722,14 +3792,11 @@ opt_nl : /* none */
| nl
;
rparen : opt_nl ')'
;
rbracket : opt_nl ']'
rparen : opt_terms ')'
;
trailer : /* none */
| nl
| terms
| comma
;
@@ -3899,6 +3966,27 @@ static void pushback(parser_state *p, int c);
static mrb_bool peeks(parser_state *p, const char *s);
static mrb_bool skips(parser_state *p, const char *s);
static inline int
nextc0(parser_state *p)
{
int c;
#ifndef MRB_DISABLE_STDIO
if (p->f) {
if (feof(p->f)) return -1;
c = fgetc(p->f);
if (c == EOF) return -1;
}
else
#endif
if (!p->s || p->s >= p->send) {
return -1;
}
else {
c = (unsigned char)*p->s++;
}
return c;
}
static inline int
nextc(parser_state *p)
{
@@ -3913,24 +4001,19 @@ nextc(parser_state *p)
cons_free(tmp);
}
else {
#ifndef MRB_DISABLE_STDIO
if (p->f) {
if (feof(p->f)) goto eof;
c = fgetc(p->f);
if (c == EOF) goto eof;
}
else
#endif
if (!p->s || p->s >= p->send) {
goto eof;
}
else {
c = (unsigned char)*p->s++;
}
c = nextc0(p);
if (c < 0) goto eof;
}
if (c >= 0) {
p->column++;
}
if (c == '\r') {
const int lf = nextc0(p);
if (lf == '\n') {
return '\n';
}
if (lf > 0) pushback(p, lf);
}
return c;
eof:
@@ -4387,12 +4470,7 @@ parse_string(parser_state *p)
}
}
if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
if (c < 0) {
p->parsing_heredoc = NULL;
}
else {
return tHEREDOC_END;
}
return tHEREDOC_END;
}
}
if (c < 0) {
@@ -4596,13 +4674,13 @@ parse_string(parser_state *p)
return tSTRING;
}
#ifdef MRB_SUFFIX_SUPPORT
static int
number_literal_suffix(parser_state *p, int mask)
number_literal_suffix(parser_state *p)
{
int c, result = 0;
node *list = 0;
int column = p->column;
int mask = NUM_SUFFIX_R|NUM_SUFFIX_I;
while ((c = nextc(p)) != -1) {
list = push(list, (node*)(intptr_t)c);
@@ -4634,7 +4712,6 @@ number_literal_suffix(parser_state *p, int mask)
}
return result;
}
#endif
static int
heredoc_identifier(parser_state *p)
@@ -4819,7 +4896,7 @@ parser_yylex(parser_state *p)
case '*':
if ((c = nextc(p)) == '*') {
if ((c = nextc(p)) == '=') {
pylval.id = intern("**",2);
pylval.id = intern_lit("**");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -4837,7 +4914,7 @@ parser_yylex(parser_state *p)
}
else {
if (c == '=') {
pylval.id = intern_c('*');
pylval.id = intern_lit("*");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -4953,7 +5030,7 @@ parser_yylex(parser_state *p)
}
if (c == '<') {
if ((c = nextc(p)) == '=') {
pylval.id = intern("<<",2);
pylval.id = intern_lit("<<");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -4975,7 +5052,7 @@ parser_yylex(parser_state *p)
}
if (c == '>') {
if ((c = nextc(p)) == '=') {
pylval.id = intern(">>",2);
pylval.id = intern_lit(">>");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -5083,7 +5160,7 @@ parser_yylex(parser_state *p)
if ((c = nextc(p)) == '&') {
p->lstate = EXPR_BEG;
if ((c = nextc(p)) == '=') {
pylval.id = intern("&&",2);
pylval.id = intern_lit("&&");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -5095,7 +5172,7 @@ parser_yylex(parser_state *p)
return tANDDOT;
}
else if (c == '=') {
pylval.id = intern_c('&');
pylval.id = intern_lit("&");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -5122,7 +5199,7 @@ parser_yylex(parser_state *p)
if ((c = nextc(p)) == '|') {
p->lstate = EXPR_BEG;
if ((c = nextc(p)) == '=') {
pylval.id = intern("||",2);
pylval.id = intern_lit("||");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -5130,7 +5207,7 @@ parser_yylex(parser_state *p)
return tOROP;
}
if (c == '=') {
pylval.id = intern_c('|');
pylval.id = intern_lit("|");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -5154,7 +5231,7 @@ parser_yylex(parser_state *p)
return '+';
}
if (c == '=') {
pylval.id = intern_c('+');
pylval.id = intern_lit("+");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -5182,7 +5259,7 @@ parser_yylex(parser_state *p)
return '-';
}
if (c == '=') {
pylval.id = intern_c('-');
pylval.id = intern_lit("-");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -5257,9 +5334,7 @@ parser_yylex(parser_state *p)
no_digits();
}
else if (nondigit) goto trailing_uc;
#ifdef MRB_SUFFIX_SUPPORT
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
#endif
suffix = number_literal_suffix(p);
pylval.nd = new_int(p, tok(p), 16, suffix);
return tINTEGER;
}
@@ -5284,9 +5359,7 @@ parser_yylex(parser_state *p)
no_digits();
}
else if (nondigit) goto trailing_uc;
#ifdef MRB_SUFFIX_SUPPORT
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
#endif
suffix = number_literal_suffix(p);
pylval.nd = new_int(p, tok(p), 2, suffix);
return tINTEGER;
}
@@ -5311,9 +5384,7 @@ parser_yylex(parser_state *p)
no_digits();
}
else if (nondigit) goto trailing_uc;
#ifdef MRB_SUFFIX_SUPPORT
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
#endif
suffix = number_literal_suffix(p);
pylval.nd = new_int(p, tok(p), 10, suffix);
return tINTEGER;
}
@@ -5347,9 +5418,7 @@ parser_yylex(parser_state *p)
pushback(p, c);
tokfix(p);
if (nondigit) goto trailing_uc;
#ifdef MRB_SUFFIX_SUPPORT
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
#endif
suffix = number_literal_suffix(p);
pylval.nd = new_int(p, tok(p), 8, suffix);
return tINTEGER;
}
@@ -5367,9 +5436,7 @@ parser_yylex(parser_state *p)
}
else {
pushback(p, c);
#ifdef MRB_SUFFIX_SUPPORT
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
#endif
suffix = number_literal_suffix(p);
pylval.nd = new_int(p, "0", 10, suffix);
return tINTEGER;
}
@@ -5459,16 +5526,12 @@ parser_yylex(parser_state *p)
yywarning_s(p, "float out of range", tok(p));
errno = 0;
}
#ifdef MRB_SUFFIX_SUPPORT
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
#endif
suffix = number_literal_suffix(p);
pylval.nd = new_float(p, tok(p), suffix);
return tFLOAT;
#endif
}
#ifdef MRB_SUFFIX_SUPPORT
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
#endif
suffix = number_literal_suffix(p);
pylval.nd = new_int(p, tok(p), 10, suffix);
return tINTEGER;
}
@@ -5516,7 +5579,7 @@ parser_yylex(parser_state *p)
return tREGEXP_BEG;
}
if ((c = nextc(p)) == '=') {
pylval.id = intern_c('/');
pylval.id = intern_lit("/");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -5535,7 +5598,7 @@ parser_yylex(parser_state *p)
case '^':
if ((c = nextc(p)) == '=') {
pylval.id = intern_c('^');
pylval.id = intern_lit("^");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -5712,7 +5775,7 @@ parser_yylex(parser_state *p)
}
}
if ((c = nextc(p)) == '=') {
pylval.id = intern_c('%');
pylval.id = intern_lit("%");
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -5766,7 +5829,7 @@ parser_yylex(parser_state *p)
tokadd(p, '$');
tokadd(p, c);
tokfix(p);
pylval.id = intern_cstr(tok(p));
pylval.id = intern(tok(p), toklen(p));
return tGVAR;
case '-':
@@ -5776,7 +5839,7 @@ parser_yylex(parser_state *p)
pushback(p, c);
gvar:
tokfix(p);
pylval.id = intern_cstr(tok(p));
pylval.id = intern(tok(p), toklen(p));
return tGVAR;
case '&': /* $&: last match */
@@ -5914,6 +5977,39 @@ parser_yylex(parser_state *p)
result = tIVAR;
break;
case '_':
if (toklen(p) == 2 && ISDIGIT(tok(p)[1]) && p->nvars) {
int n = tok(p)[1] - '0';
int nvar;
if (n > 0) {
node *nvars = p->nvars->cdr;
while (nvars) {
nvar = intn(nvars->car);
if (nvar == -2) break; /* top of the scope */
if (nvar > 0) {
yywarning(p, "numbered parameter used in outer block");
break;
}
nvars->car = nint(-1);
nvars = nvars->cdr;
}
nvar = intn(p->nvars->car);
if (nvar == -1) {
yywarning(p, "numbered parameter used in inner block");
}
if (nvar >= -1) {
pylval.num = n;
p->lstate = EXPR_END;
return tNUMPARAM;
}
else {
yywarning(p, "identifier for numbered parameter; consider another name");
}
}
}
/* fall through */
default:
if (toklast(p) == '!' || toklast(p) == '?') {
result = tFID;
@@ -5929,6 +6025,15 @@ parser_yylex(parser_state *p)
else {
pushback(p, c);
}
if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') &&
(!peek(p, '=') || (peek_n(p, '>', 1)))) {
result = tIDENTIFIER;
tokadd(p, c);
tokfix(p);
}
else {
pushback(p, c);
}
}
if (result == 0 && ISUPPER(tok(p)[0])) {
result = tCONSTANT;
@@ -5942,7 +6047,7 @@ parser_yylex(parser_state *p)
if (IS_LABEL_SUFFIX(0)) {
p->lstate = EXPR_END;
tokfix(p);
pylval.id = intern_cstr(tok(p));
pylval.id = intern(tok(p), toklen(p));
return tIDENTIFIER;
}
}
@@ -6001,7 +6106,7 @@ parser_yylex(parser_state *p)
}
}
{
mrb_sym ident = intern_cstr(tok(p));
mrb_sym ident = intern(tok(p), toklen(p));
pylval.id = ident;
if (last_state != EXPR_DOT && ISLOWER(tok(p)[0]) && local_var_p(p, ident)) {
@@ -6896,6 +7001,10 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
printf("NODE_CVAR %s\n", mrb_sym_name(mrb, sym(tree)));
break;
case NODE_NVAR:
printf("NODE_NVAR %d\n", intn(tree));
break;
case NODE_CONST:
printf("NODE_CONST %s\n", mrb_sym_name(mrb, sym(tree)));
break;
+1 -1
View File
@@ -26,7 +26,7 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
# Parser
file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y", lex_def] do |t|
FileUtils.mkdir_p File.dirname t.name
mkdir_p File.dirname t.name
yacc.run t.name, t.prerequisites.first
end
-3
View File
@@ -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
+5 -5
View File
@@ -8,7 +8,7 @@ class Complex < Numeric
end
def to_s
"#{real}#{'+' unless imaginary.negative?}#{imaginary}i"
"#{real}#{'+' unless imaginary < 0}#{imaginary}i"
end
def +@
@@ -56,7 +56,7 @@ class Complex < Numeric
if rhs.is_a? Complex
real == rhs.real && imaginary == rhs.imaginary
elsif rhs.is_a? Numeric
imaginary.zero? && real == rhs
imaginary == 0 && real == rhs
end
end
@@ -106,14 +106,14 @@ class Complex < Numeric
[Fixnum, Float].each do |cls|
[:+, :-, :*, :/, :==].each do |op|
cls.instance_exec do
cls.instance_eval do
original_operator_name = "__original_operator_#{op}_complex"
alias_method original_operator_name, op
define_method op do |rhs|
if rhs.is_a? Complex
Complex(self).send(op, rhs)
Complex(self).__send__(op, rhs)
else
send(original_operator_name, rhs)
__send__(original_operator_name, rhs)
end
end
end
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -110,8 +110,8 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
insn = iseq[i];
switch(insn){
case OP_EPUSH:
b = PEEK_S(iseq+i+1);
patch_irep(mrb, irep->reps[b], bnest + 1, top);
a = PEEK_B(iseq+i+1);
patch_irep(mrb, irep->reps[a], bnest + 1, top);
break;
case OP_LAMBDA:
@@ -390,7 +390,7 @@ void
mrb_mruby_eval_gem_init(mrb_state* mrb)
{
mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3));
mrb_define_method(mrb, mrb_class_get(mrb, "BasicObject"), "instance_eval", f_instance_eval, MRB_ARGS_ARG(1, 2));
mrb_define_method(mrb, mrb_class_get(mrb, "BasicObject"), "instance_eval", f_instance_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
}
void
+9 -4
View File
@@ -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
+1 -1
View File
@@ -409,7 +409,7 @@ mrb_mruby_fiber_gem_init(mrb_state* mrb)
c = mrb_define_class(mrb, "Fiber", mrb->object_class);
MRB_SET_INSTANCE_TT(c, MRB_TT_FIBER);
mrb_define_method(mrb, c, "initialize", fiber_init, MRB_ARGS_NONE());
mrb_define_method(mrb, c, "initialize", fiber_init, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
mrb_define_method(mrb, c, "resume", fiber_resume, MRB_ARGS_ANY());
mrb_define_method(mrb, c, "transfer", fiber_transfer, MRB_ARGS_ANY());
mrb_define_method(mrb, c, "alive?", fiber_alive_p, MRB_ARGS_NONE());
-2
View File
@@ -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
+1 -3
View File
@@ -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;
+3 -7
View File
@@ -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
+1
View File
@@ -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"),
+40 -8
View File
@@ -5,10 +5,24 @@
#ifndef MRUBY_IO_H
#define MRUBY_IO_H
#include <mruby.h>
#ifdef MRB_DISABLE_STDIO
# error IO and File conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
#endif
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(MRB_WITHOUT_IO_PREAD_PWRITE)
# undef MRB_WITH_IO_PREAD_PWRITE
#elif !defined(MRB_WITH_IO_PREAD_PWRITE)
# if defined(__unix__)
# define MRB_WITH_IO_PREAD_PWRITE
# endif
#endif
struct mrb_io {
int fd; /* file descriptor, or -1 */
int fd2; /* file descriptor to write if it's different from fd, or -1 */
@@ -19,18 +33,36 @@ struct mrb_io {
is_socket:1;
};
#define FMODE_READABLE 0x00000001
#define FMODE_WRITABLE 0x00000002
#define FMODE_READWRITE (FMODE_READABLE|FMODE_WRITABLE)
#define FMODE_BINMODE 0x00000004
#define FMODE_APPEND 0x00000040
#define FMODE_CREATE 0x00000080
#define FMODE_TRUNC 0x00000800
#define MRB_O_RDONLY 0x0000
#define MRB_O_WRONLY 0x0001
#define MRB_O_RDWR 0x0002
#define MRB_O_ACCMODE (MRB_O_RDONLY | MRB_O_WRONLY | MRB_O_RDWR)
#define MRB_O_NONBLOCK 0x0004
#define MRB_O_APPEND 0x0008
#define MRB_O_SYNC 0x0010
#define MRB_O_NOFOLLOW 0x0020
#define MRB_O_CREAT 0x0040
#define MRB_O_TRUNC 0x0080
#define MRB_O_EXCL 0x0100
#define MRB_O_NOCTTY 0x0200
#define MRB_O_DIRECT 0x0400
#define MRB_O_BINARY 0x0800
#define MRB_O_SHARE_DELETE 0x1000
#define MRB_O_TMPFILE 0x2000
#define MRB_O_NOATIME 0x4000
#define MRB_O_DSYNC 0x00008000 /* Ignored with MRB_INT16 and MRB_WITHOUT_FLOAT */
#define MRB_O_RSYNC 0x00010000 /* Ignored with MRB_INT16 and MRB_WITHOUT_FLOAT */
#define MRB_O_RDONLY_P(f) ((mrb_bool)(((f) & MRB_O_ACCMODE) == MRB_O_RDONLY))
#define MRB_O_WRONLY_P(f) ((mrb_bool)(((f) & MRB_O_ACCMODE) == MRB_O_WRONLY))
#define MRB_O_RDWR_P(f) ((mrb_bool)(((f) & MRB_O_ACCMODE) == MRB_O_RDWR))
#define MRB_O_READABLE_P(f) ((mrb_bool)((((f) & MRB_O_ACCMODE) | 2) == 2))
#define MRB_O_WRITABLE_P(f) ((mrb_bool)(((((f) & MRB_O_ACCMODE) + 1) & 2) == 2))
#define E_IO_ERROR (mrb_class_get(mrb, "IOError"))
#define E_EOF_ERROR (mrb_class_get(mrb, "EOFError"))
mrb_value mrb_io_fileno(mrb_state *mrb, mrb_value io);
int mrb_io_fileno(mrb_state *mrb, mrb_value io);
#if defined(__cplusplus)
} /* extern "C" { */
+3 -9
View File
@@ -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
+35 -35
View File
@@ -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] == ":"
-16
View File
@@ -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
+7 -12
View File
@@ -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
-4
View File
@@ -28,8 +28,4 @@ module Kernel
def gets(*args)
$stdin.gets(*args)
end
def getc(*args)
$stdin.getc(*args)
end
end
+171 -11
View File
@@ -7,12 +7,7 @@
#include "mruby/data.h"
#include "mruby/string.h"
#include "mruby/ext/io.h"
#if MRUBY_RELEASE_NO < 10000
#include "error.h"
#else
#include "mruby/error.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
@@ -53,6 +48,7 @@
#if defined(_WIN32) || defined(_WIN64)
#define PATH_SEPARATOR ";"
#define FILE_ALT_SEPARATOR "\\"
#define VOLUME_SEPARATOR ":"
#else
#define PATH_SEPARATOR ":"
#endif
@@ -70,7 +66,15 @@
#define LOCK_UN 8
#endif
#define STAT(p, s) stat(p, s)
#ifndef _WIN32
typedef struct stat mrb_stat;
# define mrb_stat(path, sb) stat(path, sb)
# define mrb_fstat(fd, sb) fstat(fd, sb)
#else
typedef struct __stat64 mrb_stat;
# define mrb_stat(path, sb) _stat64(path, sb)
# define mrb_fstat(fd, sb) _fstat64(fd, sb)
#endif
#ifdef _WIN32
static int
@@ -276,12 +280,59 @@ mrb_file__getwd(mrb_state *mrb, mrb_value klass)
return path;
}
#ifdef _WIN32
#define IS_FILESEP(x) (x == (*(char*)(FILE_SEPARATOR)) || x == (*(char*)(FILE_ALT_SEPARATOR)))
#define IS_VOLSEP(x) (x == (*(char*)(VOLUME_SEPARATOR)))
#define IS_DEVICEID(x) (x == '.' || x == '?')
#define CHECK_UNCDEV_PATH (IS_FILESEP(path[0]) && IS_FILESEP(path[1]))
static int
is_absolute_traditional_path(const char *path, size_t len)
{
if (len < 3) return 0;
return (ISALPHA(path[0]) && IS_VOLSEP(path[1]) && IS_FILESEP(path[2]));
}
static int
is_aboslute_unc_path(const char *path, size_t len) {
if (len < 2) return 0;
return (CHECK_UNCDEV_PATH && !IS_DEVICEID(path[2]));
}
static int
is_absolute_device_path(const char *path, size_t len) {
if (len < 4) return 0;
return (CHECK_UNCDEV_PATH && IS_DEVICEID(path[2]) && IS_FILESEP(path[3]));
}
static int
mrb_file_is_absolute_path(const char *path)
{
return (path[0] == '/');
size_t len = strlen(path);
if (IS_FILESEP(path[0])) return 1;
if (len > 0)
return (
is_absolute_traditional_path(path, len) ||
is_aboslute_unc_path(path, len) ||
is_absolute_device_path(path, len)
);
else
return 0;
}
#undef IS_FILESEP
#undef IS_VOLSEP
#undef IS_DEVICEID
#undef CHECK_UNCDEV_PATH
#else
static int
mrb_file_is_absolute_path(const char *path)
{
return (path[0] == *(char*)(FILE_SEPARATOR));
}
#endif
static mrb_value
mrb_file__gethome(mrb_state *mrb, mrb_value klass)
{
@@ -316,7 +367,7 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass)
path = mrb_str_new_cstr(mrb, home);
mrb_locale_free(home);
return path;
#else
#else /* _WIN32 */
argc = mrb_get_argc(mrb);
if (argc == 0) {
home = getenv("USERPROFILE");
@@ -344,7 +395,7 @@ mrb_file_mtime(mrb_state *mrb, mrb_value self)
int fd;
obj = mrb_obj_value(mrb_class_get(mrb, "Time"));
fd = (int)mrb_fixnum(mrb_io_fileno(mrb, self));
fd = mrb_io_fileno(mrb, self);
if (fstat(fd, &st) == -1)
return mrb_false_value();
return mrb_funcall(mrb, obj, "at", 1, mrb_fixnum_value(st.st_mtime));
@@ -360,7 +411,7 @@ mrb_file_flock(mrb_state *mrb, mrb_value self)
int fd;
mrb_get_args(mrb, "i", &operation);
fd = (int)mrb_fixnum(mrb_io_fileno(mrb, self));
fd = mrb_io_fileno(mrb, self);
while (flock(fd, (int)operation) == -1) {
switch (errno) {
@@ -384,6 +435,95 @@ mrb_file_flock(mrb_state *mrb, mrb_value self)
return mrb_fixnum_value(0);
}
static mrb_value
mrb_file_size(mrb_state *mrb, mrb_value self)
{
mrb_stat st;
int fd;
fd = mrb_io_fileno(mrb, self);
if (mrb_fstat(fd, &st) == -1) {
mrb_raise(mrb, E_RUNTIME_ERROR, "fstat failed");
}
if (st.st_size > MRB_INT_MAX) {
#ifdef MRB_WITHOUT_FLOAT
mrb_raise(mrb, E_RUNTIME_ERROR, "File#size too large for MRB_WITHOUT_FLOAT");
#else
return mrb_float_value(mrb, (mrb_float)st.st_size);
#endif
}
return mrb_fixnum_value((mrb_int)st.st_size);
}
static int
mrb_ftruncate(int fd, int64_t length)
{
#ifndef _WIN32
return ftruncate(fd, (off_t)length);
#else
HANDLE file;
__int64 cur;
file = (HANDLE)_get_osfhandle(fd);
if (file == INVALID_HANDLE_VALUE) {
return -1;
}
cur = _lseeki64(fd, 0, SEEK_CUR);
if (cur == -1) return -1;
if (_lseeki64(fd, (__int64)length, SEEK_SET) == -1) return -1;
if (!SetEndOfFile(file)) {
errno = EINVAL; /* TODO: GetLastError to errno */
return -1;
}
if (_lseeki64(fd, cur, SEEK_SET) == -1) return -1;
return 0;
#endif /* _WIN32 */
}
static mrb_value
mrb_file_truncate(mrb_state *mrb, mrb_value self)
{
int fd;
int64_t length;
mrb_value lenv;
fd = mrb_io_fileno(mrb, self);
mrb_get_args(mrb, "o", &lenv);
switch (mrb_type(lenv)) {
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
{
mrb_float lenf = mrb_float(lenv);
if (lenf > INT64_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "length too large");
}
length = (int64_t)lenf;
}
break;
#endif
case MRB_TT_FIXNUM:
default:
{
mrb_int leni = mrb_int(mrb, lenv);
length = (int64_t)leni;
}
break;
}
if (mrb_ftruncate(fd, length) != 0) {
mrb_raise(mrb, E_IO_ERROR, "ftruncate failed");
}
return mrb_fixnum_value(0);
}
static mrb_value
mrb_file_s_symlink(mrb_state *mrb, mrb_value klass)
{
@@ -474,7 +614,7 @@ mrb_init_file(mrb_state *mrb)
io = mrb_class_get(mrb, "IO");
file = mrb_define_class(mrb, "File", io);
MRB_SET_INSTANCE_TT(file, MRB_TT_DATA);
mrb_define_class_method(mrb, file, "umask", mrb_file_s_umask, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, file, "umask", mrb_file_s_umask, MRB_ARGS_OPT(1));
mrb_define_class_method(mrb, file, "delete", mrb_file_s_unlink, MRB_ARGS_ANY());
mrb_define_class_method(mrb, file, "unlink", mrb_file_s_unlink, MRB_ARGS_ANY());
mrb_define_class_method(mrb, file, "rename", mrb_file_s_rename, MRB_ARGS_REQ(2));
@@ -490,6 +630,8 @@ mrb_init_file(mrb_state *mrb)
mrb_define_method(mrb, file, "flock", mrb_file_flock, MRB_ARGS_REQ(1));
mrb_define_method(mrb, file, "mtime", mrb_file_mtime, MRB_ARGS_NONE());
mrb_define_method(mrb, file, "size", mrb_file_size, MRB_ARGS_NONE());
mrb_define_method(mrb, file, "truncate", mrb_file_truncate, MRB_ARGS_REQ(1));
cnst = mrb_define_module_under(mrb, file, "Constants");
mrb_define_const(mrb, cnst, "LOCK_SH", mrb_fixnum_value(LOCK_SH));
@@ -505,4 +647,22 @@ mrb_init_file(mrb_state *mrb)
#endif
mrb_define_const(mrb, cnst, "NULL", mrb_str_new_cstr(mrb, NULL_FILE));
mrb_define_const(mrb, cnst, "RDONLY", mrb_fixnum_value(MRB_O_RDONLY));
mrb_define_const(mrb, cnst, "WRONLY", mrb_fixnum_value(MRB_O_WRONLY));
mrb_define_const(mrb, cnst, "RDWR", mrb_fixnum_value(MRB_O_RDWR));
mrb_define_const(mrb, cnst, "APPEND", mrb_fixnum_value(MRB_O_APPEND));
mrb_define_const(mrb, cnst, "CREAT", mrb_fixnum_value(MRB_O_CREAT));
mrb_define_const(mrb, cnst, "EXCL", mrb_fixnum_value(MRB_O_EXCL));
mrb_define_const(mrb, cnst, "TRUNC", mrb_fixnum_value(MRB_O_TRUNC));
mrb_define_const(mrb, cnst, "NONBLOCK", mrb_fixnum_value(MRB_O_NONBLOCK));
mrb_define_const(mrb, cnst, "NOCTTY", mrb_fixnum_value(MRB_O_NOCTTY));
mrb_define_const(mrb, cnst, "BINARY", mrb_fixnum_value(MRB_O_BINARY));
mrb_define_const(mrb, cnst, "SHARE_DELETE", mrb_fixnum_value(MRB_O_SHARE_DELETE));
mrb_define_const(mrb, cnst, "SYNC", mrb_fixnum_value(MRB_O_SYNC));
mrb_define_const(mrb, cnst, "DSYNC", mrb_fixnum_value(MRB_O_DSYNC));
mrb_define_const(mrb, cnst, "RSYNC", mrb_fixnum_value(MRB_O_RSYNC));
mrb_define_const(mrb, cnst, "NOFOLLOW", mrb_fixnum_value(MRB_O_NOFOLLOW));
mrb_define_const(mrb, cnst, "NOATIME", mrb_fixnum_value(MRB_O_NOATIME));
mrb_define_const(mrb, cnst, "DIRECT", mrb_fixnum_value(MRB_O_DIRECT));
mrb_define_const(mrb, cnst, "TMPFILE", mrb_fixnum_value(MRB_O_TMPFILE));
}
-6
View File
@@ -7,12 +7,7 @@
#include "mruby/data.h"
#include "mruby/string.h"
#include "mruby/ext/io.h"
#if MRUBY_RELEASE_NO < 10000
#include "error.h"
#else
#include "mruby/error.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
@@ -33,7 +28,6 @@
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+301 -134
View File
@@ -10,12 +10,7 @@
#include "mruby/string.h"
#include "mruby/variable.h"
#include "mruby/ext/io.h"
#if MRUBY_RELEASE_NO < 10000
#include "error.h"
#else
#include "mruby/error.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
@@ -36,14 +31,21 @@
typedef long ftime_t;
typedef long fsuseconds_t;
typedef int fmode_t;
typedef int mrb_io_read_write_size;
#ifndef O_TMPFILE
#define O_TMPFILE O_TEMPORARY
#endif
#else
#include <sys/wait.h>
#include <sys/time.h>
#include <unistd.h>
typedef size_t fsize_t;
typedef time_t ftime_t;
typedef suseconds_t fsuseconds_t;
typedef mode_t fmode_t;
typedef ssize_t mrb_io_read_write_size;
#endif
#ifdef _MSC_VER
@@ -53,9 +55,14 @@ typedef mrb_int pid_t;
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define OPEN_ACCESS_MODE_FLAGS (O_RDONLY | O_WRONLY | O_RDWR)
#define OPEN_RDONLY_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_RDONLY))
#define OPEN_WRONLY_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_WRONLY))
#define OPEN_RDWR_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_RDWR))
#define OPEN_READABLE_P(f) ((mrb_bool)(OPEN_RDONLY_P(f) || OPEN_RDWR_P(f)))
#define OPEN_WRITABLE_P(f) ((mrb_bool)(OPEN_WRONLY_P(f) || OPEN_RDWR_P(f)))
static void mrb_io_free(mrb_state *mrb, void *ptr);
struct mrb_data_type mrb_io_type = { "IO", mrb_io_free };
@@ -63,17 +70,9 @@ struct mrb_data_type mrb_io_type = { "IO", mrb_io_free };
static struct mrb_io *io_get_open_fptr(mrb_state *mrb, mrb_value self);
static int mrb_io_modestr_to_flags(mrb_state *mrb, const char *modestr);
static int mrb_io_flags_to_modenum(mrb_state *mrb, int flags);
static int mrb_io_mode_to_flags(mrb_state *mrb, mrb_value mode);
static void fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet);
#if MRUBY_RELEASE_NO < 10000
static struct RClass *
mrb_module_get(mrb_state *mrb, const char *name)
{
return mrb_class_get(mrb, name);
}
#endif
static struct mrb_io *
io_get_open_fptr(mrb_state *mrb, mrb_value self)
{
@@ -113,30 +112,33 @@ io_set_process_status(mrb_state *mrb, pid_t pid, int status)
static int
mrb_io_modestr_to_flags(mrb_state *mrb, const char *mode)
{
int flags = 0;
int flags;
const char *m = mode;
switch (*m++) {
case 'r':
flags |= FMODE_READABLE;
flags = O_RDONLY;
break;
case 'w':
flags |= FMODE_WRITABLE | FMODE_CREATE | FMODE_TRUNC;
flags = O_WRONLY | O_CREAT | O_TRUNC;
break;
case 'a':
flags |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
flags = O_WRONLY | O_CREAT | O_APPEND;
break;
default:
mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode);
flags = 0; /* not reached */
}
while (*m) {
switch (*m++) {
case 'b':
flags |= FMODE_BINMODE;
#ifdef O_BINARY
flags |= O_BINARY;
#endif
break;
case '+':
flags |= FMODE_READWRITE;
flags = (flags & ~OPEN_ACCESS_MODE_FLAGS) | O_RDWR;
break;
case ':':
/* XXX: PASSTHROUGH*/
@@ -149,38 +151,72 @@ mrb_io_modestr_to_flags(mrb_state *mrb, const char *mode)
}
static int
mrb_io_flags_to_modenum(mrb_state *mrb, int flags)
mrb_io_mode_to_flags(mrb_state *mrb, mrb_value mode)
{
int modenum = 0;
if (mrb_nil_p(mode)) {
return mrb_io_modestr_to_flags(mrb, "r");
}
else if (mrb_string_p(mode)) {
return mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
}
else {
int flags = 0;
mrb_int flags0 = mrb_int(mrb, mode);
switch(flags & (FMODE_READABLE|FMODE_WRITABLE|FMODE_READWRITE)) {
case FMODE_READABLE:
modenum = O_RDONLY;
break;
case FMODE_WRITABLE:
modenum = O_WRONLY;
break;
case FMODE_READWRITE:
modenum = O_RDWR;
break;
}
switch (flags0 & MRB_O_ACCMODE) {
case MRB_O_RDONLY:
flags |= O_RDONLY;
break;
case MRB_O_WRONLY:
flags |= O_WRONLY;
break;
case MRB_O_RDWR:
flags |= O_RDWR;
break;
default:
mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %v", mode);
}
if (flags & FMODE_APPEND) {
modenum |= O_APPEND;
}
if (flags & FMODE_TRUNC) {
modenum |= O_TRUNC;
}
if (flags & FMODE_CREATE) {
modenum |= O_CREAT;
}
if (flags0 & MRB_O_APPEND) flags |= O_APPEND;
if (flags0 & MRB_O_CREAT) flags |= O_CREAT;
if (flags0 & MRB_O_EXCL) flags |= O_EXCL;
if (flags0 & MRB_O_TRUNC) flags |= O_TRUNC;
#ifdef O_NONBLOCK
if (flags0 & MRB_O_NONBLOCK) flags |= O_NONBLOCK;
#endif
#ifdef O_NOCTTY
if (flags0 & MRB_O_NOCTTY) flags |= O_NOCTTY;
#endif
#ifdef O_BINARY
if (flags & FMODE_BINMODE) {
modenum |= O_BINARY;
}
if (flags0 & MRB_O_BINARY) flags |= O_BINARY;
#endif
#ifdef O_SHARE_DELETE
if (flags0 & MRB_O_SHARE_DELETE) flags |= O_SHARE_DELETE;
#endif
#ifdef O_SYNC
if (flags0 & MRB_O_SYNC) flags |= O_SYNC;
#endif
#ifdef O_DSYNC
if (flags0 & MRB_O_DSYNC) flags |= O_DSYNC;
#endif
#ifdef O_RSYNC
if (flags0 & MRB_O_RSYNC) flags |= O_RSYNC;
#endif
#ifdef O_NOFOLLOW
if (flags0 & MRB_O_NOFOLLOW) flags |= O_NOFOLLOW;
#endif
#ifdef O_NOATIME
if (flags0 & MRB_O_NOATIME) flags |= O_NOATIME;
#endif
#ifdef O_DIRECT
if (flags0 & MRB_O_DIRECT) flags |= O_DIRECT;
#endif
#ifdef O_TMPFILE
if (flags0 & MRB_O_TMPFILE) flags |= O_TMPFILE;
#endif
return modenum;
return flags;
}
}
static void
@@ -284,16 +320,17 @@ mrb_io_alloc(mrb_state *mrb)
#endif
static int
option_to_fd(mrb_state *mrb, mrb_value obj, const char *key)
option_to_fd(mrb_state *mrb, mrb_value hash, const char *key)
{
mrb_value opt = mrb_funcall(mrb, obj, "[]", 1, mrb_symbol_value(mrb_intern_static(mrb, key, strlen(key))));
if (mrb_nil_p(opt)) {
return -1;
}
mrb_value opt;
if (!mrb_hash_p(hash)) return -1;
opt = mrb_hash_fetch(mrb, hash, mrb_symbol_value(mrb_intern_static(mrb, key, strlen(key))), mrb_nil_value());
if (mrb_nil_p(opt)) return -1;
switch (mrb_type(opt)) {
case MRB_TT_DATA: /* IO */
return (int)mrb_fixnum(mrb_io_fileno(mrb, opt));
return mrb_io_fileno(mrb, opt);
case MRB_TT_FIXNUM:
return (int)mrb_fixnum(opt);
default:
@@ -329,11 +366,11 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
ofd[0] = INVALID_HANDLE_VALUE;
ofd[1] = INVALID_HANDLE_VALUE;
mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt);
mrb_get_args(mrb, "S|oH", &cmd, &mode, &opt);
io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
pname = RSTRING_CSTR(mrb, cmd);
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
flags = mrb_io_mode_to_flags(mrb, mode);
doexec = (strcmp("-", pname) != 0);
opt_in = option_to_fd(mrb, opt, "in");
@@ -344,14 +381,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if (flags & FMODE_READABLE) {
if (OPEN_READABLE_P(flags)) {
if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
|| !SetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)) {
mrb_sys_fail(mrb, "pipe");
}
}
if (flags & FMODE_WRITABLE) {
if (OPEN_WRITABLE_P(flags)) {
if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
|| !SetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)) {
mrb_sys_fail(mrb, "pipe");
@@ -365,11 +402,11 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
si.dwFlags |= STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.dwFlags |= STARTF_USESTDHANDLES;
if (flags & FMODE_READABLE) {
if (OPEN_READABLE_P(flags)) {
si.hStdOutput = ofd[1];
si.hStdError = ofd[1];
}
if (flags & FMODE_WRITABLE) {
if (OPEN_WRITABLE_P(flags)) {
si.hStdInput = ifd[0];
}
if (!CreateProcess(
@@ -393,8 +430,8 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
fptr->fd = _open_osfhandle((intptr_t)ofd[0], 0);
fptr->fd2 = _open_osfhandle((intptr_t)ifd[1], 0);
fptr->pid = pid;
fptr->readable = ((flags & FMODE_READABLE) != 0);
fptr->writable = ((flags & FMODE_WRITABLE) != 0);
fptr->readable = OPEN_READABLE_P(flags);
fptr->writable = OPEN_WRITABLE_P(flags);
fptr->sync = 0;
DATA_TYPE(io) = &mrb_io_type;
@@ -425,18 +462,18 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
int saved_errno;
int opt_in, opt_out, opt_err;
mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt);
mrb_get_args(mrb, "S|oH", &cmd, &mode, &opt);
io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
pname = RSTRING_CSTR(mrb, cmd);
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
flags = mrb_io_mode_to_flags(mrb, mode);
doexec = (strcmp("-", pname) != 0);
opt_in = option_to_fd(mrb, opt, "in");
opt_out = option_to_fd(mrb, opt, "out");
opt_err = option_to_fd(mrb, opt, "err");
if (flags & FMODE_READABLE) {
if (OPEN_READABLE_P(flags)) {
if (pipe(pr) == -1) {
mrb_sys_fail(mrb, "pipe");
}
@@ -444,7 +481,7 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
mrb_fd_cloexec(mrb, pr[1]);
}
if (flags & FMODE_WRITABLE) {
if (OPEN_WRITABLE_P(flags)) {
if (pipe(pw) == -1) {
if (pr[0] != -1) close(pr[0]);
if (pr[1] != -1) close(pr[1]);
@@ -473,14 +510,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
if (opt_err != -1) {
dup2(opt_err, 2);
}
if (flags & FMODE_READABLE) {
if (OPEN_READABLE_P(flags)) {
close(pr[0]);
if (pr[1] != 1) {
dup2(pr[1], 1);
close(pr[1]);
}
}
if (flags & FMODE_WRITABLE) {
if (OPEN_WRITABLE_P(flags)) {
close(pw[1]);
if (pw[0] != 0) {
dup2(pw[0], 0);
@@ -499,12 +536,12 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
break;
default: /* parent */
if ((flags & FMODE_READABLE) && (flags & FMODE_WRITABLE)) {
if (OPEN_RDWR_P(flags)) {
close(pr[1]);
fd = pr[0];
close(pw[0]);
write_fd = pw[1];
} else if (flags & FMODE_READABLE) {
} else if (OPEN_RDONLY_P(flags)) {
close(pr[1]);
fd = pr[0];
} else {
@@ -518,8 +555,8 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
fptr->fd = fd;
fptr->fd2 = write_fd;
fptr->pid = pid;
fptr->readable = ((flags & FMODE_READABLE) != 0);
fptr->writable = ((flags & FMODE_WRITABLE) != 0);
fptr->readable = OPEN_READABLE_P(flags);
fptr->writable = OPEN_WRITABLE_P(flags);
fptr->sync = 0;
DATA_TYPE(io) = &mrb_io_type;
@@ -529,11 +566,11 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
case -1: /* error */
saved_errno = errno;
if (flags & FMODE_READABLE) {
if (OPEN_READABLE_P(flags)) {
close(pr[0]);
close(pr[1]);
}
if (flags & FMODE_WRITABLE) {
if (OPEN_WRITABLE_P(flags)) {
close(pw[0]);
close(pw[1]);
}
@@ -618,7 +655,7 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
mode = opt = mrb_nil_value();
mrb_get_args(mrb, "i|So", &fd, &mode, &opt);
mrb_get_args(mrb, "i|oo", &fd, &mode, &opt);
if (mrb_nil_p(mode)) {
mode = mrb_str_new_cstr(mrb, "r");
}
@@ -626,7 +663,7 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
opt = mrb_hash_new(mrb);
}
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
flags = mrb_io_mode_to_flags(mrb, mode);
mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, ""));
@@ -641,8 +678,8 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
DATA_PTR(io) = fptr;
fptr->fd = (int)fd;
fptr->readable = ((flags & FMODE_READABLE) != 0);
fptr->writable = ((flags & FMODE_WRITABLE) != 0);
fptr->readable = OPEN_READABLE_P(flags);
fptr->writable = OPEN_WRITABLE_P(flags);
fptr->sync = 0;
return io;
}
@@ -797,32 +834,48 @@ mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
mrb_value mode = mrb_nil_value();
mrb_int fd, perm = -1;
const char *pat;
int flags, modenum;
int flags;
mrb_get_args(mrb, "S|Si", &path, &mode, &perm);
if (mrb_nil_p(mode)) {
mode = mrb_str_new_cstr(mrb, "r");
}
mrb_get_args(mrb, "S|oi", &path, &mode, &perm);
if (perm < 0) {
perm = 0666;
}
pat = RSTRING_CSTR(mrb, path);
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
modenum = mrb_io_flags_to_modenum(mrb, flags);
fd = mrb_cloexec_open(mrb, pat, modenum, perm);
flags = mrb_io_mode_to_flags(mrb, mode);
fd = mrb_cloexec_open(mrb, pat, flags, perm);
return mrb_fixnum_value(fd);
}
static mrb_value mrb_io_sysread_common(mrb_state *mrb,
mrb_io_read_write_size (*readfunc)(int, void *, fsize_t, off_t),
mrb_value io, mrb_value buf, mrb_int maxlen, off_t offset);
static mrb_io_read_write_size
mrb_sysread_dummy(int fd, void *buf, fsize_t nbytes, off_t offset)
{
return (mrb_io_read_write_size)read(fd, buf, nbytes);
}
mrb_value
mrb_io_sysread(mrb_state *mrb, mrb_value io)
{
struct mrb_io *fptr;
mrb_value buf = mrb_nil_value();
mrb_int maxlen;
int ret;
mrb_get_args(mrb, "i|S", &maxlen, &buf);
return mrb_io_sysread_common(mrb, mrb_sysread_dummy, io, buf, maxlen, 0);
}
static mrb_value
mrb_io_sysread_common(mrb_state *mrb,
mrb_io_read_write_size (*readfunc)(int, void *, fsize_t, off_t),
mrb_value io, mrb_value buf, mrb_int maxlen, off_t offset)
{
struct mrb_io *fptr;
int ret;
if (maxlen < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative expanding string size");
}
@@ -836,7 +889,8 @@ mrb_io_sysread(mrb_state *mrb, mrb_value io)
if (RSTRING_LEN(buf) != maxlen) {
buf = mrb_str_resize(mrb, buf, maxlen);
} else {
}
else {
mrb_str_modify(mrb, RSTRING(buf));
}
@@ -844,25 +898,16 @@ mrb_io_sysread(mrb_state *mrb, mrb_value io)
if (!fptr->readable) {
mrb_raise(mrb, E_IO_ERROR, "not opened for reading");
}
ret = read(fptr->fd, RSTRING_PTR(buf), (fsize_t)maxlen);
switch (ret) {
case 0: /* EOF */
if (maxlen == 0) {
buf = mrb_str_new_cstr(mrb, "");
} else {
mrb_raise(mrb, E_EOF_ERROR, "sysread failed: End of File");
}
break;
case -1: /* Error */
mrb_sys_fail(mrb, "sysread failed");
break;
default:
if (RSTRING_LEN(buf) != ret) {
buf = mrb_str_resize(mrb, buf, ret);
}
break;
ret = readfunc(fptr->fd, RSTRING_PTR(buf), (fsize_t)maxlen, offset);
if (ret < 0) {
mrb_sys_fail(mrb, "sysread failed");
}
if (RSTRING_LEN(buf) != ret) {
buf = mrb_str_resize(mrb, buf, ret);
}
if (ret == 0 && maxlen > 0) {
mrb_raise(mrb, E_EOF_ERROR, "sysread failed: End of File");
}
return buf;
}
@@ -894,11 +939,12 @@ mrb_io_sysseek(mrb_state *mrb, mrb_value io)
}
}
mrb_value
mrb_io_syswrite(mrb_state *mrb, mrb_value io)
static mrb_value
mrb_io_syswrite_common(mrb_state *mrb,
mrb_io_read_write_size (*writefunc)(int, const void *, fsize_t, off_t),
mrb_value io, mrb_value buf, off_t offset)
{
struct mrb_io *fptr;
mrb_value str, buf;
int fd, length;
fptr = io_get_open_fptr(mrb, io);
@@ -906,19 +952,12 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
mrb_raise(mrb, E_IO_ERROR, "not opened for writing");
}
mrb_get_args(mrb, "S", &str);
if (!mrb_string_p(str)) {
buf = mrb_funcall(mrb, str, "to_s", 0);
} else {
buf = str;
}
if (fptr->fd2 == -1) {
fd = fptr->fd;
} else {
fd = fptr->fd2;
}
length = write(fd, RSTRING_PTR(buf), (fsize_t)RSTRING_LEN(buf));
length = writefunc(fd, RSTRING_PTR(buf), (fsize_t)RSTRING_LEN(buf), offset);
if (length == -1) {
mrb_sys_fail(mrb, 0);
}
@@ -926,6 +965,22 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
return mrb_fixnum_value(length);
}
static mrb_io_read_write_size
mrb_syswrite_dummy(int fd, const void *buf, fsize_t nbytes, off_t offset)
{
return (mrb_io_read_write_size)write(fd, buf, nbytes);
}
mrb_value
mrb_io_syswrite(mrb_state *mrb, mrb_value io)
{
mrb_value buf;
mrb_get_args(mrb, "S", &buf);
return mrb_io_syswrite_common(mrb, mrb_syswrite_dummy, io, buf, 0);
}
mrb_value
mrb_io_close(mrb_state *mrb, mrb_value self)
{
@@ -1063,7 +1118,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
mrb_get_args(mrb, "*", &argv, &argc);
if (argc < 1 || argc > 4) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%i for 1..4)", argc);
mrb_argnum_error(mrb, argc, 1, 4);
}
timeout = mrb_nil_value();
@@ -1206,12 +1261,19 @@ retry:
return result;
}
mrb_value
int
mrb_io_fileno(mrb_state *mrb, mrb_value io)
{
struct mrb_io *fptr;
fptr = io_get_open_fptr(mrb, io);
return mrb_fixnum_value(fptr->fd);
return fptr->fd;
}
static mrb_value
mrb_io_fileno_m(mrb_state *mrb, mrb_value io)
{
int fd = mrb_io_fileno(mrb, io);
return mrb_fixnum_value(fd);
}
mrb_value
@@ -1294,15 +1356,70 @@ mrb_io_sync(mrb_state *mrb, mrb_value self)
return mrb_bool_value(fptr->sync);
}
static mrb_value
io_bufread(mrb_state *mrb, mrb_value self)
#ifndef MRB_WITH_IO_PREAD_PWRITE
# define mrb_io_pread mrb_notimplement_m
# define mrb_io_pwrite mrb_notimplement_m
#else
static off_t
value2off(mrb_state *mrb, mrb_value offv)
{
mrb_value str, str2;
mrb_int len, newlen;
switch (mrb_type(offv)) {
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
{
mrb_float tmp = mrb_float(offv);
if (tmp < INT64_MIN || tmp > INT64_MAX) {
/* fall through to use convert by `mrb_int()` (and raise error if out of range) */
} else {
return (off_t)tmp;
}
}
/* fall through */
#endif /* MRB_WITHOUT_FLOAT */
default:
return (off_t)mrb_int(mrb, offv);
}
}
/*
* call-seq:
* pread(maxlen, offset, outbuf = "") -> outbuf
*/
static mrb_value
mrb_io_pread(mrb_state *mrb, mrb_value io)
{
mrb_value buf = mrb_nil_value();
mrb_value off;
mrb_int maxlen;
mrb_get_args(mrb, "io|S!", &maxlen, &off, &buf);
return mrb_io_sysread_common(mrb, pread, io, buf, maxlen, value2off(mrb, off));
}
/*
* call-seq:
* pwrite(buffer, offset) -> wrote_bytes
*/
static mrb_value
mrb_io_pwrite(mrb_state *mrb, mrb_value io)
{
mrb_value buf, off;
mrb_get_args(mrb, "So", &buf, &off);
return mrb_io_syswrite_common(mrb, pwrite, io, buf, value2off(mrb, off));
}
#endif /* MRB_WITH_IO_PREAD_PWRITE */
static mrb_value
io_bufread(mrb_state *mrb, mrb_value str, mrb_int len)
{
mrb_value str2;
mrb_int newlen;
struct RString *s;
char *p;
mrb_get_args(mrb, "Si", &str, &len);
s = RSTRING(str);
mrb_str_modify(mrb, s);
p = RSTR_PTR(s);
@@ -1315,6 +1432,53 @@ io_bufread(mrb_state *mrb, mrb_value self)
return str2;
}
static mrb_value
mrb_io_bufread(mrb_state *mrb, mrb_value self)
{
mrb_value str;
mrb_int len;
mrb_get_args(mrb, "Si", &str, &len);
return io_bufread(mrb, str, len);
}
static mrb_value
mrb_io_readchar(mrb_state *mrb, mrb_value self)
{
mrb_value buf;
mrb_int len = 1;
#ifdef MRB_UTF8_STRING
unsigned char c;
#endif
mrb_get_args(mrb, "S", &buf);
mrb_assert(RSTRING_PTR(buf) > 0);
mrb_str_modify(mrb, RSTRING(buf));
#ifdef MRB_UTF8_STRING
c = RSTRING_PTR(buf)[0];
if (c & 0x80) {
len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf));
if (len == 1 && RSTRING_LEN(buf) < 4) { /* partial UTF-8 */
mrb_int blen = RSTRING_LEN(buf);
ssize_t n;
struct mrb_io *fptr = (struct mrb_io*)io_get_open_fptr(mrb, self);
if (!fptr->readable) {
mrb_raise(mrb, E_IO_ERROR, "not opened for reading");
}
/* refill the buffer */
mrb_str_resize(mrb, buf, 4096);
n = read(fptr->fd, RSTRING_PTR(buf)+blen, 4096-blen);
if (n < 0) mrb_sys_fail(mrb, "sysread failed");
mrb_str_resize(mrb, buf, blen+n);
}
len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf));
}
#endif
return io_bufread(mrb, buf, len);
}
void
mrb_init_io(mrb_state *mrb)
{
@@ -1324,23 +1488,23 @@ mrb_init_io(mrb_state *mrb)
MRB_SET_INSTANCE_TT(io, MRB_TT_DATA);
mrb_include_module(mrb, io, mrb_module_get(mrb, "Enumerable")); /* 15.2.20.3 */
mrb_define_class_method(mrb, io, "_popen", mrb_io_s_popen, MRB_ARGS_ANY());
mrb_define_class_method(mrb, io, "_popen", mrb_io_s_popen, MRB_ARGS_ARG(1,2));
mrb_define_class_method(mrb, io, "_sysclose", mrb_io_s_sysclose, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, io, "for_fd", mrb_io_s_for_fd, MRB_ARGS_ANY());
mrb_define_class_method(mrb, io, "select", mrb_io_s_select, MRB_ARGS_ANY());
mrb_define_class_method(mrb, io, "sysopen", mrb_io_s_sysopen, MRB_ARGS_ANY());
mrb_define_class_method(mrb, io, "for_fd", mrb_io_s_for_fd, MRB_ARGS_ARG(1,2));
mrb_define_class_method(mrb, io, "select", mrb_io_s_select, MRB_ARGS_ARG(1,3));
mrb_define_class_method(mrb, io, "sysopen", mrb_io_s_sysopen, MRB_ARGS_ARG(1,2));
#if !defined(_WIN32) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
mrb_define_class_method(mrb, io, "_pipe", mrb_io_s_pipe, MRB_ARGS_NONE());
#endif
mrb_define_method(mrb, io, "initialize", mrb_io_initialize, MRB_ARGS_ANY()); /* 15.2.20.5.21 (x)*/
mrb_define_method(mrb, io, "initialize", mrb_io_initialize, MRB_ARGS_ARG(1,2)); /* 15.2.20.5.21 (x)*/
mrb_define_method(mrb, io, "initialize_copy", mrb_io_initialize_copy, MRB_ARGS_REQ(1));
mrb_define_method(mrb, io, "_check_readable", mrb_io_check_readable, MRB_ARGS_NONE());
mrb_define_method(mrb, io, "isatty", mrb_io_isatty, MRB_ARGS_NONE());
mrb_define_method(mrb, io, "sync", mrb_io_sync, MRB_ARGS_NONE());
mrb_define_method(mrb, io, "sync=", mrb_io_set_sync, MRB_ARGS_REQ(1));
mrb_define_method(mrb, io, "sysread", mrb_io_sysread, MRB_ARGS_ANY());
mrb_define_method(mrb, io, "sysseek", mrb_io_sysseek, MRB_ARGS_REQ(1));
mrb_define_method(mrb, io, "sysread", mrb_io_sysread, MRB_ARGS_ARG(1,1));
mrb_define_method(mrb, io, "sysseek", mrb_io_sysseek, MRB_ARGS_ARG(1,1));
mrb_define_method(mrb, io, "syswrite", mrb_io_syswrite, MRB_ARGS_REQ(1));
mrb_define_method(mrb, io, "close", mrb_io_close, MRB_ARGS_NONE()); /* 15.2.20.5.1 */
mrb_define_method(mrb, io, "close_write", mrb_io_close_write, MRB_ARGS_NONE());
@@ -1348,7 +1512,10 @@ mrb_init_io(mrb_state *mrb)
mrb_define_method(mrb, io, "close_on_exec?", mrb_io_close_on_exec_p, MRB_ARGS_NONE());
mrb_define_method(mrb, io, "closed?", mrb_io_closed, MRB_ARGS_NONE()); /* 15.2.20.5.2 */
mrb_define_method(mrb, io, "pid", mrb_io_pid, MRB_ARGS_NONE()); /* 15.2.20.5.2 */
mrb_define_method(mrb, io, "fileno", mrb_io_fileno, MRB_ARGS_NONE());
mrb_define_method(mrb, io, "fileno", mrb_io_fileno_m, MRB_ARGS_NONE());
mrb_define_method(mrb, io, "pread", mrb_io_pread, MRB_ARGS_ANY()); /* ruby 2.5 feature */
mrb_define_method(mrb, io, "pwrite", mrb_io_pwrite, MRB_ARGS_ANY()); /* ruby 2.5 feature */
mrb_define_class_method(mrb, io, "_bufread", io_bufread, MRB_ARGS_REQ(2));
mrb_define_method(mrb, io, "_readchar", mrb_io_readchar, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, io, "_bufread", mrb_io_bufread, MRB_ARGS_REQ(2));
}
+16
View File
@@ -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")
+28
View File
@@ -564,6 +564,34 @@ assert('IO#sysseek') do
end
end
assert('IO#pread') do
skip "IO#pread is not implemented on this configuration" unless MRubyIOTestUtil::MRB_WITH_IO_PREAD_PWRITE
IO.open(IO.sysopen($mrbtest_io_rfname, 'r'), 'r') do |io|
assert_equal $mrbtest_io_msg.byteslice(5, 8), io.pread(8, 5)
assert_equal 0, io.pos
assert_equal $mrbtest_io_msg.byteslice(1, 5), io.pread(5, 1)
assert_equal 0, io.pos
assert_raise(RuntimeError) { io.pread(20, -9) }
end
end
assert('IO#pwrite') do
skip "IO#pwrite is not implemented on this configuration" unless MRubyIOTestUtil::MRB_WITH_IO_PREAD_PWRITE
IO.open(IO.sysopen($mrbtest_io_wfname, 'w+'), 'w+') do |io|
assert_equal 6, io.pwrite("Warld!", 7)
assert_equal 0, io.pos
assert_equal 7, io.pwrite("Hello, ", 0)
assert_equal 0, io.pos
assert_equal "Hello, Warld!", io.read
assert_equal 6, io.pwrite("world!", 7)
assert_equal 13, io.pos
io.pos = 0
assert_equal "Hello, world!", io.read
end
end
assert('IO.pipe') do
begin
called = false
+57 -25
View File
@@ -1,5 +1,7 @@
#include <mruby/common.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#if defined(_WIN32) || defined(_WIN64)
@@ -7,7 +9,6 @@
#include <io.h>
#include <fcntl.h>
#include <direct.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
@@ -18,7 +19,9 @@ typedef int mode_t;
#define open _open
#define close _close
#ifdef _MSC_VER
#if defined(_MSC_VER) || \
(defined(MRB_MINGW32_VERSION) && MRB_MINGW32_VERSION < 3021) || \
(defined(MRB_MINGW64_VERSION) && MRB_MINGW64_VERSION < 4000)
#include <sys/stat.h>
static int
@@ -50,10 +53,10 @@ mkdtemp(char *temp)
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <fcntl.h>
#endif
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "mruby.h"
@@ -61,6 +64,37 @@ mkdtemp(char *temp)
#include "mruby/error.h"
#include "mruby/string.h"
#include "mruby/variable.h"
#include <mruby/ext/io.h>
int wd_save;
int socket_available_p;
#if !defined(_WIN32) && !defined(_WIN64)
static int mrb_io_socket_available()
{
int fd, retval = 0;
struct sockaddr_un sun0;
char socketname[] = "tmp.mruby-io-socket-ok.XXXXXXXX";
if (!(fd = mkstemp(socketname))) {
goto sock_test_out;
}
unlink(socketname);
close(fd);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
goto sock_test_out;
}
sun0.sun_family = AF_UNIX;
strncpy(sun0.sun_path, socketname, sizeof(sun0.sun_path));
if (bind(fd, (struct sockaddr *)&sun0, sizeof(sun0)) == 0) {
retval = 1;
}
sock_test_out:
unlink(socketname);
close(fd);
return retval;
}
#endif
static mrb_value
mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
@@ -77,6 +111,14 @@ mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
#if !defined(_WIN32) && !defined(_WIN64)
int fd2, fd3;
struct sockaddr_un sun0;
if(!(socket_available_p = mrb_io_socket_available())) {
char *tmpdir;
wd_save = open(".", O_DIRECTORY);
tmpdir = getenv("TMPDIR");
if (tmpdir) chdir(tmpdir);
else chdir("/tmp");
}
#endif
mask = umask(077);
@@ -134,7 +176,7 @@ mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a socket");
}
sun0.sun_family = AF_UNIX;
snprintf(sun0.sun_path, sizeof(sun0.sun_path), "%s", socketname);
strncpy(sun0.sun_path, socketname, sizeof(sun0.sun_path));
if (bind(fd3, (struct sockaddr *)&sun0, sizeof(sun0)) == -1) {
mrb_raisef(mrb, E_RUNTIME_ERROR, "can't bind AF_UNIX socket to %s: %d",
sun0.sun_path,
@@ -173,28 +215,13 @@ mrb_io_test_io_cleanup(mrb_state *mrb, mrb_value self)
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"), mrb_nil_value());
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_msg"), mrb_nil_value());
return mrb_nil_value();
}
static mrb_value
mrb_io_test_file_setup(mrb_state *mrb, mrb_value self)
{
mrb_value ary = mrb_io_test_io_setup(mrb, self);
#if !defined(_WIN32) && !defined(_WIN64)
if (symlink("/usr/bin", "test-bin") == -1) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a symbolic link");
if(!socket_available_p) {
fchdir(wd_save);
close(wd_save);
}
#endif
return ary;
}
static mrb_value
mrb_io_test_file_cleanup(mrb_state *mrb, mrb_value self)
{
mrb_io_test_io_cleanup(mrb, self);
remove("test-bin");
return mrb_nil_value();
}
@@ -238,6 +265,12 @@ mrb_io_win_p(mrb_state *mrb, mrb_value klass)
#endif
}
#ifdef MRB_WITH_IO_PREAD_PWRITE
# define MRB_WITH_IO_PREAD_PWRITE_ENABLED TRUE
#else
# define MRB_WITH_IO_PREAD_PWRITE_ENABLED FALSE
#endif
void
mrb_mruby_io_gem_test(mrb_state* mrb)
{
@@ -245,10 +278,9 @@ mrb_mruby_io_gem_test(mrb_state* mrb)
mrb_define_class_method(mrb, io_test, "io_test_setup", mrb_io_test_io_setup, MRB_ARGS_NONE());
mrb_define_class_method(mrb, io_test, "io_test_cleanup", mrb_io_test_io_cleanup, MRB_ARGS_NONE());
mrb_define_class_method(mrb, io_test, "file_test_setup", mrb_io_test_file_setup, MRB_ARGS_NONE());
mrb_define_class_method(mrb, io_test, "file_test_cleanup", mrb_io_test_file_cleanup, MRB_ARGS_NONE());
mrb_define_class_method(mrb, io_test, "mkdtemp", mrb_io_test_mkdtemp, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, io_test, "rmdir", mrb_io_test_rmdir, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, io_test, "win?", mrb_io_win_p, MRB_ARGS_NONE());
mrb_define_const(mrb, io_test, "MRB_WITH_IO_PREAD_PWRITE", mrb_bool_value(MRB_WITH_IO_PREAD_PWRITE_ENABLED));
}
+1 -1
View File
@@ -213,7 +213,7 @@ mrb_mruby_kernel_ext_gem_init(mrb_state *mrb)
mrb_define_module_function(mrb, krn, "fail", mrb_f_raise, MRB_ARGS_OPT(2));
mrb_define_module_function(mrb, krn, "caller", mrb_f_caller, MRB_ARGS_OPT(2));
mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE());
mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ANY());
mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ARG(1,1));
#ifndef MRB_WITHOUT_FLOAT
mrb_define_module_function(mrb, krn, "Float", mrb_f_float, MRB_ARGS_REQ(1));
#endif
+37 -9
View File
@@ -49,24 +49,52 @@ assert('Kernel#__method__') do
end
assert('Kernel#Integer') do
assert_equal(26, Integer("0x1a"))
assert_equal(930, Integer("0930", 10))
assert_equal(7, Integer("111", 2))
assert_equal(0, Integer("0"))
assert_equal(0, Integer("00000"))
assert_operator(26, :eql?, Integer("0x1a"))
assert_operator(930, :eql?, Integer("0930", 10))
assert_operator(7, :eql?, Integer("111", 2))
assert_operator(0, :eql?, Integer("0"))
assert_operator(0, :eql?, Integer("00000"))
assert_operator(123, :eql?, Integer('1_2_3'))
assert_operator(123, :eql?, Integer("\t\r\n\f\v 123 \t\r\n\f\v"))
assert_raise(TypeError) { Integer(nil) }
assert_raise(ArgumentError) { Integer('a') }
assert_raise(ArgumentError) { Integer('4a5') }
assert_raise(ArgumentError) { Integer('1_2__3') }
assert_raise(ArgumentError) { Integer('68_') }
assert_raise(ArgumentError) { Integer('68_ ') }
assert_raise(ArgumentError) { Integer('_68') }
assert_raise(ArgumentError) { Integer(' _68') }
assert_raise(ArgumentError) { Integer('6 8') }
assert_raise(ArgumentError) { Integer("15\0") }
assert_raise(ArgumentError) { Integer("15.0") }
skip unless Object.const_defined?(:Float)
assert_equal(123, Integer(123.999))
assert_operator(123, :eql?, Integer(123.999))
end
assert('Kernel#Float') do
skip unless Object.const_defined?(:Float)
assert_equal(1.0, Float(1))
assert_equal(123.456, Float(123.456))
assert_equal(123.456, Float("123.456"))
assert_operator(1.0, :eql?, Float(1))
assert_operator(123.456, :eql?, Float(123.456))
assert_operator(123.456, :eql?, Float("123.456"))
assert_operator(123.0, :eql?, Float('1_2_3'))
assert_operator(12.34, :eql?, Float('1_2.3_4'))
assert_operator(0.9, :eql?, Float('.9'))
assert_operator(0.9, :eql?, Float(" \t\r\n\f\v.9 \t\r\n\f\v"))
assert_operator(16.0, :eql?, Float("0x10"))
assert_raise(TypeError) { Float(nil) }
assert_raise(ArgumentError) { Float("1. 5") }
assert_raise(ArgumentError) { Float("1.5a") }
assert_raise(ArgumentError) { Float("1.5\0") }
assert_raise(ArgumentError) { Float('a') }
assert_raise(ArgumentError) { Float('4a5') }
assert_raise(ArgumentError) { Float('1_2__3') }
assert_raise(ArgumentError) { Float('68_') }
assert_raise(ArgumentError) { Float('68._7') }
assert_raise(ArgumentError) { Float('68.7_') }
assert_raise(ArgumentError) { Float('68.7_ ') }
assert_raise(ArgumentError) { Float('_68') }
assert_raise(ArgumentError) { Float(' _68') }
assert_raise(ArgumentError) { Float('1_2.3__4') }
end
assert('Kernel#String') do
+113 -6
View File
@@ -1,6 +1,14 @@
##
# Math Test
def assert_float_and_int(exp_ary, act_ary)
assert('assert_float_and_int') do
flo_exp, int_exp, flo_act, int_act = *exp_ary, *act_ary
assert_float(flo_exp, flo_act)
assert_operator(int_exp, :eql?, int_act)
end
end
assert('Math.sin 0') do
assert_float(0, Math.sin(0))
end
@@ -109,12 +117,6 @@ assert('Math.hypot') do
assert_float(5.0, Math.hypot(3, 4))
end
assert('Math.frexp 1234') do
n = 1234
fraction, exponent = Math.frexp(n)
assert_float(n, Math.ldexp(fraction, exponent))
end
assert('Math.erf 1') do
assert_float(0.842700792949715, Math.erf(1))
end
@@ -130,3 +132,108 @@ end
assert('Math.erfc -1') do
assert_float(1.8427007929497148, Math.erfc(-1))
end
assert('Math.acos') do
assert_float(0 * Math::PI / 4, Math.acos( 1.0))
assert_float(1 * Math::PI / 4, Math.acos( 1.0 / Math.sqrt(2)))
assert_float(2 * Math::PI / 4, Math.acos( 0.0))
assert_float(4 * Math::PI / 4, Math.acos(-1.0))
assert_raise(Math::DomainError) { Math.acos(+1.1) }
assert_raise(Math::DomainError) { Math.acos(-1.1) }
end
assert('Math.asin') do
assert_float( 0 * Math::PI / 4, Math.asin( 0.0))
assert_float( 1 * Math::PI / 4, Math.asin( 1.0 / Math.sqrt(2)))
assert_float( 2 * Math::PI / 4, Math.asin( 1.0))
assert_float(-2 * Math::PI / 4, Math.asin(-1.0))
assert_raise(Math::DomainError) { Math.asin(+1.1) }
assert_raise(Math::DomainError) { Math.asin(-1.1) }
assert_raise(Math::DomainError) { Math.asin(2.0) }
end
assert('Math.atan') do
assert_float( 0 * Math::PI / 4, Math.atan( 0.0))
assert_float( 1 * Math::PI / 4, Math.atan( 1.0))
assert_float( 2 * Math::PI / 4, Math.atan(1.0 / 0.0))
assert_float(-1 * Math::PI / 4, Math.atan(-1.0))
end
assert('Math.cosh') do
assert_float(1, Math.cosh(0))
assert_float((Math::E ** 1 + Math::E ** -1) / 2, Math.cosh(1))
assert_float((Math::E ** 2 + Math::E ** -2) / 2, Math.cosh(2))
end
assert('Math.sinh') do
assert_float(0, Math.sinh(0))
assert_float((Math::E ** 1 - Math::E ** -1) / 2, Math.sinh(1))
assert_float((Math::E ** 2 - Math::E ** -2) / 2, Math.sinh(2))
end
assert('Math.tanh') do
assert_float(Math.sinh(0) / Math.cosh(0), Math.tanh(0))
assert_float(Math.sinh(1) / Math.cosh(1), Math.tanh(1))
assert_float(Math.sinh(2) / Math.cosh(2), Math.tanh(2))
assert_float(+1.0, Math.tanh(+1000.0))
assert_float(-1.0, Math.tanh(-1000.0))
end
assert('Math.acosh') do
assert_float(0, Math.acosh(1))
assert_float(1, Math.acosh((Math::E ** 1 + Math::E ** -1) / 2))
assert_float(2, Math.acosh((Math::E ** 2 + Math::E ** -2) / 2))
assert_raise(Math::DomainError) { Math.acosh(0.9) }
assert_raise(Math::DomainError) { Math.acosh(0) }
end
assert('Math.asinh') do
assert_float(0, Math.asinh(0))
assert_float(1, Math.asinh((Math::E ** 1 - Math::E ** -1) / 2))
assert_float(2, Math.asinh((Math::E ** 2 - Math::E ** -2) / 2))
end
assert('Math.atanh') do
assert_float(0, Math.atanh(Math.sinh(0) / Math.cosh(0)))
assert_float(1, Math.atanh(Math.sinh(1) / Math.cosh(1)))
assert_float(2, Math.atanh(Math.sinh(2) / Math.cosh(2)))
assert_float(Float::INFINITY, Math.atanh(1))
assert_float(-Float::INFINITY, Math.atanh(-1))
assert_raise(Math::DomainError) { Math.atanh(+1.1) }
assert_raise(Math::DomainError) { Math.atanh(-1.1) }
end
assert('Math.atan2') do
assert_float(+0.0, Math.atan2(+0.0, +0.0))
assert_float(-0.0, Math.atan2(-0.0, +0.0))
assert_float(+Math::PI, Math.atan2(+0.0, -0.0))
assert_float(-Math::PI, Math.atan2(-0.0, -0.0))
inf = Float::INFINITY
expected = 3.0 * Math::PI / 4.0
assert_float(+expected, Math.atan2(+inf, -inf))
assert_float(-expected, Math.atan2(-inf, -inf))
expected = Math::PI / 4.0
assert_float(+expected, Math.atan2(+inf, +inf))
assert_float(-expected, Math.atan2(-inf, +inf))
assert_float(0, Math.atan2(0, 1))
assert_float(Math::PI / 4, Math.atan2(1, 1))
assert_float(Math::PI / 2, Math.atan2(1, 0))
end
assert('Math.ldexp') do
assert_float(0.0, Math.ldexp(0.0, 0.0))
assert_float(0.5, Math.ldexp(0.5, 0.0))
assert_float(1.0, Math.ldexp(0.5, 1.0))
assert_float(2.0, Math.ldexp(0.5, 2.0))
assert_float(3.0, Math.ldexp(0.75, 2.0))
end
assert('Math.frexp') do
assert_float_and_int([0.0, 0], Math.frexp(0.0))
assert_float_and_int([0.5, 0], Math.frexp(0.5))
assert_float_and_int([0.5, 1], Math.frexp(1.0))
assert_float_and_int([0.5, 2], Math.frexp(2.0))
assert_float_and_int([0.75, 2], Math.frexp(3.0))
end
+25 -14
View File
@@ -139,7 +139,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
proc = mrb->c->ci[-1].proc;
if (MRB_PROC_CFUNC_P(proc)) {
if (proc == NULL || MRB_PROC_CFUNC_P(proc)) {
return mrb_ary_new(mrb);
}
vars = mrb_hash_new(mrb);
@@ -172,7 +172,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
KHASH_DECLARE(st, mrb_sym, char, FALSE)
static void
method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
method_entry_loop(mrb_state *mrb, struct RClass *klass, khash_t(st) *set, khash_t(st) *undef)
{
khint_t i;
@@ -181,20 +181,28 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
for (i=0;i<kh_end(h);i++) {
if (kh_exist(h, i)) {
mrb_method_t m = kh_value(h, i);
if (MRB_METHOD_UNDEF_P(m)) continue;
kh_put(st, mrb, set, kh_key(h, i));
if (MRB_METHOD_UNDEF_P(m)) {
if (undef) {
kh_put(st, mrb, undef, kh_key(h, i));
}
}
else if (undef == NULL ||
kh_get(st, mrb, undef, kh_key(h, i)) == kh_end(undef)) {
kh_put(st, mrb, set, kh_key(h, i));
}
}
}
}
static mrb_value
mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj)
mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *klass, int obj)
{
khint_t i;
mrb_value ary;
mrb_bool prepended = FALSE;
struct RClass* oldklass;
khash_t(st)* set = kh_init(st, mrb);
struct RClass *oldklass;
khash_t(st) *set = kh_init(st, mrb);
khash_t(st) *undef = (recur ? kh_init(st, mrb) : NULL);
if (!recur && (klass->flags & MRB_FL_CLASS_IS_PREPENDED)) {
MRB_CLASS_ORIGIN(klass);
@@ -203,7 +211,7 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl
oldklass = 0;
while (klass && (klass != oldklass)) {
method_entry_loop(mrb, klass, set);
method_entry_loop(mrb, klass, set, undef);
if ((klass->tt == MRB_TT_ICLASS && !prepended) ||
(klass->tt == MRB_TT_SCLASS)) {
}
@@ -221,6 +229,7 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl
}
}
kh_destroy(st, mrb, set);
if (undef) kh_destroy(st, mrb, undef);
return ary;
}
@@ -313,18 +322,19 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
{
khint_t i;
mrb_value ary;
struct RClass* klass;
khash_t(st)* set = kh_init(st, mrb);
struct RClass *klass;
khash_t(st) *set = kh_init(st, mrb);
khash_t(st) *undef = (recur ? kh_init(st, mrb) : NULL);
klass = mrb_class(mrb, obj);
if (klass && (klass->tt == MRB_TT_SCLASS)) {
method_entry_loop(mrb, klass, set);
method_entry_loop(mrb, klass, set, undef);
klass = klass->super;
}
if (recur) {
while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) {
method_entry_loop(mrb, klass, set);
method_entry_loop(mrb, klass, set, undef);
klass = klass->super;
}
}
@@ -336,6 +346,7 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
}
}
kh_destroy(st, mrb, set);
if (undef) kh_destroy(st, mrb, undef);
return ary;
}
@@ -694,8 +705,8 @@ mrb_mruby_metaprog_gem_init(mrb_state* mrb)
mrb_define_method(mrb, krn, "protected_methods", mrb_obj_protected_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.37 */
mrb_define_method(mrb, krn, "public_methods", mrb_obj_public_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.38 */
mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.45 */
mrb_define_method(mrb, krn, "define_singleton_method", mod_define_singleton_method, MRB_ARGS_ANY());
mrb_define_method(mrb, krn, "send", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.44 */
mrb_define_method(mrb, krn, "define_singleton_method", mod_define_singleton_method, MRB_ARGS_REQ(1)|MRB_ARGS_BLOCK());
mrb_define_method(mrb, krn, "send", mrb_f_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK()); /* 15.3.1.3.44 */
mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_OPT(1)); /* 15.2.2.4.19 */
mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */
+1
View File
@@ -49,6 +49,7 @@ There is no dependency on other mrbgems.
## License
Copyright (c) 2012 Internet Initiative Japan Inc.
Copyright (c) 2017 mruby developers
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
+1 -1
View File
@@ -1,6 +1,6 @@
MRuby::Gem::Specification.new('mruby-pack') do |spec|
spec.license = 'MIT'
spec.authors = 'Internet Initiative Japan Inc.'
spec.authors = ['Internet Initiative Japan Inc.', 'mruby developers']
spec.summary = 'Array#pack and String#unpack method'
spec.cc.include_paths << "#{build.root}/src"
+6 -2
View File
@@ -2,7 +2,12 @@
** pack.c - Array#pack, String#unpack
*/
#include "mruby.h"
#include <mruby.h>
#ifdef MRB_DISABLE_STDIO
# error pack/unpack conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
#endif
#include "mruby/error.h"
#include "mruby/array.h"
#include "mruby/class.h"
@@ -13,7 +18,6 @@
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
struct tmpl {
+5 -1
View File
@@ -1,6 +1,10 @@
#include <mruby.h>
#ifdef MRB_DISABLE_STDIO
# error print conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
#endif
#include <mruby/string.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if defined(_WIN32)
+2 -2
View File
@@ -175,8 +175,8 @@ mrb_mruby_proc_ext_gem_init(mrb_state* mrb)
mrb_define_method(mrb, p, "inspect", mrb_proc_inspect, MRB_ARGS_NONE());
mrb_define_method(mrb, p, "parameters", mrb_proc_parameters, MRB_ARGS_NONE());
mrb_define_class_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE());
mrb_define_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE());
mrb_define_class_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
mrb_define_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
}
void
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-sleep') do |spec|
spec.license = 'MIT'
spec.authors = 'MATSUMOTO Ryosuke'
spec.authors = ['MATSUMOTO Ryosuke', 'mruby developers']
spec.version = '0.0.1'
end
+1
View File
@@ -2,6 +2,7 @@
** mrb_sleep - sleep methods for mruby
**
** Copyright (c) mod_mruby developers 2012-
** Copyright (c) mruby developers 2018
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
+1
View File
@@ -35,6 +35,7 @@ Date: Tue, 21 May 2013 04:31:30 GMT
## License
Copyright (c) 2013 Internet Initiative Japan Inc.
Copyright (c) 2017 mruby developers
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
+2 -2
View File
@@ -1,13 +1,13 @@
MRuby::Gem::Specification.new('mruby-socket') do |spec|
spec.license = 'MIT'
spec.authors = 'Internet Initiative Japan'
spec.authors = ['Internet Initiative Japan', 'mruby developers']
spec.summary = 'standard socket class'
spec.cc.include_paths << "#{build.root}/src"
#spec.cc.defines << "HAVE_SA_LEN=0"
# If Windows, use winsock
if ( /mswin|mingw|win32/ =~ RUBY_PLATFORM ) then
if for_windows?
spec.linker.libraries << "wsock32"
spec.linker.libraries << "ws2_32"
end
+1 -1
View File
@@ -476,7 +476,7 @@ mrb_basicsocket_setsockopt(mrb_state *mrb, mrb_value self)
optname = mrb_fixnum(mrb_funcall(mrb, so, "optname", 0));
optval = mrb_funcall(mrb, so, "data", 0);
} else {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%i for 3)", argc);
mrb_argnum_error(mrb, argc, 3, 3);
}
s = socket_fd(mrb, self);
+3 -2
View File
@@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include "mruby.h"
@@ -8,7 +7,9 @@
#include <io.h>
#ifdef _MSC_VER
#if defined(_MSC_VER) || \
(defined(MRB_MINGW32_VERSION) && MRB_MINGW32_VERSION < 3021) || \
(defined(MRB_MINGW64_VERSION) && MRB_MINGW64_VERSION < 4000)
#include <fcntl.h>
#include <sys/stat.h>
+2 -2
View File
@@ -18,8 +18,8 @@ mrb_mruby_sprintf_gem_init(mrb_state* mrb)
}
krn = mrb->kernel_module;
mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, MRB_ARGS_ANY());
mrb_define_method(mrb, krn, "format", mrb_f_sprintf, MRB_ARGS_ANY());
mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, MRB_ARGS_REQ(1)|MRB_ARGS_REST());
mrb_define_method(mrb, krn, "format", mrb_f_sprintf, MRB_ARGS_REQ(1)|MRB_ARGS_REST());
}
void
+4 -1
View File
@@ -6,8 +6,11 @@
#include <mruby.h>
#ifdef MRB_DISABLE_STDIO
# error sprintf conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
#endif
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <mruby/string.h>
#include <mruby/hash.h>
+2 -2
View File
@@ -174,8 +174,8 @@ mrb_str_concat_m(mrb_state *mrb, mrb_value self)
str = int_chr_binary(mrb, str);
#endif
else
str = mrb_ensure_string_type(mrb, str);
mrb_str_concat(mrb, self, str);
mrb_ensure_string_type(mrb, str);
mrb_str_cat_str(mrb, self, str);
return self;
}

Some files were not shown because too many files have changed in this diff Show More