summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--AUTHORS1
-rw-r--r--LEGAL40
-rw-r--r--README.md3
-rw-r--r--Rakefile31
-rw-r--r--TODO1
-rw-r--r--build_config.rb36
-rw-r--r--doc/mrbgems/README.md3
-rw-r--r--examples/targets/ArduinoDue.rb32
-rw-r--r--include/mrbconf.h72
-rw-r--r--include/mruby.h59
-rw-r--r--include/mruby/array.h17
-rw-r--r--include/mruby/class.h6
-rw-r--r--include/mruby/compile.h66
-rw-r--r--include/mruby/data.h2
-rw-r--r--include/mruby/dump.h170
-rw-r--r--include/mruby/hash.h2
-rw-r--r--include/mruby/irep.h14
-rw-r--r--include/mruby/khash.h20
-rw-r--r--include/mruby/numeric.h8
-rw-r--r--include/mruby/string.h29
-rw-r--r--include/mruby/value.h87
-rw-r--r--include/mruby/variable.h10
-rw-r--r--mrbgems/mruby-array-ext/mrbgem.rake4
-rw-r--r--mrbgems/mruby-array-ext/mrblib/array.rb98
-rw-r--r--mrbgems/mruby-array-ext/src/array.c140
-rw-r--r--mrbgems/mruby-array-ext/test/array.rb109
-rw-r--r--mrbgems/mruby-enum-ext/mrbgem.rake4
-rw-r--r--mrbgems/mruby-enum-ext/mrblib/enum.rb164
-rw-r--r--mrbgems/mruby-enum-ext/test/enum.rb44
-rw-r--r--mrbgems/mruby-eval/mrbgem.rake4
-rw-r--r--mrbgems/mruby-eval/src/eval.c23
-rw-r--r--mrbgems/mruby-hash-ext/mrbgem.rake4
-rw-r--r--mrbgems/mruby-hash-ext/mrblib/hash.rb12
-rw-r--r--mrbgems/mruby-hash-ext/test/hash.rb20
-rw-r--r--mrbgems/mruby-math/src/math.c40
-rw-r--r--mrbgems/mruby-numeric-ext/mrbgem.rake4
-rw-r--r--mrbgems/mruby-numeric-ext/src/numeric_ext.c31
-rw-r--r--mrbgems/mruby-numeric-ext/test/numeric.rb10
-rw-r--r--mrbgems/mruby-print/mrbgem.rake4
-rw-r--r--mrbgems/mruby-print/mrblib/print.rb64
-rw-r--r--mrbgems/mruby-print/src/print.c44
-rw-r--r--mrbgems/mruby-random/mrbgem.rake4
-rw-r--r--mrbgems/mruby-random/src/mt19937ar.c232
-rw-r--r--mrbgems/mruby-random/src/mt19937ar.h87
-rw-r--r--mrbgems/mruby-random/src/random.c233
-rw-r--r--mrbgems/mruby-random/src/random.h12
-rw-r--r--mrbgems/mruby-random/test/random.rb32
-rw-r--r--mrbgems/mruby-sprintf/mrbgem.rake4
-rw-r--r--mrbgems/mruby-sprintf/src/kernel.c30
-rw-r--r--mrbgems/mruby-sprintf/src/sprintf.c (renamed from src/sprintf.c)95
-rw-r--r--mrbgems/mruby-sprintf/test/sprintf.rb3
-rw-r--r--mrbgems/mruby-string-ext/mrbgem.rake4
-rw-r--r--mrbgems/mruby-string-ext/mrblib/string.rb38
-rw-r--r--mrbgems/mruby-string-ext/src/string.c31
-rw-r--r--mrbgems/mruby-string-ext/test/string.rb72
-rw-r--r--mrbgems/mruby-struct/src/struct.c150
-rw-r--r--mrbgems/mruby-time/src/time.c38
-rw-r--r--mrblib/array.rb2
-rw-r--r--mrblib/compar.rb4
-rw-r--r--mrblib/enum.rb12
-rw-r--r--mrblib/hash.rb2
-rw-r--r--mrblib/init_mrblib.c2
-rw-r--r--mrblib/print.rb84
-rw-r--r--src/array.c201
-rw-r--r--src/class.c209
-rw-r--r--src/codegen.c241
-rw-r--r--src/crc.c12
-rw-r--r--src/dump.c881
-rw-r--r--src/error.c254
-rw-r--r--src/error.h3
-rw-r--r--src/etc.c8
-rw-r--r--src/gc.c78
-rw-r--r--src/hash.c59
-rw-r--r--src/init.c4
-rw-r--r--src/kernel.c134
-rw-r--r--src/keywords78
-rw-r--r--src/lex.def92
-rw-r--r--src/load.c987
-rw-r--r--src/node.h11
-rw-r--r--src/numeric.c241
-rw-r--r--src/object.c47
-rw-r--r--src/opcode.h25
-rw-r--r--src/parse.y962
-rw-r--r--src/pool.c6
-rw-r--r--src/print.c56
-rw-r--r--src/proc.c2
-rw-r--r--src/range.c103
-rw-r--r--src/state.c56
-rw-r--r--src/string.c368
-rw-r--r--src/symbol.c247
-rw-r--r--src/value_array.h27
-rw-r--r--src/variable.c165
-rw-r--r--src/vm.c408
-rw-r--r--tasks/mrbgem_spec.rake12
-rw-r--r--tasks/mrbgems.rake47
-rw-r--r--tasks/mrbgems_test.rake8
-rw-r--r--tasks/mruby_build.rake14
-rw-r--r--tasks/mruby_build_commands.rake55
-rw-r--r--tasks/mruby_build_gem.rake11
-rw-r--r--tasks/toolchains/androideabi.rake114
-rw-r--r--test/driver.c44
-rw-r--r--test/init_mrbtest.c3
-rw-r--r--test/t/literals.rb202
-rw-r--r--tools/mirb/mirb.c127
-rw-r--r--tools/mrbc/mrbc.c33
-rw-r--r--tools/mruby/mruby.c39
-rw-r--r--travis_config.rb10
108 files changed, 5961 insertions, 3427 deletions
diff --git a/.travis.yml b/.travis.yml
index 109013b10..48da43be4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,4 @@
# no installation...
+env: MRUBY_CONFIG=travis_config.rb
script: "./minirake all test"
diff --git a/AUTHORS b/AUTHORS
index dc5d7a508..17fe246de 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -10,3 +10,4 @@ Original Authors "mruby developers" are:
Masamitsu MURASE
Masaki Muranaka
Internet Initiative Japan Inc.
+ Tadashi FUKUZAWA
diff --git a/LEGAL b/LEGAL
index 036b35a95..a36f0bcc1 100644
--- a/LEGAL
+++ b/LEGAL
@@ -5,4 +5,42 @@ All the files in this distribution are covered under the MIT license
(see the file MITL) except some files mentioned below:
-(Currently no items are listed.)
+mrbgems/mruby-random/src/mt19937ar.[ch]
+
+ A C-program for MT19937, with initialization improved 2002/1/26.
+ Coded by Takuji Nishimura and Makoto Matsumoto.
+
+ Before using, initialize the state by using init_genrand(seed)
+ or init_by_array(init_key, key_length).
+
+ Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+ All rights reserved.
+ Copyright (C) 2005, Mutsuo Saito,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The names of its contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
index 93a9c0f01..32d177334 100644
--- a/README.md
+++ b/README.md
@@ -110,6 +110,7 @@ Please ask us if you want to distribute your code under another license.
## How to Contribute
-Send pull request to <http://github.com/mruby/mruby>. We consider you have granted
+See the [contribution guidelines](https://github.com/mruby/mruby/blob/master/CONTRIBUTING.md)
+then send a pull request to <http://github.com/mruby/mruby>. We consider you have granted
non-exclusive right to your contributed code under MIT license. If you want to be named
as one of mruby developers, include update to the AUTHORS file in your pull request.
diff --git a/Rakefile b/Rakefile
index 633c50385..ab5e6c6e6 100644
--- a/Rakefile
+++ b/Rakefile
@@ -2,6 +2,7 @@
# Build description.
# basic build file for mruby
MRUBY_ROOT = File.dirname(File.expand_path(__FILE__))
+MRUBY_BUILD_HOST_IS_CYGWIN = RUBY_PLATFORM.include?('cygwin')
# load build systems
load "#{MRUBY_ROOT}/tasks/ruby_ext.rake"
@@ -9,10 +10,8 @@ load "#{MRUBY_ROOT}/tasks/mruby_build.rake"
load "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake"
# load configuration file
-MRUBY_CONFIGS = ["#{MRUBY_ROOT}/build_config.rb", ENV['MRUBY_CONFIG']].compact
-MRUBY_CONFIGS.each do |config|
- load config unless config.empty?
-end
+MRUBY_CONFIG = (ENV['MRUBY_CONFIG'] && ENV['MRUBY_CONFIG'] != '') ? ENV['MRUBY_CONFIG'] : "#{MRUBY_ROOT}/build_config.rb"
+load MRUBY_CONFIG
# load basic rules
MRuby.each_target do |build|
@@ -48,6 +47,30 @@ depfiles = MRuby.targets['host'].bins.map do |bin|
install_path
end
+MRuby.each_target do
+ gems.map do | gem |
+ current_dir = gem.dir.relative_path_from(Dir.pwd)
+ relative_from_root = gem.dir.relative_path_from(MRUBY_ROOT)
+ current_build_dir = "#{build_dir}/#{relative_from_root}"
+
+ gem.bins.each do | bin |
+ exec = exefile("#{build_dir}/bin/#{bin}")
+ objs = Dir.glob("#{current_dir}/tool/#{bin}/*.c").map { |f| objfile(f.pathmap("#{current_build_dir}/tool/#{bin}/%n")) }
+
+ file exec => objs + [libfile("#{build_dir}/lib/libmruby")] do |t|
+ gem_flags = gems.map { |g| g.linker.flags }
+ gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries }
+ gem_flags_after_libraries = gems.map { |g| g.linker.flags_after_libraries }
+ gem_libraries = gems.map { |g| g.linker.libraries }
+ gem_library_paths = gems.map { |g| g.linker.library_paths }
+ linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries
+ end
+
+ depfiles += [ exec ]
+ end
+ end
+end
+
depfiles += MRuby.targets.reject { |n, t| n == 'host' }.map { |n, t|
[t.libfile("#{t.build_dir}/lib/libmruby")] + t.bins.map { |bin| t.exefile("#{t.build_dir}/bin/#{bin}") }
}.flatten
diff --git a/TODO b/TODO
index f8e463bca..a26b805a3 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,5 @@
Things to do (Things that are not done yet)
-* Here document
* Special variables ($1,$2..)
* super in aliased methods
* BEGIN/END (Were we not supporting this?)
diff --git a/build_config.rb b/build_config.rb
index d3feccd71..5ea4aad4f 100644
--- a/build_config.rb
+++ b/build_config.rb
@@ -11,18 +11,46 @@ MRuby::Build.new do |conf|
# conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master'
# conf.gem :git => '[email protected]:masuidrive/mrbgems-example.git', :branch => 'master', :options => '-v'
+ # Use standard Kernel#sprintf method
+ conf.gem "#{root}/mrbgems/mruby-sprintf"
+
+ # Use standard print/puts/p
+ conf.gem "#{root}/mrbgems/mruby-print"
+
# Use standard Math module
- conf.gem 'mrbgems/mruby-math'
+ conf.gem "#{root}/mrbgems/mruby-math"
# Use standard Time class
- conf.gem 'mrbgems/mruby-time'
+ conf.gem "#{root}/mrbgems/mruby-time"
# Use standard Struct class
- conf.gem 'mrbgems/mruby-struct'
+ conf.gem "#{root}/mrbgems/mruby-struct"
+
+ # Use extensional Enumerable module
+ conf.gem "#{root}/mrbgems/mruby-enum-ext"
+
+ # Use extensional String class
+ conf.gem "#{root}/mrbgems/mruby-string-ext"
+
+ # Use extensional Numeric class
+ conf.gem "#{root}/mrbgems/mruby-numeric-ext"
+
+ # Use extensional Array class
+ conf.gem "#{root}/mrbgems/mruby-array-ext"
+
+ # Use extensional Hash class
+ conf.gem "#{root}/mrbgems/mruby-hash-ext"
+
+ # Use Random class
+ conf.gem "#{root}/mrbgems/mruby-random"
+
+ # No use eval method
+ # conf.gem "#{root}/mrbgems/mruby-eval"
+
# Generate binaries
# conf.bins = %w(mrbc mruby mirb)
-
+
# C compiler settings
# conf.cc do |cc|
# cc.command = ENV['CC'] || 'gcc'
diff --git a/doc/mrbgems/README.md b/doc/mrbgems/README.md
index 6c473b57d..eb6596ec8 100644
--- a/doc/mrbgems/README.md
+++ b/doc/mrbgems/README.md
@@ -23,6 +23,9 @@ A remote GIT repository location for a GEM is also supported:
conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master'
+ conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master'
+
+NOTE: ':bitbucket' option supports only git. Hg is unsupported in this version.
## GEM Structure
diff --git a/examples/targets/ArduinoDue.rb b/examples/targets/ArduinoDue.rb
new file mode 100644
index 000000000..3fad6ecea
--- /dev/null
+++ b/examples/targets/ArduinoDue.rb
@@ -0,0 +1,32 @@
+# Cross Compiling configuration for Arduino Duea
+# http://arduino.cc/en/Main/ArduinoBoardDue
+#
+# Requires Arduino IDE >= 1.5
+MRuby::CrossBuild.new("Arduino Due") do |conf|
+ toolchain :gcc
+
+ # GNU Linux
+ ARDUINO_PATH = '/opt/arduino'
+ BIN_PATH = "#{ARDUINO_PATH}/hardware/tools/g++_arm_none_eabi/bin"
+ SAM_PATH = "#{ARDUINO_PATH}/hardware/arduino/sam"
+ TARGET_PATH = "#{SAM_PATH}/variants/arduino_due_x"
+
+ conf.cc do |cc|
+ cc.command = "#{BIN_PATH}/arm-none-eabi-gcc"
+ cc.include_paths = ["#{SAM_PATH}/system/libsam -I#{SAM_PATH}/system/CMSIS/CMSIS/Include/",
+ "#{SAM_PATH}/system/CMSIS/Device/ATMEL/",
+ "#{SAM_PATH}/cores/arduino -I#{TARGET_PATH}",
+ "#{MRUBY_ROOT}/include"]
+ cc.flags << '-g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 ' +
+ '-Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=152 -D__SAM3X8E__ -mthumb -DUSB_PID=0x003e -DUSB_VID=0x2341 -DUSBCON'
+ cc.compile_options = "%{flags} -o %{outfile} -c %{infile}"
+ end
+
+ conf.archiver do |archiver|
+ archiver.command = "#{BIN_PATH}/arm-none-eabi-ar"
+ archiver.archive_options = 'rcs %{outfile} %{objs}'
+ end
+
+ # No binaries necessary
+ conf.bins = []
+end
diff --git a/include/mrbconf.h b/include/mrbconf.h
index c84480af7..d8dca7d61 100644
--- a/include/mrbconf.h
+++ b/include/mrbconf.h
@@ -8,6 +8,7 @@
#define MRUBYCONF_H
#include <stdint.h>
+#include <stddef.h>
/* configuration options: */
/* add -DMRB_USE_FLOAT to use float instead of double for floating point numbers */
@@ -23,7 +24,7 @@
//#define MRB_ENDIAN_BIG
/* argv max size in mrb_funcall */
-//#define MRB_FUNCALL_ARGC_MAX 16
+//#define MRB_FUNCALL_ARGC_MAX 16
/* number of object per heap page */
//#define MRB_HEAP_PAGE_SIZE 1024
@@ -34,6 +35,9 @@
/* initial size for IV khash; ignored when MRB_USE_IV_SEGLIST is set */
//#define MRB_IVHASH_INIT_SIZE 8
+/* initial size for IREP array */
+//#define MRB_IREP_ARRAY_INIT_SIZE (256u)
+
/* default size of khash table bucket */
//#define KHASH_DEFAULT_SIZE 32
@@ -43,8 +47,13 @@
/* page size of memory pool */
//#define POOL_PAGE_SIZE 16000
+/* initial minimum size for string buffer */
+//#define MRB_STR_BUF_MIN_SIZE 128
+
+/* array size for parser buffer */
+//#define MRB_PARSER_BUF_SIZE 1024
+
/* -DDISABLE_XXXX to drop following features */
-//#define DISABLE_SPRINTF /* Kernel.sprintf method */
//#define DISABLE_STDIO /* use of stdio */
/* -DENABLE_XXXX to enable following features */
@@ -62,27 +71,36 @@
# define str_to_mrb_float(buf) strtod(buf, NULL)
#endif
-#ifdef MRB_INT64
+#if defined(MRB_INT64)
# ifdef MRB_NAN_BOXING
# error Cannot use NaN boxing when mrb_int is 64bit
# else
typedef int64_t mrb_int;
# define MRB_INT_MIN INT64_MIN
# define MRB_INT_MAX INT64_MAX
-# define str_to_mrb_int(buf) strtoll(buf, NULL, 10)
+# define PRIdMRB_INT PRId64
+# define PRIiMRB_INT PRIi64
+# define PRIoMRB_INT PRIo64
+# define PRIxMRB_INT PRIx64
+# define PRIXMRB_INT PRIX64
# endif
+#elif defined(MRB_INT16)
+ typedef int16_t mrb_int;
+# define MRB_INT_MIN INT16_MIN
+# define MRB_INT_MAX INT16_MAX
#else
typedef int32_t mrb_int;
# define MRB_INT_MIN INT32_MIN
# define MRB_INT_MAX INT32_MAX
-# define str_to_mrb_int(buf) strtol(buf, NULL, 10)
+# define PRIdMRB_INT PRId32
+# define PRIiMRB_INT PRIi32
+# define PRIoMRB_INT PRIo32
+# define PRIxMRB_INT PRIx32
+# define PRIXMRB_INT PRIX32
#endif
typedef short mrb_sym;
/* define ENABLE_XXXX from DISABLE_XXX */
-#ifndef DISABLE_SPRINTF
-#define ENABLE_SPRINTF
-#endif
#ifndef DISABLE_STDIO
#define ENABLE_STDIO
#endif
@@ -90,14 +108,6 @@ typedef short mrb_sym;
#define DISABLE_DEBUG
#endif
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-#ifndef TRUE
-# define TRUE 1
-#endif
-
#ifdef _MSC_VER
# include <float.h>
# define inline __inline
@@ -106,9 +116,39 @@ typedef short mrb_sym;
# define isinf(n) (!_finite(n) && !_isnan(n))
# define strtoll _strtoi64
# define PRId32 "I32d"
+# define PRIi32 "I32i"
+# define PRIo32 "I32o"
+# define PRIx32 "I32x"
+# define PRIX32 "I32X"
# define PRId64 "I64d"
+# define PRIi64 "I64i"
+# define PRIo64 "I64o"
+# define PRIx64 "I64x"
+# define PRIX64 "I64X"
+# ifdef __cplusplus
+typedef bool mrb_bool;
+# else
+typedef unsigned int mrb_bool;
+# endif
#else
# include <inttypes.h>
+# ifdef __cplusplus
+typedef bool mrb_bool;
+# else
+typedef _Bool mrb_bool;
+# endif
+#endif
+
+#ifdef ENABLE_STDIO
+# include <stdio.h>
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#ifndef TRUE
+# define TRUE 1
#endif
#endif /* MRUBYCONF_H */
diff --git a/include/mruby.h b/include/mruby.h
index 61df6e9ed..e204820a3 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -32,12 +32,12 @@
extern "C" {
#endif
-#include <stdlib.h>
#include "mrbconf.h"
#include "mruby/value.h"
typedef int32_t mrb_code;
+typedef int32_t mrb_aspec;
struct mrb_state;
@@ -90,6 +90,7 @@ typedef struct mrb_state {
size_t irep_len, irep_capa;
mrb_sym init_sym;
+ struct RObject *top_self;
struct RClass *object_class;
struct RClass *class_class;
struct RClass *module_class;
@@ -121,17 +122,14 @@ typedef struct mrb_state {
size_t gc_threshold;
int gc_interval_ratio;
int gc_step_ratio;
- unsigned int gc_disabled:1;
- unsigned int gc_full:1;
- unsigned int is_generational_gc_mode:1;
+ mrb_bool gc_disabled:1;
+ mrb_bool gc_full:1;
+ mrb_bool is_generational_gc_mode:1;
size_t majorgc_old_threshold;
struct alloca_header *mems;
mrb_sym symidx;
struct kh_n2s *name2sym; /* symbol table */
-#ifdef INCLUDE_REGEXP
- struct RNode *local_svar;/* regexp */
-#endif
#ifdef ENABLE_DEBUG
void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs);
@@ -141,6 +139,7 @@ typedef struct mrb_state {
struct RClass *eStandardError_class;
void *ud; /* auxiliary data */
+
} mrb_state;
typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
@@ -149,16 +148,17 @@ struct RClass *mrb_define_module(mrb_state *, const char*);
mrb_value mrb_singleton_class(mrb_state*, mrb_value);
void mrb_include_module(mrb_state*, struct RClass*, struct RClass*);
-void mrb_define_method(mrb_state*, struct RClass*, const char*, mrb_func_t,int);
-void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, int);
-void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t,int);
-void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t,int);
+void mrb_define_method(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec);
+void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec);
+void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec);
+void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec);
void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value);
void mrb_undef_method(mrb_state*, struct RClass*, const char*);
void mrb_undef_class_method(mrb_state*, struct RClass*, const char*);
mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv);
struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super);
struct RClass * mrb_module_new(mrb_state *mrb);
+int mrb_class_defined(mrb_state *mrb, const char *name);
struct RClass * mrb_class_get(mrb_state *mrb, const char *name);
struct RClass * mrb_class_obj_get(mrb_state *mrb, const char *name);
@@ -169,49 +169,56 @@ struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, con
struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name);
/* required arguments */
-#define ARGS_REQ(n) (((n)&0x1f) << 19)
+#define ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 19)
/* optional arguments */
-#define ARGS_OPT(n) (((n)&0x1f) << 14)
+#define ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 14)
/* rest argument */
-#define ARGS_REST() (1 << 13)
+#define ARGS_REST() ((mrb_aspec)(1 << 13))
/* required arguments after rest */
-#define ARGS_POST(n) (((n)&0x1f) << 8)
+#define ARGS_POST(n) ((mrb_aspec)((n)&0x1f) << 8)
/* keyword arguments (n of keys, kdict) */
-#define ARGS_KEY(n1,n2) ((((n1)&0x1f) << 3) | ((n2)?(1<<2):0))
+#define ARGS_KEY(n1,n2) ((mrb_aspec)((((n1)&0x1f) << 3) | ((n2)?(1<<2):0)))
/* block argument */
-#define ARGS_BLOCK() (1 << 1)
+#define ARGS_BLOCK() ((mrb_aspec)(1 << 1))
/* accept any number of arguments */
#define ARGS_ANY() ARGS_REST()
/* accept no arguments */
-#define ARGS_NONE() 0
+#define ARGS_NONE() ((mrb_aspec)0)
int mrb_get_args(mrb_state *mrb, const char *format, ...);
mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, int,...);
mrb_value mrb_funcall_argv(mrb_state*, mrb_value, mrb_sym, int, mrb_value*);
mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, int, mrb_value*, mrb_value);
-mrb_sym mrb_intern(mrb_state*,const char*);
-mrb_sym mrb_intern2(mrb_state*,const char*,int);
+mrb_sym mrb_intern_cstr(mrb_state*,const char*);
+mrb_sym mrb_intern2(mrb_state*,const char*,size_t);
mrb_sym mrb_intern_str(mrb_state*,mrb_value);
const char *mrb_sym2name(mrb_state*,mrb_sym);
-const char *mrb_sym2name_len(mrb_state*,mrb_sym,int*);
+const char *mrb_sym2name_len(mrb_state*,mrb_sym,size_t*);
+mrb_value mrb_sym2str(mrb_state*,mrb_sym);
mrb_value mrb_str_format(mrb_state *, int, const mrb_value *, mrb_value);
+/* For backward compatibility. */
+static inline
+mrb_sym mrb_intern(mrb_state *mrb,const char *cstr)
+{
+ return mrb_intern_cstr(mrb, cstr);
+}
+
void *mrb_malloc(mrb_state*, size_t);
void *mrb_calloc(mrb_state*, size_t, size_t);
void *mrb_realloc(mrb_state*, void*, size_t);
struct RBasic *mrb_obj_alloc(mrb_state*, enum mrb_vtype, struct RClass*);
void *mrb_free(mrb_state*, void*);
-mrb_value mrb_str_new(mrb_state *mrb, const char *p, int len); /* mrb_str_new */
+mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len);
mrb_value mrb_str_new_cstr(mrb_state*, const char*);
-mrb_value mrb_str_new2(mrb_state *mrb, const char *p);
mrb_state* mrb_open(void);
mrb_state* mrb_open_allocf(mrb_allocf, void *ud);
+void mrb_irep_free(mrb_state*, struct mrb_irep*);
void mrb_close(mrb_state*);
-int mrb_checkstack(mrb_state*,int);
mrb_value mrb_top_self(mrb_state *);
mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value);
@@ -234,11 +241,11 @@ int mrb_gc_arena_save(mrb_state*);
void mrb_gc_arena_restore(mrb_state*,int);
void mrb_gc_mark(mrb_state*,struct RBasic*);
#define mrb_gc_mark_value(mrb,val) do {\
- if (mrb_type(val) >= MRB_TT_OBJECT) mrb_gc_mark((mrb), mrb_object(val));\
+ if (mrb_type(val) >= MRB_TT_OBJECT) mrb_gc_mark((mrb), mrb_basic_ptr(val));\
} while (0)
void mrb_field_write_barrier(mrb_state *, struct RBasic*, struct RBasic*);
#define mrb_field_write_barrier_value(mrb, obj, val) do{\
- if ((val.tt >= MRB_TT_OBJECT)) mrb_field_write_barrier((mrb), (obj), mrb_object(val));\
+ if ((val.tt >= MRB_TT_OBJECT)) mrb_field_write_barrier((mrb), (obj), mrb_basic_ptr(val));\
} while (0)
void mrb_write_barrier(mrb_state *, struct RBasic*);
diff --git a/include/mruby/array.h b/include/mruby/array.h
index 9f9483545..d52ca1596 100644
--- a/include/mruby/array.h
+++ b/include/mruby/array.h
@@ -14,14 +14,14 @@ extern "C" {
typedef struct mrb_shared_array {
int refcnt;
mrb_value *ptr;
- int len;
+ mrb_int len;
} mrb_shared_array;
struct RArray {
MRB_OBJECT_HEADER;
- int len;
+ mrb_int len;
union {
- int capa;
+ mrb_int capa;
mrb_shared_array *shared;
} aux;
mrb_value *ptr;
@@ -36,26 +36,25 @@ struct RArray {
#define MRB_ARY_SHARED 256
void mrb_ary_decref(mrb_state*, mrb_shared_array*);
-mrb_value mrb_ary_new_capa(mrb_state*, int);
+mrb_value mrb_ary_new_capa(mrb_state*, mrb_int);
mrb_value mrb_ary_new(mrb_state *mrb);
-mrb_value mrb_ary_new_elts(mrb_state *mrb, int n, const mrb_value *elts);
+mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals);
void mrb_ary_concat(mrb_state*, mrb_value, mrb_value);
mrb_value mrb_ary_splat(mrb_state*, mrb_value);
void mrb_ary_push(mrb_state*, mrb_value, mrb_value);
mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary);
-mrb_value mrb_ary_new_from_values(mrb_state *mrb, int size, mrb_value *vals);
mrb_value mrb_ary_aget(mrb_state *mrb, mrb_value self);
mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n);
void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val);
-int mrb_ary_len(mrb_state *mrb, mrb_value ary);
+mrb_int mrb_ary_len(mrb_state *mrb, mrb_value ary);
void mrb_ary_replace(mrb_state *mrb, mrb_value a, mrb_value b);
mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item);
-mrb_value mrb_ary_new4(mrb_state *mrb, int n, const mrb_value *elts);
mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr);
-mrb_value mrb_ary_entry(mrb_value ary, int offset);
+mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self);
mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self);
+mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep);
#if defined(__cplusplus)
} /* extern "C" { */
diff --git a/include/mruby/class.h b/include/mruby/class.h
index e2f1bae46..4ab954d9e 100644
--- a/include/mruby/class.h
+++ b/include/mruby/class.h
@@ -39,10 +39,8 @@ mrb_class(mrb_state *mrb, mrb_value v)
return mrb->fixnum_class;
case MRB_TT_FLOAT:
return mrb->float_class;
- case MRB_TT_MAIN:
- return mrb->object_class;
default:
- return mrb_object(v)->c;
+ return mrb_obj_ptr(v)->c;
}
}
@@ -55,7 +53,7 @@ struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
void mrb_define_method_vm(mrb_state*, struct RClass*, mrb_sym, mrb_value);
void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *);
-void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, int aspec);
+void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b);
struct RClass *mrb_class_outer_module(mrb_state*, struct RClass *);
diff --git a/include/mruby/compile.h b/include/mruby/compile.h
index d0de0153b..51615fe9f 100644
--- a/include/mruby/compile.h
+++ b/include/mruby/compile.h
@@ -12,7 +12,6 @@ extern "C" {
#endif
#include "mruby.h"
-#include <stdio.h>
#include <setjmp.h>
/* load context */
@@ -21,9 +20,9 @@ typedef struct mrbc_context {
int slen;
char *filename;
short lineno;
- int capture_errors:1;
- int dump_result:1;
- int no_exec:1;
+ mrb_bool capture_errors:1;
+ mrb_bool dump_result:1;
+ mrb_bool no_exec:1;
} mrbc_context;
mrbc_context* mrbc_context_new(mrb_state *mrb);
@@ -59,20 +58,58 @@ struct mrb_parser_message {
char* message;
};
+#define STR_FUNC_PARSING 0x01
+#define STR_FUNC_EXPAND 0x02
+#define STR_FUNC_REGEXP 0x04
+#define STR_FUNC_WORD 0x08
+#define STR_FUNC_SYMBOL 0x10
+#define STR_FUNC_ARRAY 0x20
+#define STR_FUNC_HEREDOC 0x40
+#define STR_FUNC_XQUOTE 0x80
+
+enum mrb_string_type {
+ str_not_parsing = (0),
+ str_squote = (STR_FUNC_PARSING),
+ str_dquote = (STR_FUNC_PARSING|STR_FUNC_EXPAND),
+ str_regexp = (STR_FUNC_PARSING|STR_FUNC_REGEXP|STR_FUNC_EXPAND),
+ str_sword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY),
+ str_dword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY|STR_FUNC_EXPAND),
+ str_ssym = (STR_FUNC_PARSING|STR_FUNC_SYMBOL),
+ str_ssymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY),
+ str_dsymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY|STR_FUNC_EXPAND),
+ str_heredoc = (STR_FUNC_PARSING|STR_FUNC_HEREDOC),
+ str_xquote = (STR_FUNC_PARSING|STR_FUNC_XQUOTE|STR_FUNC_EXPAND),
+};
+
+/* heredoc structure */
+struct mrb_parser_heredoc_info {
+ mrb_bool allow_indent:1;
+ mrb_bool line_head:1;
+ enum mrb_string_type type;
+ const char *term;
+ int term_len;
+ mrb_ast_node *doc;
+};
+
+#ifndef MRB_PARSER_BUF_SIZE
+# define MRB_PARSER_BUF_SIZE 1024
+#endif
+
/* parser structure */
struct mrb_parser_state {
mrb_state *mrb;
struct mrb_pool *pool;
mrb_ast_node *cells;
const char *s, *send;
+#ifdef ENABLE_STDIO
FILE *f;
+#endif
char *filename;
int lineno;
int column;
enum mrb_lex_state_enum lstate;
- int sterm;
- int regexp;
+ mrb_ast_node *lex_strterm; /* (type nest_level beg . end) */
unsigned int cond_stack;
unsigned int cmdarg_stack;
@@ -82,15 +119,18 @@ struct mrb_parser_state {
mrb_ast_node *locals;
mrb_ast_node *pb;
- char buf[1024];
+ char buf[MRB_PARSER_BUF_SIZE];
int bidx;
- mrb_ast_node *heredoc;
+ mrb_ast_node *heredocs; /* list of mrb_parser_heredoc_info* */
+ mrb_ast_node *parsing_heredoc;
+ mrb_bool heredoc_starts_nextline:1;
+ mrb_bool heredoc_end_now:1; /* for mirb */
void *ylval;
- int nerr;
- int nwarn;
+ size_t nerr;
+ size_t nwarn;
mrb_ast_node *tree;
int capture_errors;
@@ -105,16 +145,22 @@ void mrb_parser_free(struct mrb_parser_state*);
void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
/* utility functions */
+#ifdef ENABLE_STDIO
struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*);
+#endif
struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*);
struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mrbc_context*);
int mrb_generate_code(mrb_state*, struct mrb_parser_state*);
/* program load functions */
+#ifdef ENABLE_STDIO
mrb_value mrb_load_file(mrb_state*,FILE*);
+#endif
mrb_value mrb_load_string(mrb_state *mrb, const char *s);
mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len);
+#ifdef ENABLE_STDIO
mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
+#endif
mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt);
mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *cxt);
diff --git a/include/mruby/data.h b/include/mruby/data.h
index 55405e994..6ddaebfaa 100644
--- a/include/mruby/data.h
+++ b/include/mruby/data.h
@@ -19,7 +19,7 @@ typedef struct mrb_data_type {
struct RData {
MRB_OBJECT_HEADER;
struct iv_tbl *iv;
- mrb_data_type *type;
+ const mrb_data_type *type;
void *data;
};
diff --git a/include/mruby/dump.h b/include/mruby/dump.h
index 8b78e74d0..2533a4c93 100644
--- a/include/mruby/dump.h
+++ b/include/mruby/dump.h
@@ -1,5 +1,5 @@
/*
-** mruby/dump.h - mruby binary dumper (Rite binary format)
+** mruby/dump.h - mruby binary dumper (mrbc binary format)
**
** See Copyright Notice in mruby.h
*/
@@ -12,122 +12,114 @@ extern "C" {
#endif
#include "mruby.h"
-#ifdef ENABLE_STDIO
-#include <stdio.h>
-#endif
-#include <stdint.h>
#ifdef ENABLE_STDIO
-int mrb_dump_irep(mrb_state*,int,FILE*);
-int mrb_bdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname);
-
-int mrb_read_irep_file(mrb_state*,FILE*);
+int mrb_dump_irep_binary(mrb_state*, size_t, int, FILE*);
+int mrb_dump_irep_cfunc(mrb_state *mrb, size_t n, int, FILE *f, const char *initname);
+int32_t mrb_read_irep_file(mrb_state*, FILE*);
#endif
-int mrb_read_irep(mrb_state*,const char*);
+int32_t mrb_read_irep(mrb_state*, const uint8_t*);
#ifdef ENABLE_STDIO
mrb_value mrb_load_irep_file(mrb_state*,FILE*);
#endif
-/* dump type */
-#define DUMP_TYPE_CODE 0
-#define DUMP_TYPE_BIN 1
-#define DUMP_TYPE_HEX 2
-
/* dump/load error code
*
* NOTE: MRB_DUMP_GENERAL_FAILURE is caused by
* unspecified issues like malloc failed.
*/
-#define MRB_DUMP_OK 0
-#define MRB_DUMP_GENERAL_FAILURE -1
-#define MRB_DUMP_WRITE_FAULT -2
-#define MRB_DUMP_READ_FAULT -3
-#define MRB_DUMP_CRC_ERROR -4
-#define MRB_DUMP_INVALID_FILE_HEADER -5
-#define MRB_DUMP_INVALID_IREP -6
-#define MRB_DUMP_INVALID_ARGUMENT -7
-
-/* size of long/int/short value on dump/load */
-#define MRB_DUMP_SIZE_OF_LONG 4
-#define MRB_DUMP_SIZE_OF_INT 4
-#define MRB_DUMP_SIZE_OF_SHORT 2
-#define MRB_DUMP_SIZE_OF_CHAR 1
+#define MRB_DUMP_OK 0
+#define MRB_DUMP_GENERAL_FAILURE -1
+#define MRB_DUMP_WRITE_FAULT -2
+#define MRB_DUMP_READ_FAULT -3
+#define MRB_DUMP_CRC_ERROR -4
+#define MRB_DUMP_INVALID_FILE_HEADER -5
+#define MRB_DUMP_INVALID_IREP -6
+#define MRB_DUMP_INVALID_ARGUMENT -7
/* null symbol length */
-#define MRB_DUMP_NULL_SYM_LEN 0xFFFF
+#define MRB_DUMP_NULL_SYM_LEN 0xFFFF
-/* Use HEX format string */
-#define RITE_FILE_IS_HEX
+/* Rite Binary File header */
+#define RITE_BINARY_IDENFIFIER "RITE"
+#define RITE_BINARY_FORMAT_VER "0001"
+#define RITE_COMPILER_NAME "MATZ"
+#define RITE_COMPILER_VERSION "0000"
-#ifdef RITE_FILE_IS_HEX
-#define RITE_FILE_HEX_SIZE 2
-#else
-#define RITE_FILE_HEX_SIZE 1
-#endif
+#define RITE_VM_VER "0000"
-/* Rite Binary File header */
-#define RITE_FILE_IDENFIFIER "RITE"
-#define RITE_FILE_FORMAT_VER "00090000"
-#define RITE_VM_VER "00090000"
-#define RITE_COMPILER_TYPE "MATZ "
-#define RITE_COMPILER_VER "00090000"
-#define RITE_RESERVED " "
-
-/* irep header */
-#define RITE_IREP_IDENFIFIER 'S'
-#define RITE_IREP_TYPE_CLASS 'C'
-#define RITE_IREP_TYPE_MODULE 'M'
-
-#define MRB_DUMP_DEFAULT_STR_LEN 128
-
-//Rite Binary file_header
-typedef struct {
- unsigned char rbfi[4]; //Rite Binary File Identify
- unsigned char rbfv[8]; //Rite Binary File Format Version
- unsigned char risv[8]; //Rite Instruction Specification Version
- unsigned char rct[8]; //Rite Compiler Type
- unsigned char rcv[8]; //Rite Compiler Version
- unsigned char rbds[4]; //Rite Binary Data Size
- unsigned char nirep[2]; //Number of ireps
- unsigned char sirep[2]; //Start index
- unsigned char rsv[8]; //Reserved
-} rite_binary_header;
-
-// Rite File file_header
-typedef struct {
- unsigned char rbfi[4]; //Rite Binary File Identify
- unsigned char rbfv[8]; //Rite Binary File Format Version
- unsigned char risv[8]; //Rite Instruction Specification Version
- unsigned char rct[8]; //Rite Compiler Type
- unsigned char rcv[8]; //Rite Compiler Version
- unsigned char rbds[8]; //Rite Binary Data Size
- unsigned char nirep[4]; //Number of ireps
- unsigned char sirep[4]; //Start index
- unsigned char rsv[8]; //Reserved
- unsigned char hcrc[4]; //HCRC
-} rite_file_header;
+#define RITE_BINARY_EOF "END\0"
+#define RITE_SECTION_IREP_IDENTIFIER "IREP"
+#define RITE_SECTION_LIENO_IDENTIFIER "LINE"
+
+#define MRB_DUMP_DEFAULT_STR_LEN 128
+
+// binary header
+struct rite_binary_header {
+ uint8_t binary_identify[4]; // Binary Identifier
+ uint8_t binary_version[4]; // Binary Format Version
+ uint8_t binary_crc[2]; // Binary CRC
+ uint8_t binary_size[4]; // Binary Size
+ uint8_t compiler_name[4]; // Compiler name
+ uint8_t compiler_version[4];
+};
+
+// section header
+#define RITE_SECTION_HEADER \
+ uint8_t section_identify[4]; \
+ uint8_t section_size[4]
+
+struct rite_section_header {
+ RITE_SECTION_HEADER;
+};
+
+struct rite_section_irep_header {
+ RITE_SECTION_HEADER;
+
+ uint8_t rite_version[4]; // Rite Instruction Specification Version
+ uint8_t nirep[2]; // Number of ireps
+ uint8_t sirep[2]; // Start index
+};
+
+struct rite_section_lineno_header {
+ RITE_SECTION_HEADER;
+
+ uint8_t nirep[2]; // Number of ireps
+ uint8_t sirep[2]; // Start index
+};
+
+struct rite_binary_footer {
+ RITE_SECTION_HEADER;
+};
+
+static inline int
+uint8_to_bin(uint8_t s, uint8_t *bin)
+{
+ *bin = s;
+ return sizeof(uint8_t);
+}
static inline int
-uint16_to_bin(uint16_t s, char *bin)
+uint16_to_bin(uint16_t s, uint8_t *bin)
{
*bin++ = (s >> 8) & 0xff;
*bin = s & 0xff;
- return (MRB_DUMP_SIZE_OF_SHORT);
+ return sizeof(uint16_t);
}
static inline int
-uint32_to_bin(uint32_t l, char *bin)
+uint32_to_bin(uint32_t l, uint8_t *bin)
{
*bin++ = (l >> 24) & 0xff;
*bin++ = (l >> 16) & 0xff;
*bin++ = (l >> 8) & 0xff;
*bin = l & 0xff;
- return (MRB_DUMP_SIZE_OF_LONG);
+ return sizeof(uint32_t);
}
static inline uint32_t
-bin_to_uint32(unsigned char bin[])
+bin_to_uint32(const uint8_t *bin)
{
return (uint32_t)bin[0] << 24 |
(uint32_t)bin[1] << 16 |
@@ -136,12 +128,22 @@ bin_to_uint32(unsigned char bin[])
}
static inline uint16_t
-bin_to_uint16(unsigned char bin[])
+bin_to_uint16(const uint8_t *bin)
{
return (uint16_t)bin[0] << 8 |
(uint16_t)bin[1];
}
+static inline uint8_t
+bin_to_uint8(const uint8_t *bin)
+{
+ return (uint8_t)bin[0];
+}
+
+/* crc.c */
+uint32_t
+calc_crc_16_ccitt(const uint8_t *src, uint32_t nbytes, uint16_t crcwk);
+
#if defined(__cplusplus)
} /* extern "C" { */
#endif
diff --git a/include/mruby/hash.h b/include/mruby/hash.h
index ac28f13fd..baace7567 100644
--- a/include/mruby/hash.h
+++ b/include/mruby/hash.h
@@ -33,7 +33,7 @@ mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
/* RHASH_TBL allocates st_table if not available. */
#define RHASH(obj) ((struct RHash*)((obj).value.p))
#define RHASH_TBL(h) (RHASH(h)->ht)
-#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern(mrb, "ifnone"))
+#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern2(mrb, "ifnone", 6))
#define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h)
struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash);
diff --git a/include/mruby/irep.h b/include/mruby/irep.h
index 100afb494..0305b9e0b 100644
--- a/include/mruby/irep.h
+++ b/include/mruby/irep.h
@@ -12,10 +12,10 @@ extern "C" {
#endif
typedef struct mrb_irep {
- int idx:16;
- int nlocals:16;
- int nregs:16;
- int flags:8;
+ uint16_t idx;
+ uint16_t nlocals;
+ uint16_t nregs;
+ uint8_t flags;
mrb_code *iseq;
mrb_value *pool;
@@ -23,15 +23,15 @@ typedef struct mrb_irep {
/* debug info */
const char *filename;
- short *lines;
+ uint16_t *lines;
- int ilen, plen, slen;
+ size_t ilen, plen, slen;
} mrb_irep;
#define MRB_ISEQ_NO_FREE 1
mrb_irep *mrb_add_irep(mrb_state *mrb);
-mrb_value mrb_load_irep(mrb_state*,const char*);
+mrb_value mrb_load_irep(mrb_state*, const uint8_t*);
#if defined(__cplusplus)
} /* extern "C" { */
diff --git a/include/mruby/khash.h b/include/mruby/khash.h
index 9eddc0bb3..db8048f5a 100644
--- a/include/mruby/khash.h
+++ b/include/mruby/khash.h
@@ -11,7 +11,7 @@
extern "C" {
#endif
-#include <stdint.h>
+#include "mruby.h"
#include <string.h>
typedef uint32_t khint_t;
@@ -22,7 +22,7 @@ typedef khint_t khiter_t;
#endif
#define KHASH_MIN_SIZE 8
-#define UPPER_BOUND(x) ((x)>>2|(x>>1))
+#define UPPER_BOUND(x) ((x)>>2|(x)>>1)
//extern uint8_t __m[];
@@ -75,6 +75,14 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
void kh_del_##name(kh_##name##_t *h, khint_t x); \
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
+static inline void
+kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
+{
+ while (len-- > 0) {
+ *p++ = c;
+ }
+}
+
/* define kh_xxx_funcs
name: hash name
@@ -92,8 +100,8 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
h->upper_bound = UPPER_BOUND(sz); \
h->e_flags = (uint8_t *)mrb_malloc(h->mrb, sizeof(uint8_t)*sz/4); \
h->d_flags = h->e_flags + sz/8; \
- memset(h->e_flags, 0xff, sz/8*sizeof(uint8_t)); \
- memset(h->d_flags, 0x00, sz/8*sizeof(uint8_t)); \
+ kh_fill_flags(h->e_flags, 0xff, sz/8); \
+ kh_fill_flags(h->d_flags, 0x00, sz/8); \
h->keys = (khkey_t *)mrb_malloc(h->mrb, sizeof(khkey_t)*sz); \
h->vals = (khval_t *)mrb_malloc(h->mrb, sizeof(khval_t)*sz); \
h->mask = sz-1; \
@@ -124,8 +132,8 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
void kh_clear_##name(kh_##name##_t *h) \
{ \
if (h && h->e_flags) { \
- memset(h->e_flags, 0xff, h->n_buckets/8*sizeof(uint8_t)); \
- memset(h->d_flags, 0x00, h->n_buckets/8*sizeof(uint8_t)); \
+ kh_fill_flags(h->e_flags, 0xff, h->n_buckets/8); \
+ kh_fill_flags(h->d_flags, 0x00, h->n_buckets/8); \
h->size = h->n_occupied = 0; \
} \
} \
diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h
index 9a5ba449f..aac7b9920 100644
--- a/include/mruby/numeric.h
+++ b/include/mruby/numeric.h
@@ -11,14 +11,14 @@
extern "C" {
#endif
-#include <limits.h>
-
#define POSFIXABLE(f) ((f) <= MRB_INT_MAX)
#define NEGFIXABLE(f) ((f) >= MRB_INT_MIN)
#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
-mrb_value mrb_flt2big(mrb_state *mrb, mrb_float d);
-mrb_value mrb_fix2str(mrb_state *mrb, mrb_value x, int base);
+mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
+mrb_value mrb_flo_to_str(mrb_state *mrb, mrb_value flo, int max_digit);
+
+mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base);
mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y);
diff --git a/include/mruby/string.h b/include/mruby/string.h
index 353d8cefc..970d5ace6 100644
--- a/include/mruby/string.h
+++ b/include/mruby/string.h
@@ -11,27 +11,21 @@
extern "C" {
#endif
-#ifndef RB_GC_GUARD
-#define RB_GC_GUARD(v) v
-#endif
-
#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
-#define STR_BUF_MIN_SIZE 128
-
extern const char mrb_digitmap[];
typedef struct mrb_shared_string {
int refcnt;
char *ptr;
- int len;
+ mrb_int len;
} mrb_shared_string;
struct RString {
MRB_OBJECT_HEADER;
- int len;
+ mrb_int len;
union {
- int capa;
+ mrb_int capa;
mrb_shared_string *shared;
} aux;
char *ptr;
@@ -49,21 +43,20 @@ void mrb_str_decref(mrb_state*, mrb_shared_string*);
mrb_value mrb_str_literal(mrb_state*, mrb_value);
void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value);
+mrb_value mrb_ptr_to_str(mrb_state *, void *);
mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj);
mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, int len); /* mrb_str_resize */
-mrb_value mrb_string_value(mrb_state *mrb, mrb_value *ptr); /* StringValue */
-mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, int len);
+mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_buf_new(mrb_state *mrb, int capa);
-mrb_value mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len);
+mrb_value mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len);
char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
char *mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr);
-int mrb_str_sublen(mrb_state *mrb, mrb_value str, int pos);
int mrb_str_offset(mrb_state *mrb, mrb_value str, int pos);
mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str); /* mrb_str_dup */
mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self);
-mrb_value mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr);
+mrb_value mrb_str_cat_cstr(mrb_state *, mrb_value, const char *);
mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, int badcheck);
double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, int badcheck);
mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str);
@@ -72,12 +65,18 @@ mrb_value mrb_str_buf_append(mrb_state *mrb, mrb_value str, mrb_value str2);
mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str);
int mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2);
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
-mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len);
+mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, mrb_int len);
mrb_value mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2);
int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
+/* For backward compatibility */
+static inline mrb_value
+mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr) {
+ return mrb_str_cat_cstr(mrb, str, ptr);
+}
+
#if defined(__cplusplus)
} /* extern "C" { */
#endif
diff --git a/include/mruby/value.h b/include/mruby/value.h
index b5381a0cc..1cc5263ad 100644
--- a/include/mruby/value.h
+++ b/include/mruby/value.h
@@ -18,22 +18,21 @@ enum mrb_vtype {
MRB_TT_UNDEF, /* 5 */
MRB_TT_FLOAT, /* 6 */
MRB_TT_VOIDP, /* 7 */
- MRB_TT_MAIN, /* 8 */
- MRB_TT_OBJECT, /* 9 */
- MRB_TT_CLASS, /* 10 */
- MRB_TT_MODULE, /* 11 */
- MRB_TT_ICLASS, /* 12 */
- MRB_TT_SCLASS, /* 13 */
- MRB_TT_PROC, /* 14 */
- MRB_TT_ARRAY, /* 15 */
- MRB_TT_HASH, /* 16 */
- MRB_TT_STRING, /* 17 */
- MRB_TT_RANGE, /* 18 */
- MRB_TT_EXCEPTION, /* 19 */
- MRB_TT_FILE, /* 20 */
- MRB_TT_ENV, /* 21 */
- MRB_TT_DATA, /* 22 */
- MRB_TT_MAXDEFINE /* 23 */
+ MRB_TT_OBJECT, /* 8 */
+ MRB_TT_CLASS, /* 9 */
+ MRB_TT_MODULE, /* 10 */
+ MRB_TT_ICLASS, /* 11 */
+ MRB_TT_SCLASS, /* 12 */
+ MRB_TT_PROC, /* 13 */
+ MRB_TT_ARRAY, /* 14 */
+ MRB_TT_HASH, /* 15 */
+ MRB_TT_STRING, /* 16 */
+ MRB_TT_RANGE, /* 17 */
+ MRB_TT_EXCEPTION, /* 18 */
+ MRB_TT_FILE, /* 19 */
+ MRB_TT_ENV, /* 20 */
+ MRB_TT_DATA, /* 21 */
+ MRB_TT_MAXDEFINE /* 22 */
};
typedef struct mrb_value {
@@ -77,22 +76,21 @@ enum mrb_vtype {
MRB_TT_UNDEF, /* 6 */
MRB_TT_FLOAT, /* 7 */
MRB_TT_VOIDP, /* 8 */
- MRB_TT_MAIN, /* 9 */
- MRB_TT_OBJECT, /* 10 */
- MRB_TT_CLASS, /* 11 */
- MRB_TT_MODULE, /* 12 */
- MRB_TT_ICLASS, /* 13 */
- MRB_TT_SCLASS, /* 14 */
- MRB_TT_PROC, /* 15 */
- MRB_TT_ARRAY, /* 16 */
- MRB_TT_HASH, /* 17 */
- MRB_TT_STRING, /* 18 */
- MRB_TT_RANGE, /* 19 */
- MRB_TT_EXCEPTION, /* 20 */
- MRB_TT_FILE, /* 21 */
- MRB_TT_ENV, /* 22 */
- MRB_TT_DATA, /* 23 */
- MRB_TT_MAXDEFINE /* 24 */
+ MRB_TT_OBJECT, /* 9 */
+ MRB_TT_CLASS, /* 10 */
+ MRB_TT_MODULE, /* 11 */
+ MRB_TT_ICLASS, /* 12 */
+ MRB_TT_SCLASS, /* 13 */
+ MRB_TT_PROC, /* 14 */
+ MRB_TT_ARRAY, /* 15 */
+ MRB_TT_HASH, /* 16 */
+ MRB_TT_STRING, /* 17 */
+ MRB_TT_RANGE, /* 18 */
+ MRB_TT_EXCEPTION, /* 19 */
+ MRB_TT_FILE, /* 20 */
+ MRB_TT_ENV, /* 21 */
+ MRB_TT_DATA, /* 22 */
+ MRB_TT_MAXDEFINE /* 23 */
};
#ifdef MRB_ENDIAN_BIG
@@ -144,7 +142,6 @@ mrb_float_value(mrb_float f)
#define mrb_fixnum(o) (o).value.i
#define mrb_symbol(o) (o).value.sym
-#define mrb_object(o) ((struct RBasic *) (o).value.p)
#define mrb_voidp(o) (o).value.p
#define mrb_fixnum_p(o) (mrb_type(o) == MRB_TT_FIXNUM)
#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT)
@@ -155,12 +152,13 @@ mrb_float_value(mrb_float f)
#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING)
#define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH)
#define mrb_voidp_p(o) (mrb_type(o) == MRB_TT_VOIDP)
-#define mrb_test(o) (mrb_type(o) != MRB_TT_FALSE)
+#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE)
+#define mrb_test(o) mrb_bool(o)
#define MRB_OBJECT_HEADER \
enum mrb_vtype tt:8;\
- unsigned int color:3;\
- unsigned int flags:21;\
+ uint32_t color:3;\
+ uint32_t flags:21;\
struct RClass *c;\
struct RBasic *gcnext
@@ -187,7 +185,9 @@ struct RBasic {
MRB_OBJECT_HEADER;
};
-#define mrb_basic(v) ((struct RBasic*)((v).value.p))
+#define mrb_basic_ptr(v) ((struct RBasic*)((v).value.p))
+/* obsolete macro mrb_basic; will be removed soon */
+#define mrb_basic(v) mrb_basic_ptr(v)
struct RObject {
MRB_OBJECT_HEADER;
@@ -195,7 +195,9 @@ struct RObject {
};
#define mrb_obj_ptr(v) ((struct RObject*)((v).value.p))
-#define mrb_immediate_p(x) (mrb_type(x) <= MRB_TT_MAIN)
+/* obsolete macro mrb_object; will be removed soon */
+#define mrb_object(o) mrb_obj_ptr(o)
+#define mrb_immediate_p(x) (mrb_type(x) <= MRB_TT_VOIDP)
#define mrb_special_const_p(x) mrb_immediate_p(x)
static inline mrb_value
@@ -271,4 +273,13 @@ mrb_undef_value(void)
return v;
}
+static inline mrb_value
+mrb_bool_value(mrb_bool boolean)
+{
+ mrb_value v;
+
+ MRB_SET_VALUE(v, boolean ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1);
+ return v;
+}
+
#endif /* MRUBY_OBJECT_H */
diff --git a/include/mruby/variable.h b/include/mruby/variable.h
index a1f52217d..f699f5dfd 100644
--- a/include/mruby/variable.h
+++ b/include/mruby/variable.h
@@ -36,16 +36,16 @@ mrb_value mrb_vm_const_get(mrb_state*, mrb_sym);
void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value);
mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym);
void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value);
-int mrb_const_defined(mrb_state*, mrb_value, mrb_sym);
+mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym);
void mrb_const_remove(mrb_state*, mrb_value, mrb_sym);
mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
-int mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
+mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
void mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym);
void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v);
-int mrb_iv_defined(mrb_state*, mrb_value, mrb_sym);
+mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym);
mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym);
void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src);
int mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id);
@@ -60,8 +60,8 @@ mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
mrb_value mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym);
void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v);
void mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v);
-int mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
-int mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym);
+mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
+mrb_bool mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym);
/* GC functions */
void mrb_gc_mark_gv(mrb_state*);
diff --git a/mrbgems/mruby-array-ext/mrbgem.rake b/mrbgems/mruby-array-ext/mrbgem.rake
new file mode 100644
index 000000000..38e0ad267
--- /dev/null
+++ b/mrbgems/mruby-array-ext/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-array-ext') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'mruby developers'
+end
diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb
new file mode 100644
index 000000000..b3ff9bfca
--- /dev/null
+++ b/mrbgems/mruby-array-ext/mrblib/array.rb
@@ -0,0 +1,98 @@
+class Array
+ def uniq!
+ ary = self.dup
+ result = []
+ while ary.size > 0
+ result << ary.shift
+ ary.delete(result.last)
+ end
+ if result.size == self.size
+ nil
+ else
+ self.replace(result)
+ end
+ end
+
+ def uniq
+ ary = self.dup
+ ary.uniq!
+ ary
+ end
+
+ def -(elem)
+ raise TypeError, "can't convert to Array" unless elem.class == Array
+
+ hash = {}
+ array = []
+ elem.each { |x| hash[x] = true }
+ self.each { |x| array << x unless hash[x] }
+ array
+ end
+
+ def |(elem)
+ raise TypeError, "can't convert to Array" unless elem.class == Array
+
+ ary = self + elem
+ ary.uniq! or ary
+ end
+
+ def &(elem)
+ raise TypeError, "can't convert to Array" unless elem.class == Array
+
+ hash = {}
+ array = []
+ elem.each{|v| hash[v] = true }
+ self.each do |v|
+ if hash[v]
+ array << v
+ hash.delete v
+ end
+ end
+ array
+ end
+
+ def flatten(depth=nil)
+ ar = []
+ self.each do |e|
+ if e.is_a?(Array) && (depth.nil? || depth > 0)
+ ar += e.flatten(depth.nil? ? nil : depth - 1)
+ else
+ ar << e
+ end
+ end
+ ar
+ end
+
+ def flatten!(depth=nil)
+ modified = false
+ ar = []
+ self.each do |e|
+ if e.is_a?(Array) && (depth.nil? || depth > 0)
+ ar += e.flatten(depth.nil? ? nil : depth - 1)
+ modified = true
+ else
+ ar << e
+ end
+ end
+ if modified
+ self.replace(ar)
+ else
+ nil
+ end
+ end
+
+ def compact
+ result = self.dup
+ result.compact!
+ result
+ end
+
+ def compact!
+ result = self.select { |e| e != nil }
+ if result.size == self.size
+ nil
+ else
+ self.replace(result)
+ end
+ end
+end
diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c
new file mode 100644
index 000000000..7d7425efd
--- /dev/null
+++ b/mrbgems/mruby-array-ext/src/array.c
@@ -0,0 +1,140 @@
+#include "mruby.h"
+#include "mruby/value.h"
+#include "mruby/array.h"
+
+/*
+ * call-seq:
+ * Array.try_convert(obj) -> array or nil
+ *
+ * Try to convert <i>obj</i> into an array, using +to_ary+ method.
+ * Returns converted array or +nil+ if <i>obj</i> cannot be converted
+ * for any reason. This method can be used to check if an argument is an
+ * array.
+ *
+ * Array.try_convert([1]) #=> [1]
+ * Array.try_convert("1") #=> nil
+ *
+ * if tmp = Array.try_convert(arg)
+ * # the argument is an array
+ * elsif tmp = String.try_convert(arg)
+ * # the argument is a string
+ * end
+ *
+ */
+
+static mrb_value
+mrb_ary_s_try_convert(mrb_state *mrb, mrb_value self)
+{
+ mrb_value ary;
+
+ mrb_get_args(mrb, "o", &ary);
+ return mrb_check_array_type(mrb, ary);
+}
+
+/*
+ * call-seq:
+ * ary.assoc(obj) -> new_ary or nil
+ *
+ * Searches through an array whose elements are also arrays
+ * comparing _obj_ with the first element of each contained array
+ * using obj.==.
+ * Returns the first contained array that matches (that
+ * is, the first associated array),
+ * or +nil+ if no match is found.
+ * See also <code>Array#rassoc</code>.
+ *
+ * s1 = [ "colors", "red", "blue", "green" ]
+ * s2 = [ "letters", "a", "b", "c" ]
+ * s3 = "foo"
+ * a = [ s1, s2, s3 ]
+ * a.assoc("letters") #=> [ "letters", "a", "b", "c" ]
+ * a.assoc("foo") #=> nil
+ */
+
+static mrb_value
+mrb_ary_assoc(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int i;
+ mrb_value v, k;
+
+ mrb_get_args(mrb, "o", &k);
+
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
+ if (!mrb_nil_p(v) && RARRAY_LEN(v) > 0 &&
+ mrb_equal(mrb, RARRAY_PTR(v)[0], k))
+ return v;
+ }
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * ary.rassoc(obj) -> new_ary or nil
+ *
+ * Searches through the array whose elements are also arrays. Compares
+ * _obj_ with the second element of each contained array using
+ * <code>==</code>. Returns the first contained array that matches. See
+ * also <code>Array#assoc</code>.
+ *
+ * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
+ * a.rassoc("two") #=> [2, "two"]
+ * a.rassoc("four") #=> nil
+ */
+
+static mrb_value
+mrb_ary_rassoc(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int i;
+ mrb_value v, value;
+
+ mrb_get_args(mrb, "o", &value);
+
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ v = RARRAY_PTR(ary)[i];
+ if (mrb_type(v) == MRB_TT_ARRAY &&
+ RARRAY_LEN(v) > 1 &&
+ mrb_equal(mrb, RARRAY_PTR(v)[1], value))
+ return v;
+ }
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * ary.at(index) -> obj or nil
+ *
+ * Returns the element at _index_. A
+ * negative index counts from the end of +self+. Returns +nil+
+ * if the index is out of range. See also <code>Array#[]</code>.
+ *
+ * a = [ "a", "b", "c", "d", "e" ]
+ * a.at(0) #=> "a"
+ * a.at(-1) #=> "e"
+ */
+
+static mrb_value
+mrb_ary_at(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int pos;
+ mrb_get_args(mrb, "i", &pos);
+
+ return mrb_ary_entry(ary, pos);
+}
+
+void
+mrb_mruby_array_ext_gem_init(mrb_state* mrb)
+{
+ struct RClass * a = mrb->array_class;
+
+ mrb_define_class_method(mrb, a, "try_convert", mrb_ary_s_try_convert, ARGS_REQ(1));
+
+ mrb_define_method(mrb, a, "assoc", mrb_ary_assoc, ARGS_REQ(1));
+ mrb_define_method(mrb, a, "at", mrb_ary_at, ARGS_REQ(1));
+ mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, ARGS_REQ(1));
+}
+
+void
+mrb_mruby_array_ext_gem_final(mrb_state* mrb)
+{
+}
diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb
new file mode 100644
index 000000000..1c441cec4
--- /dev/null
+++ b/mrbgems/mruby-array-ext/test/array.rb
@@ -0,0 +1,109 @@
+##
+# Array(Ext) Test
+
+assert("Array::try_convert") do
+ Array.try_convert([1]) == [1] and
+ Array.try_convert("1").nil?
+end
+
+assert("Array#assoc") do
+ s1 = [ "colors", "red", "blue", "green" ]
+ s2 = [ "letters", "a", "b", "c" ]
+ s3 = "foo"
+ a = [ s1, s2, s3 ]
+
+ a.assoc("letters") == [ "letters", "a", "b", "c" ] and
+ a.assoc("foo").nil?
+end
+
+assert("Array#at") do
+ a = [ "a", "b", "c", "d", "e" ]
+ a.at(0) == "a" and a.at(-1) == "e"
+end
+
+assert("Array#rassoc") do
+ a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
+
+ a.rassoc("two") == [2, "two"] and
+ a.rassoc("four").nil?
+end
+
+assert("Array#uniq!") do
+ a = [1, 2, 3, 1]
+ a.uniq!
+ a == [1, 2, 3]
+end
+
+assert("Array#uniq") do
+ a = [1, 2, 3, 1]
+ a.uniq == [1, 2, 3] && a == [1, 2, 3, 1]
+end
+
+assert("Array#-") do
+ a = [1, 2, 3, 1]
+ b = [1]
+ c = 1
+ e1 = nil
+
+ begin
+ a - c
+ rescue => e1
+ end
+
+ (a - b) == [2, 3] and e1.class == TypeError and a == [1, 2, 3, 1]
+end
+
+assert("Array#|") do
+ a = [1, 2, 3, 1]
+ b = [1, 4]
+ c = 1
+ e1 = nil
+
+ begin
+ a | c
+ rescue => e1
+ end
+
+ (a | b) == [1, 2, 3, 4] and e1.class == TypeError and a == [1, 2, 3, 1]
+end
+
+assert("Array#&") do
+ a = [1, 2, 3, 1]
+ b = [1, 4]
+ c = 1
+ e1 = nil
+
+ begin
+ a & c
+ rescue => e1
+ end
+
+ (a & b) == [1] and e1.class == TypeError and a == [1, 2, 3, 1]
+end
+
+assert("Array#flatten") do
+ [1, 2, "3", {4=>5}, :'6'] == [1, 2, "3", {4=>5}, :'6'].flatten and
+ [1, 2, 3, 4, 5, 6] == [1, 2, [3, 4, 5], 6].flatten and
+ [1, 2, 3, 4, 5, 6] == [1, 2, [3, [4, 5], 6]].flatten and
+ [1, [2, [3, [4, [5, [6]]]]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(0) and
+ [1, 2, [3, [4, [5, [6]]]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(1) and
+ [1, 2, 3, [4, [5, [6]]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(2) and
+ [1, 2, 3, 4, [5, [6]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(3) and
+ [1, 2, 3, 4, 5, [6]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(4) and
+ [1, 2, 3, 4, 5, 6] == [1, [2, [3, [4, [5, [6]]]]]].flatten(5)
+end
+
+assert("Array#flatten!") do
+ [1, 2, 3, 4, 5, 6] == [1, 2, [3, [4, 5], 6]].flatten!
+end
+
+assert("Array#compact") do
+ a = [1, nil, "2", nil, :t, false, nil]
+ a.compact == [1, "2", :t, false] && a == [1, nil, "2", nil, :t, false, nil]
+end
+
+assert("Array#compact!") do
+ a = [1, nil, "2", nil, :t, false, nil]
+ a.compact!
+ a == [1, "2", :t, false]
+end
diff --git a/mrbgems/mruby-enum-ext/mrbgem.rake b/mrbgems/mruby-enum-ext/mrbgem.rake
new file mode 100644
index 000000000..758d298dc
--- /dev/null
+++ b/mrbgems/mruby-enum-ext/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-enum-ext') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'mruby developers'
+end
diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb
new file mode 100644
index 000000000..f250d39f1
--- /dev/null
+++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb
@@ -0,0 +1,164 @@
+##
+# Enumerable
+#
+module Enumerable
+ ##
+ # call-seq:
+ # enum.drop(n) -> array
+ #
+ # Drops first n elements from <i>enum</i>, and returns rest elements
+ # in an array.
+ #
+ # a = [1, 2, 3, 4, 5, 0]
+ # a.drop(3) #=> [4, 5, 0]
+
+ def drop(n)
+ raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer
+ raise ArgumentError, "attempt to drop negative size" if n < 0
+
+ ary = []
+ self.each {|e| n == 0 ? ary << e : n -= 1 }
+ ary
+ end
+
+ ##
+ # call-seq:
+ # enum.drop_while {|arr| block } -> array
+ #
+ # Drops elements up to, but not including, the first element for
+ # which the block returns +nil+ or +false+ and returns an array
+ # containing the remaining elements.
+ #
+ # a = [1, 2, 3, 4, 5, 0]
+ # a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
+
+ def drop_while(&block)
+ ary, state = [], false
+ self.each do |e|
+ state = true if !state and !block.call(e)
+ ary << e if state
+ end
+ ary
+ end
+
+ ##
+ # call-seq:
+ # enum.take(n) -> array
+ #
+ # Returns first n elements from <i>enum</i>.
+ #
+ # a = [1, 2, 3, 4, 5, 0]
+ # a.take(3) #=> [1, 2, 3]
+
+ def take(n)
+ raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer
+ raise ArgumentError, "attempt to take negative size" if n < 0
+
+ ary = []
+ self.each do |e|
+ break if ary.size >= n
+ ary << e
+ end
+ ary
+ end
+
+ ##
+ # call-seq:
+ # enum.take_while {|arr| block } -> array
+ #
+ # Passes elements to the block until the block returns +nil+ or +false+,
+ # then stops iterating and returns an array of all prior elements.
+ #
+ #
+ # a = [1, 2, 3, 4, 5, 0]
+ # a.take_while {|i| i < 3 } #=> [1, 2]
+
+ def take_while(&block)
+ ary = []
+ self.each do |e|
+ return ary unless block.call(e)
+ ary << e
+ end
+ ary
+ end
+
+ ##
+ # call-seq:
+ # enum.each_cons(n) {...} -> nil
+ #
+ # Iterates the given block for each array of consecutive <n>
+ # elements.
+ #
+ # e.g.:
+ # (1..10).each_cons(3) {|a| p a}
+ # # outputs below
+ # [1, 2, 3]
+ # [2, 3, 4]
+ # [3, 4, 5]
+ # [4, 5, 6]
+ # [5, 6, 7]
+ # [6, 7, 8]
+ # [7, 8, 9]
+ # [8, 9, 10]
+
+ def each_cons(n, &block)
+ raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer
+ raise ArgumentError, "invalid size" if n <= 0
+
+ ary = []
+ self.each do |e|
+ ary.shift if ary.size == n
+ ary << e
+ block.call(ary.dup) if ary.size == n
+ end
+ end
+
+ ##
+ # call-seq:
+ # enum.each_slice(n) {...} -> nil
+ #
+ # Iterates the given block for each slice of <n> elements.
+ #
+ # e.g.:
+ # (1..10).each_slice(3) {|a| p a}
+ # # outputs below
+ # [1, 2, 3]
+ # [4, 5, 6]
+ # [7, 8, 9]
+ # [10]
+
+ def each_slice(n, &block)
+ raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer
+ raise ArgumentError, "invalid slice size" if n <= 0
+
+ ary = []
+ self.each do |e|
+ ary << e
+ if ary.size == n
+ block.call(ary)
+ ary = []
+ end
+ end
+ block.call(ary) unless ary.empty?
+ end
+
+ ##
+ # call-seq:
+ # enum.group_by {| obj | block } -> a_hash
+ #
+ # Returns a hash, which keys are evaluated result from the
+ # block, and values are arrays of elements in <i>enum</i>
+ # corresponding to the key.
+ #
+ # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
+
+ def group_by(&block)
+ h = {}
+ self.each do |e|
+ key = block.call(e)
+ h.key?(key) ? (h[key] << e) : (h[key] = [e])
+ end
+ h
+ end
+
+end
diff --git a/mrbgems/mruby-enum-ext/test/enum.rb b/mrbgems/mruby-enum-ext/test/enum.rb
new file mode 100644
index 000000000..aa56cdf84
--- /dev/null
+++ b/mrbgems/mruby-enum-ext/test/enum.rb
@@ -0,0 +1,44 @@
+##
+# Enumerable(Ext) Test
+
+assert("Enumerable#drop") do
+ a = [1, 2, 3, 4, 5, 0]
+
+ assert_equal a.drop(3), [4, 5, 0]
+ assert_equal a.drop(6), []
+end
+
+assert("Enumerable#drop_while") do
+ a = [1, 2, 3, 4, 5, 0]
+ assert_equal a.drop_while {|i| i < 3 }, [3, 4, 5, 0]
+end
+
+assert("Enumerable#take") do
+ a = [1, 2, 3, 4, 5, 0]
+ assert_equal a.take(3), [1, 2, 3]
+end
+
+assert("Enumerable#take_while") do
+ a = [1, 2, 3, 4, 5, 0]
+ assert_equal a.take_while {|i| i < 3 }, [1, 2]
+end
+
+assert("Enumerable#each_cons") do
+ a = []
+ (1..5).each_cons(3){|e| a << e}
+ assert_equal a, [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
+end
+
+assert("Enumerable#each_slice") do
+ a = []
+ (1..10).each_slice(3){|e| a << e}
+ assert_equal a, [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
+end
+
+assert("Enumerable#group_by") do
+ r = (1..6).group_by {|i| i % 3 }
+ assert_equal r[0], [3, 6]
+ assert_equal r[1], [1, 4]
+ assert_equal r[2], [2, 5]
+end
+
diff --git a/mrbgems/mruby-eval/mrbgem.rake b/mrbgems/mruby-eval/mrbgem.rake
new file mode 100644
index 000000000..f80cf1b9e
--- /dev/null
+++ b/mrbgems/mruby-eval/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-eval') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'mruby developers'
+end
diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c
new file mode 100644
index 000000000..039558596
--- /dev/null
+++ b/mrbgems/mruby-eval/src/eval.c
@@ -0,0 +1,23 @@
+#include "mruby.h"
+#include "mruby/compile.h"
+
+static mrb_value
+f_eval(mrb_state *mrb, mrb_value self)
+{
+ char *s;
+ int len;
+
+ mrb_get_args(mrb, "s", &s, &len);
+ return mrb_load_nstring(mrb, s, len);
+}
+
+void
+mrb_mruby_eval_gem_init(mrb_state* mrb)
+{
+ mrb_define_class_method(mrb, mrb->kernel_module, "eval", f_eval, ARGS_REQ(1));
+}
+
+void
+mrb_mruby_eval_gem_final(mrb_state* mrb)
+{
+}
diff --git a/mrbgems/mruby-hash-ext/mrbgem.rake b/mrbgems/mruby-hash-ext/mrbgem.rake
new file mode 100644
index 000000000..3163c8c88
--- /dev/null
+++ b/mrbgems/mruby-hash-ext/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-hash-ext') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'mruby developers'
+end
diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb
new file mode 100644
index 000000000..3e1bac0a2
--- /dev/null
+++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb
@@ -0,0 +1,12 @@
+class Hash
+ def merge!(other, &block)
+ if block
+ other.each_key{|k|
+ self[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k]
+ }
+ else
+ other.each_key{|k| self[k] = other[k]}
+ end
+ self
+ end
+end
diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb
new file mode 100644
index 000000000..98eb313a4
--- /dev/null
+++ b/mrbgems/mruby-hash-ext/test/hash.rb
@@ -0,0 +1,20 @@
+##
+# Hash(Ext) Test
+
+assert('Hash#merge!') do
+ a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
+ b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' }
+
+ result_1 = a.merge! b
+
+ a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
+ result_2 = a.merge!(b) do |key, original, new|
+ original
+ end
+
+ result_1 == {'abc_key' => 'abc_value', 'cba_key' => 'XXX',
+ 'xyz_key' => 'xyz_value' } and
+ result_2 == {'abc_key' => 'abc_value', 'cba_key' => 'cba_value',
+ 'xyz_key' => 'xyz_value' }
+end
+
diff --git a/mrbgems/mruby-math/src/math.c b/mrbgems/mruby-math/src/math.c
index 9955d9862..76058250f 100644
--- a/mrbgems/mruby-math/src/math.c
+++ b/mrbgems/mruby-math/src/math.c
@@ -26,13 +26,13 @@
double
erfc(double x);
-/*
+/*
** Implementations of error functions
** credits to http://www.digitalmars.com/archives/cplusplus/3634.html
*/
/* Implementation of Error function */
-double
+double
erf(double x)
{
static const double two_sqrtpi = 1.128379167095512574;
@@ -55,24 +55,24 @@ erf(double x)
}
/* Implementation of complementary Error function */
-double
+double
erfc(double x)
{
- static const double one_sqrtpi= 0.564189583547756287;
- double a = 1;
- double b = x;
- double c = x;
- double d = x*x+0.5;
+ static const double one_sqrtpi= 0.564189583547756287;
+ double a = 1;
+ double b = x;
+ double c = x;
+ double d = x*x+0.5;
double q1;
double q2 = b/d;
double n = 1.0;
double t;
if (fabs(x) < 2.2) {
- return 1.0 - erf(x);
- }
- if (x < 0.0) { /*signbit(x)*/
- return 2.0 - erfc(-x);
- }
+ return 1.0 - erf(x);
+ }
+ if (x < 0.0) { /*signbit(x)*/
+ return 2.0 - erfc(-x);
+ }
do {
t = a*n+b*x;
a = b;
@@ -306,7 +306,7 @@ math_asinh(mrb_state *mrb, mrb_value obj)
mrb_float x;
mrb_get_args(mrb, "f", &x);
-
+
x = asinh(x);
return mrb_float_value(x);
@@ -477,10 +477,10 @@ static mrb_value
math_sqrt(mrb_state *mrb, mrb_value obj)
{
mrb_float x;
-
+
mrb_get_args(mrb, "f", &x);
x = sqrt(x);
-
+
return mrb_float_value(x);
}
@@ -544,7 +544,7 @@ math_frexp(mrb_state *mrb, mrb_value obj)
{
mrb_float x;
int exp;
-
+
mrb_get_args(mrb, "f", &x);
x = frexp(x, &exp);
@@ -633,13 +633,13 @@ mrb_mruby_math_gem_init(mrb_state* mrb)
{
struct RClass *mrb_math;
mrb_math = mrb_define_module(mrb, "Math");
-
+
#ifdef M_PI
mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(M_PI));
#else
mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(atan(1.0)*4.0));
#endif
-
+
#ifdef M_E
mrb_define_const(mrb, mrb_math, "E", mrb_float_value(M_E));
#else
@@ -660,7 +660,7 @@ mrb_mruby_math_gem_init(mrb_state* mrb)
mrb_define_module_function(mrb, mrb_math, "acos", math_acos, ARGS_REQ(1));
mrb_define_module_function(mrb, mrb_math, "atan", math_atan, ARGS_REQ(1));
mrb_define_module_function(mrb, mrb_math, "atan2", math_atan2, ARGS_REQ(2));
-
+
mrb_define_module_function(mrb, mrb_math, "sinh", math_sinh, ARGS_REQ(1));
mrb_define_module_function(mrb, mrb_math, "cosh", math_cosh, ARGS_REQ(1));
mrb_define_module_function(mrb, mrb_math, "tanh", math_tanh, ARGS_REQ(1));
diff --git a/mrbgems/mruby-numeric-ext/mrbgem.rake b/mrbgems/mruby-numeric-ext/mrbgem.rake
new file mode 100644
index 000000000..69c4fde4c
--- /dev/null
+++ b/mrbgems/mruby-numeric-ext/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-numeric-ext') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'mruby developers'
+end
diff --git a/mrbgems/mruby-numeric-ext/src/numeric_ext.c b/mrbgems/mruby-numeric-ext/src/numeric_ext.c
new file mode 100644
index 000000000..09904c1a9
--- /dev/null
+++ b/mrbgems/mruby-numeric-ext/src/numeric_ext.c
@@ -0,0 +1,31 @@
+#include <limits.h>
+#include "mruby.h"
+#include "mruby/numeric.h"
+
+static mrb_value
+mrb_int_chr(mrb_state *mrb, mrb_value x)
+{
+ mrb_int chr;
+ char c;
+
+ chr = mrb_fixnum(x);
+ if (chr >= (1 << CHAR_BIT)) {
+ mrb_raisef(mrb, E_RANGE_ERROR, "%" PRIdMRB_INT " out of char range", chr);
+ }
+ c = (char)chr;
+
+ return mrb_str_new(mrb, &c, 1);
+}
+
+void
+mrb_mruby_numeric_ext_gem_init(mrb_state* mrb)
+{
+ struct RClass *i = mrb_class_get(mrb, "Integer");
+
+ mrb_define_method(mrb, i, "chr", mrb_int_chr, ARGS_NONE());
+}
+
+void
+mrb_mruby_numeric_ext_gem_final(mrb_state* mrb)
+{
+}
diff --git a/mrbgems/mruby-numeric-ext/test/numeric.rb b/mrbgems/mruby-numeric-ext/test/numeric.rb
new file mode 100644
index 000000000..6c1cf0fce
--- /dev/null
+++ b/mrbgems/mruby-numeric-ext/test/numeric.rb
@@ -0,0 +1,10 @@
+##
+# Numeric(Ext) Test
+
+assert('Integer#chr') do
+ assert_equal(65.chr, "A")
+ assert_equal(0x42.chr, "B")
+
+ # multibyte encoding (not support yet)
+ assert_raise(RangeError) { 12345.chr }
+end
diff --git a/mrbgems/mruby-print/mrbgem.rake b/mrbgems/mruby-print/mrbgem.rake
new file mode 100644
index 000000000..dc7831280
--- /dev/null
+++ b/mrbgems/mruby-print/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-print') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'mruby developers'
+end
diff --git a/mrbgems/mruby-print/mrblib/print.rb b/mrbgems/mruby-print/mrblib/print.rb
new file mode 100644
index 000000000..38a10661b
--- /dev/null
+++ b/mrbgems/mruby-print/mrblib/print.rb
@@ -0,0 +1,64 @@
+##
+# Kernel
+#
+# ISO 15.3.1
+module Kernel
+ ##
+ # Invoke method +print+ on STDOUT and passing +*args+
+ #
+ # ISO 15.3.1.2.10
+ def print(*args)
+ i = 0
+ len = args.size
+ while i < len
+ __printstr__ args[i].to_s
+ i += 1
+ end
+ end
+
+ ##
+ # Invoke method +puts+ on STDOUT and passing +*args*+
+ #
+ # ISO 15.3.1.2.11
+ def puts(*args)
+ i = 0
+ len = args.size
+ while i < len
+ s = args[i].to_s
+ __printstr__ s
+ __printstr__ "\n" if (s[-1] != "\n")
+ i += 1
+ end
+ __printstr__ "\n" if len == 0
+ nil
+ end
+
+ ##
+ # Print human readable object description
+ #
+ # ISO 15.3.1.3.34
+ def p(*args)
+ i = 0
+ len = args.size
+ while i < len
+ __printstr__ args[i].inspect
+ __printstr__ "\n"
+ i += 1
+ end
+ args[0]
+ end
+
+ unless Kernel.respond_to?(:sprintf)
+ def printf(*args)
+ raise NotImplementedError.new('printf not available')
+ end
+ def sprintf(*args)
+ raise NotImplementedError.new('sprintf not available')
+ end
+ else
+ def printf(*args)
+ __printstr__(sprintf(*args))
+ nil
+ end
+ end
+end
diff --git a/mrbgems/mruby-print/src/print.c b/mrbgems/mruby-print/src/print.c
new file mode 100644
index 000000000..608e3cc2d
--- /dev/null
+++ b/mrbgems/mruby-print/src/print.c
@@ -0,0 +1,44 @@
+#include "mruby.h"
+#include "mruby/string.h"
+#include <stdio.h>
+
+static void
+printstr(mrb_state *mrb, mrb_value obj)
+{
+ struct RString *str;
+ char *s;
+ int len;
+
+ if (mrb_string_p(obj)) {
+ str = mrb_str_ptr(obj);
+ s = str->ptr;
+ len = str->len;
+ fwrite(s, len, 1, stdout);
+ }
+}
+
+/* 15.3.1.2.9 */
+/* 15.3.1.3.34 */
+mrb_value
+mrb_printstr(mrb_state *mrb, mrb_value self)
+{
+ mrb_value argv;
+
+ mrb_get_args(mrb, "o", &argv);
+ printstr(mrb, argv);
+
+ return argv;
+}
+
+void
+mrb_mruby_print_gem_init(mrb_state* mrb)
+{
+ struct RClass *krn;
+ krn = mrb->kernel_module;
+ mrb_define_method(mrb, krn, "__printstr__", mrb_printstr, ARGS_REQ(1));
+}
+
+void
+mrb_mruby_print_gem_final(mrb_state* mrb)
+{
+}
diff --git a/mrbgems/mruby-random/mrbgem.rake b/mrbgems/mruby-random/mrbgem.rake
new file mode 100644
index 000000000..7c2b2ddd5
--- /dev/null
+++ b/mrbgems/mruby-random/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-random') do |spec|
+ spec.license = 'MIT, BSD New(mt19937ar)'
+ spec.authors = 'mruby developers'
+end
diff --git a/mrbgems/mruby-random/src/mt19937ar.c b/mrbgems/mruby-random/src/mt19937ar.c
new file mode 100644
index 000000000..8e3295a82
--- /dev/null
+++ b/mrbgems/mruby-random/src/mt19937ar.c
@@ -0,0 +1,232 @@
+/*
+ A C-program for MT19937, with initialization improved 2002/1/26.
+ Coded by Takuji Nishimura and Makoto Matsumoto.
+
+ Before using, initialize the state by using init_genrand(seed)
+ or init_by_array(init_key, key_length).
+
+ Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+ All rights reserved.
+ Copyright (C) 2005, Mutsuo Saito,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The names of its contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+ Any feedback is very welcome.
+ http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+ email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+*/
+
+#include <stdio.h>
+#include "mt19937ar.h"
+
+/* Period parameters */
+//#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0dfUL /* constant vector a */
+#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
+
+static unsigned long mt[N]; /* the array for the state vector */
+static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
+
+void mrb_random_init_genrand(mt_state *t, unsigned long s)
+{
+ t->mt[0]= s & 0xffffffffUL;
+ for (t->mti=1; t->mti<N; t->mti++) {
+ t->mt[t->mti] =
+ (1812433253UL * (t->mt[t->mti-1] ^ (t->mt[t->mti-1] >> 30)) + t->mti);
+ t->mt[t->mti] &= 0xffffffffUL;
+ }
+}
+
+unsigned long mrb_random_genrand_int32(mt_state *t)
+{
+ unsigned long y;
+ static unsigned long mag01[2]={0x0UL, MATRIX_A};
+ /* mag01[x] = x * MATRIX_A for x=0,1 */
+
+ if (t->mti >= N) { /* generate N words at one time */
+ int kk;
+
+ if (t->mti == N+1) /* if init_genrand() has not been called, */
+ mrb_random_init_genrand(t, 5489UL); /* a default initial seed is used */
+
+ for (kk=0;kk<N-M;kk++) {
+ y = (t->mt[kk]&UPPER_MASK)|(t->mt[kk+1]&LOWER_MASK);
+ t->mt[kk] = t->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ for (;kk<N-1;kk++) {
+ y = (t->mt[kk]&UPPER_MASK)|(t->mt[kk+1]&LOWER_MASK);
+ t->mt[kk] = t->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ y = (t->mt[N-1]&UPPER_MASK)|(t->mt[0]&LOWER_MASK);
+ t->mt[N-1] = t->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+
+ t->mti = 0;
+ }
+
+ y = t->mt[t->mti++];
+
+ /* Tempering */
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9d2c5680UL;
+ y ^= (y << 15) & 0xefc60000UL;
+ y ^= (y >> 18);
+
+ t->gen_int = y;
+
+ return y;
+}
+
+double mrb_random_genrand_real1(mt_state *t)
+{
+ mrb_random_genrand_int32(t);
+ t->gen_dbl = t->gen_int*(1.0/4294967295.0);
+ return t->gen_dbl;
+ /* divided by 2^32-1 */
+}
+
+/* initializes mt[N] with a seed */
+void init_genrand(unsigned long s)
+{
+ mt[0]= s & 0xffffffffUL;
+ for (mti=1; mti<N; mti++) {
+ mt[mti] =
+ (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
+ /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
+ /* In the previous versions, MSBs of the seed affect */
+ /* only MSBs of the array mt[]. */
+ /* 2002/01/09 modified by Makoto Matsumoto */
+ mt[mti] &= 0xffffffffUL;
+ /* for >32 bit machines */
+ }
+}
+
+/* initialize by an array with array-length */
+/* init_key is the array for initializing keys */
+/* key_length is its length */
+/* slight change for C++, 2004/2/26 */
+void init_by_array(unsigned long init_key[], int key_length)
+{
+ int i, j, k;
+ init_genrand(19650218UL);
+ i=1; j=0;
+ k = (N>key_length ? N : key_length);
+ for (; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+ + init_key[j] + j; /* non linear */
+ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+ i++; j++;
+ if (i>=N) { mt[0] = mt[N-1]; i=1; }
+ if (j>=key_length) j=0;
+ }
+ for (k=N-1; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
+ - i; /* non linear */
+ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+ i++;
+ if (i>=N) { mt[0] = mt[N-1]; i=1; }
+ }
+
+ mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
+}
+
+/* generates a random number on [0,0xffffffff]-interval */
+unsigned long genrand_int32(void)
+{
+ unsigned long y;
+ static unsigned long mag01[2]={0x0UL, MATRIX_A};
+ /* mag01[x] = x * MATRIX_A for x=0,1 */
+
+ if (mti >= N) { /* generate N words at one time */
+ int kk;
+
+ if (mti == N+1) /* if init_genrand() has not been called, */
+ init_genrand(5489UL); /* a default initial seed is used */
+
+ for (kk=0;kk<N-M;kk++) {
+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+ mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ for (;kk<N-1;kk++) {
+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+ mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+ mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+
+ mti = 0;
+ }
+
+ y = mt[mti++];
+
+ /* Tempering */
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9d2c5680UL;
+ y ^= (y << 15) & 0xefc60000UL;
+ y ^= (y >> 18);
+
+ return y;
+}
+
+/* generates a random number on [0,0x7fffffff]-interval */
+long genrand_int31(void)
+{
+ return (long)(genrand_int32()>>1);
+}
+
+/* generates a random number on [0,1]-real-interval */
+double genrand_real1(void)
+{
+ return genrand_int32()*(1.0/4294967295.0);
+ /* divided by 2^32-1 */
+}
+
+/* generates a random number on [0,1)-real-interval */
+double genrand_real2(void)
+{
+ return genrand_int32()*(1.0/4294967296.0);
+ /* divided by 2^32 */
+}
+
+/* generates a random number on (0,1)-real-interval */
+double genrand_real3(void)
+{
+ return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
+ /* divided by 2^32 */
+}
+
+/* generates a random number on [0,1) with 53-bit resolution*/
+double genrand_res53(void)
+{
+ unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
+ return(a*67108864.0+b)*(1.0/9007199254740992.0);
+}
+/* These real versions are due to Isaku Wada, 2002/01/09 added */
diff --git a/mrbgems/mruby-random/src/mt19937ar.h b/mrbgems/mruby-random/src/mt19937ar.h
new file mode 100644
index 000000000..3f36cb1ff
--- /dev/null
+++ b/mrbgems/mruby-random/src/mt19937ar.h
@@ -0,0 +1,87 @@
+/*
+ A C-program for MT19937, with initialization improved 2002/1/26.
+ Coded by Takuji Nishimura and Makoto Matsumoto.
+
+ Before using, initialize the state by using init_genrand(seed)
+ or init_by_array(init_key, key_length).
+
+ Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+ All rights reserved.
+ Copyright (C) 2005, Mutsuo Saito
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The names of its contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+ Any feedback is very welcome.
+ http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+ email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+*/
+
+#define N 624
+
+typedef struct {
+ unsigned long mt[N];
+ int mti;
+ union {
+ unsigned long gen_int;
+ double gen_dbl;
+ };
+} mt_state;
+
+void mrb_random_init_genrand(mt_state *, unsigned long);
+unsigned long mrb_random_genrand_int32(mt_state *);
+double mrb_random_genrand_real1(mt_state *t);
+
+/* initializes mt[N] with a seed */
+void init_genrand(unsigned long s);
+
+/* initialize by an array with array-length */
+/* init_key is the array for initializing keys */
+/* key_length is its length */
+/* slight change for C++, 2004/2/26 */
+void init_by_array(unsigned long init_key[], int key_length);
+
+/* generates a random number on [0,0xffffffff]-interval */
+unsigned long genrand_int32(void);
+
+/* generates a random number on [0,0x7fffffff]-interval */
+long genrand_int31(void);
+
+/* These real versions are due to Isaku Wada, 2002/01/09 added */
+/* generates a random number on [0,1]-real-interval */
+double genrand_real1(void);
+
+/* generates a random number on [0,1)-real-interval */
+double genrand_real2(void);
+
+/* generates a random number on (0,1)-real-interval */
+double genrand_real3(void);
+
+/* generates a random number on [0,1) with 53-bit resolution*/
+double genrand_res53(void);
diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c
new file mode 100644
index 000000000..6500b3f84
--- /dev/null
+++ b/mrbgems/mruby-random/src/random.c
@@ -0,0 +1,233 @@
+/*
+** random.c - Random module
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include "mruby.h"
+#include "mruby/variable.h"
+#include "mruby/data.h"
+#include "mt19937ar.h"
+
+#include <time.h>
+
+#define GLOBAL_RAND_SEED_KEY "$mrb_g_rand_seed"
+#define INSTANCE_RAND_SEED_KEY "$mrb_i_rand_seed"
+#define MT_STATE_KEY "$mrb_i_mt_state"
+
+static void mt_state_free(mrb_state *mrb, void *p)
+{
+}
+
+static const struct mrb_data_type mt_state_type = {
+ MT_STATE_KEY, mt_state_free,
+};
+
+static mt_state *mrb_mt_get_context(mrb_state *mrb, mrb_value self)
+{
+ mt_state *t;
+ mrb_value context;
+
+ context = mrb_iv_get(mrb, self, mrb_intern(mrb, MT_STATE_KEY));
+ t = (mt_state *)mrb_check_datatype(mrb, context, &mt_state_type);
+ if (!t)
+ mrb_raise(mrb, E_RUNTIME_ERROR, "mt_state get from mrb_iv_get failed");
+
+ return t;
+}
+
+static void mt_g_srand(unsigned long seed)
+{
+ init_genrand(seed);
+}
+
+static unsigned long mt_g_rand()
+{
+ return genrand_int32();
+}
+
+static double mt_g_rand_real()
+{
+ return genrand_real1();
+}
+
+static mrb_value mrb_random_mt_g_srand(mrb_state *mrb, mrb_value seed)
+{
+ if (mrb_nil_p(seed)) {
+ seed = mrb_fixnum_value(time(NULL) + mt_g_rand());
+ if (mrb_fixnum(seed) < 0) {
+ seed = mrb_fixnum_value( 0 - mrb_fixnum(seed));
+ }
+ }
+
+ mt_g_srand((unsigned) mrb_fixnum(seed));
+
+ return seed;
+}
+
+static mrb_value mrb_random_mt_g_rand(mrb_state *mrb, mrb_value max)
+{
+ mrb_value value;
+
+ if (mrb_fixnum(max) == 0) {
+ value = mrb_float_value(mt_g_rand_real());
+ } else {
+ value = mrb_fixnum_value(mt_g_rand() % mrb_fixnum(max));
+ }
+
+ return value;
+}
+
+static void mt_srand(mt_state *t, unsigned long seed)
+{
+ mrb_random_init_genrand(t, seed);
+}
+
+static unsigned long mt_rand(mt_state *t)
+{
+ return mrb_random_genrand_int32(t);
+}
+
+static double mt_rand_real(mt_state *t)
+{
+ return mrb_random_genrand_real1(t);
+}
+
+static mrb_value mrb_random_mt_srand(mrb_state *mrb, mt_state *t, mrb_value seed)
+{
+ if (mrb_nil_p(seed)) {
+ seed = mrb_fixnum_value(time(NULL) + mt_rand(t));
+ if (mrb_fixnum(seed) < 0) {
+ seed = mrb_fixnum_value( 0 - mrb_fixnum(seed));
+ }
+ }
+
+ mt_srand(t, (unsigned) mrb_fixnum(seed));
+
+ return seed;
+}
+
+static mrb_value mrb_random_mt_rand(mrb_state *mrb, mt_state *t, mrb_value max)
+{
+ mrb_value value;
+
+ if (mrb_fixnum(max) == 0) {
+ value = mrb_float_value(mt_rand_real(t));
+ } else {
+ value = mrb_fixnum_value(mt_rand(t) % mrb_fixnum(max));
+ }
+
+ return value;
+}
+
+static mrb_value get_opt(mrb_state* mrb)
+{
+ mrb_value arg;
+
+ arg = mrb_fixnum_value(0);
+ mrb_get_args(mrb, "|o", &arg);
+
+ if (!mrb_nil_p(arg)) {
+ if (!mrb_fixnum_p(arg)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type");
+ }
+ arg = mrb_check_convert_type(mrb, arg, MRB_TT_FIXNUM, "Fixnum", "to_int");
+ if (mrb_fixnum(arg) < 0) {
+ arg = mrb_fixnum_value(0 - mrb_fixnum(arg));
+ }
+ }
+ return arg;
+}
+
+static mrb_value mrb_random_g_rand(mrb_state *mrb, mrb_value self)
+{
+ mrb_value max;
+ mrb_value seed;
+
+ max = get_opt(mrb);
+ seed = mrb_gv_get(mrb, mrb_intern(mrb, GLOBAL_RAND_SEED_KEY));
+ if (mrb_nil_p(seed)) {
+ mrb_random_mt_g_srand(mrb, mrb_nil_value());
+ }
+ return mrb_random_mt_g_rand(mrb, max);
+}
+
+static mrb_value mrb_random_g_srand(mrb_state *mrb, mrb_value self)
+{
+ mrb_value seed;
+ mrb_value old_seed;
+
+ seed = get_opt(mrb);
+ seed = mrb_random_mt_g_srand(mrb, seed);
+ old_seed = mrb_gv_get(mrb, mrb_intern(mrb, GLOBAL_RAND_SEED_KEY));
+ mrb_gv_set(mrb, mrb_intern(mrb, GLOBAL_RAND_SEED_KEY), seed);
+ return old_seed;
+}
+
+static mrb_value mrb_random_init(mrb_state *mrb, mrb_value self)
+{
+ mrb_value seed;
+
+
+ mt_state *t = (mt_state *)mrb_malloc(mrb, sizeof(mt_state));
+ t->mti = N + 1;
+
+ seed = get_opt(mrb);
+ seed = mrb_random_mt_srand(mrb, t, seed);
+ mrb_iv_set(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY), seed);
+ mrb_iv_set(mrb, self, mrb_intern(mrb, MT_STATE_KEY),
+ mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &mt_state_type, (void*) t)));
+ return self;
+}
+
+static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self)
+{
+ mrb_value max;
+ mrb_value seed;
+ mt_state *t = mrb_mt_get_context(mrb, self);
+
+ max = get_opt(mrb);
+ seed = mrb_iv_get(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY));
+ if (mrb_nil_p(seed)) {
+ mrb_random_mt_srand(mrb, t, mrb_nil_value());
+ }
+ mrb_iv_set(mrb, self, mrb_intern(mrb, MT_STATE_KEY),
+ mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &mt_state_type, (void*) t)));
+ return mrb_random_mt_rand(mrb, t, max);
+}
+
+static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self)
+{
+ mrb_value seed;
+ mrb_value old_seed;
+ mt_state *t = mrb_mt_get_context(mrb, self);
+
+ seed = get_opt(mrb);
+ seed = mrb_random_mt_srand(mrb, t, seed);
+ old_seed = mrb_iv_get(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY));
+ mrb_iv_set(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY), seed);
+ mrb_iv_set(mrb, self, mrb_intern(mrb, MT_STATE_KEY),
+ mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &mt_state_type, (void*) t)));
+ return old_seed;
+}
+
+void mrb_mruby_random_gem_init(mrb_state *mrb)
+{
+ struct RClass *random;
+
+ mrb_define_method(mrb, mrb->kernel_module, "rand", mrb_random_g_rand, ARGS_OPT(1));
+ mrb_define_method(mrb, mrb->kernel_module, "srand", mrb_random_g_srand, ARGS_OPT(1));
+
+ random = mrb_define_class(mrb, "Random", mrb->object_class);
+ mrb_define_class_method(mrb, random, "rand", mrb_random_g_rand, ARGS_OPT(1));
+ mrb_define_class_method(mrb, random, "srand", mrb_random_g_srand, ARGS_OPT(1));
+
+ mrb_define_method(mrb, random, "initialize", mrb_random_init, ARGS_OPT(1));
+ mrb_define_method(mrb, random, "rand", mrb_random_rand, ARGS_OPT(1));
+ mrb_define_method(mrb, random, "srand", mrb_random_srand, ARGS_OPT(1));
+}
+
+void mrb_mruby_random_gem_final(mrb_state *mrb)
+{
+}
+
diff --git a/mrbgems/mruby-random/src/random.h b/mrbgems/mruby-random/src/random.h
new file mode 100644
index 000000000..3dc5d4e77
--- /dev/null
+++ b/mrbgems/mruby-random/src/random.h
@@ -0,0 +1,12 @@
+/*
+// random.h - Random module
+//
+// See Copyright Notice in mruby.h
+*/
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+void mrb_mruby_random_gem_init(mrb_state *mrb);
+
+#endif
diff --git a/mrbgems/mruby-random/test/random.rb b/mrbgems/mruby-random/test/random.rb
new file mode 100644
index 000000000..01d231d5c
--- /dev/null
+++ b/mrbgems/mruby-random/test/random.rb
@@ -0,0 +1,32 @@
+##
+# Random Test
+
+assert("Random#srand") do
+ r1 = Random.new(123)
+ r2 = Random.new(123)
+ r1.rand == r2.rand
+end
+
+assert("Kernel::srand") do
+ srand(234)
+ r1 = rand
+ srand(234)
+ r2 = rand
+ r1 == r2
+end
+
+assert("Random::srand") do
+ Random.srand(345)
+ r1 = rand
+ srand(345)
+ r2 = Random.rand
+ r1 == r2
+end
+
+assert("fixnum") do
+ rand(3).class == Fixnum
+end
+
+assert("float") do
+ rand.class == Float
+end
diff --git a/mrbgems/mruby-sprintf/mrbgem.rake b/mrbgems/mruby-sprintf/mrbgem.rake
new file mode 100644
index 000000000..8772a5174
--- /dev/null
+++ b/mrbgems/mruby-sprintf/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-sprintf') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'mruby developers'
+end
diff --git a/mrbgems/mruby-sprintf/src/kernel.c b/mrbgems/mruby-sprintf/src/kernel.c
new file mode 100644
index 000000000..8f54a3d85
--- /dev/null
+++ b/mrbgems/mruby-sprintf/src/kernel.c
@@ -0,0 +1,30 @@
+/*
+** kernel.c - Kernel module suppliment
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include "mruby.h"
+
+mrb_value mrb_f_sprintf(mrb_state *mrb, mrb_value obj); /* in sprintf.c */
+
+void
+mrb_mruby_sprintf_gem_init(mrb_state* mrb)
+{
+ struct RClass *krn;
+
+ if (mrb->kernel_module == NULL) {
+ mrb->kernel_module = mrb_define_module(mrb, "Kernel"); /* Might be PARANOID. */
+ }
+ krn = mrb->kernel_module;
+
+ mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, ARGS_ANY());
+ mrb_define_method(mrb, krn, "format", mrb_f_sprintf, ARGS_ANY());
+}
+
+void
+mrb_mruby_sprintf_gem_final(mrb_state* mrb)
+{
+ /* nothing to do. */
+}
+
diff --git a/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c
index 905182147..fed730c74 100644
--- a/src/sprintf.c
+++ b/mrbgems/mruby-sprintf/src/sprintf.c
@@ -6,8 +6,7 @@
#include "mruby.h"
-#ifdef ENABLE_SPRINTF
-
+#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "mruby/string.h"
@@ -28,7 +27,7 @@
#define BITSPERDIG (sizeof(mrb_int)*CHAR_BIT)
#define EXTENDSIGN(n, l) (((~0 << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0 << (n)))
-static void fmt_setup(char*,size_t,int,int,int,int);
+static void fmt_setup(char*,size_t,int,int,mrb_int,mrb_int);
static char*
remove_sign_bits(char *str, int base)
@@ -80,11 +79,12 @@ static mrb_value
mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
{
char buf[64], *b = buf + sizeof buf;
- unsigned long val = mrb_fixnum(x);
+ mrb_int num = mrb_fixnum(x);
+ unsigned long val = (unsigned long)num;
char d;
if (base != 2) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %d", base);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base));
}
if (val >= (1 << 10))
@@ -98,7 +98,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
*--b = mrb_digitmap[(int)(val % base)];
} while (val /= base);
- if (mrb_fixnum(x) < 0) {
+ if (num < 0) {
b = remove_sign_bits(b, base);
switch (base) {
case 16: d = 'f'; break;
@@ -112,7 +112,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
}
}
- return mrb_str_new2(mrb, b);
+ return mrb_str_new_cstr(mrb, b);
}
#define FNONE 0
@@ -149,17 +149,17 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
#define GETARG() (!mrb_undef_p(nextvalue) ? nextvalue : \
posarg == -1 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%d) mixed with numbered", nextarg), mrb_undef_value()) : \
+ (mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with numbered", mrb_fixnum_value(nextarg)), mrb_undef_value()) : \
posarg == -2 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%d) mixed with named", nextarg), mrb_undef_value()) : \
+ (mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with named", mrb_fixnum_value(nextarg)), mrb_undef_value()) : \
(posarg = nextarg++, GETNTHARG(posarg)))
#define GETPOSARG(n) (posarg > 0 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%d) after unnumbered(%d)", n, posarg), mrb_undef_value()) : \
+ (mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after unnumbered(%S)", mrb_fixnum_value(n), mrb_fixnum_value(posarg)), mrb_undef_value()) : \
posarg == -2 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%d) after named", n), mrb_undef_value()) : \
+ (mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after named", mrb_fixnum_value(n)), mrb_undef_value()) : \
((n < 1) ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid index - %d$", n), mrb_undef_value()) : \
+ (mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid index - %S$", mrb_fixnum_value(n)), mrb_undef_value()) : \
(posarg = -1, GETNTHARG(n))))
#define GETNTHARG(nth) \
@@ -167,9 +167,9 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
#define GETNAMEARG(id, name, len) ( \
posarg > 0 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%.*s after unnumbered(%d)", (len), (name), posarg), mrb_undef_value()) : \
+ (mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after unnumbered(%S)", mrb_str_new(mrb, (name), (len)), mrb_fixnum_value(posarg)), mrb_undef_value()) : \
posarg == -1 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%.*s after numbered", (len), (name)), mrb_undef_value()) : \
+ (mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after numbered", mrb_str_new(mrb, (name), (len))), mrb_undef_value()) : \
(posarg = -2, mrb_hash_fetch(mrb, get_hash(mrb, &hash, argc, argv), id, mrb_undef_value())))
#define GETNUM(n, val) \
@@ -497,10 +497,13 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
{
const char *p, *end;
char *buf;
- long blen, bsiz;
+ mrb_int blen;
+ mrb_int bsiz;
mrb_value result;
- int n;
- int width, prec, flags = FNONE;
+ mrb_int n;
+ mrb_int width;
+ mrb_int prec;
+ int flags = FNONE;
int nextarg = 1;
int posarg = 0;
mrb_value nextvalue;
@@ -525,7 +528,7 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
++argc;
--argv;
- mrb_string_value(mrb, &fmt);
+ fmt = mrb_str_to_str(mrb, fmt);
p = RSTRING_PTR(fmt);
end = p + RSTRING_LEN(fmt);
blen = 0;
@@ -551,7 +554,7 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
retry:
switch (*p) {
default:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - %%%c", *p);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - \\%%S", mrb_str_new(mrb, p, 1));
break;
case ' ':
@@ -590,7 +593,7 @@ retry:
GETNUM(n, width);
if (*p == '$') {
if (!mrb_undef_p(nextvalue)) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "value given twice - %d$", n);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "value given twice - %S$", mrb_fixnum_value(n));
}
nextvalue = GETPOSARG(n);
p++;
@@ -610,20 +613,20 @@ retry:
for (; p < end && *p != term; )
p++;
if (id) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "name%.*s after <%s>",
- (int)(p - start + 1), start, mrb_sym2name(mrb, id));
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "name%S after <%S>",
+ mrb_str_new(mrb, start, p - start + 1), mrb_sym2str(mrb, id));
}
symname = mrb_str_new(mrb, start + 1, p - start - 1);
id = mrb_intern_str(mrb, symname);
nextvalue = GETNAMEARG(mrb_symbol_value(id), start, (int)(p - start + 1));
if (mrb_undef_p(nextvalue)) {
- mrb_raisef(mrb, E_KEY_ERROR, "key%.*s not found", (int)(p - start + 1), start);
+ mrb_raisef(mrb, E_KEY_ERROR, "key%S not found", mrb_str_new(mrb, start, p - start + 1));
}
if (term == '}') goto format_s;
p++;
goto retry;
}
-
+
case '*':
CHECK_FOR_WIDTH(flags);
flags |= FWIDTH;
@@ -658,7 +661,7 @@ retry:
case '\n':
case '\0':
p--;
-
+
case '%':
if (flags != FNONE) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format character - %");
@@ -711,7 +714,8 @@ retry:
format_s:
{
mrb_value arg = GETARG();
- long len, slen;
+ mrb_int len;
+ mrb_int slen;
if (*p == 'p') arg = mrb_inspect(mrb, arg);
str = mrb_obj_as_string(mrb, arg);
@@ -762,12 +766,12 @@ retry:
case 'u': {
mrb_value val = GETARG();
char fbuf[32], nbuf[64], *s;
- const char *prefix = 0;
+ const char *prefix = NULL;
int sign = 0, dots = 0;
char sc = 0;
- long v = 0, org_v = 0;
+ mrb_int v = 0, org_v = 0;
int base;
- int len;
+ mrb_int len;
switch (*p) {
case 'd':
@@ -802,14 +806,14 @@ retry:
val = mrb_fixnum_value((mrb_int)mrb_float(val));
goto bin_retry;
}
- val = mrb_flt2big(mrb, mrb_float(val));
+ val = mrb_flo_to_fixnum(mrb, val);
if (mrb_fixnum_p(val)) goto bin_retry;
break;
case MRB_TT_STRING:
val = mrb_str_to_inum(mrb, val, 0, TRUE);
goto bin_retry;
case MRB_TT_FIXNUM:
- v = (long)mrb_fixnum(val);
+ v = mrb_fixnum(val);
break;
default:
val = mrb_Integer(mrb, val);
@@ -839,7 +843,7 @@ retry:
dots = 1;
}
else {
- val = mrb_fix2str(mrb, mrb_fixnum_value(v), base);
+ val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
}
v = mrb_fixnum(mrb_str_to_inum(mrb, val, 10, 0/*Qfalse*/));
}
@@ -890,7 +894,12 @@ retry:
}
}
}
- len = (int)strlen(s);
+ {
+ size_t size;
+ size = strlen(s);
+ /* PARANOID: assert(size <= MRB_INT_MAX) */
+ len = (mrb_int)size;
+ }
if (dots) {
prec -= 2;
@@ -908,22 +917,26 @@ retry:
if (prefix && !prefix[1]) { /* octal */
if (dots) {
- prefix = 0;
+ prefix = NULL;
}
else if (len == 1 && *s == '0') {
len = 0;
if (flags & FPREC) prec--;
}
else if ((flags & FPREC) && (prec > len)) {
- prefix = 0;
+ prefix = NULL;
}
}
else if (len == 1 && *s == '0') {
- prefix = 0;
+ prefix = NULL;
}
if (prefix) {
- width -= (int)strlen(prefix);
+ size_t size;
+ size = strlen(prefix);
+ /* PARANOID: assert(size <= MRB_INT_MAX).
+ * this check is absolutely paranoid. */
+ width -= (mrb_int)size;
}
if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
@@ -1066,7 +1079,7 @@ retry:
}
static void
-fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
+fmt_setup(char *buf, size_t size, int c, int flags, mrb_int width, mrb_int prec)
{
char *end = buf + size;
int n;
@@ -1079,17 +1092,15 @@ fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
if (flags & FSPACE) *buf++ = ' ';
if (flags & FWIDTH) {
- n = snprintf(buf, end - buf, "%d", width);
+ n = snprintf(buf, end - buf, "%d", (int)width);
buf += n;
}
if (flags & FPREC) {
- n = snprintf(buf, end - buf, ".%d", prec);
+ n = snprintf(buf, end - buf, ".%d", (int)prec);
buf += n;
}
*buf++ = c;
*buf = '\0';
}
-
-#endif /* ENABLE_SPRINTF */
diff --git a/mrbgems/mruby-sprintf/test/sprintf.rb b/mrbgems/mruby-sprintf/test/sprintf.rb
new file mode 100644
index 000000000..52e94fb83
--- /dev/null
+++ b/mrbgems/mruby-sprintf/test/sprintf.rb
@@ -0,0 +1,3 @@
+##
+# Kernel#sprintf Kernel#format Test
+
diff --git a/mrbgems/mruby-string-ext/mrbgem.rake b/mrbgems/mruby-string-ext/mrbgem.rake
new file mode 100644
index 000000000..83db97eb4
--- /dev/null
+++ b/mrbgems/mruby-string-ext/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-string-ext') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'mruby developers'
+end
diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb
new file mode 100644
index 000000000..142a63882
--- /dev/null
+++ b/mrbgems/mruby-string-ext/mrblib/string.rb
@@ -0,0 +1,38 @@
+class String
+ def lstrip
+ a = 0
+ z = self.size - 1
+ a += 1 while " \f\n\r\t\v".include?(self[a]) and a <= z
+ (z >= 0) ? self[a..z] : ""
+ end
+
+ def rstrip
+ a = 0
+ z = self.size - 1
+ z -= 1 while " \f\n\r\t\v\0".include?(self[z]) and a <= z
+ (z >= 0) ? self[a..z] : ""
+ end
+
+ def strip
+ a = 0
+ z = self.size - 1
+ a += 1 while " \f\n\r\t\v".include?(self[a]) and a <= z
+ z -= 1 while " \f\n\r\t\v\0".include?(self[z]) and a <= z
+ (z >= 0) ? self[a..z] : ""
+ end
+
+ def lstrip!
+ s = self.lstrip
+ (s == self) ? nil : self.replace(s)
+ end
+
+ def rstrip!
+ s = self.rstrip
+ (s == self) ? nil : self.replace(s)
+ end
+
+ def strip!
+ s = self.strip
+ (s == self) ? nil : self.replace(s)
+ end
+end
diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c
new file mode 100644
index 000000000..b10b021a2
--- /dev/null
+++ b/mrbgems/mruby-string-ext/src/string.c
@@ -0,0 +1,31 @@
+#include "mruby.h"
+#include "mruby/string.h"
+
+static mrb_value
+mrb_str_getbyte(mrb_state *mrb, mrb_value str)
+{
+ mrb_int pos;
+ mrb_get_args(mrb, "i", &pos);
+
+ if (pos < 0)
+ pos += RSTRING_LEN(str);
+ if (pos < 0 || RSTRING_LEN(str) <= pos)
+ return mrb_nil_value();
+
+ return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[pos]);
+}
+
+
+void
+mrb_mruby_string_ext_gem_init(mrb_state* mrb)
+{
+ struct RClass * s = mrb->string_class;
+
+ mrb_define_method(mrb, s, "dump", mrb_str_dump, ARGS_NONE());
+ mrb_define_method(mrb, s, "getbyte", mrb_str_getbyte, ARGS_REQ(1));
+}
+
+void
+mrb_mruby_string_ext_gem_final(mrb_state* mrb)
+{
+}
diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb
new file mode 100644
index 000000000..eaff81890
--- /dev/null
+++ b/mrbgems/mruby-string-ext/test/string.rb
@@ -0,0 +1,72 @@
+##
+# String(Ext) Test
+
+assert('String#getbyte') do
+ str1 = "hello"
+ bytes1 = [104, 101, 108, 108, 111]
+ assert_equal bytes1[0], str1.getbyte(0)
+ assert_equal bytes1[-1], str1.getbyte(-1)
+ assert_equal bytes1[6], str1.getbyte(6)
+
+ str2 = "\xFF"
+ bytes2 = [0xFF]
+ assert_equal bytes2[0], str2.getbyte(0)
+end
+
+assert('String#dump') do
+ "foo".dump == "\"foo\""
+end
+
+assert('String#strip') do
+ s = " abc "
+ s.strip
+ "".strip == "" and " \t\r\n\f\v".strip == "" and
+ "\0a\0".strip == "\0a" and
+ "abc".strip == "abc" and
+ " abc".strip == "abc" and
+ "abc ".strip == "abc" and
+ " abc ".strip == "abc" and
+ s == " abc "
+end
+
+assert('String#lstrip') do
+ s = " abc "
+ s.lstrip
+ "".lstrip == "" and " \t\r\n\f\v".lstrip == "" and
+ "\0a\0".lstrip == "\0a\0" and
+ "abc".lstrip == "abc" and
+ " abc".lstrip == "abc" and
+ "abc ".lstrip == "abc " and
+ " abc ".lstrip == "abc " and
+ s == " abc "
+end
+
+assert('String#rstrip') do
+ s = " abc "
+ s.rstrip
+ "".rstrip == "" and " \t\r\n\f\v".rstrip == "" and
+ "\0a\0".rstrip == "\0a" and
+ "abc".rstrip == "abc" and
+ " abc".rstrip == " abc" and
+ "abc ".rstrip == "abc" and
+ " abc ".rstrip == " abc" and
+ s == " abc "
+end
+
+assert('String#strip!') do
+ s = " abc "
+ t = "abc"
+ s.strip! == "abc" and s == "abc" and t.strip! == nil
+end
+
+assert('String#lstrip!') do
+ s = " abc "
+ t = "abc "
+ s.lstrip! == "abc " and s == "abc " and t.lstrip! == nil
+end
+
+assert('String#rstrip!') do
+ s = " abc "
+ t = " abc"
+ s.rstrip! == " abc" and s == " abc" and t.rstrip! == nil
+end
diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c
index a49d8244b..20ea8b5c5 100644
--- a/mrbgems/mruby-struct/src/struct.c
+++ b/mrbgems/mruby-struct/src/struct.c
@@ -49,7 +49,7 @@ mrb_struct_iv_get(mrb_state *mrb, mrb_value c, const char *name)
mrb_value
mrb_struct_s_members(mrb_state *mrb, mrb_value klass)
{
- mrb_value members = struct_ivar_get(mrb, klass, mrb_intern(mrb, "__members__"));
+ mrb_value members = struct_ivar_get(mrb, klass, mrb_intern2(mrb, "__members__", 11));
if (mrb_nil_p(members)) {
mrb_raise(mrb, E_TYPE_ERROR, "uninitialized struct");
@@ -66,8 +66,9 @@ mrb_struct_members(mrb_state *mrb, mrb_value s)
mrb_value members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_obj_class(mrb, s)));
if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) {
if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "struct size differs (%ld required %ld given)",
- RARRAY_LEN(members), RSTRUCT_LEN(s));
+ mrb_raisef(mrb, E_TYPE_ERROR,
+ "struct size differs (%S required %S given)",
+ mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
}
}
return members;
@@ -112,7 +113,7 @@ mrb_value
mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id)
{
mrb_value members, slot, *ptr, *ptr_members;
- long i, len;
+ mrb_int i, len;
ptr = RSTRUCT_PTR(obj);
members = mrb_struct_members(mrb, obj);
@@ -124,7 +125,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id)
return ptr[i];
}
}
- mrb_raisef(mrb, E_NAME_ERROR, "%s is not struct member", mrb_sym2name(mrb, id));
+ mrb_raisef(mrb, E_NAME_ERROR, "%S is not struct member", mrb_sym2str(mrb, id));
return mrb_nil_value(); /* not reached */
}
@@ -166,7 +167,7 @@ mrb_id_attrset(mrb_state *mrb, mrb_sym id)
{
const char *name;
char *buf;
- int len;
+ size_t len;
mrb_sym mid;
name = mrb_sym2name_len(mrb, id, &len);
@@ -184,7 +185,8 @@ static mrb_value
mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val)
{
const char *name;
- int i, len;
+ int i;
+ size_t len;
mrb_sym mid;
mrb_value members, slot, *ptr, *ptr_members;
@@ -202,8 +204,8 @@ mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val)
return ptr[i] = val;
}
}
- mrb_raisef(mrb, E_NAME_ERROR, "`%s' is not a struct member",
- mrb_sym2name(mrb, mid));
+ mrb_raisef(mrb, E_NAME_ERROR, "`%S' is not a struct member",
+ mrb_sym2str(mrb, mid));
return mrb_nil_value(); /* not reached */
}
@@ -236,7 +238,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k
{
mrb_value nstr, *ptr_members;
mrb_sym id;
- long i, len;
+ mrb_int i, len;
struct RClass *c;
if (mrb_nil_p(name)) {
@@ -247,7 +249,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k
name = mrb_str_to_str(mrb, name);
id = mrb_to_id(mrb, name);
if (!mrb_is_const_id(id)) {
- mrb_raisef(mrb, E_NAME_ERROR, "identifier %s needs to be constant", mrb_string_value_ptr(mrb, name));
+ mrb_raisef(mrb, E_NAME_ERROR, "identifier %S needs to be constant", name);
}
if (mrb_const_defined_at(mrb, klass, id)) {
mrb_warn("redefining constant Struct::%s", mrb_string_value_ptr(mrb, name));
@@ -257,7 +259,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k
}
MRB_SET_INSTANCE_TT(c, MRB_TT_ARRAY);
nstr = mrb_obj_value(c);
- mrb_iv_set(mrb, nstr, mrb_intern(mrb, "__members__"), members);
+ mrb_iv_set(mrb, nstr, mrb_intern2(mrb, "__members__", 11), members);
mrb_define_class_method(mrb, c, "new", mrb_instance_new, ARGS_ANY());
mrb_define_class_method(mrb, c, "[]", mrb_instance_new, ARGS_ANY());
@@ -288,7 +290,7 @@ mrb_struct_define(mrb_state *mrb, const char *name, ...)
char *mem;
if (!name) nm = mrb_nil_value();
- else nm = mrb_str_new2(mrb, name);
+ else nm = mrb_str_new_cstr(mrb, name);
ary = mrb_ary_new(mrb);
va_start(ar, name);
@@ -341,7 +343,7 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass)
mrb_value name, rest;
mrb_value *pargv;
int argcnt;
- long i;
+ mrb_int i;
mrb_value b, st;
mrb_sym id;
mrb_value *argv;
@@ -352,8 +354,8 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass)
mrb_get_args(mrb, "*&", &argv, &argc, &b);
if (argc == 0) { /* special case to avoid crash */
rest = mrb_ary_new(mrb);
- }
- else {
+ }
+ else {
if (argc > 0) name = argv[0];
if (argc > 1) rest = argv[1];
if (mrb_array_p(rest)) {
@@ -378,7 +380,7 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass)
id = mrb_to_id(mrb, RARRAY_PTR(rest)[i]);
RARRAY_PTR(rest)[i] = mrb_symbol_value(id);
}
- }
+ }
st = make_struct(mrb, name, rest, struct_class(mrb));
if (!mrb_nil_p(b)) {
mrb_funcall(mrb, b, "call", 1, &st);
@@ -392,7 +394,7 @@ num_members(mrb_state *mrb, struct RClass *klass)
{
mrb_value members;
- members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern(mrb, "__members__"));
+ members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern2(mrb, "__members__", 11));
if (!mrb_array_p(members)) {
mrb_raise(mrb, E_TYPE_ERROR, "broken members");
}
@@ -444,7 +446,7 @@ inspect_struct(mrb_state *mrb, mrb_value s, int recur)
const char *cn = mrb_class_name(mrb, mrb_obj_class(mrb, s));
mrb_value members, str = mrb_str_new(mrb, "#<struct ", 9);
mrb_value *ptr, *ptr_members;
- long i, len;
+ mrb_int i, len;
if (cn) {
mrb_str_append(mrb, str, mrb_str_new_cstr(mrb, cn));
@@ -471,7 +473,7 @@ inspect_struct(mrb_state *mrb, mrb_value s, int recur)
id = mrb_symbol(slot);
if (mrb_is_local_id(id) || mrb_is_const_id(id)) {
const char *name;
- int len;
+ size_t len;
name = mrb_sym2name_len(mrb, id, &len);
mrb_str_append(mrb, str, mrb_str_new(mrb, name, len));
@@ -531,7 +533,7 @@ static mrb_value
mrb_struct_aref_id(mrb_state *mrb, mrb_value s, mrb_sym id)
{
mrb_value *ptr, members, *ptr_members;
- long i, len;
+ mrb_int i, len;
ptr = RSTRUCT_PTR(s);
members = mrb_struct_members(mrb, s);
@@ -542,7 +544,7 @@ mrb_struct_aref_id(mrb_state *mrb, mrb_value s, mrb_sym id)
return ptr[i];
}
}
- mrb_raisef(mrb, E_NAME_ERROR, "no member '%s' in struct", mrb_sym2name(mrb, id));
+ mrb_raisef(mrb, E_NAME_ERROR, "no member '%S' in struct", mrb_sym2str(mrb, id));
return mrb_nil_value(); /* not reached */
}
@@ -568,7 +570,7 @@ mrb_struct_aref_id(mrb_state *mrb, mrb_value s, mrb_sym id)
mrb_value
mrb_struct_aref_n(mrb_state *mrb, mrb_value s, mrb_value idx)
{
- long i;
+ mrb_int i;
if (mrb_string_p(idx) || mrb_symbol_p(idx)) {
return mrb_struct_aref_id(mrb, s, mrb_to_id(mrb, idx));
@@ -577,11 +579,13 @@ mrb_struct_aref_n(mrb_state *mrb, mrb_value s, mrb_value idx)
i = mrb_fixnum(idx);
if (i < 0) i = RSTRUCT_LEN(s) + i;
if (i < 0)
- mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too small for struct(size:%ld)",
- i, RSTRUCT_LEN(s));
+ mrb_raisef(mrb, E_INDEX_ERROR,
+ "offset %S too small for struct(size:%S)",
+ mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
if (RSTRUCT_LEN(s) <= i)
- mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too large for struct(size:%ld)",
- i, RSTRUCT_LEN(s));
+ mrb_raisef(mrb, E_INDEX_ERROR,
+ "offset %S too large for struct(size:%S)",
+ mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
return RSTRUCT_PTR(s)[i];
}
@@ -598,13 +602,14 @@ static mrb_value
mrb_struct_aset_id(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val)
{
mrb_value members, *ptr, *ptr_members;
- long i, len;
+ mrb_int i, len;
members = mrb_struct_members(mrb, s);
len = RARRAY_LEN(members);
if (RSTRUCT_LEN(s) != len) {
- mrb_raisef(mrb, E_TYPE_ERROR, "struct size differs (%ld required %ld given)",
- len, RSTRUCT_LEN(s));
+ mrb_raisef(mrb, E_TYPE_ERROR,
+ "struct size differs (%S required %S given)",
+ mrb_fixnum_value(len), mrb_fixnum_value(RSTRUCT_LEN(s)));
}
ptr = RSTRUCT_PTR(s);
ptr_members = RARRAY_PTR(members);
@@ -614,7 +619,7 @@ mrb_struct_aset_id(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val)
return val;
}
}
- mrb_raisef(mrb, E_NAME_ERROR, "no member '%s' in struct", mrb_sym2name(mrb, id));
+ mrb_raisef(mrb, E_NAME_ERROR, "no member '%S' in struct", mrb_sym2str(mrb, id));
return val; /* not reach */
}
@@ -643,7 +648,7 @@ mrb_struct_aset_id(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val)
mrb_value
mrb_struct_aset(mrb_state *mrb, mrb_value s)
{
- long i;
+ mrb_int i;
mrb_value idx;
mrb_value val;
@@ -656,12 +661,14 @@ mrb_struct_aset(mrb_state *mrb, mrb_value s)
i = mrb_fixnum(idx);
if (i < 0) i = RSTRUCT_LEN(s) + i;
if (i < 0) {
- mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too small for struct(size:%ld)",
- i, RSTRUCT_LEN(s));
+ mrb_raisef(mrb, E_INDEX_ERROR,
+ "offset %S too small for struct(size:%S)",
+ mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
}
if (RSTRUCT_LEN(s) <= i) {
- mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too large for struct(size:%ld)",
- i, RSTRUCT_LEN(s));
+ mrb_raisef(mrb, E_INDEX_ERROR,
+ "offset %S too large for struct(size:%S)",
+ mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
}
return RSTRUCT_PTR(s)[i] = val;
}
@@ -689,22 +696,35 @@ mrb_struct_equal(mrb_state *mrb, mrb_value s)
{
mrb_value s2;
mrb_value *ptr, *ptr2;
- long i, len;
+ mrb_int i, len;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &s2);
- if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value();
- if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) return mrb_false_value();
- if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) return mrb_false_value();
- if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
+ if (mrb_obj_equal(mrb, s, s2)) {
+ equal_p = 1;
+ }
+ else if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct") ||
+ mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
+ equal_p = 0;
+ }
+ else if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
mrb_bug("inconsistent struct"); /* should never happen */
+ equal_p = 0; /* This substuture is just to suppress warnings. never called. */
}
- ptr = RSTRUCT_PTR(s);
- ptr2 = RSTRUCT_PTR(s2);
- len = RSTRUCT_LEN(s);
- for (i=0; i<len; i++) {
- if (!mrb_equal(mrb, ptr[i], ptr2[i])) return mrb_false_value();
+ else {
+ ptr = RSTRUCT_PTR(s);
+ ptr2 = RSTRUCT_PTR(s2);
+ len = RSTRUCT_LEN(s);
+ equal_p = 1;
+ for (i=0; i<len; i++) {
+ if (!mrb_equal(mrb, ptr[i], ptr2[i])) {
+ equal_p = 0;
+ break;
+ }
+ }
}
- return mrb_true_value();
+
+ return mrb_bool_value(equal_p);
}
/* 15.2.18.4.12(x) */
@@ -720,23 +740,35 @@ mrb_struct_eql(mrb_state *mrb, mrb_value s)
{
mrb_value s2;
mrb_value *ptr, *ptr2;
- long i, len;
+ mrb_int i, len;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &s2);
- if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value();
- if (strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s2)), "Struct")) return mrb_false_value();
- if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) return mrb_false_value();
- if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
+ if (mrb_obj_equal(mrb, s, s2)) {
+ eql_p = 1;
+ }
+ else if (strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s2)), "Struct") ||
+ mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
+ eql_p = 0;
+ }
+ else if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
mrb_bug("inconsistent struct"); /* should never happen */
+ eql_p = 0; /* This substuture is just to suppress warnings. never called. */
}
-
- ptr = RSTRUCT_PTR(s);
- ptr2 = RSTRUCT_PTR(s2);
- len = RSTRUCT_LEN(s);
- for (i=0; i<len; i++) {
- if (!mrb_eql(mrb, ptr[i], ptr2[i])) return mrb_false_value();
+ else {
+ ptr = RSTRUCT_PTR(s);
+ ptr2 = RSTRUCT_PTR(s2);
+ len = RSTRUCT_LEN(s);
+ eql_p = 1;
+ for (i=0; i<len; i++) {
+ if (!mrb_eql(mrb, ptr[i], ptr2[i])) {
+ eql_p = 0;
+ break;
+ }
+ }
}
- return mrb_true_value();
+
+ return mrb_bool_value(eql_p);
}
/*
diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c
index ecc9090f1..0ffc0e6f8 100644
--- a/mrbgems/mruby-time/src/time.c
+++ b/mrbgems/mruby-time/src/time.c
@@ -6,7 +6,6 @@
#include "mruby.h"
-#include <string.h>
#include <stdio.h>
#include <time.h>
#include "mruby/class.h"
@@ -87,11 +86,6 @@ timegm(struct tm *tm)
* second level. Also, there are only 2 timezones, namely UTC and LOCAL.
*/
-#ifndef mrb_bool_value
-#define mrb_bool_value(val) ((val) ? mrb_true_value() : mrb_false_value())
-#endif
-
-
enum mrb_timezone {
MRB_TIMEZONE_NONE = 0,
MRB_TIMEZONE_UTC = 1,
@@ -130,7 +124,7 @@ mrb_time_free(mrb_state *mrb, void *ptr)
static struct mrb_data_type mrb_time_type = { "Time", mrb_time_free };
/** Updates the datetime of a mrb_time based on it's timezone and
-seconds setting. Returns self on cussess, NULL of failure. */
+seconds setting. Returns self on success, NULL of failure. */
static struct mrb_time*
mrb_time_update_datetime(struct mrb_time *self)
{
@@ -242,8 +236,8 @@ mrb_time_at(mrb_state *mrb, mrb_value self)
static struct mrb_time*
time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
- mrb_int ahour, mrb_int amin, mrb_int asec, mrb_int ausec,
- enum mrb_timezone timezone)
+ mrb_int ahour, mrb_int amin, mrb_int asec, mrb_int ausec,
+ enum mrb_timezone timezone)
{
time_t nowsecs;
struct tm nowtime = { 0 };
@@ -278,7 +272,7 @@ mrb_time_gm(mrb_state *mrb, mrb_value self)
mrb_get_args(mrb, "i|iiiiii",
&ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
return mrb_time_wrap(mrb, mrb_class_ptr(self),
- time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_UTC));
+ time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_UTC));
}
@@ -292,7 +286,7 @@ mrb_time_local(mrb_state *mrb, mrb_value self)
mrb_get_args(mrb, "i|iiiiii",
&ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
return mrb_time_wrap(mrb, mrb_class_ptr(self),
- time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL));
+ time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL));
}
@@ -301,15 +295,14 @@ mrb_time_eq(mrb_state *mrb, mrb_value self)
{
mrb_value other;
struct mrb_time *tm1, *tm2;
+ mrb_bool eq_p;
mrb_get_args(mrb, "o", &other);
tm1 = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
tm2 = (struct mrb_time *)mrb_get_datatype(mrb, other, &mrb_time_type);
- if (!tm1 || !tm2) return mrb_false_value();
- if (tm1->sec == tm2->sec && tm1->usec == tm2->usec) {
- return mrb_true_value();
- }
- return mrb_false_value();
+ eq_p = tm1 && tm2 && tm1->sec == tm2->sec && tm1->usec == tm2->usec;
+
+ return mrb_bool_value(eq_p);
}
static mrb_value
@@ -437,10 +430,10 @@ mrb_time_asctime(mrb_state *mrb, mrb_value self)
if (!tm) return mrb_nil_value();
d = &tm->datetime;
len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d",
- wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday,
- d->tm_hour, d->tm_min, d->tm_sec,
- tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "",
- d->tm_year + 1900);
+ wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday,
+ d->tm_hour, d->tm_min, d->tm_sec,
+ tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "",
+ d->tm_year + 1900);
return mrb_str_new(mrb, buf, len);
}
@@ -528,9 +521,11 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self)
if (tm) {
mrb_time_free(mrb, tm);
}
+ DATA_TYPE(self) = &mrb_time_type;
+ DATA_PTR(self) = NULL;
n = mrb_get_args(mrb, "|iiiiiii",
- &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
+ &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
if (n == 0) {
tm = current_mrb_time(mrb);
}
@@ -538,7 +533,6 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self)
tm = time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL);
}
DATA_PTR(self) = tm;
- DATA_TYPE(self) = &mrb_time_type;
return self;
}
diff --git a/mrblib/array.rb b/mrblib/array.rb
index abbb38cb6..82df90950 100644
--- a/mrblib/array.rb
+++ b/mrblib/array.rb
@@ -52,7 +52,7 @@ class Array
##
# Alias for collect!
- #
+ #
# ISO 15.2.12.5.20
alias map! collect!
diff --git a/mrblib/compar.rb b/mrblib/compar.rb
index 9f2ab887d..40fb2e7f0 100644
--- a/mrblib/compar.rb
+++ b/mrblib/compar.rb
@@ -25,7 +25,7 @@ module Comparable
# Return true if +self+ is less
# than or equal to +other+.
# Otherwise return false.
- #
+ #
# ISO 15.3.3.2.2
def <= other
cmp = self <=> other
@@ -88,7 +88,7 @@ module Comparable
end
##
- # Return true if +self+ is greater
+ # Return true if +self+ is greater
# than or equal to +min+ and
# less than or equal to +max+.
# Otherwise return false.
diff --git a/mrblib/enum.rb b/mrblib/enum.rb
index 2774bc856..0593e1f04 100644
--- a/mrblib/enum.rb
+++ b/mrblib/enum.rb
@@ -73,7 +73,7 @@ module Enumerable
##
# Call the given block for each element
# which is yield by +each+. Append all
- # values of each block together and
+ # values of each block together and
# return this value.
#
# ISO 15.3.2.2.3
@@ -89,7 +89,7 @@ module Enumerable
# Call the given block for each element
# which is yield by +each+. Return
# +ifnone+ if no block value was true.
- # Otherwise return the first block value
+ # Otherwise return the first block value
# which had was true.
#
# ISO 15.3.2.2.4
@@ -158,8 +158,8 @@ module Enumerable
# Call the given block for each element
# which is yield by +each+ and which return
# value was true when invoking === with
- # +pattern+. Return an array with all
- # elements or the respective block values.
+ # +pattern+. Return an array with all
+ # elements or the respective block values.
#
# ISO 15.3.2.2.9
def grep(pattern, &block)
@@ -291,9 +291,9 @@ module Enumerable
##
# Call the given block for each element
- # which is yield by +each+. Return an
+ # which is yield by +each+. Return an
# array which contains two arrays. The
- # first array contains all elements
+ # first array contains all elements
# whose block value was true. The second
# array contains all elements whose
# block value was false.
diff --git a/mrblib/hash.rb b/mrblib/hash.rb
index 7b7b3f8ac..c304d4845 100644
--- a/mrblib/hash.rb
+++ b/mrblib/hash.rb
@@ -64,7 +64,7 @@ class Hash
# it will be called for each element with
# a duplicate key. The value of the block
# will be the final value of this element.
- #
+ #
# ISO 15.2.13.4.22
def merge(other, &block)
h = {}
diff --git a/mrblib/init_mrblib.c b/mrblib/init_mrblib.c
index eb7156bf1..f65b185a3 100644
--- a/mrblib/init_mrblib.c
+++ b/mrblib/init_mrblib.c
@@ -4,7 +4,7 @@
#include "mruby/string.h"
#include "mruby/proc.h"
-extern const char mrblib_irep[];
+extern const uint8_t mrblib_irep[];
void
mrb_init_mrblib(mrb_state *mrb)
diff --git a/mrblib/print.rb b/mrblib/print.rb
index 68c7837f3..1ae3ae84b 100644
--- a/mrblib/print.rb
+++ b/mrblib/print.rb
@@ -3,78 +3,16 @@
#
# ISO 15.3.1
module Kernel
- unless Kernel.respond_to?(:__printstr__)
- def print(*a)
- raise NotImplementedError.new('print not available')
- end
- def puts(*a)
- raise NotImplementedError.new('puts not available')
- end
- def p(*a)
- raise NotImplementedError.new('p not available')
- end
- def printf(*args)
- raise NotImplementedError.new('printf not available')
- end
- else
- unless Kernel.respond_to?(:sprintf)
- def printf(*args)
- raise NotImplementedError.new('printf not available')
- end
- def sprintf(*args)
- raise NotImplementedError.new('sprintf not available')
- end
- end
-
-
- ##
- # Invoke method +print+ on STDOUT and passing +*args+
- #
- # ISO 15.3.1.2.10
- def print(*args)
- i = 0
- len = args.size
- while i < len
- __printstr__ args[i].to_s
- i += 1
- end
- end
-
- ##
- # Invoke method +puts+ on STDOUT and passing +*args*+
- #
- # ISO 15.3.1.2.11
- def puts(*args)
- i = 0
- len = args.size
- while i < len
- s = args[i].to_s
- __printstr__ s
- __printstr__ "\n" if (s[-1] != "\n")
- i += 1
- end
- __printstr__ "\n" if len == 0
- nil
- end
-
- ##
- # Print human readable object description
- #
- # ISO 15.3.1.3.34
- def p(*args)
- i = 0
- len = args.size
- while i < len
- __printstr__ args[i].inspect
- __printstr__ "\n"
- i += 1
- end
- args[0]
- end
-
- def printf(*args)
- __printstr__(sprintf(*args))
- nil
- end
+ def print(*a)
+ raise NotImplementedError.new('print not available')
+ end
+ def puts(*a)
+ raise NotImplementedError.new('puts not available')
+ end
+ def p(*a)
+ raise NotImplementedError.new('p not available')
+ end
+ def printf(*args)
+ raise NotImplementedError.new('printf not available')
end
end
diff --git a/src/array.c b/src/array.c
index c767283aa..88f56f6b4 100644
--- a/src/array.c
+++ b/src/array.c
@@ -4,20 +4,25 @@
** See Copyright Notice in mruby.h
*/
+#ifndef SIZE_MAX
+ /* Some versions of VC++
+ * has SIZE_MAX in stdint.h
+ */
+# include <limits.h>
+#endif
#include "mruby.h"
#include "mruby/array.h"
-#include <string.h>
-#include "mruby/string.h"
#include "mruby/class.h"
+#include "mruby/string.h"
+#include "value_array.h"
#define ARY_DEFAULT_LEN 4
#define ARY_SHRINK_RATIO 5 /* must be larger than 2 */
-#ifdef INT_MAX
-# define ARY_MAX_SIZE (INT_MAX / sizeof(mrb_value))
-#endif
+#define ARY_C_MAX_SIZE (SIZE_MAX / sizeof(mrb_value))
+#define ARY_MAX_SIZE ((ARY_C_MAX_SIZE < (size_t)MRB_INT_MAX) ? (mrb_int)ARY_C_MAX_SIZE : MRB_INT_MAX)
static inline mrb_value
-ary_elt(mrb_value ary, int offset)
+ary_elt(mrb_value ary, mrb_int offset)
{
if (RARRAY_LEN(ary) == 0) return mrb_nil_value();
if (offset < 0 || RARRAY_LEN(ary) <= offset) {
@@ -27,16 +32,14 @@ ary_elt(mrb_value ary, int offset)
}
static struct RArray*
-ary_new_capa(mrb_state *mrb, int capa)
+ary_new_capa(mrb_state *mrb, mrb_int capa)
{
struct RArray *a;
- int blen;
+ mrb_int blen;
-#ifdef INT_MAX
if (capa > ARY_MAX_SIZE) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big");
}
-#endif
blen = capa * sizeof(mrb_value) ;
if (blen < capa) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big");
@@ -51,7 +54,7 @@ ary_new_capa(mrb_state *mrb, int capa)
}
mrb_value
-mrb_ary_new_capa(mrb_state *mrb, int capa)
+mrb_ary_new_capa(mrb_state *mrb, mrb_int capa)
{
struct RArray *a = ary_new_capa(mrb, capa);
return mrb_obj_value(a);
@@ -87,21 +90,6 @@ array_copy(mrb_value *dst, const mrb_value *src, size_t size)
}
}
-
-mrb_value
-mrb_ary_new_from_values(mrb_state *mrb, int size, mrb_value *vals)
-{
- mrb_value ary;
- struct RArray *a;
-
- ary = mrb_ary_new_capa(mrb, size);
- a = mrb_ary_ptr(ary);
- array_copy(a->ptr, vals, size);
- a->len = size;
-
- return ary;
-}
-
mrb_value
mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr)
{
@@ -112,7 +100,7 @@ mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr)
}
static void
-ary_fill_with_nil(mrb_value *ptr, int size)
+ary_fill_with_nil(mrb_value *ptr, mrb_int size)
{
mrb_value nil = mrb_nil_value();
@@ -134,13 +122,13 @@ ary_modify(mrb_state *mrb, struct RArray *a)
}
else {
mrb_value *ptr, *p;
- int len;
+ mrb_int len;
p = a->ptr;
len = a->len * sizeof(mrb_value);
ptr = (mrb_value *)mrb_malloc(mrb, len);
if (p) {
- array_copy(ptr, p, a->len);
+ array_copy(ptr, p, a->len);
}
a->ptr = ptr;
a->aux.capa = a->len;
@@ -170,15 +158,13 @@ ary_make_shared(mrb_state *mrb, struct RArray *a)
}
static void
-ary_expand_capa(mrb_state *mrb, struct RArray *a, int len)
+ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len)
{
- int capa = a->aux.capa;
+ mrb_int capa = a->aux.capa;
-#ifdef INT_MAX
if (len > ARY_MAX_SIZE) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
-#endif
while(capa < len) {
if (capa == 0) {
@@ -189,20 +175,24 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, int len)
}
}
-#ifdef INT_MAX
if (capa > ARY_MAX_SIZE) capa = ARY_MAX_SIZE; /* len <= capa <= ARY_MAX_SIZE */
-#endif
if (capa > a->aux.capa) {
+ mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa);
+
+ if(!expanded_ptr) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "out of memory");
+ }
+
a->aux.capa = capa;
- a->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa);
+ a->ptr = expanded_ptr;
}
}
static void
ary_shrink_capa(mrb_state *mrb, struct RArray *a)
{
- int capa = a->aux.capa;
+ mrb_int capa = a->aux.capa;
if (capa < ARY_DEFAULT_LEN * 2) return;
if (capa <= a->len * ARY_SHRINK_RATIO) return;
@@ -228,13 +218,13 @@ mrb_ary_s_create(mrb_state *mrb, mrb_value self)
int len;
mrb_get_args(mrb, "*", &vals, &len);
- return mrb_ary_new_from_values(mrb, (int)len, vals);
+ return mrb_ary_new_from_values(mrb, len, vals);
}
static void
-ary_concat(mrb_state *mrb, struct RArray *a, mrb_value *ptr, int blen)
+ary_concat(mrb_state *mrb, struct RArray *a, mrb_value *ptr, mrb_int blen)
{
- int len = a->len + blen;
+ mrb_int len = a->len + blen;
ary_modify(mrb, a);
if (a->aux.capa < len) ary_expand_capa(mrb, a, len);
@@ -255,7 +245,7 @@ mrb_value
mrb_ary_concat_m(mrb_state *mrb, mrb_value self)
{
mrb_value *ptr;
- int blen;
+ mrb_int blen;
mrb_get_args(mrb, "a", &ptr, &blen);
ary_concat(mrb, mrb_ary_ptr(self), ptr, blen);
@@ -269,7 +259,7 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self)
struct RArray *a2;
mrb_value ary;
mrb_value *ptr;
- int blen;
+ mrb_int blen;
mrb_get_args(mrb, "a", &ptr, &blen);
ary = mrb_ary_new_capa(mrb, a1->len + blen);
@@ -305,14 +295,14 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
mrb_value ary2;
struct RArray *a1, *a2;
mrb_value r = mrb_nil_value();
- int i, len;
+ mrb_int i, len;
mrb_get_args(mrb, "o", &ary2);
if (!mrb_array_p(ary2)) return mrb_nil_value();
a1 = RARRAY(ary1); a2 = RARRAY(ary2);
if (a1->len == a2->len && a1->ptr == a2->ptr) return mrb_fixnum_value(0);
else {
- mrb_sym cmp = mrb_intern(mrb, "<=>");
+ mrb_sym cmp = mrb_intern2(mrb, "<=>", 3);
len = RARRAY_LEN(ary1);
if (len > RARRAY_LEN(ary2)) {
@@ -329,7 +319,7 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
}
static void
-ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, int len)
+ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, mrb_int len)
{
ary_modify(mrb, a);
if (a->aux.capa < len)
@@ -429,25 +419,19 @@ mrb_ary_reverse(mrb_state *mrb, mrb_value self)
}
mrb_value
-mrb_ary_new4(mrb_state *mrb, int n, const mrb_value *elts)
+mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals)
{
mrb_value ary;
+ struct RArray *a;
- ary = mrb_ary_new_capa(mrb, n);
- if (n > 0 && elts) {
- array_copy(RARRAY_PTR(ary), elts, n);
- RARRAY_LEN(ary) = n;
- }
+ ary = mrb_ary_new_capa(mrb, size);
+ a = mrb_ary_ptr(ary);
+ array_copy(a->ptr, vals, size);
+ a->len = size;
return ary;
}
-mrb_value
-mrb_ary_new_elts(mrb_state *mrb, int n, const mrb_value *elts)
-{
- return mrb_ary_new4(mrb, n, elts);
-}
-
void
mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem) /* mrb_ary_push */
{
@@ -505,7 +489,7 @@ mrb_ary_shift(mrb_state *mrb, mrb_value self)
}
else {
mrb_value *ptr = a->ptr;
- int size = a->len;
+ mrb_int size = a->len;
val = *ptr;
while((int)(--size)) {
@@ -536,7 +520,7 @@ mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item)
ary_modify(mrb, a);
if (a->aux.capa < a->len + 1)
ary_expand_capa(mrb, a, a->len + 1);
- memmove(a->ptr + 1, a->ptr, sizeof(mrb_value)*a->len);
+ value_move(a->ptr + 1, a->ptr, a->len);
a->ptr[0] = item;
}
a->len++;
@@ -563,7 +547,7 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self)
if (len == 0) return self;
if (a->aux.capa < a->len + len)
ary_expand_capa(mrb, a, a->len + len);
- memmove(a->ptr + len, a->ptr, sizeof(mrb_value)*a->len);
+ value_move(a->ptr + len, a->ptr, a->len);
}
array_copy(a->ptr, vals, len);
a->len += len;
@@ -594,7 +578,7 @@ mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) /* rb_ary_s
if (n < 0) {
n += a->len;
if (n < 0) {
- mrb_raisef(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len);
+ mrb_raisef(mrb, E_INDEX_ERROR, "index %S out of array", mrb_fixnum_value(n - a->len));
}
}
if (a->len <= (int)n) {
@@ -612,9 +596,9 @@ mrb_value
mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_value rpl)
{
struct RArray *a = mrb_ary_ptr(ary);
- int tail, size;
+ mrb_int tail, size;
mrb_value *argv;
- int i, argc;
+ mrb_int i, argc;
ary_modify(mrb, a);
/* range check */
@@ -648,7 +632,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
ary_fill_with_nil(a->ptr + a->len, (int)(head - a->len));
}
else if (head < a->len) {
- memmove(a->ptr + head + argc, a->ptr + tail, sizeof(mrb_value)*(a->len - tail));
+ value_move(a->ptr + head + argc, a->ptr + tail, a->len - tail);
}
for(i = 0; i < argc; i++) {
@@ -660,7 +644,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
return ary;
}
-int
+mrb_int
mrb_ary_len(mrb_state *mrb, mrb_value ary)
{
return RARRAY_LEN(ary);
@@ -677,7 +661,7 @@ mrb_ary_decref(mrb_state *mrb, mrb_shared_array *shared)
}
static mrb_value
-ary_subseq(mrb_state *mrb, struct RArray *a, int beg, int len)
+ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len)
{
struct RArray *b;
@@ -714,11 +698,12 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self)
len = mrb_fixnum(argv[0]);
if (len < 0) return mrb_nil_value();
if (a->len == (int)index) return mrb_ary_new(mrb);
- if ((int)len > a->len - index) len = a->len - index;
+ if (len > a->len - index) len = a->len - index;
return ary_subseq(mrb, a, index, len);
default:
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ break;
}
return mrb_nil_value(); /* dummy to avoid warning : not reach here */
@@ -757,7 +742,7 @@ mrb_ary_delete_at(mrb_state *mrb, mrb_value self)
mrb_int index;
mrb_value val;
mrb_value *ptr;
- int len;
+ mrb_int len;
mrb_get_args(mrb, "i", &index);
if (index < 0) index += a->len;
@@ -803,7 +788,7 @@ mrb_value
mrb_ary_last(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
- int size;
+ mrb_int size;
mrb_value *vals;
int len;
@@ -830,7 +815,7 @@ mrb_value
mrb_ary_index_m(mrb_state *mrb, mrb_value self)
{
mrb_value obj;
- int i;
+ mrb_int i;
mrb_get_args(mrb, "o", &obj);
for (i = 0; i < RARRAY_LEN(self); i++) {
@@ -845,7 +830,7 @@ mrb_value
mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
{
mrb_value obj;
- int i;
+ mrb_int i;
mrb_get_args(mrb, "o", &obj);
for (i = RARRAY_LEN(self) - 1; i >= 0; i--) {
@@ -894,7 +879,7 @@ mrb_ary_empty_p(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
- return ((a->len == 0)? mrb_true_value(): mrb_false_value());
+ return mrb_bool_value(a->len == 0);
}
mrb_value
@@ -904,7 +889,7 @@ mrb_check_array_type(mrb_state *mrb, mrb_value ary)
}
mrb_value
-mrb_ary_entry(mrb_value ary, int offset)
+mrb_ary_entry(mrb_value ary, mrb_int offset)
{
if (offset < 0) {
offset += RARRAY_LEN(ary);
@@ -915,7 +900,7 @@ mrb_ary_entry(mrb_value ary, int offset)
static mrb_value
inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
{
- int i;
+ mrb_int i;
mrb_value s, arystr;
char head[] = { '[' };
char sep[] = { ',', ' ' };
@@ -967,17 +952,13 @@ static mrb_value
mrb_ary_inspect(mrb_state *mrb, mrb_value ary)
{
if (RARRAY_LEN(ary) == 0) return mrb_str_new(mrb, "[]", 2);
- #if 0 /* THREAD */
- return mrb_exec_recursive(inspect_ary_r, ary, 0);
- #else
return inspect_ary(mrb, ary, mrb_ary_new(mrb));
- #endif
}
static mrb_value
join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list)
{
- int i;
+ mrb_int i;
mrb_value result, val, tmp;
/* check recursive */
@@ -1075,31 +1056,39 @@ static mrb_value
mrb_ary_equal(mrb_state *mrb, mrb_value ary1)
{
mrb_value ary2;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &ary2);
- if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value();
- if (mrb_special_const_p(ary2)) return mrb_false_value();
- if (!mrb_array_p(ary2)) {
- if (!mrb_respond_to(mrb, ary2, mrb_intern(mrb, "to_ary"))) {
- return mrb_false_value();
- }
- if (mrb_equal(mrb, ary2, ary1)){
- return mrb_true_value();
+ if (mrb_obj_equal(mrb, ary1, ary2)) {
+ equal_p = 1;
+ }
+ else if (mrb_special_const_p(ary2)) {
+ equal_p = 0;
+ }
+ else if (!mrb_array_p(ary2)) {
+ if (!mrb_respond_to(mrb, ary2, mrb_intern2(mrb, "to_ary", 6))) {
+ equal_p = 0;
}
else {
- return mrb_false_value();
+ equal_p = mrb_equal(mrb, ary2, ary1);
}
}
- if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value();
+ else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) {
+ equal_p = 0;
+ }
else {
- int i;
+ mrb_int i;
+ equal_p = 1;
for (i=0; i<RARRAY_LEN(ary1); i++) {
- if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i)))
- return mrb_false_value();
+ if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) {
+ equal_p = 0;
+ break;
+ }
}
- return mrb_true_value();
}
+
+ return mrb_bool_value(equal_p);
}
/* 15.2.12.5.34 (x) */
@@ -1115,20 +1104,30 @@ static mrb_value
mrb_ary_eql(mrb_state *mrb, mrb_value ary1)
{
mrb_value ary2;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &ary2);
- if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value();
- if (!mrb_array_p(ary2)) return mrb_false_value();
- if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value();
+ if (mrb_obj_equal(mrb, ary1, ary2)) {
+ eql_p = 1;
+ }
+ else if (!mrb_array_p(ary2)) {
+ eql_p = 0;
+ }
+ else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) {
+ eql_p = 0;
+ }
else {
- int i;
-
+ mrb_int i;
+ eql_p = 1;
for (i=0; i<RARRAY_LEN(ary1); i++) {
- if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i)))
- return mrb_false_value();
+ if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) {
+ eql_p = 0;
+ break;
+ }
}
- return mrb_true_value();
}
+
+ return mrb_bool_value(eql_p);
}
void
diff --git a/src/class.c b/src/class.c
index c0e71dad7..9dc7b46d6 100644
--- a/src/class.c
+++ b/src/class.c
@@ -6,14 +6,13 @@
#include "mruby.h"
#include <stdarg.h>
-#include <stdio.h>
#include <ctype.h>
+#include "mruby/array.h"
#include "mruby/class.h"
+#include "mruby/numeric.h"
#include "mruby/proc.h"
#include "mruby/string.h"
-#include "mruby/numeric.h"
#include "mruby/variable.h"
-#include "mruby/array.h"
#include "error.h"
KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal)
@@ -29,7 +28,7 @@ mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
if (kh_exist(h, k)){
struct RProc *m = kh_value(h, k);
if (m) {
- mrb_gc_mark(mrb, (struct RBasic*)m);
+ mrb_gc_mark(mrb, (struct RBasic*)m);
}
}
}
@@ -54,7 +53,7 @@ void
mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
{
mrb_obj_iv_set(mrb, (struct RObject*)c,
- mrb_intern(mrb, "__classid__"), mrb_symbol_value(name));
+ mrb_intern2(mrb, "__classid__", 11), mrb_symbol_value(name));
}
#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))
@@ -88,7 +87,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
o->c = sc;
mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc);
mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o);
- mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern(mrb, "__attached__"), mrb_obj_value(o));
+ mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern2(mrb, "__attached__", 12), mrb_obj_value(o));
}
struct RClass*
@@ -115,7 +114,7 @@ setup_class(mrb_state *mrb, mrb_value outer, struct RClass *c, mrb_sym id)
mrb_name_class(mrb, c, id);
mrb_const_set(mrb, outer, id, mrb_obj_value(c));
mrb_obj_iv_set(mrb, (struct RObject*)c,
- mrb_intern(mrb, "__outer__"), outer);
+ mrb_intern2(mrb, "__outer__", 9), outer);
}
struct RClass*
@@ -123,7 +122,7 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c)
{
mrb_value outer;
- outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__outer__"));
+ outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__outer__", 9));
if (mrb_nil_p(outer)) return 0;
return mrb_class_ptr(outer);
}
@@ -177,11 +176,11 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
c = mrb_class_ptr(v);
if (!mrb_nil_p(super)) {
if (mrb_type(super) != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super));
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", super);
}
if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %s", mrb_sym2name(mrb, id));
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", mrb_sym2str(mrb, id));
}
}
return c;
@@ -189,7 +188,7 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
if (!mrb_nil_p(super)) {
if (mrb_type(super) != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super));
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", super);
}
s = mrb_class_ptr(super);
}
@@ -204,13 +203,19 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
return c;
}
+int
+mrb_class_defined(mrb_state *mrb, const char *name)
+{
+ return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_intern(mrb, name));
+}
+
static struct RClass *
class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
{
mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
if (mrb_type(c) != MRB_TT_MODULE && mrb_type(c) != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "%s is not a class/module", mrb_sym2name(mrb, id));
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_sym2str(mrb, id));
}
return mrb_class_ptr(c);
}
@@ -246,13 +251,13 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s
if (mrb_const_defined_at(mrb, outer, id)) {
c = class_from_sym(mrb, outer, id);
if (mrb_class_real(c->super) != super) {
- mrb_name_error(mrb, id, "%s is already defined", mrb_sym2name(mrb, id));
+ mrb_name_error(mrb, id, "%S is already defined", mrb_sym2str(mrb, id));
}
return c;
}
if (!super) {
- mrb_warn("no super class for `%s::%s', Object assumed",
- mrb_obj_classname(mrb, mrb_obj_value(outer)), mrb_sym2name(mrb, id));
+ mrb_warn("no super class for `%S::%S', Object assumed",
+ mrb_obj_value(outer), mrb_sym2str(mrb, id));
}
c = mrb_class_new(mrb, super);
setup_class(mrb, mrb_obj_value(outer), c, id);
@@ -291,17 +296,19 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro
}
void
-mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, int aspec)
+mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec)
{
struct RProc *p;
+ int ai = mrb_gc_arena_save(mrb);
p = mrb_proc_new_cfunc(mrb, func);
p->target_class = c;
mrb_define_method_raw(mrb, c, mid, p);
+ mrb_gc_arena_restore(mrb, ai);
}
void
-mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec)
+mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
{
mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, aspec);
}
@@ -329,7 +336,7 @@ check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const
tmp = mrb_check_convert_type(mrb, val, t, c, m);
if (mrb_nil_p(tmp)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "expected %s", c);
+ mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_cstr(mrb, c));
}
return tmp;
}
@@ -356,7 +363,7 @@ to_hash(mrb_state *mrb, mrb_value val)
retrieve arguments from mrb_state.
mrb_get_args(mrb, format, ...)
-
+
returns number of arguments parsed.
fortmat specifiers:
@@ -367,7 +374,7 @@ to_hash(mrb_state *mrb, mrb_value val)
H: Hash [mrb_value]
s: String [char*,int]
z: String [char*]
- a: Array [mrb_value*,int]
+ a: Array [mrb_value*,mrb_int]
f: Float [mrb_float]
i: Integer [mrb_int]
b: Binary [int]
@@ -401,6 +408,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (argc <= i && !opt) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
}
+ break;
}
switch (c) {
@@ -489,10 +497,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value aa;
struct RArray *a;
mrb_value **pb;
- int *pl;
+ mrb_int *pl;
pb = va_arg(ap, mrb_value**);
- pl = va_arg(ap, int*);
+ pl = va_arg(ap, mrb_int*);
if (i < argc) {
aa = to_ary(mrb, *sp++);
a = mrb_ary_ptr(aa);
@@ -597,8 +605,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
else {
mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0);
- mrb_raisef(mrb, E_TYPE_ERROR, "%s is not a symbol",
- mrb_string_value_ptr(mrb, obj));
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj);
}
i++;
}
@@ -646,7 +653,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
break;
default:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %c", c);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %S", mrb_str_new(mrb, &c, 1));
break;
}
}
@@ -774,7 +781,7 @@ mrb_mod_include_p(mrb_state *mrb, mrb_value mod)
}
return mrb_false_value();
}
-
+
static mrb_value
mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
{
@@ -902,7 +909,6 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
return mrb_obj_value(mrb->false_class);
case MRB_TT_TRUE:
return mrb_obj_value(mrb->true_class);
- case MRB_TT_MAIN:
case MRB_TT_VOIDP:
return mrb_obj_value(mrb->object_class);
case MRB_TT_SYMBOL:
@@ -913,26 +919,26 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
default:
break;
}
- obj = mrb_object(v);
+ obj = mrb_basic_ptr(v);
prepare_singleton_class(mrb, obj);
return mrb_obj_value(obj->c);
}
void
-mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, int aspec)
+mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, mrb_aspec aspec)
{
prepare_singleton_class(mrb, (struct RBasic*)o);
mrb_define_method_id(mrb, o->c, mrb_intern(mrb, name), func, aspec);
}
void
-mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec)
+mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
{
mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec);
}
void
-mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec)
+mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
{
mrb_define_class_method(mrb, c, name, func, aspec);
mrb_define_method(mrb, c, name, func, aspec);
@@ -973,8 +979,8 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
if (RSTRING_LEN(inspect) > 64) {
inspect = mrb_any_to_s(mrb, mrb_obj_value(c));
}
- mrb_raisef(mrb, E_NAME_ERROR, "undefined method '%s' for class %s",
- mrb_sym2name(mrb, mid), RSTRING_PTR(inspect));
+ mrb_raisef(mrb, E_NAME_ERROR, "undefined method '%S' for class %S",
+ mrb_sym2str(mrb, mid), inspect);
}
return m;
}
@@ -1081,9 +1087,7 @@ mrb_bob_init(mrb_state *mrb, mrb_value cv)
static mrb_value
mrb_bob_not(mrb_state *mrb, mrb_value cv)
{
- if (mrb_test(cv))
- return mrb_false_value();
- return mrb_true_value();
+ return mrb_bool_value(!mrb_test(cv));
}
/* 15.3.1.3.30 */
@@ -1131,13 +1135,18 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod)
mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol");
}
- inspect = mrb_funcall(mrb, mod, "inspect", 0);
- if (RSTRING_LEN(inspect) > 64) {
+ if (mrb_respond_to(mrb,mod,mrb_intern2(mrb,"inspect",7))){
+ inspect = mrb_funcall(mrb, mod, "inspect", 0);
+ if (RSTRING_LEN(inspect) > 64) {
+ inspect = mrb_any_to_s(mrb, mod);
+ }
+ }
+ else {
inspect = mrb_any_to_s(mrb, mod);
}
- mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%s' for %s",
- mrb_sym2name(mrb, mrb_symbol(name)), RSTRING_PTR(inspect));
+ mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S",
+ mrb_sym2str(mrb, mrb_symbol(name)), inspect);
/* not reached */
return mrb_nil_value();
}
@@ -1154,16 +1163,16 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid)
k = kh_get(mt, h, mid);
if (k != kh_end(h)) {
if (kh_value(h, k)) {
- return TRUE; /* method exists */
+ return TRUE; /* method exists */
}
else {
- return FALSE; /* undefined method */
+ return FALSE; /* undefined method */
}
}
}
c = c->super;
}
- return FALSE; /* no method */
+ return FALSE; /* no method */
}
int
@@ -1177,9 +1186,10 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
{
mrb_value path;
const char *name;
- int len;
+ size_t len;
+ mrb_sym classpath = mrb_intern2(mrb, "__classpath__", 13);
- path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"));
+ path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath);
if (mrb_nil_p(path)) {
struct RClass *outer = mrb_class_outer_module(mrb, c);
mrb_sym sym = mrb_class_sym(mrb, c, outer);
@@ -1196,7 +1206,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
name = mrb_sym2name_len(mrb, sym, &len);
path = mrb_str_new(mrb, name, len);
}
- mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"), path);
+ mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path);
}
return path;
}
@@ -1215,10 +1225,9 @@ mrb_class_name(mrb_state *mrb, struct RClass* c)
{
mrb_value path = mrb_class_path(mrb, c);
if (mrb_nil_p(path)) {
- char buf[32];
-
- snprintf(buf, 32, "#<Class:%p>", c);
- path = mrb_str_new_cstr(mrb, buf);
+ path = mrb_str_new(mrb, "#<Class:", 8);
+ mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c));
+ mrb_str_cat(mrb, path, ">", 1);
}
return mrb_str_ptr(path)->ptr;
}
@@ -1239,8 +1248,7 @@ void
mrb_check_inheritable(mrb_state *mrb, struct RClass *super)
{
if (super->tt != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)",
- mrb_obj_classname(mrb, mrb_obj_value(super)));
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", mrb_obj_value(super));
}
if (super->tt == MRB_TT_SCLASS) {
mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of singleton class");
@@ -1337,51 +1345,57 @@ mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const
static mrb_value
mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
{
+ mrb_value str;
+
if (mrb_type(klass) == MRB_TT_SCLASS) {
- mrb_value s = mrb_str_new(mrb, "#<", 2);
- mrb_value v = mrb_iv_get(mrb, klass, mrb_intern(mrb, "__attached__"));
+ mrb_value v = mrb_iv_get(mrb, klass, mrb_intern2(mrb, "__attached__", 12));
+
+ str = mrb_str_new(mrb, "#<Class:", 8);
- mrb_str_cat2(mrb, s, "Class:");
switch (mrb_type(v)) {
case MRB_TT_CLASS:
case MRB_TT_MODULE:
case MRB_TT_SCLASS:
- mrb_str_append(mrb, s, mrb_inspect(mrb, v));
+ mrb_str_append(mrb, str, mrb_inspect(mrb, v));
break;
default:
- mrb_str_append(mrb, s, mrb_any_to_s(mrb, v));
+ mrb_str_append(mrb, str, mrb_any_to_s(mrb, v));
break;
}
- mrb_str_cat2(mrb, s, ">");
-
- return s;
+ mrb_str_cat(mrb, str, ">", 1);
}
else {
- struct RClass *c = mrb_class_ptr(klass);
- const char *cn = mrb_class_name(mrb, c);
+ struct RClass *c;
+ mrb_value path;
- if (!cn) {
- char buf[256];
- int n = 0;
+ str = mrb_str_buf_new(mrb, 32);
+ c = mrb_class_ptr(klass);
+ path = mrb_class_path(mrb, c);
+ if (mrb_nil_p(path)) {
switch (mrb_type(klass)) {
case MRB_TT_CLASS:
- n = snprintf(buf, sizeof(buf), "#<Class:%p>", c);
+ mrb_str_cat(mrb, str, "#<Class:", 8);
break;
case MRB_TT_MODULE:
- n = snprintf(buf, sizeof(buf), "#<Module:%p>", c);
+ mrb_str_cat(mrb, str, "#<Module:", 9);
break;
default:
+ /* Shouldn't be happened? */
+ mrb_str_cat(mrb, str, "#<??????:", 9);
break;
}
- return mrb_str_dup(mrb, mrb_str_new(mrb, buf, n));
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c));
+ mrb_str_cat(mrb, str, ">", 1);
}
else {
- return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, cn));
+ str = path;
}
}
+
+ return str;
}
mrb_value
@@ -1454,11 +1468,11 @@ static void
check_cv_name(mrb_state *mrb, mrb_sym id)
{
const char *s;
- int len;
+ size_t len;
s = mrb_sym2name_len(mrb, id, &len);
if (len < 3 || !(s[0] == '@' && s[1] == '@')) {
- mrb_name_error(mrb, id, "`%s' is not allowed as a class variable name", s);
+ mrb_name_error(mrb, id, "`%S' is not allowed as a class variable name", mrb_sym2str(mrb, id));
}
}
@@ -1481,12 +1495,12 @@ static mrb_value
mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod)
{
mrb_sym id;
+ mrb_bool defined_p;
mrb_get_args(mrb, "n", &id);
check_cv_name(mrb, id);
- if(mrb_cv_defined(mrb, mod, id))
- return mrb_true_value();
- return mrb_false_value();
+ defined_p = mrb_cv_defined(mrb, mod, id);
+ return mrb_bool_value(defined_p);
}
/* 15.2.2.4.17 */
@@ -1580,12 +1594,12 @@ mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod)
if (!mrb_undef_p(val)) return val;
if (mrb_cv_defined(mrb, mod, id)){
- mrb_name_error(mrb, id, "cannot remove %s for %s",
- mrb_sym2name(mrb, id), mrb_class_name(mrb, mrb_class_ptr(mod)));
+ mrb_name_error(mrb, id, "cannot remove %S for %S",
+ mrb_sym2str(mrb, id), mod);
}
- mrb_name_error(mrb, id, "class variable %s not defined for %s",
- mrb_sym2name(mrb, id), mrb_class_name(mrb, mrb_class_ptr(mod)));
+ mrb_name_error(mrb, id, "class variable %S not defined for %S",
+ mrb_sym2str(mrb, id), mod);
/* not reached */
return mrb_nil_value();
@@ -1622,17 +1636,17 @@ static mrb_value
mrb_mod_method_defined(mrb_state *mrb, mrb_value mod)
{
mrb_sym id;
+ mrb_bool method_defined_p;
mrb_get_args(mrb, "n", &id);
- if (mrb_obj_respond_to(mrb_class_ptr(mod), id)) {
- return mrb_true_value();
- }
- return mrb_false_value();
+ method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), id);
+ return mrb_bool_value(method_defined_p);
}
static void
-remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid)
+remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid)
{
+ struct RClass *c = mrb_class_ptr(mod);
khash_t(mt) *h = c->mt;
khiter_t k;
@@ -1644,8 +1658,8 @@ remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid)
}
}
- mrb_name_error(mrb, mid, "method `%s' not defined in %s",
- mrb_sym2name(mrb, mid), mrb_class_name(mrb, c));
+ mrb_name_error(mrb, mid, "method `%S' not defined in %S",
+ mrb_sym2str(mrb, mid), mod);
}
/* 15.2.2.4.41 */
@@ -1660,13 +1674,12 @@ remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid)
mrb_value
mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
{
- struct RClass *c = mrb_class_ptr(mod);
int argc;
mrb_value *argv;
mrb_get_args(mrb, "*", &argv, &argc);
while (argc--) {
- remove_method(mrb, c, mrb_symbol(*argv));
+ remove_method(mrb, mod, mrb_symbol(*argv));
argv++;
}
return mod;
@@ -1676,11 +1689,11 @@ static void
check_const_name(mrb_state *mrb, mrb_sym id)
{
const char *s;
- int len;
+ size_t len;
s = mrb_sym2name_len(mrb, id, &len);
if (len < 1 || !ISUPPER(*s)) {
- mrb_name_error(mrb, id, "wrong constant name %s", s);
+ mrb_name_error(mrb, id, "wrong constant name %S", mrb_sym2str(mrb, id));
}
}
@@ -1688,13 +1701,13 @@ mrb_value
mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
{
mrb_sym id;
+ mrb_bool const_defined_p;
mrb_get_args(mrb, "n", &id);
check_const_name(mrb, id);
- if(mrb_const_defined(mrb, mod, id)) {
- return mrb_true_value();
- }
- return mrb_false_value();
+ const_defined_p = mrb_const_defined(mrb, mod, id);
+
+ return mrb_bool_value(const_defined_p);
}
mrb_value
@@ -1729,7 +1742,7 @@ mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
check_const_name(mrb, id);
val = mrb_iv_remove(mrb, mod, id);
if (mrb_undef_p(val)) {
- mrb_name_error(mrb, id, "constant %s not defined", mrb_sym2name(mrb, id));
+ mrb_name_error(mrb, id, "constant %S not defined", mrb_sym2str(mrb, id));
}
return val;
}
@@ -1738,11 +1751,12 @@ static mrb_value
mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
{
mrb_value obj;
+ mrb_bool eqq;
mrb_get_args(mrb, "o", &obj);
- if (!mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod)))
- return mrb_false_value();
- return mrb_true_value();
+ eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod));
+
+ return mrb_bool_value(eqq);
}
void
@@ -1790,6 +1804,7 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, cls, "new", mrb_instance_new, ARGS_ANY()); /* 15.2.3.3.3 */
mrb_define_method(mrb, cls, "inherited", mrb_bob_init, ARGS_REQ(1));
+ MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined, ARGS_REQ(1)); /* 15.2.2.4.16 */
mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, ARGS_REQ(1)); /* 15.2.2.4.17 */
mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, ARGS_REQ(2)); /* 15.2.2.4.18 */
diff --git a/src/codegen.c b/src/codegen.c
index ff7e87c28..b8909e809 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -4,18 +4,16 @@
** See Copyright Notice in mruby.h
*/
-#define CODEGEN_DUMP
-
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
#include "mruby.h"
-#include "mruby/string.h"
-#include "mruby/irep.h"
#include "mruby/compile.h"
+#include "mruby/irep.h"
#include "mruby/numeric.h"
-#include "opcode.h"
+#include "mruby/string.h"
#include "node.h"
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
+#include "opcode.h"
#include "re.h"
typedef mrb_ast_node node;
@@ -49,7 +47,7 @@ typedef struct scope {
int pc;
int lastlabel;
int ainfo:15;
- int mscope:1;
+ mrb_bool mscope:1;
struct loopinfo *loop;
int ensure_level;
@@ -330,12 +328,23 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
if (c1 == OP_SUB) c = -c;
if (c > 127 || c < -127) break;
- if (0 <= c)
+ if (0 <= c)
s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c);
else
s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
return;
}
+ case OP_STRCAT:
+ if (c0 == OP_STRING) {
+ int i = GETARG_Bx(i0);
+
+ if (mrb_type(s->irep->pool[i]) == MRB_TT_STRING &&
+ RSTRING_LEN(s->irep->pool[i]) == 0) {
+ s->pc--;
+ return;
+ }
+ }
+ break;
default:
break;
}
@@ -368,6 +377,7 @@ dispatch(codegen_scope *s, int pc)
fprintf(stderr, "bug: dispatch on non JMP op\n");
#endif
scope_error(s);
+ break;
}
s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
}
@@ -410,9 +420,27 @@ new_lit(codegen_scope *s, mrb_value val)
{
int i;
- for (i=0; i<s->irep->plen; i++) {
- if (mrb_obj_equal(s->mrb, s->irep->pool[i], val)) return i;
+
+ switch (mrb_type(val)) {
+ case MRB_TT_STRING:
+ for (i=0; i<s->irep->plen; i++) {
+ mrb_value pv = s->irep->pool[i];
+ mrb_int len;
+
+ if (mrb_type(pv) != MRB_TT_STRING) continue;
+ if ((len = RSTRING_LEN(pv)) != RSTRING_LEN(val)) continue;
+ if (memcmp(RSTRING_PTR(pv), RSTRING_PTR(val), len) == 0)
+ return i;
+ }
+ break;
+ case MRB_TT_FLOAT:
+ default:
+ for (i=0; i<s->irep->plen; i++) {
+ if (mrb_obj_equal(s->mrb, s->irep->pool[i], val)) return i;
+ }
+ break;
}
+
if (s->irep->plen == s->pcapa) {
s->pcapa *= 2;
s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
@@ -511,11 +539,11 @@ for_body(codegen_scope *s, node *tree)
// generate loop variable
n2 = tree->car;
if (n2->car && !n2->car->cdr && !n2->cdr) {
- genop(s, MKOP_Ax(OP_ENTER, 1<<18));
+ genop(s, MKOP_Ax(OP_ENTER, 0x40000));
gen_assignment(s, n2->car->car, 1, NOVAL);
}
else {
- genop(s, MKOP_Ax(OP_ENTER, 1<<18));
+ genop(s, MKOP_Ax(OP_ENTER, 0x40000));
gen_vmassignment(s, n2, 1, VAL);
}
codegen(s, tree->cdr->cdr->car, VAL);
@@ -530,7 +558,7 @@ for_body(codegen_scope *s, node *tree)
s = prev;
genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx - base, OP_L_BLOCK));
pop();
- idx = new_msym(s, mrb_intern(s->mrb, "each"));
+ idx = new_msym(s, mrb_intern2(s->mrb, "each", 4));
genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
}
@@ -550,7 +578,8 @@ lambda_body(codegen_scope *s, node *tree, int blk)
}
tree = tree->cdr;
if (tree->car) {
- int ma, oa, ra, pa, ka, kd, ba, a;
+ int32_t a;
+ int ma, oa, ra, pa, ka, kd, ba;
int pos, i;
node *n, *opt;
@@ -565,8 +594,8 @@ lambda_body(codegen_scope *s, node *tree, int blk)
ka = kd = 0;
ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
- a = ((ma & 0x1f) << 18)
- | ((oa & 0x1f) << 13)
+ a = ((int32_t)(ma & 0x1f) << 18)
+ | ((int32_t)(oa & 0x1f) << 13)
| ((ra & 1) << 12)
| ((pa & 0x1f) << 7)
| ((ka & 0x1f) << 2)
@@ -661,7 +690,7 @@ static mrb_sym
attrsym(codegen_scope *s, mrb_sym a)
{
const char *name;
- int len;
+ size_t len;
char *name2;
name = mrb_sym2name_len(s->mrb, a, &len);
@@ -679,7 +708,7 @@ gen_values(codegen_scope *s, node *t, int val)
int n = 0;
while (t) {
- if ((intptr_t)t->car->car == NODE_SPLAT) { // splat mode
+ if (n >= 127 || (intptr_t)t->car->car == NODE_SPLAT) { // splat mode
if (val) {
pop_n(n);
genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
@@ -760,7 +789,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val)
}
pop_n(n+1);
{
- int len;
+ size_t len;
const char *name = mrb_sym2name_len(s->mrb, sym, &len);
if (!noop && len == 1 && name[0] == '+') {
@@ -926,6 +955,68 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
}
static void
+gen_send_intern(codegen_scope *s)
+{
+ pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "intern", 6)), 0));
+ push();
+}
+static void
+gen_literal_array(codegen_scope *s, node *tree, int sym, int val)
+{
+ if (val) {
+ int i = 0, j = 0;
+
+ while (tree) {
+ switch ((intptr_t)tree->car->car) {
+ case NODE_STR:
+ if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0))
+ break;
+ /* fall through */
+ case NODE_BEGIN:
+ codegen(s, tree->car, VAL);
+ ++j;
+ break;
+
+ case NODE_LITERAL_DELIM:
+ if (j > 0) {
+ j = 0;
+ ++i;
+ if (sym)
+ gen_send_intern(s);
+ }
+ break;
+ }
+ if (j >= 2) {
+ pop(); pop();
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ push();
+ j = 1;
+ }
+ tree = tree->cdr;
+ }
+ if (j > 0) {
+ j = 0;
+ ++i;
+ if (sym)
+ gen_send_intern(s);
+ }
+ pop_n(i);
+ genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
+ push();
+ }
+ else {
+ while (tree) {
+ switch ((intptr_t)tree->car->car) {
+ case NODE_BEGIN: case NODE_BLOCK:
+ codegen(s, tree->car, NOVAL);
+ }
+ tree = tree->cdr;
+ }
+ }
+}
+
+static void
raise_error(codegen_scope *s, const char *msg)
{
int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
@@ -1059,12 +1150,12 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n4->car, VAL);
}
else {
- genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern(s->mrb, "StandardError"))));
+ genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern2(s->mrb, "StandardError", 13))));
push();
}
genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1));
tmp = new_label(s);
genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
@@ -1161,7 +1252,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (e) {
if (val) pop();
pos2 = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, 0));
+ genop(s, MKOP_sBx(OP_JMP, 0));
dispatch(s, pos1);
codegen(s, e, val);
dispatch(s, pos2);
@@ -1268,7 +1359,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (head) {
genop(s, MKOP_AB(OP_MOVE, cursp(), head));
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1));
}
else {
pop();
@@ -1462,7 +1553,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_OP_ASGN:
{
mrb_sym sym = sym(tree->cdr->car);
- int len;
+ size_t len;
const char *name = mrb_sym2name_len(s->mrb, sym, &len);
int idx;
@@ -1609,7 +1700,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
pop_n(n+1);
if (sendv) n = CALL_MAXARGS;
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "call")), n));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "call", 4)), n));
if (val) push();
}
break;
@@ -1757,12 +1848,13 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_BACK_REF:
{
- char buf[4];
- int len;
+ char buf[2] = { '$' };
+ mrb_value str;
int sym;
- len = snprintf(buf, sizeof(buf), "$%c", (int)(intptr_t)tree);
- sym = new_sym(s, mrb_intern2(s->mrb, buf, len));
+ buf[1] = (char)(intptr_t)tree;
+ str = mrb_str_new(s->mrb, buf, 2);
+ sym = new_sym(s, mrb_intern_str(s->mrb, str));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
}
@@ -1770,12 +1862,14 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_NTH_REF:
{
- char buf[4];
- int len;
int sym;
+ mrb_state *mrb = s->mrb;
+ mrb_value fix = mrb_fixnum_value((intptr_t)tree);
+ mrb_value str = mrb_str_buf_new(mrb, 4);
- len = snprintf(buf, sizeof(buf), "$%d", (int)(intptr_t)tree);
- sym = new_sym(s, mrb_intern2(s->mrb, buf, len));
+ mrb_str_buf_cat(mrb, str, "$", 1);
+ mrb_str_buf_append(mrb, str, mrb_fixnum_to_str(mrb, fix, 10));
+ sym = new_sym(s, mrb_intern_str(mrb, str));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
}
@@ -1876,7 +1970,7 @@ codegen(codegen_scope *s, node *tree, int val)
default:
{
- int sym = new_msym(s, mrb_intern(s->mrb, "-"));
+ int sym = new_msym(s, mrb_intern2(s->mrb, "-", 1));
genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
push();
@@ -1902,6 +1996,9 @@ codegen(codegen_scope *s, node *tree, int val)
}
break;
+ case NODE_HEREDOC:
+ tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
+ /* fall through */
case NODE_DSTR:
if (val) {
node *n = tree;
@@ -1911,7 +2008,7 @@ codegen(codegen_scope *s, node *tree, int val)
while (n) {
codegen(s, n->car, VAL);
pop(); pop();
- genop(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1));
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
push();
n = n->cdr;
}
@@ -1928,6 +2025,34 @@ codegen(codegen_scope *s, node *tree, int val)
}
break;
+ case NODE_WORDS:
+ gen_literal_array(s, tree, FALSE, val);
+ break;
+
+ case NODE_SYMBOLS:
+ gen_literal_array(s, tree, TRUE, val);
+ break;
+
+ case NODE_XSTR:
+ if (val) {
+ char *p = (char*)tree->car;
+ size_t len = (intptr_t)tree->cdr;
+ int ai = mrb_gc_arena_save(s->mrb);
+ int sym = new_sym(s, mrb_intern2(s->mrb, "Kernel", 6));
+ int off = new_lit(s, mrb_str_new(s->mrb, p, len));
+
+ genop(s, MKOP_A(OP_OCLASS, cursp()));
+ genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ push();
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ pop();
+ sym = new_sym(s, mrb_intern2(s->mrb, "`", 1));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
+ mrb_gc_arena_restore(s->mrb, ai);
+ push();
+ }
+ break;
+
case NODE_REGX:
if (val) {
char *p1 = (char*)tree->car;
@@ -1949,9 +2074,9 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
}
pop();
- sym = new_sym(s, mrb_intern(s->mrb, "compile"));
+ sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7));
genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
- mrb_gc_arena_restore(s->mrb, ai);
+ mrb_gc_arena_restore(s->mrb, ai);
push();
}
break;
@@ -1973,22 +2098,22 @@ codegen(codegen_scope *s, node *tree, int val)
while (n) {
codegen(s, n->car, VAL);
pop(); pop();
- genop(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1));
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
push();
n = n->cdr;
}
n = tree->cdr->cdr;
if (n->car) {
- p = (char*)n->car;
- off = new_lit(s, mrb_str_new(s->mrb, p, strlen(p)));
- codegen(s, tree->car, VAL);
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
- pop();
- genop(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1));
+ p = (char*)n->car;
+ off = new_lit(s, mrb_str_new(s->mrb, p, strlen(p)));
+ codegen(s, tree->car, VAL);
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ pop();
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
}
if (n->cdr) {
- char *p2 = (char*)n->cdr;
- int off;
+ char *p2 = (char*)n->cdr;
+ int off;
push();
off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2)));
@@ -1997,9 +2122,9 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
}
pop();
- sym = new_sym(s, mrb_intern(s->mrb, "compile"));
+ sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7));
genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
- mrb_gc_arena_restore(s->mrb, ai);
+ mrb_gc_arena_restore(s->mrb, ai);
push();
}
else {
@@ -2026,9 +2151,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_DSYM:
codegen(s, tree, val);
if (val) {
- pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "intern")), 0));
- push();
+ gen_send_intern(s);
}
break;
@@ -2064,7 +2187,7 @@ codegen(codegen_scope *s, node *tree, int val)
{
int a = new_msym(s, sym(tree->car));
int b = new_msym(s, sym(tree->cdr));
- int c = new_msym(s, mrb_intern(s->mrb, "alias_method"));
+ int c = new_msym(s, mrb_intern2(s->mrb, "alias_method", 12));
genop(s, MKOP_A(OP_TCLASS, cursp()));
push();
@@ -2083,7 +2206,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_UNDEF:
{
- int undef = new_msym(s, mrb_intern(s->mrb, "undef_method"));
+ int undef = new_msym(s, mrb_intern2(s->mrb, "undef_method", 12));
int num = 0;
node *t = tree;
@@ -2278,7 +2401,7 @@ scope_finish(codegen_scope *s)
irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
irep->ilen = s->pc;
if (s->lines) {
- irep->lines = (short *)codegen_realloc(s, s->lines, sizeof(short)*s->pc);
+ irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
}
else {
irep->lines = 0;
@@ -2370,13 +2493,14 @@ codedump(mrb_state *mrb, int n)
{
#ifdef ENABLE_STDIO
mrb_irep *irep = mrb->irep[n];
- int i;
+ int i, ai;
mrb_code c;
if (!irep) return;
printf("irep %d nregs=%d nlocals=%d pools=%d syms=%d\n", n,
- irep->nregs, irep->nlocals, irep->plen, irep->slen);
+ irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen);
for (i=0; i<irep->ilen; i++) {
+ ai = mrb_gc_arena_save(mrb);
printf("%03d ", i);
c = irep->iseq[i];
switch (GET_OPCODE(c)) {
@@ -2677,6 +2801,7 @@ codedump(mrb_state *mrb, int n)
GETARG_A(c), GETARG_B(c), GETARG_C(c));
break;
}
+ mrb_gc_arena_restore(mrb, ai);
}
printf("\n");
#endif
diff --git a/src/crc.c b/src/crc.c
index 0451c363c..463c7abe6 100644
--- a/src/crc.c
+++ b/src/crc.c
@@ -6,6 +6,8 @@
#include <limits.h>
#include <stdint.h>
+#include <sys/types.h>
+
// Calculate CRC (CRC-16-CCITT)
//
// 0000_0000_0000_0000_0000_0000_0000_0000
@@ -13,13 +15,14 @@
// carry
#define CRC_16_CCITT 0x11021ul //x^16+x^12+x^5+1
#define CRC_XOR_PATTERN (CRC_16_CCITT << 8)
-#define CRC_CARRY_BIT (1 << 24)
+#define CRC_CARRY_BIT (0x01000000)
uint16_t
-calc_crc_16_ccitt(unsigned char *src, int nbytes)
+calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc)
{
- uint32_t crcwk = 0ul;
- int ibyte, ibit;
+ size_t ibyte;
+ uint32_t ibit;
+ uint32_t crcwk = crc << 8;
for (ibyte = 0; ibyte < nbytes; ibyte++) {
crcwk |= *src++;
@@ -32,3 +35,4 @@ calc_crc_16_ccitt(unsigned char *src, int nbytes)
}
return (uint16_t)(crcwk >> 8);
}
+
diff --git a/src/dump.c b/src/dump.c
index ba5a69a56..4714278b0 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -1,5 +1,5 @@
/*
-** dump.c - mruby binary dumper (Rite binary format)
+** dump.c - mruby binary dumper (mrbc binary format)
**
** See Copyright Notice in mruby.h
*/
@@ -12,739 +12,516 @@
#include "mruby/irep.h"
#include "mruby/numeric.h"
-static const unsigned char def_rite_binary_header[] =
- RITE_FILE_IDENFIFIER
- RITE_FILE_FORMAT_VER
- RITE_VM_VER
- RITE_COMPILER_TYPE
- RITE_COMPILER_VER
- "0000" //Binary data size
- "00" //Number of ireps
- "00" //Start index
- RITE_RESERVED
-;
-
-static const unsigned char def_rite_file_header[] =
- RITE_FILE_IDENFIFIER
- RITE_FILE_FORMAT_VER
- RITE_VM_VER
- RITE_COMPILER_TYPE
- RITE_COMPILER_VER
- "00000000" //Binary data size
- "0000" //Number of ireps
- "0000" //Start index
- RITE_RESERVED
- "0000" //CRC
-;
-
-const char bin2hex[] = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-#define DUMP_SIZE(size, type) ((type == DUMP_TYPE_BIN) ? size : size * RITE_FILE_HEX_SIZE)
-
-enum {
- DUMP_IREP_HEADER = 0,
- DUMP_ISEQ_BLOCK,
- DUMP_POOL_BLOCK,
- DUMP_SYMS_BLOCK,
- DUMP_SECTION_NUM,
-};
+static size_t
+get_irep_record_size(mrb_state *mrb, mrb_irep *irep);
-#ifdef ENABLE_STDIO
-
-uint16_t calc_crc_16_ccitt(unsigned char*,int);
-static inline int uint8_dump(uint8_t,char*,int);
-static inline int uint16_dump(uint16_t,char*,int);
-static inline int uint32_dump(uint32_t,char*,int);
-static char* str_dump(char*,char*,uint16_t,int);
-static uint16_t str_dump_len(char*,uint16_t, int);
-static uint32_t get_irep_header_size(mrb_state*,int);
-static uint32_t get_iseq_block_size(mrb_state*,mrb_irep*,int);
-static uint32_t get_pool_block_size(mrb_state*,mrb_irep*,int);
-static uint32_t get_syms_block_size(mrb_state*,mrb_irep*,int);
-static uint32_t get_irep_record_size(mrb_state*,int,int);
-static int write_irep_header(mrb_state*,mrb_irep*,char*,int);
-static int write_iseq_block(mrb_state*,mrb_irep*,char*,int);
-static int write_pool_block(mrb_state*,mrb_irep*,char*,int);
-static int write_syms_block(mrb_state*,mrb_irep*,char*,int);
-static int calc_crc_section(mrb_state*,mrb_irep*,uint16_t*,int);
-static int write_rite_header(mrb_state*,int,char*,uint32_t);
-static int dump_rite_header(mrb_state*,int,FILE*,uint32_t);
-static int write_irep_record(mrb_state*,int,char*,uint32_t*,int);
-static int dump_irep_record(mrb_state*,int,FILE*,uint32_t*);
-static int mrb_write_irep(mrb_state*,int,char*);
-
-
-static inline int
-uint8_dump(uint8_t bin, char *hex, int type)
-{
- if (type == DUMP_TYPE_BIN) {
- *hex = bin;
- } else {
- *hex++ = bin2hex[(bin >> 4) & 0x0f];
- *hex = bin2hex[bin & 0x0f];
- }
- return DUMP_SIZE(MRB_DUMP_SIZE_OF_CHAR, type);
-}
-
-static inline int
-uint16_dump(uint16_t bin, char *hex, int type)
-{
- if (type == DUMP_TYPE_BIN) {
- return (uint16_to_bin(bin, hex));
- } else {
- *hex++ = bin2hex[(bin >> 12)& 0x0f];
- *hex++ = bin2hex[(bin >> 8) & 0x0f];
- *hex++ = bin2hex[(bin >> 4) & 0x0f];
- *hex = bin2hex[bin & 0x0f];
- return DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type);
- }
-}
-
-static inline int
-uint32_dump(uint32_t bin, char *hex, int type)
+static uint32_t
+get_irep_header_size(mrb_state *mrb)
{
- if (type == DUMP_TYPE_BIN) {
- return (uint32_to_bin(bin, hex));
- } else {
- *hex++ = bin2hex[(bin >> 28) & 0x0f];
- *hex++ = bin2hex[(bin >> 24) & 0x0f];
- *hex++ = bin2hex[(bin >> 20) & 0x0f];
- *hex++ = bin2hex[(bin >> 16) & 0x0f];
- *hex++ = bin2hex[(bin >> 12) & 0x0f];
- *hex++ = bin2hex[(bin >> 8) & 0x0f];
- *hex++ = bin2hex[(bin >> 4) & 0x0f];
- *hex = bin2hex[bin & 0x0f];
- return DUMP_SIZE(MRB_DUMP_SIZE_OF_LONG, type);
- }
-}
-
-#define CHAR_ESC_LEN 13 /* sizeof(\x{ hex of 32bit unsigned int } \0) */
+ uint32_t size = 0;
-static char*
-str_dump(char *str, char *hex, uint16_t len, int type)
-{
- if (type == DUMP_TYPE_BIN)
- memcpy(hex, str, len);
- else {
- char *src, *dst, buf[CHAR_ESC_LEN + 1];
- int n;
-
- for (src = str, dst = hex; len > 0; src++, dst++, len--) {
- switch (*src) {
- case 0x07:/* BEL */ *dst++ = '\\'; *dst = 'a'; break;
- case 0x08:/* BS */ *dst++ = '\\'; *dst = 'b'; break;
- case 0x09:/* HT */ *dst++ = '\\'; *dst = 't'; break;
- case 0x0A:/* LF */ *dst++ = '\\'; *dst = 'n'; break;
- case 0x0B:/* VT */ *dst++ = '\\'; *dst = 'v'; break;
- case 0x0C:/* FF */ *dst++ = '\\'; *dst = 'f'; break;
- case 0x0D:/* CR */ *dst++ = '\\'; *dst = 'r'; break;
- case 0x5C:/* \ */ *dst++ = '\\'; *dst = '\\'; break;
- case 0x22:/* " */ /* fall through */
- case 0x27:/* ' */ /* fall through */
- // case 0x3F:/* ? */ /* fall through */
- default:
- if (*src >= ' ' && *src <= '~') {
- *dst = *src;
- } else {
- n = sprintf(buf, "\\%03o", *src & 0377);
- memcpy(dst, buf, n);
- dst += (n-1);
- }
- break;
- }
- }
- }
+ size += sizeof(uint32_t) * 1;
+ size += sizeof(uint16_t) * 2;
- return hex;
+ return size;
}
-static uint16_t
-str_dump_len(char *str, uint16_t len, int type)
+static size_t
+write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
{
- uint16_t dump_len = 0;
+ uint8_t *cur = buf;
- if (type == DUMP_TYPE_BIN)
- dump_len = len;
- else {
- char *src;
-
- for (src = str; len > 0; src++, len--) {
- switch (*src) {
- case 0x07:/* BEL */ /* fall through */
- case 0x08:/* BS */ /* fall through */
- case 0x09:/* HT */ /* fall through */
- case 0x0A:/* LF */ /* fall through */
- case 0x0B:/* VT */ /* fall through */
- case 0x0C:/* FF */ /* fall through */
- case 0x0D:/* CR */ /* fall through */
- case 0x5C:/* \ */ /* fall through */
- dump_len += 2;
- break;
-
- case 0x22:/* " */ /* fall through */
- case 0x27:/* ' */ /* fall through */
- // case 0x3F:/* ? */ /* fall through */
- default:
- if (*src >= ' ' && *src <= '~') {
- dump_len++;
- } else {
- dump_len += 4; /* octet "\\nnn" */
- }
- break;
- }
- }
- }
+ cur += uint32_to_bin(get_irep_record_size(mrb, irep), cur); /* record size */
+ cur += uint16_to_bin((uint16_t)irep->nlocals, cur); /* number of local variable */
+ cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */
- return dump_len;
+ return (cur - buf);
}
+
static uint32_t
-get_irep_header_size(mrb_state *mrb, int type)
+get_iseq_block_size(mrb_state *mrb, mrb_irep *irep)
{
uint32_t size = 0;
-
- size += 2;
- size += DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type) * 4;
-
+ size += sizeof(uint32_t); /* ilen */
+ size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */
return size;
}
-static uint32_t
-get_iseq_block_size(mrb_state *mrb, mrb_irep *irep, int type)
+static int
+write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
{
- uint32_t size = 0;
+ uint8_t *cur = buf;
+ size_t iseq_no;
- size += MRB_DUMP_SIZE_OF_LONG; /* ilen */
- size += irep->ilen * MRB_DUMP_SIZE_OF_LONG; /* iseq(n) */
- size += MRB_DUMP_SIZE_OF_SHORT; /* crc */
+ cur += uint32_to_bin(irep->ilen, cur); /* number of opcode */
+ for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
+ cur += uint32_to_bin(irep->iseq[iseq_no], cur); /* opcode */
+ }
- return DUMP_SIZE(size, type);
+ return (cur - buf);
}
-static uint32_t
-get_pool_block_size(mrb_state *mrb, mrb_irep *irep, int type)
+
+static size_t
+get_pool_block_size(mrb_state *mrb, mrb_irep *irep)
{
- uint32_t size = 0;
- int pool_no;
+ size_t size = 0;
+ size_t pool_no;
+ int len;
mrb_value str;
char buf[32];
- size += MRB_DUMP_SIZE_OF_LONG; /* plen */
- size += irep->plen; /* tt(n) */
- size += irep->plen * MRB_DUMP_SIZE_OF_SHORT; /* len(n) */
- size += MRB_DUMP_SIZE_OF_SHORT; /* crc */
- size = DUMP_SIZE(size, type);
+ size += sizeof(uint32_t); /* plen */
+ size += irep->plen * (sizeof(uint8_t) + sizeof(uint16_t)); /* len(n) */
for (pool_no = 0; pool_no < irep->plen; pool_no++) {
- uint16_t nlen =0;
- int len;
+ int ai = mrb_gc_arena_save(mrb);
switch (mrb_type(irep->pool[pool_no])) {
case MRB_TT_FIXNUM:
- str = mrb_fix2str(mrb, irep->pool[pool_no], 10);
- size += (uint32_t)RSTRING_LEN(str);
+ str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10);
+ size += RSTRING_LEN(str);
break;
+
case MRB_TT_FLOAT:
- len = mrb_float_to_str( buf, mrb_float(irep->pool[pool_no]));
- size += (uint32_t)len;
+ len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no]));
+ size += len;
break;
+
case MRB_TT_STRING:
- str = mrb_string_value( mrb, &irep->pool[pool_no]);
- nlen = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type);
- size += nlen;
+ str = mrb_str_to_str(mrb, irep->pool[pool_no]);
+ size += RSTRING_LEN(str);
break;
+
default:
break;
}
- }
-
- return size;
-}
-
-static uint32_t
-get_syms_block_size(mrb_state *mrb, mrb_irep *irep, int type)
-{
- uint32_t size = 0;
- int sym_no;
-
- size += MRB_DUMP_SIZE_OF_LONG; /* slen */
- size += MRB_DUMP_SIZE_OF_SHORT; /* crc */
- size = DUMP_SIZE(size, type);
-
- for (sym_no = 0; sym_no < irep->slen; sym_no++) {
- const char * name;
- uint16_t nlen =0;
- size += DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type); /* snl(n) */
- if (irep->syms[sym_no] != 0) {
- int len;
-
- name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
- nlen = str_dump_len((char*)name, len, type);
- size += nlen; /* sn(n) */
- }
+ mrb_gc_arena_restore(mrb, ai);
}
return size;
}
-static uint32_t
-get_irep_record_size(mrb_state *mrb, int irep_no, int type)
-{
- uint32_t size = 0;
- mrb_irep *irep = mrb->irep[irep_no];
-
- size += DUMP_SIZE(MRB_DUMP_SIZE_OF_LONG, type); /* rlen */
- size += get_irep_header_size(mrb, type);
- size += get_iseq_block_size(mrb, irep, type);
- size += get_pool_block_size(mrb, irep, type);
- size += get_syms_block_size(mrb, irep, type);
-
- return size;
-}
-
-static int
-write_irep_header(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
-{
- char *buf_top = buf;
-
- *buf++ = RITE_IREP_IDENFIFIER; /* record identifier */
- *buf++ = RITE_IREP_TYPE_CLASS; /* class or module */
- buf += uint16_dump((uint16_t)irep->nlocals, buf, type); /* number of local variable */
- buf += uint16_dump((uint16_t)irep->nregs, buf, type); /* number of register variable */
- buf += uint16_dump(DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type)/* crc */, buf, type); /* offset of isec block */
-
- return (int)(buf - buf_top);
-}
-
-static int
-write_iseq_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
-{
- char *buf_top = buf;
- int iseq_no;
-
- buf += uint32_dump((uint32_t)irep->ilen, buf, type); /* number of opcode */
-
- for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
- buf += uint32_dump((uint32_t)irep->iseq[iseq_no], buf, type); /* opcode */
- }
-
- return (int)(buf - buf_top);
-}
-
static int
-write_pool_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
+write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
{
- int pool_no;
+ size_t pool_no;
+ uint8_t *cur = buf;
+ size_t len;
mrb_value str;
- char *buf_top = buf;
- char *char_buf;
- uint16_t buf_size =0;
- uint16_t len =0;
- int result;
-
- buf_size = MRB_DUMP_DEFAULT_STR_LEN;
- char_buf = (char *)mrb_malloc(mrb, buf_size);
- if (char_buf == NULL) {
- result = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
+ const char *char_ptr;
+ char char_buf[30];
- buf += uint32_dump((uint32_t)irep->plen, buf, type); /* number of pool */
+ cur += uint32_to_bin(irep->plen, cur); /* number of pool */
for (pool_no = 0; pool_no < irep->plen; pool_no++) {
- buf += uint8_dump(mrb_type(irep->pool[pool_no]), buf, type); /* data type */
- memset(char_buf, 0, buf_size);
+ int ai = mrb_gc_arena_save(mrb);
+
+ cur += uint8_to_bin(mrb_type(irep->pool[pool_no]), cur); /* data type */
switch (mrb_type(irep->pool[pool_no])) {
case MRB_TT_FIXNUM:
- str = mrb_fix2str(mrb, irep->pool[pool_no], 10);
- memcpy(char_buf, RSTRING_PTR(str), RSTRING_LEN(str));
+ str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10);
+ char_ptr = RSTRING_PTR(str);
len = RSTRING_LEN(str);
break;
case MRB_TT_FLOAT:
len = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no]));
+ char_ptr = &char_buf[0];
break;
case MRB_TT_STRING:
str = irep->pool[pool_no];
- len = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type);
- if (len > buf_size - 1) {
- buf_size = len + 1;
- char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size);
- if (char_buf == NULL) {
- result = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
- memset(char_buf, 0, buf_size);
- }
- str_dump(RSTRING_PTR(str), char_buf, RSTRING_LEN(str), type);
+ char_ptr = RSTRING_PTR(str);
+ len = RSTRING_LEN(str);
break;
default:
- buf += uint16_dump(0, buf, type); /* data length = 0 */
continue;
}
- buf += uint16_dump(len, buf, type); /* data length */
+ cur += uint16_to_bin(len, cur); /* data length */
+ memcpy(cur, char_ptr, len);
+ cur += len;
- memcpy(buf, char_buf, len);
- buf += len;
+ mrb_gc_arena_restore(mrb, ai);
}
- result = (int)(buf - buf_top);
-error_exit:
- mrb_free(mrb, char_buf);
- return result;
+ return (int)(cur - buf);
+}
+
+
+static size_t
+get_syms_block_size(mrb_state *mrb, mrb_irep *irep)
+{
+ size_t size = 0;
+ size_t sym_no;
+ size_t len;
+
+ size += sizeof(uint32_t); /* slen */
+ for (sym_no = 0; sym_no < irep->slen; sym_no++) {
+ size += sizeof(uint16_t); /* snl(n) */
+ if (irep->syms[sym_no] != 0) {
+ mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
+ size += len + 1; /* sn(n) + null char */
+ }
+ }
+
+ return size;
}
static int
-write_syms_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
+write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
{
- int sym_no;
- char *buf_top = buf;
- char *char_buf;
- uint16_t buf_size =0;
-
- buf_size = MRB_DUMP_DEFAULT_STR_LEN;
- char_buf = (char *)mrb_malloc(mrb, buf_size);
- if (char_buf == NULL)
- goto error_exit;
+ size_t sym_no;
+ uint8_t *cur = buf;
+ const char *name;
- buf += uint32_dump((uint32_t)irep->slen, buf, type); /* number of symbol */
+ cur += uint32_to_bin(irep->slen, cur); /* number of symbol */
for (sym_no = 0; sym_no < irep->slen; sym_no++) {
- const char * name;
- uint16_t nlen =0;
-
if (irep->syms[sym_no] != 0) {
- int len;
+ size_t len;
name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
- nlen = str_dump_len((char*)name, len, type);
- if ( nlen > buf_size - 1) {
- buf_size = nlen + 1;
- char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size);
- if (char_buf == NULL)
- goto error_exit;
+ if (len > UINT16_MAX) {
+ return MRB_DUMP_GENERAL_FAILURE;
}
- memset(char_buf, 0, buf_size);
- str_dump((char*)name, char_buf, len, type);
- buf += uint16_dump(nlen, buf, type); /* length of symbol name */
- memcpy(buf, char_buf, nlen); /* symbol name */
- buf += nlen;
+ cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */
+ memcpy(cur, name, len); /* symbol name */
+ cur += (uint16_t)len;
+ *cur++ = '\0';
}
else {
- buf += uint16_dump(MRB_DUMP_NULL_SYM_LEN, buf, type); /* length of symbol name */
+ cur += uint16_to_bin(MRB_DUMP_NULL_SYM_LEN, cur); /* length of symbol name */
}
}
-error_exit:
- mrb_free(mrb, char_buf);
- return (int)(buf - buf_top);
+ return (int)(cur - buf);
}
-static int
-calc_crc_section(mrb_state *mrb, mrb_irep *irep, uint16_t *crc, int section)
+
+
+static size_t
+get_irep_record_size(mrb_state *mrb, mrb_irep *irep)
{
- char *buf, *buf_top;
- uint32_t buf_size;
- int type = DUMP_TYPE_BIN;
- int result;
+ uint32_t size = 0;
- switch (section) {
- case DUMP_IREP_HEADER: buf_size = get_irep_header_size(mrb, type); break;
- case DUMP_ISEQ_BLOCK: buf_size = get_iseq_block_size(mrb, irep, type); break;
- case DUMP_POOL_BLOCK: buf_size = get_pool_block_size(mrb, irep, type); break;
- case DUMP_SYMS_BLOCK: buf_size = get_syms_block_size(mrb, irep, type); break;
- default: return MRB_DUMP_GENERAL_FAILURE;
- }
+ //size += sizeof(uint16_t); /* rlen */
+ size += get_irep_header_size(mrb);
+ size += get_iseq_block_size(mrb, irep);
+ size += get_pool_block_size(mrb, irep);
+ size += get_syms_block_size(mrb, irep);
- buf = (char *)mrb_calloc(mrb, 1, buf_size);
- if (buf == NULL)
- return MRB_DUMP_GENERAL_FAILURE;
+ return size;
+}
- buf_top = buf;
-
- switch (section) {
- case DUMP_IREP_HEADER:
- result = write_irep_header(mrb, irep, buf, type);
- break;
- case DUMP_ISEQ_BLOCK:
- result = write_iseq_block(mrb, irep, buf, type);
- break;
- case DUMP_POOL_BLOCK:
- result = write_pool_block(mrb, irep, buf, type);
- break;
- case DUMP_SYMS_BLOCK:
- result = write_syms_block(mrb, irep, buf, type);
- break;
- default:
- result = MRB_DUMP_GENERAL_FAILURE;
- break; /* Already checked above. */
+static int
+write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, uint32_t *irep_record_size)
+{
+ if (irep == NULL) {
+ return MRB_DUMP_INVALID_IREP;
}
- if (result < 0) {
- goto error_exit;
+
+ *irep_record_size = get_irep_record_size(mrb, irep);
+ if (*irep_record_size == 0) {
+ return MRB_DUMP_GENERAL_FAILURE;
}
- buf += result;
- *crc = calc_crc_16_ccitt((unsigned char*)buf_top, (int)(buf - buf_top));
+ memset(bin, 0, *irep_record_size);
- mrb_free(mrb, buf_top);
+ //bin += uint16_to_bin(*irep_record_size, bin);
+ bin += write_irep_header(mrb, irep, bin);
+ bin += write_iseq_block(mrb, irep, bin);
+ bin += write_pool_block(mrb, irep, bin);
+ bin += write_syms_block(mrb, irep, bin);
- result = MRB_DUMP_OK;
- error_exit:
- return result;
+ return MRB_DUMP_OK;
}
-static uint16_t
-calc_rite_header_crc(mrb_state *mrb, int top, rite_binary_header *binary_header, uint32_t rbds, int type)
+static size_t
+mrb_write_eof(mrb_state *mrb, uint8_t *bin)
{
- memcpy( binary_header, def_rite_binary_header, sizeof(*binary_header));
+ struct rite_binary_footer footer;
- uint32_dump(rbds, (char*)binary_header->rbds, type);
- uint16_dump((uint16_t)mrb->irep_len, (char*)binary_header->nirep, type);
- uint16_dump((uint16_t)top, (char*)binary_header->sirep, type);
+ memcpy(footer.section_identify, RITE_BINARY_EOF, sizeof(footer.section_identify));
+ uint32_to_bin(sizeof(struct rite_binary_footer), footer.section_size);
+ memcpy(bin, &footer, sizeof(struct rite_binary_footer));
- return calc_crc_16_ccitt((unsigned char*)binary_header, sizeof(*binary_header));
+ return sizeof(struct rite_binary_footer);
}
+
static int
-write_rite_header(mrb_state *mrb, int top, char* bin, uint32_t rbds)
-{
- rite_binary_header *binary_header;
- uint16_t crc;
- int type = DUMP_TYPE_BIN;
+mrb_write_section_irep_header(mrb_state *mrb, uint32_t section_size, uint16_t nirep, uint16_t sirep, uint8_t *bin)
+{
+ struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin;
- binary_header = (rite_binary_header*)bin;
- crc = calc_rite_header_crc(mrb, top, binary_header, rbds, type);
- bin += sizeof(*binary_header);
- uint16_dump(crc, bin, type);
+ memcpy(header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(header->section_identify));
+ uint32_to_bin(section_size, header->section_size);
+ memcpy(header->rite_version, RITE_VM_VER, sizeof(header->rite_version));
+ uint16_to_bin(nirep, header->nirep);
+ uint16_to_bin(sirep, header->sirep);
return MRB_DUMP_OK;
}
static int
-calc_rite_file_header(mrb_state *mrb, int top, uint32_t rbds, rite_file_header *file_header)
+mrb_write_section_irep(mrb_state *mrb, size_t start_index, uint8_t *bin)
{
- rite_binary_header *binary_header, b_header;
- uint16_t crc;
- int type;
+ int result;
+ size_t irep_no;
+ uint32_t section_size = 0, rlen = 0; /* size of irep record */
+ uint8_t *cur = bin;
+
+ if (mrb == NULL || start_index >= mrb->irep_len || bin == NULL) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
- /* calc crc */
- type = DUMP_TYPE_BIN;
- binary_header = &b_header;
- crc = calc_rite_header_crc(mrb, top, binary_header, rbds, type);
+ cur += sizeof(struct rite_section_irep_header);
+ section_size += sizeof(struct rite_section_irep_header);
- /* dump rbc header */
- memcpy( file_header, def_rite_file_header, sizeof(*file_header));
+ for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) {
+ result = write_irep_record(mrb, mrb->irep[irep_no], cur, &rlen);
+ if (result != MRB_DUMP_OK) {
+ return result;
+ }
+ cur += rlen;
+ section_size += rlen;
+ }
- type = DUMP_TYPE_HEX;
- uint32_dump(rbds, (char*)file_header->rbds, type);
- uint16_dump((uint16_t)mrb->irep_len, (char*)file_header->nirep, type);
- uint16_dump((uint16_t)top, (char*)file_header->sirep, type);
- uint16_dump(crc, (char*)file_header->hcrc, type);
+ mrb_write_section_irep_header(mrb, section_size, mrb->irep_len - start_index, start_index, bin);
return MRB_DUMP_OK;
}
static int
-dump_rite_header(mrb_state *mrb, int top, FILE* fp, uint32_t rbds)
-{
- int rc = MRB_DUMP_OK;
- rite_file_header file_header;
-
- if (fseek(fp, 0, SEEK_SET) != 0)
- return MRB_DUMP_GENERAL_FAILURE;
-
- rc = calc_rite_file_header(mrb, top, rbds, &file_header);
- if (rc != MRB_DUMP_OK)
- return rc;
+mrb_write_section_lineno_header(mrb_state *mrb, uint32_t section_size, uint16_t nirep, uint16_t sirep, uint8_t *bin)
+{
+ struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin;
- if (fwrite(&file_header, sizeof(file_header), 1, fp) != 1)
- return MRB_DUMP_WRITE_FAULT;
+ // TODO
+ memcpy(header->section_identify, RITE_SECTION_LIENO_IDENTIFIER, sizeof(header->section_identify));
+ uint32_to_bin(section_size, header->section_size);
+ uint16_to_bin(nirep, header->nirep);
+ uint16_to_bin(sirep, header->sirep);
return MRB_DUMP_OK;
}
-static int
-write_irep_record(mrb_state *mrb, int irep_no, char* bin, uint32_t *rlen, int type)
+static size_t
+get_debug_record_size(mrb_state *mrb, mrb_irep *irep)
{
- uint32_t irep_record_size;
- mrb_irep *irep = mrb->irep[irep_no];
- int section;
+ size_t size = 0;
- if (irep == NULL)
- return MRB_DUMP_INVALID_IREP;
+ size += sizeof(uint32_t); // record size
+ size += sizeof(uint16_t); // filename size
+ if(irep->filename) {
+ size += strlen(irep->filename); // filename
+ }
+ size += sizeof(uint32_t); // niseq
+ if(irep->lines) {
+ size += sizeof(uint16_t) * irep->ilen; // lineno
+ }
- /* buf alloc */
- irep_record_size = get_irep_record_size(mrb, irep_no, type);
- if (irep_record_size == 0)
- return MRB_DUMP_GENERAL_FAILURE;
+ return size;
+}
- memset( bin, 0, irep_record_size);
+static int
+write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin)
+{
+ uint8_t *cur = bin;
+ size_t filename_len = 0;
+ int iseq_no;
- /* rlen */
- *rlen = irep_record_size - DUMP_SIZE(MRB_DUMP_SIZE_OF_LONG, type);
+ cur += sizeof(uint32_t); /* record size */
- bin += uint32_dump(*rlen, bin, type);
+ if(irep->filename) {
+ filename_len = strlen(irep->filename);
+ }
+ cur += uint16_to_bin(filename_len, cur); /* filename size */
- for (section = 0; section < DUMP_SECTION_NUM; section++) {
- int rc;
- uint16_t crc;
+ if(filename_len) {
+ memcpy(cur, irep->filename, filename_len);
+ cur += filename_len; /* filename */
+ }
- switch (section) {
- case DUMP_IREP_HEADER: bin += write_irep_header(mrb, irep, bin, type); break;
- case DUMP_ISEQ_BLOCK: bin += write_iseq_block(mrb, irep, bin, type); break;
- case DUMP_POOL_BLOCK: bin += write_pool_block(mrb, irep, bin, type); break;
- case DUMP_SYMS_BLOCK: bin += write_syms_block(mrb, irep, bin, type); break;
- default: break;
+ if(irep->lines) {
+ cur += uint32_to_bin(irep->ilen, cur); /* niseq */
+ for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
+ cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */
}
-
- rc = calc_crc_section(mrb, irep, &crc, section);
- if (rc != MRB_DUMP_OK)
- return rc;
-
- bin += uint16_dump(crc, bin, type); /* crc */
+ }
+ else {
+ cur += uint32_to_bin(0, cur); /* niseq */
}
- return MRB_DUMP_OK;
+ uint32_to_bin(cur - bin, bin); /* record size */
+
+ return (cur - bin);
}
static int
-dump_irep_record(mrb_state *mrb, int irep_no, FILE* fp, uint32_t *rlen)
+mrb_write_section_lineno(mrb_state *mrb, int start_index, uint8_t *bin)
{
- int rc = MRB_DUMP_OK;
- uint32_t irep_record_size;
- char *buf;
- mrb_irep *irep = mrb->irep[irep_no];
-
- if (irep == NULL)
- return MRB_DUMP_INVALID_IREP;
+ int irep_no;
+ uint32_t section_size = 0, rlen = 0; /* size of irep record */
+ uint8_t *cur = bin;
- /* buf alloc */
- irep_record_size = get_irep_record_size(mrb, irep_no, DUMP_TYPE_HEX);
- if (irep_record_size == 0)
- return MRB_DUMP_GENERAL_FAILURE;
+ if (mrb == NULL || start_index < 0 || start_index >= mrb->irep_len || bin == NULL) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
- buf = (char *)mrb_calloc(mrb, 1, irep_record_size);
- if (buf == NULL)
- return MRB_DUMP_GENERAL_FAILURE;
+ cur += sizeof(struct rite_section_lineno_header);
+ section_size += sizeof(struct rite_section_lineno_header);
- rc = write_irep_record(mrb, irep_no, buf, rlen, DUMP_TYPE_HEX);
- if (rc != MRB_DUMP_OK) {
- rc = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
+ for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) {
+ rlen = write_lineno_record(mrb, mrb->irep[irep_no], cur);
+ cur += rlen;
+ section_size += rlen;
}
+ mrb_write_section_lineno_header(mrb, section_size, mrb->irep_len - start_index, start_index, bin);
- if (fwrite(buf, irep_record_size, 1, fp) != 1)
- rc = MRB_DUMP_WRITE_FAULT;
+ return MRB_DUMP_OK;
+}
-error_exit:
- mrb_free(mrb, buf);
+static int
+write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t* bin)
+{
+ struct rite_binary_header *header = (struct rite_binary_header*)bin;
+ uint16_t crc;
+ size_t offset;
+
+ memcpy(header->binary_identify, RITE_BINARY_IDENFIFIER, sizeof(header->binary_identify));
+ memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version));
+ memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name));
+ memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version));
+ uint32_to_bin(binary_size, header->binary_size);
+
+ offset = (&(header->binary_crc[0]) - bin) + sizeof(uint16_t);
+ crc = calc_crc_16_ccitt(bin + offset, binary_size - offset, 0);
+ uint16_to_bin(crc, header->binary_crc);
- return rc;
+ return MRB_DUMP_OK;
}
static int
-mrb_write_irep(mrb_state *mrb, int top, char *bin)
+mrb_dump_irep(mrb_state *mrb, size_t start_index, int debug_info, uint8_t **bin, size_t *bin_size)
{
- int rc;
- uint32_t rlen=0; /* size of irep record */
- int irep_no;
- char *bin_top;
+ int result = MRB_DUMP_GENERAL_FAILURE;
+ size_t section_size = 0;
+ size_t section_irep_size;
+ size_t section_lineno_size = 0;
+ size_t irep_no;
+ uint8_t *cur = NULL;
+
+ if (mrb == NULL || start_index >= mrb->irep_len) {
+ *bin = NULL;
+ return MRB_DUMP_GENERAL_FAILURE;
+ }
- if (mrb == NULL || top < 0 || top >= mrb->irep_len || bin == NULL)
- return MRB_DUMP_INVALID_ARGUMENT;
+ section_irep_size = sizeof(struct rite_section_irep_header);
+ for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) {
+ section_irep_size += get_irep_record_size(mrb, mrb->irep[irep_no]);
+ }
+ section_size += section_irep_size;
- bin_top = bin;
- bin += sizeof(rite_binary_header) + MRB_DUMP_SIZE_OF_SHORT/* crc */;
+ /* DEBUG section size */
+ if(debug_info) {
+ section_lineno_size += sizeof(struct rite_section_lineno_header);
+ for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) {
+ section_lineno_size += get_debug_record_size(mrb, mrb->irep[irep_no]);
+ }
+ section_size += section_lineno_size;
+ }
+
+ *bin_size += sizeof(struct rite_binary_header) + section_size + sizeof(struct rite_binary_footer);
+ cur = *bin = (uint8_t *)mrb_malloc(mrb, *bin_size);
+ if(cur == NULL) {
+ goto error_exit;
+ }
- for (irep_no=top; irep_no<mrb->irep_len; irep_no++) {
- rc = write_irep_record(mrb, irep_no, bin, &rlen, DUMP_TYPE_BIN);
- if (rc != MRB_DUMP_OK)
- return rc;
+ cur += sizeof(struct rite_binary_header);
- bin += (rlen + DUMP_SIZE(MRB_DUMP_SIZE_OF_LONG, DUMP_TYPE_BIN));
+ result = mrb_write_section_irep(mrb, start_index, cur);
+ if (result != MRB_DUMP_OK) {
+ goto error_exit;
+ }
+
+ cur += section_irep_size;
+
+ /* write DEBUG section */
+ if(debug_info) {
+ result = mrb_write_section_lineno(mrb, start_index, cur);
+ if (result != MRB_DUMP_OK) {
+ goto error_exit;
+ }
+ cur += section_lineno_size;
}
- bin += uint32_dump(0, bin, DUMP_TYPE_BIN); /* end of file */
+ mrb_write_eof(mrb, cur);
- rc = write_rite_header(mrb, top, bin_top, (bin - bin_top)); //TODO: Remove top(SIREP)
+ result = write_rite_binary_header(mrb, *bin_size, *bin);
- return rc;
+error_exit:
+ if (result != MRB_DUMP_OK) {
+ mrb_free(mrb, *bin);
+ *bin = NULL;
+ }
+ return result;
}
+
+#ifdef ENABLE_STDIO
+
int
-mrb_dump_irep(mrb_state *mrb, int top, FILE* fp)
+mrb_dump_irep_binary(mrb_state *mrb, size_t start_index, int debug_info, FILE* fp)
{
- int rc;
- uint32_t rbds=0; /* size of Rite Binary Data */
- uint32_t rlen=0; /* size of irep record */
- int irep_no;
+ uint8_t *bin = NULL;
+ size_t bin_size = 0;
+ int result;
- if (mrb == NULL || top < 0 || top >= mrb->irep_len || fp == NULL)
+ if (fp == NULL) {
return MRB_DUMP_INVALID_ARGUMENT;
-
- if (fwrite(&def_rite_file_header, sizeof(rite_file_header), 1, fp) != 1) /* dummy write */
- return MRB_DUMP_WRITE_FAULT;
-
- for (irep_no=top; irep_no<mrb->irep_len; irep_no++) {
- rc = dump_irep_record(mrb, irep_no, fp, &rlen);
- if (rc != MRB_DUMP_OK)
- return rc;
-
- rbds += rlen;
}
- if (fwrite("00000000"/* end of file */, 8, 1, fp) != 1)
- return MRB_DUMP_WRITE_FAULT;
-
- rc = dump_rite_header(mrb, top, fp, rbds); //TODO: Remove top(SIREP)
+ result = mrb_dump_irep(mrb, start_index, debug_info, &bin, &bin_size);
+ if (result == MRB_DUMP_OK) {
+ fwrite(bin, bin_size, 1, fp);
+ }
- return rc;
+ mrb_free(mrb, bin);
+ return result;
}
int
-mrb_bdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname)
+mrb_dump_irep_cfunc(mrb_state *mrb, size_t start_index, int debug_info, FILE *fp, const char *initname)
{
- int rc;
- int irep_no;
- char *buf;
- int buf_size = 0;
- int buf_idx = 0;
+ uint8_t *bin = NULL;
+ size_t bin_size = 0, bin_idx = 0;
+ int result;
- if (mrb == NULL || n < 0 || n >= mrb->irep_len || f == NULL || initname == NULL)
+ if (fp == NULL || initname == NULL) {
return MRB_DUMP_INVALID_ARGUMENT;
+ }
- buf_size = sizeof(rite_binary_header) + MRB_DUMP_SIZE_OF_SHORT/* crc */;
- for (irep_no=n; irep_no<mrb->irep_len; irep_no++)
- buf_size += get_irep_record_size(mrb, irep_no, DUMP_TYPE_BIN);
- buf_size += MRB_DUMP_SIZE_OF_LONG; /* end of file */
-
- buf = (char *)mrb_malloc(mrb, buf_size);
- if (buf == NULL)
- return MRB_DUMP_GENERAL_FAILURE;
-
- rc = mrb_write_irep(mrb, n, buf);
-
- if (rc == MRB_DUMP_OK) {
- fprintf(f, "const char %s[] = {", initname);
- while (buf_idx < buf_size ) {
- if (buf_idx % 16 == 0 ) fputs("\n", f);
- fprintf(f, "0x%02x,", (unsigned char)buf[buf_idx++]);
+ result = mrb_dump_irep(mrb, start_index, debug_info, &bin, &bin_size);
+ if (result == MRB_DUMP_OK) {
+ fprintf(fp, "const uint8_t %s[] = {", initname);
+ while (bin_idx < bin_size) {
+ if (bin_idx % 16 == 0 ) fputs("\n", fp);
+ fprintf(fp, "0x%02x,", bin[bin_idx++]);
}
- fputs("\n};\n", f);
+ fputs("\n};\n", fp);
}
- mrb_free(mrb, buf);
-
- return rc;
+ mrb_free(mrb, bin);
+ return result;
}
#endif /* ENABLE_STDIO */
diff --git a/src/error.c b/src/error.c
index 70a84455f..5f1476115 100644
--- a/src/error.c
+++ b/src/error.c
@@ -4,17 +4,19 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include <stdarg.h>
-#include <stdio.h>
+#include <errno.h>
#include <setjmp.h>
+#include <stdarg.h>
+#include <stdlib.h>
#include <string.h>
-#include "error.h"
-#include "mruby/variable.h"
-#include "mruby/string.h"
+#include "mruby.h"
+#include "mruby/array.h"
#include "mruby/class.h"
-#include "mruby/proc.h"
#include "mruby/irep.h"
+#include "mruby/proc.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
+#include "error.h"
mrb_value
mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len)
@@ -25,7 +27,7 @@ mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len)
mrb_value
mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str)
{
- mrb_string_value(mrb, &str);
+ str = mrb_str_to_str(mrb, str);
return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, str);
}
@@ -43,7 +45,7 @@ exc_initialize(mrb_state *mrb, mrb_value exc)
mrb_value mesg;
if (mrb_get_args(mrb, "|o", &mesg) == 1) {
- mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), mesg);
+ mrb_iv_set(mrb, exc, mrb_intern2(mrb, "mesg", 4), mesg);
}
return exc;
}
@@ -72,7 +74,7 @@ exc_exception(mrb_state *mrb, mrb_value self)
if (argc == 0) return self;
if (mrb_obj_equal(mrb, self, a)) return self;
exc = mrb_obj_clone(mrb, self);
- mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), a);
+ mrb_iv_set(mrb, exc, mrb_intern2(mrb, "mesg", 4), a);
return exc;
}
@@ -88,9 +90,9 @@ exc_exception(mrb_state *mrb, mrb_value self)
static mrb_value
exc_to_s(mrb_state *mrb, mrb_value exc)
{
- mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg"));
+ mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4));
- if (mrb_nil_p(mesg)) return mrb_str_new2(mrb, mrb_obj_classname(mrb, exc));
+ if (mrb_nil_p(mesg)) return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc));
return mesg;
}
@@ -122,32 +124,32 @@ exc_inspect(mrb_state *mrb, mrb_value exc)
{
mrb_value str, mesg, file, line;
- mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg"));
- file = mrb_attr_get(mrb, exc, mrb_intern(mrb, "file"));
- line = mrb_attr_get(mrb, exc, mrb_intern(mrb, "line"));
-
+ mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4));
+ file = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "file", 4));
+ line = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "line", 4));
+
if (!mrb_nil_p(file) && !mrb_nil_p(line)) {
str = file;
- mrb_str_cat2(mrb, str, ":");
+ mrb_str_cat(mrb, str, ":", 1);
mrb_str_append(mrb, str, line);
- mrb_str_cat2(mrb, str, ": ");
+ mrb_str_cat(mrb, str, ": ", 2);
if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
mrb_str_append(mrb, str, mesg);
- mrb_str_cat2(mrb, str, " (");
+ mrb_str_cat(mrb, str, " (", 2);
}
- mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc));
+ mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc));
if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
- mrb_str_cat2(mrb, str, ")");
+ mrb_str_cat(mrb, str, ")", 1);
}
}
else {
- str = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc));
+ str = mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc));
if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
- mrb_str_cat2(mrb, str, ": ");
+ mrb_str_cat(mrb, str, ": ", 2);
mrb_str_append(mrb, str, mesg);
} else {
- mrb_str_cat2(mrb, str, ": ");
- mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc));
+ mrb_str_cat(mrb, str, ": ", 2);
+ mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc));
}
}
return str;
@@ -159,25 +161,29 @@ exc_equal(mrb_state *mrb, mrb_value exc)
{
mrb_value obj;
mrb_value mesg;
- mrb_sym id_mesg = mrb_intern(mrb, "mesg");
+ mrb_bool equal_p;
+ mrb_sym id_mesg = mrb_intern2(mrb, "mesg", 4);
mrb_get_args(mrb, "o", &obj);
- if (mrb_obj_equal(mrb, exc, obj)) return mrb_true_value();
-
- if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) {
- if (mrb_respond_to(mrb, obj, mrb_intern(mrb, "message"))) {
- mesg = mrb_funcall(mrb, obj, "message", 0);
- }
- else
- return mrb_false_value();
+ if (mrb_obj_equal(mrb, exc, obj)) {
+ equal_p = 1;
}
else {
- mesg = mrb_attr_get(mrb, obj, id_mesg);
+ if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) {
+ if (mrb_respond_to(mrb, obj, mrb_intern2(mrb, "message", 7))) {
+ mesg = mrb_funcall(mrb, obj, "message", 0);
+ }
+ else
+ return mrb_false_value();
+ }
+ else {
+ mesg = mrb_attr_get(mrb, obj, id_mesg);
+ }
+
+ equal_p = mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg);
}
- if (!mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg))
- return mrb_false_value();
- return mrb_true_value();
+ return mrb_bool_value(equal_p);
}
static void
@@ -186,16 +192,16 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
mrb_callinfo *ci = mrb->ci;
mrb_code *pc = ci->pc;
- mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->cibase));
+ mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase));
ci--;
while (ci >= mrb->cibase) {
if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
- mrb_irep *irep = ci->proc->body.irep;
+ mrb_irep *irep = ci->proc->body.irep;
if (irep->filename && irep->lines && irep->iseq <= pc && pc < irep->iseq + irep->ilen) {
- mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "file"), mrb_str_new_cstr(mrb, irep->filename));
- mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "line"), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1]));
- return;
+ mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, irep->filename));
+ mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1]));
+ return;
}
}
pc = ci->pc;
@@ -206,12 +212,10 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
void
mrb_exc_raise(mrb_state *mrb, mrb_value exc)
{
- mrb->exc = (struct RObject*)mrb_object(exc);
+ mrb->exc = mrb_obj_ptr(exc);
exc_debug_info(mrb, mrb->exc);
if (!mrb->jmp) {
-#ifdef ENABLE_STDIO
mrb_p(mrb, exc);
-#endif
abort();
}
longjmp(*(jmp_buf*)mrb->jmp, 1);
@@ -221,114 +225,123 @@ void
mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg)
{
mrb_value mesg;
- mesg = mrb_str_new2(mrb, msg);
+ mesg = mrb_str_new_cstr(mrb, msg);
mrb_exc_raise(mrb, mrb_exc_new3(mrb, c, mesg));
}
+mrb_value
+mrb_vformat(mrb_state *mrb, const char *format, va_list ap)
+{
+ const char *p = format;
+ const char *b = p;
+ ptrdiff_t size;
+ mrb_value ary = mrb_ary_new_capa(mrb, 4);
+
+ while (*p) {
+ const char c = *p++;
+
+ if (c == '%') {
+ if (*p == 'S') {
+ size = p - b - 1;
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
+ mrb_ary_push(mrb, ary, va_arg(ap, mrb_value));
+ b = p + 1;
+ }
+ }
+ else if (c == '\\') {
+ if (*p) {
+ size = p - b - 1;
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, p, 1));
+ b = ++p;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ if (b == format) {
+ return mrb_str_new_cstr(mrb, format);
+ }
+ else {
+ size = p - b;
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
+ return mrb_ary_join(mrb, ary, mrb_str_new(mrb,NULL,0));
+ }
+}
+
+mrb_value
+mrb_format(mrb_state *mrb, const char *format, ...)
+{
+ va_list ap;
+ mrb_value str;
+
+ va_start(ap, format);
+ str = mrb_vformat(mrb, format, ap);
+ va_end(ap);
+
+ return str;
+}
+
void
mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...)
{
va_list args;
- char buf[256];
- int n;
+ mrb_value mesg;
va_start(args, fmt);
- n = vsnprintf(buf, sizeof(buf), fmt, args);
+ mesg = mrb_vformat(mrb, fmt, args);
va_end(args);
- if (n < 0) {
- n = 0;
- }
- mrb_exc_raise(mrb, mrb_exc_new(mrb, c, buf, n));
+ mrb_exc_raise(mrb, mrb_exc_new3(mrb, c, mesg));
}
void
mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...)
{
- mrb_value exc, argv[2];
+ mrb_value exc;
+ mrb_value argv[2];
va_list args;
- char buf[256];
- int n;
va_start(args, fmt);
- n = vsnprintf(buf, sizeof(buf), fmt, args);
+ argv[0] = mrb_vformat(mrb, fmt, args);
va_end(args);
- if (n < 0) {
- n = 0;
- }
- argv[0] = mrb_str_new(mrb, buf, n);
+
argv[1] = mrb_symbol_value(id); /* ignore now */
exc = mrb_class_new_instance(mrb, 1, argv, E_NAME_ERROR);
mrb_exc_raise(mrb, exc);
}
-mrb_value
-mrb_sprintf(mrb_state *mrb, const char *fmt, ...)
-{
- va_list args;
- char buf[256];
- int n;
-
- va_start(args, fmt);
- n = vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- if (n < 0) {
- n = 0;
- }
- return mrb_str_new(mrb, buf, n);
-}
-
void
mrb_warn(const char *fmt, ...)
{
+#ifdef ENABLE_STDIO
va_list args;
va_start(args, fmt);
printf("warning: ");
vprintf(fmt, args);
va_end(args);
+#endif
}
void
mrb_bug(const char *fmt, ...)
{
+#ifdef ENABLE_STDIO
va_list args;
va_start(args, fmt);
printf("bug: ");
vprintf(fmt, args);
va_end(args);
+#endif
exit(EXIT_FAILURE);
}
-static const char *
-mrb_strerrno(int err)
-{
-#define defined_error(name, num) if (err == num) return name;
-#define undefined_error(name)
-//#include "known_errors.inc"
-#undef defined_error
-#undef undefined_error
- return NULL;
-}
-
-void
-mrb_bug_errno(const char *mesg, int errno_arg)
-{
- if (errno_arg == 0)
- mrb_bug("%s: errno == 0 (NOERROR)", mesg);
- else {
- const char *errno_str = mrb_strerrno(errno_arg);
- if (errno_str)
- mrb_bug("%s: %s (%s)", mesg, strerror(errno_arg), errno_str);
- else
- mrb_bug("%s: %s (%d)", mesg, strerror(errno_arg), errno_arg);
- }
-}
-
int
sysexit_status(mrb_state *mrb, mrb_value err)
{
- mrb_value st = mrb_iv_get(mrb, err, mrb_intern(mrb, "status"));
+ mrb_value st = mrb_iv_get(mrb, err, mrb_intern2(mrb, "status", 6));
return mrb_fixnum(st);
}
@@ -366,19 +379,19 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr)
n = 1;
exception_call:
{
- mrb_sym exc = mrb_intern(mrb, "exception");
- if (mrb_respond_to(mrb, argv[0], exc)) {
- mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1);
- }
- else {
- /* undef */
- mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected");
- }
+ mrb_sym exc = mrb_intern2(mrb, "exception", 9);
+ if (mrb_respond_to(mrb, argv[0], exc)) {
+ mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1);
+ }
+ else {
+ /* undef */
+ mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected");
+ }
}
break;
default:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%d for 0..3)", argc);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 0..3)", mrb_fixnum_value(argc));
break;
}
if (argc > 0) {
@@ -400,7 +413,20 @@ mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv)
void
mrb_sys_fail(mrb_state *mrb, const char *mesg)
{
- mrb_raise(mrb, E_RUNTIME_ERROR, mesg);
+ struct RClass *sce;
+ mrb_int no;
+
+ no = (mrb_int)errno;
+ if (mrb_class_defined(mrb, "SystemCallError")) {
+ sce = mrb_class_get(mrb, "SystemCallError");
+ if (mesg != NULL) {
+ mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 2, mrb_fixnum_value(no), mrb_str_new_cstr(mrb, mesg));
+ } else {
+ mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 1, mrb_fixnum_value(no));
+ }
+ } else {
+ mrb_raise(mrb, E_RUNTIME_ERROR, mesg);
+ }
}
void
diff --git a/src/error.h b/src/error.h
index ba3fdac6c..83d0938aa 100644
--- a/src/error.h
+++ b/src/error.h
@@ -8,12 +8,11 @@
#define MRUBY_ERROR_H
void mrb_sys_fail(mrb_state *mrb, const char *mesg);
-void mrb_bug_errno(const char*, int);
int sysexit_status(mrb_state *mrb, mrb_value err);
mrb_value mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str);
mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr);
mrb_value mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv);
-mrb_value mrb_sprintf(mrb_state *mrb, const char *fmt, ...);
+mrb_value mrb_format(mrb_state *mrb, const char *format, ...);
void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...);
void mrb_exc_print(mrb_state *mrb, struct RObject *exc);
diff --git a/src/etc.c b/src/etc.c
index 5d2c836e7..0b58ad67c 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -37,14 +37,13 @@ mrb_get_datatype(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
void *
mrb_check_datatype(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
{
- static const char mesg[] = "wrong argument type %s (expected %s)";
-
if (mrb_special_const_p(obj) || (mrb_type(obj) != MRB_TT_DATA)) {
mrb_check_type(mrb, obj, MRB_TT_DATA);
}
if (DATA_TYPE(obj) != type) {
const char *etype = DATA_TYPE(obj)->struct_name;
- mrb_raisef(mrb, E_TYPE_ERROR, mesg, etype, type->struct_name);
+ mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)",
+ mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->struct_name));
}
return DATA_PTR(obj);
}
@@ -93,8 +92,7 @@ mrb_to_id(mrb_state *mrb, mrb_value name)
tmp = mrb_check_string_type(mrb, name);
if (mrb_nil_p(tmp)) {
tmp = mrb_inspect(mrb, name);
- mrb_raisef(mrb, E_TYPE_ERROR, "%s is not a symbol",
- RSTRING_PTR(tmp));
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp);
}
name = tmp;
/* fall through */
diff --git a/src/gc.c b/src/gc.c
index ae47de025..c90e00c89 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -4,21 +4,23 @@
** See Copyright Notice in mruby.h
*/
+#ifndef SIZE_MAX
+ /* Some versions of VC++
+ * has SIZE_MAX in stdint.h
+ */
+# include <limits.h>
+#endif
+#include <string.h>
#include "mruby.h"
-#include "mruby/class.h"
#include "mruby/array.h"
-#include "mruby/string.h"
+#include "mruby/class.h"
+#include "mruby/data.h"
#include "mruby/hash.h"
-#include "mruby/range.h"
-#include <string.h>
#include "mruby/proc.h"
-#include "mruby/data.h"
+#include "mruby/range.h"
+#include "mruby/string.h"
#include "mruby/variable.h"
-#ifndef SIZE_MAX
-#include <limits.h> // for SIZE_MAX
-#endif
-
/*
= Tri-color Incremental Garbage Collection
@@ -197,7 +199,7 @@ struct heap_page {
struct heap_page *next;
struct heap_page *free_next;
struct heap_page *free_prev;
- unsigned int old:1;
+ mrb_bool old:1;
RVALUE objects[MRB_HEAP_PAGE_SIZE];
};
@@ -301,7 +303,7 @@ mrb_free_heap(mrb_state *mrb)
page = page->next;
for (p = tmp->objects, e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
if (p->as.free.tt != MRB_TT_FREE)
- obj_free(mrb, &p->as.basic);
+ obj_free(mrb, &p->as.basic);
}
mrb_free(mrb, tmp);
}
@@ -322,7 +324,7 @@ void
mrb_gc_protect(mrb_state *mrb, mrb_value obj)
{
if (mrb_special_const_p(obj)) return;
- gc_protect(mrb, mrb_basic(obj));
+ gc_protect(mrb, mrb_basic_ptr(obj));
}
struct RBasic*
@@ -542,7 +544,9 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
static void
root_scan_phase(mrb_state *mrb)
{
- int i, j, e;
+ int j;
+ size_t i;
+ size_t e;
mrb_callinfo *ci;
if (!is_minor_gc(mrb)) {
@@ -557,6 +561,8 @@ root_scan_phase(mrb_state *mrb)
}
/* mark class hierarchy */
mrb_gc_mark(mrb, (struct RBasic*)mrb->object_class);
+ /* mark top_self */
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self);
/* mark exception */
mrb_gc_mark(mrb, (struct RBasic*)mrb->exc);
/* mark stack */
@@ -586,7 +592,7 @@ root_scan_phase(mrb_state *mrb)
mrb_irep *irep = mrb->irep[i];
if (!irep) continue;
for (j=0; j<irep->plen; j++) {
- mrb_gc_mark_value(mrb, irep->pool[j]);
+ mrb_gc_mark_value(mrb, irep->pool[j]);
}
}
}
@@ -982,8 +988,8 @@ gc_enable(mrb_state *mrb, mrb_value obj)
int old = mrb->gc_disabled;
mrb->gc_disabled = FALSE;
- if (old) return mrb_true_value();
- return mrb_false_value();
+
+ return mrb_bool_value(old);
}
/*
@@ -1004,8 +1010,8 @@ gc_disable(mrb_state *mrb, mrb_value obj)
int old = mrb->gc_disabled;
mrb->gc_disabled = TRUE;
- if (old) return mrb_true_value();
- return mrb_false_value();
+
+ return mrb_bool_value(old);
}
/*
@@ -1101,10 +1107,7 @@ change_gen_gc_mode(mrb_state *mrb, mrb_int enable)
static mrb_value
gc_generational_mode_get(mrb_state *mrb, mrb_value self)
{
- if (mrb->is_generational_gc_mode)
- return mrb_true_value();
- else
- return mrb_false_value();
+ return mrb_bool_value(mrb->is_generational_gc_mode);
}
/*
@@ -1124,10 +1127,7 @@ gc_generational_mode_set(mrb_state *mrb, mrb_value self)
if (mrb->is_generational_gc_mode != enable)
change_gen_gc_mode(mrb, enable);
- if (enable)
- return mrb_true_value();
- else
- return mrb_false_value();
+ return mrb_bool_value(enable);
}
#ifdef GC_TEST
@@ -1168,8 +1168,8 @@ test_mrb_field_write_barrier(void)
puts("test_mrb_field_write_barrier");
mrb->is_generational_gc_mode = FALSE;
- obj = mrb_basic(mrb_ary_new(mrb));
- value = mrb_basic(mrb_str_new_cstr(mrb, "value"));
+ obj = mrb_basic_ptr(mrb_ary_new(mrb));
+ value = mrb_basic_ptr(mrb_str_new_cstr(mrb, "value"));
paint_black(obj);
paint_partial_white(mrb,value);
@@ -1210,15 +1210,15 @@ test_mrb_field_write_barrier(void)
{
puts("test_mrb_field_write_barrier_value");
- obj = mrb_basic(mrb_ary_new(mrb));
+ obj = mrb_basic_ptr(mrb_ary_new(mrb));
mrb_value value = mrb_str_new_cstr(mrb, "value");
paint_black(obj);
- paint_partial_white(mrb, mrb_basic(value));
+ paint_partial_white(mrb, mrb_basic_ptr(value));
mrb->gc_state = GC_STATE_MARK;
mrb_field_write_barrier_value(mrb, obj, value);
- gc_assert(is_gray(mrb_basic(value)));
+ gc_assert(is_gray(mrb_basic_ptr(value)));
}
mrb_close(mrb);
@@ -1231,7 +1231,7 @@ test_mrb_write_barrier(void)
struct RBasic *obj;
puts("test_mrb_write_barrier");
- obj = mrb_basic(mrb_ary_new(mrb));
+ obj = mrb_basic_ptr(mrb_ary_new(mrb));
paint_black(obj);
puts(" in GC_STATE_MARK");
@@ -1260,12 +1260,12 @@ test_add_gray_list(void)
puts("test_add_gray_list");
change_gen_gc_mode(mrb, FALSE);
gc_assert(mrb->gray_list == NULL);
- obj1 = mrb_basic(mrb_str_new_cstr(mrb, "test"));
+ obj1 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test"));
add_gray_list(mrb, obj1);
gc_assert(mrb->gray_list == obj1);
gc_assert(is_gray(obj1));
- obj2 = mrb_basic(mrb_str_new_cstr(mrb, "test"));
+ obj2 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test"));
add_gray_list(mrb, obj2);
gc_assert(mrb->gray_list == obj2);
gc_assert(mrb->gray_list->gcnext == obj1);
@@ -1294,12 +1294,12 @@ test_gc_gray_mark(void)
puts(" in MRB_TT_ARRAY");
obj_v = mrb_ary_new(mrb);
value_v = mrb_str_new_cstr(mrb, "test");
- paint_gray(mrb_basic(obj_v));
- paint_partial_white(mrb, mrb_basic(value_v));
+ paint_gray(mrb_basic_ptr(obj_v));
+ paint_partial_white(mrb, mrb_basic_ptr(value_v));
mrb_ary_push(mrb, obj_v, value_v);
- gray_num = gc_gray_mark(mrb, mrb_basic(obj_v));
- gc_assert(is_black(mrb_basic(obj_v)));
- gc_assert(is_gray(mrb_basic(value_v)));
+ gray_num = gc_gray_mark(mrb, mrb_basic_ptr(obj_v));
+ gc_assert(is_black(mrb_basic_ptr(obj_v)));
+ gc_assert(is_gray(mrb_basic_ptr(value_v)));
gc_assert(gray_num == 1);
mrb_close(mrb);
diff --git a/src/hash.c b/src/hash.c
index 2439a235d..e32ee73e1 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -5,17 +5,17 @@
*/
#include "mruby.h"
+#include "mruby/array.h"
+#include "mruby/class.h"
#include "mruby/hash.h"
#include "mruby/khash.h"
-#include "mruby/class.h"
-#include "mruby/array.h"
#include "mruby/string.h"
#include "mruby/variable.h"
static inline khint_t
mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key)
{
- khint_t h = mrb_type(key) << 24;
+ khint_t h = (khint_t)mrb_type(key) << 24;
mrb_value h2;
h2 = mrb_funcall(mrb, key, "hash", 0, 0);
@@ -52,11 +52,15 @@ mrb_gc_mark_ht(mrb_state *mrb, struct RHash *hash)
khash_t(ht) *h = hash->ht;
if (!h) return;
- for (k = kh_begin(h); k != kh_end(h); k++)
+ for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)) {
- mrb_gc_mark_value(mrb, kh_key(h, k));
- mrb_gc_mark_value(mrb, kh_value(h, k));
+ mrb_value key = kh_key(h, k);
+ mrb_value val = kh_value(h, k);
+
+ mrb_gc_mark_value(mrb, key);
+ mrb_gc_mark_value(mrb, val);
}
+ }
}
size_t
@@ -258,7 +262,7 @@ mrb_hash_init_core(mrb_state *mrb, mrb_value hash)
RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
ifnone = block;
}
- mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
+ mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone);
return hash;
}
@@ -423,7 +427,7 @@ mrb_hash_set_default(mrb_state *mrb, mrb_value hash)
mrb_get_args(mrb, "o", &ifnone);
mrb_hash_modify(mrb, hash);
- mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
+ mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone);
RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT);
return ifnone;
@@ -474,7 +478,7 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash)
mrb_get_args(mrb, "o", &ifnone);
mrb_hash_modify(mrb, hash);
- mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
+ mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone);
RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
return ifnone;
@@ -559,7 +563,7 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash)
delVal = mrb_hash_delete_key(mrb, hash, delKey);
mrb_gc_protect(mrb, delVal);
- return mrb_assoc_new(mrb, delKey, delVal);
+ return mrb_assoc_new(mrb, delKey, delVal);
}
}
}
@@ -755,7 +759,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash)
else {
ifnone = RHASH_IFNONE(hash2);
}
- mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
+ mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone);
return hash;
}
@@ -797,13 +801,16 @@ static mrb_value
mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
{
khash_t(ht) *h = RHASH_TBL(self);
+ mrb_bool empty_p;
if (h) {
- if (kh_size(h) == 0)
- return mrb_true_value();
- return mrb_false_value();
+ empty_p = (kh_size(h) == 0);
}
- return mrb_true_value();
+ else {
+ empty_p = 1;
+ }
+
+ return mrb_bool_value(empty_p);
}
/* 15.2.13.4.11 */
@@ -887,7 +894,7 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur)
ai = mrb_gc_arena_save(mrb);
- if (RSTRING_LEN(str) > 1) mrb_str_cat2(mrb, str, ", ");
+ if (RSTRING_LEN(str) > 1) mrb_str_cat(mrb, str, ", ", 2);
str2 = mrb_inspect(mrb, kh_key(h,k));
mrb_str_append(mrb, str, str2);
@@ -1006,14 +1013,17 @@ mrb_hash_has_keyWithKey(mrb_state *mrb, mrb_value hash, mrb_value key)
{
khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
+ mrb_bool result;
if (h) {
k = kh_get(ht, h, key);
- if (k != kh_end(h))
- return mrb_true_value();
+ result = (k != kh_end(h));
+ }
+ else {
+ result = 0;
}
- return mrb_false_value();
+ return mrb_bool_value(result);
}
/* 15.2.13.4.13 */
@@ -1094,7 +1104,7 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql)
if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value();
if (!mrb_hash_p(hash2)) {
- if (!mrb_respond_to(mrb, hash2, mrb_intern(mrb, "to_hash"))) {
+ if (!mrb_respond_to(mrb, hash2, mrb_intern2(mrb, "to_hash", 7))) {
return mrb_false_value();
}
if (eql)
@@ -1105,8 +1115,7 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql)
h1 = RHASH_TBL(hash1);
h2 = RHASH_TBL(hash2);
if (!h1) {
- if (!h2) return mrb_true_value();
- return mrb_false_value();
+ return mrb_bool_value(!h2);
}
if (!h2) return mrb_false_value();
if (kh_size(h1) != kh_size(h2)) return mrb_false_value();
@@ -1119,9 +1128,9 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql)
key = kh_key(h1,k1);
k2 = kh_get(ht, h2, key);
if (k2 != kh_end(h2)) {
- if (mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2))) {
- continue; /* next key */
- }
+ if (mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2))) {
+ continue; /* next key */
+ }
}
return mrb_false_value();
}
diff --git a/src/init.c b/src/init.c
index 0d1a24881..e97c72d68 100644
--- a/src/init.c
+++ b/src/init.c
@@ -21,7 +21,6 @@ void mrb_init_hash(mrb_state*);
void mrb_init_numeric(mrb_state*);
void mrb_init_range(mrb_state*);
void mrb_init_gc(mrb_state*);
-void mrb_init_print(mrb_state*);
void mrb_init_math(mrb_state*);
void mrb_init_mrblib(mrb_state*);
void mrb_init_mrbgems(mrb_state*);
@@ -48,9 +47,6 @@ mrb_init_core(mrb_state *mrb)
mrb_init_numeric(mrb); DONE;
mrb_init_range(mrb); DONE;
mrb_init_gc(mrb); DONE;
-#ifdef ENABLE_STDIO
- mrb_init_print(mrb); DONE;
-#endif
mrb_init_mrblib(mrb); DONE;
#ifndef DISABLE_GEMS
mrb_init_mrbgems(mrb); DONE;
diff --git a/src/kernel.c b/src/kernel.c
index e45953fd3..f14a94b3a 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -5,10 +5,10 @@
*/
#include "mruby.h"
-#include "mruby/string.h"
-#include "mruby/proc.h"
#include "mruby/array.h"
#include "mruby/class.h"
+#include "mruby/proc.h"
+#include "mruby/string.h"
#include "mruby/variable.h"
#include "error.h"
@@ -29,7 +29,7 @@ typedef enum {
int
mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj)
{
- struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern(mrb, "to_s"));
+ struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern2(mrb, "to_s", 4));
if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s))
return TRUE;
return FALSE;
@@ -55,9 +55,6 @@ mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
if ((mrb_type(obj) == MRB_TT_OBJECT) && mrb_obj_basic_to_s_p(mrb, obj)) {
return mrb_obj_iv_inspect(mrb, mrb_obj_ptr(obj));
}
- else if (mrb_type(obj) == MRB_TT_MAIN) {
- return mrb_str_new(mrb, "main", 4);
- }
return mrb_any_to_s(mrb, obj);
}
@@ -96,28 +93,24 @@ static mrb_value
mrb_obj_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &arg);
- if (mrb_obj_equal(mrb, self, arg)) {
- return mrb_true_value();
- }
- else {
- return mrb_false_value();
- }
+ eql_p = mrb_obj_equal(mrb, self, arg);
+
+ return mrb_bool_value(eql_p);
}
static mrb_value
mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &arg);
- if (mrb_equal(mrb, self, arg)) {
- return mrb_false_value();
- }
- else {
- return mrb_true_value();
- }
+ eql_p = mrb_obj_equal(mrb, self, arg);
+
+ return mrb_bool_value(!eql_p);
}
/* 15.3.1.3.2 */
@@ -133,14 +126,12 @@ static mrb_value
mrb_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &arg);
- if (mrb_equal(mrb, self, arg)){
- return mrb_true_value();
- }
- else {
- return mrb_false_value();
- }
+ equal_p = mrb_equal(mrb, self, arg);
+
+ return mrb_bool_value(equal_p);
}
/* 15.3.1.3.3 */
@@ -191,7 +182,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
mrb_sym name;
mrb_value block, *argv;
int argc;
-
+
mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block);
return mrb_funcall_with_block(mrb,self, name, argc, argv, block);
}
@@ -225,21 +216,28 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
{
mrb_callinfo *ci = mrb->ci;
mrb_value *bp;
+ mrb_bool given_p;
bp = mrb->stbase + ci->stackidx + 1;
ci--;
- if (ci <= mrb->cibase) return mrb_false_value();
- /* block_given? called within block; check upper scope */
- if (ci->proc->env && ci->proc->env->stack) {
- if (ci->proc->env->stack == mrb->stbase || mrb_nil_p(ci->proc->env->stack[1]))
- return mrb_false_value();
- return mrb_true_value();
+ if (ci <= mrb->cibase) {
+ given_p = 0;
}
- if (ci->argc > 0) {
- bp += ci->argc;
+ else {
+ /* block_given? called within block; check upper scope */
+ if (ci->proc->env && ci->proc->env->stack) {
+ given_p = !(ci->proc->env->stack == mrb->stbase ||
+ mrb_nil_p(ci->proc->env->stack[1]));
+ }
+ else {
+ if (ci->argc > 0) {
+ bp += ci->argc;
+ }
+ given_p = !mrb_nil_p(*bp);
+ }
}
- if (mrb_nil_p(*bp)) return mrb_false_value();
- return mrb_true_value();
+
+ return mrb_bool_value(given_p);
}
/* 15.3.1.3.7 */
@@ -263,7 +261,7 @@ mrb_obj_class_m(mrb_state *mrb, mrb_value self)
struct RClass*
mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
{
- struct RClass *klass = mrb_basic(obj)->c;
+ struct RClass *klass = mrb_basic_ptr(obj)->c;
if (klass->tt != MRB_TT_SCLASS)
return klass;
@@ -282,7 +280,7 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
clone->super = klass->super;
if (klass->iv) {
mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass));
- mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern(mrb, "__attached__"), obj);
+ mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern2(mrb, "__attached__", 12), obj);
}
if (klass->mt) {
clone->mt = kh_copy(mt, mrb, klass->mt);
@@ -305,7 +303,7 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
case MRB_TT_SCLASS:
case MRB_TT_HASH:
case MRB_TT_DATA:
- mrb_iv_copy(mrb, dest, obj);
+ mrb_iv_copy(mrb, dest, obj);
break;
default:
@@ -347,7 +345,7 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self)
mrb_value clone;
if (mrb_special_const_p(self)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %s", mrb_obj_classname(mrb, self));
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self);
}
p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self));
p->c = mrb_singleton_class_clone(mrb, self);
@@ -383,7 +381,7 @@ mrb_obj_dup(mrb_state *mrb, mrb_value obj)
mrb_value dup;
if (mrb_special_const_p(obj)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %s", mrb_obj_classname(mrb, obj));
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %S", obj);
}
p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
dup = mrb_obj_value(p);
@@ -483,7 +481,7 @@ mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *a
* call-seq:
* obj.instance_eval {| | block } -> obj
*
- * Evaluates the given block,within the context of the receiver (_obj_).
+ * Evaluates the given block,within the context of the receiver (_obj_).
* In order to set the context, the variable +self+ is set to _obj_ while
* the code is executing, giving the code access to _obj_'s
* instance variables. In the version of <code>instance_eval</code>
@@ -518,6 +516,7 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
default:
cv = mrb_singleton_class(mrb, self);
c = mrb_class_ptr(cv);
+ break;
}
return mrb_yield_internal(mrb, b, 0, 0, self, c);
}
@@ -541,25 +540,23 @@ static mrb_value
obj_is_instance_of(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
+ mrb_bool instance_of_p;
mrb_get_args(mrb, "o", &arg);
- if (mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg))){
- return mrb_true_value();
- }
- else {
- return mrb_false_value();
- }
+ instance_of_p = mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg));
+
+ return mrb_bool_value(instance_of_p);
}
static void
check_iv_name(mrb_state *mrb, mrb_sym id)
{
const char *s;
- int len;
+ size_t len;
s = mrb_sym2name_len(mrb, id, &len);
if (len < 2 || !(s[0] == '@' && s[1] != '@')) {
- mrb_name_error(mrb, id, "`%s' is not allowed as an instance variable name", s);
+ mrb_name_error(mrb, id, "`%S' is not allowed as an instance variable name", mrb_sym2str(mrb, id));
}
}
@@ -585,12 +582,13 @@ mrb_value
mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self)
{
mrb_sym mid;
+ mrb_bool defined_p;
mrb_get_args(mrb, "n", &mid);
check_iv_name(mrb, mid);
- if (mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid))
- return mrb_true_value();
- return mrb_false_value();
+ defined_p = mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid);
+
+ return mrb_bool_value(defined_p);
}
/* 15.3.1.3.21 */
@@ -687,14 +685,12 @@ mrb_value
mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
+ mrb_bool kind_of_p;
mrb_get_args(mrb, "o", &arg);
- if (mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg))) {
- return mrb_true_value();
- }
- else {
- return mrb_false_value();
- }
+ kind_of_p = mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg));
+
+ return mrb_bool_value(kind_of_p);
}
static void
@@ -913,7 +909,7 @@ mrb_f_raise(mrb_state *mrb, mrb_value self)
{
mrb_value a[2], exc;
int argc;
-
+
argc = mrb_get_args(mrb, "|oo", &a[0], &a[1]);
switch (argc) {
@@ -929,8 +925,9 @@ mrb_f_raise(mrb_state *mrb, mrb_value self)
/* fall through */
default:
exc = mrb_make_exception(mrb, argc, a);
- mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern(mrb, "lastpc"), mrb_voidp_value(mrb->ci->pc));
+ mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb->ci->pc));
mrb_exc_raise(mrb, exc);
+ break;
}
return mrb_nil_value(); /* not reached */
}
@@ -967,7 +964,7 @@ mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self)
check_iv_name(mrb, sym);
val = mrb_iv_remove(mrb, self, sym);
if (mrb_undef_p(val)) {
- mrb_name_error(mrb, sym, "instance variable %s not defined", mrb_sym2name(mrb, sym));
+ mrb_name_error(mrb, sym, "instance variable %S not defined", mrb_sym2str(mrb, sym));
}
return val;
}
@@ -1000,15 +997,17 @@ obj_respond_to(mrb_state *mrb, mrb_value self)
int argc;
mrb_value mid, priv;
mrb_sym id;
+ mrb_bool respond_to_p;
mrb_get_args(mrb, "*", &argv, &argc);
mid = argv[0];
if (argc > 1) priv = argv[1];
else priv = mrb_nil_value();
id = mrb_to_id(mrb, mid);
- if (basic_obj_respond_to(mrb, self, id, !mrb_test(priv)))
- return mrb_true_value();
- return mrb_false_value();
+
+ respond_to_p = basic_obj_respond_to(mrb, self, id, !mrb_test(priv));
+
+ return mrb_bool_value(respond_to_p);
}
/* 15.3.1.3.45 */
@@ -1054,8 +1053,6 @@ mrb_obj_singleton_methods_m(mrb_state *mrb, mrb_value self)
return mrb_obj_singleton_methods(mrb, argc, argv, self);
}
-mrb_value mrb_f_sprintf(mrb_state *mrb, mrb_value obj); /* in sprintf.c */
-
void
mrb_init_kernel(mrb_state *mrb)
{
@@ -1108,11 +1105,6 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, ARGS_ANY()); /* 15.3.1.3.45 */
mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, ARGS_NONE()); /* 15.3.1.3.46 */
-#ifdef ENABLE_SPRINTF
- mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, ARGS_ANY()); /* in sprintf.c */
- mrb_define_method(mrb, krn, "format", mrb_f_sprintf, ARGS_ANY()); /* in sprintf.c */
-#endif
-
mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
mrb_alias_method(mrb, mrb->module_class, mrb_intern(mrb, "dup"), mrb_intern(mrb, "clone"));
}
diff --git a/src/keywords b/src/keywords
index be5324875..9cb86608c 100644
--- a/src/keywords
+++ b/src/keywords
@@ -8,43 +8,43 @@ static const struct kwtable *reserved_word(const char *, unsigned int);
struct kwtable;
%%
__ENCODING__, {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END
-__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END
-__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END
-BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END
-END, {keyword_END, keyword_END}, EXPR_END
-alias, {keyword_alias, keyword_alias}, EXPR_FNAME
-and, {keyword_and, keyword_and}, EXPR_VALUE
-begin, {keyword_begin, keyword_begin}, EXPR_BEG
-break, {keyword_break, keyword_break}, EXPR_MID
-case, {keyword_case, keyword_case}, EXPR_VALUE
-class, {keyword_class, keyword_class}, EXPR_CLASS
-def, {keyword_def, keyword_def}, EXPR_FNAME
-do, {keyword_do, keyword_do}, EXPR_BEG
-else, {keyword_else, keyword_else}, EXPR_BEG
-elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE
-end, {keyword_end, keyword_end}, EXPR_END
-ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG
-false, {keyword_false, keyword_false}, EXPR_END
-for, {keyword_for, keyword_for}, EXPR_VALUE
-if, {keyword_if, modifier_if}, EXPR_VALUE
-in, {keyword_in, keyword_in}, EXPR_VALUE
-module, {keyword_module, keyword_module}, EXPR_VALUE
-next, {keyword_next, keyword_next}, EXPR_MID
-nil, {keyword_nil, keyword_nil}, EXPR_END
-not, {keyword_not, keyword_not}, EXPR_ARG
-or, {keyword_or, keyword_or}, EXPR_VALUE
-redo, {keyword_redo, keyword_redo}, EXPR_END
-rescue, {keyword_rescue, modifier_rescue}, EXPR_MID
-retry, {keyword_retry, keyword_retry}, EXPR_END
-return, {keyword_return, keyword_return}, EXPR_MID
-self, {keyword_self, keyword_self}, EXPR_END
-super, {keyword_super, keyword_super}, EXPR_ARG
-then, {keyword_then, keyword_then}, EXPR_BEG
-true, {keyword_true, keyword_true}, EXPR_END
-undef, {keyword_undef, keyword_undef}, EXPR_FNAME
-unless, {keyword_unless, modifier_unless}, EXPR_VALUE
-until, {keyword_until, modifier_until}, EXPR_VALUE
-when, {keyword_when, keyword_when}, EXPR_VALUE
-while, {keyword_while, modifier_while}, EXPR_VALUE
-yield, {keyword_yield, keyword_yield}, EXPR_ARG
+__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END
+__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END
+BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END
+END, {keyword_END, keyword_END}, EXPR_END
+alias, {keyword_alias, keyword_alias}, EXPR_FNAME
+and, {keyword_and, keyword_and}, EXPR_VALUE
+begin, {keyword_begin, keyword_begin}, EXPR_BEG
+break, {keyword_break, keyword_break}, EXPR_MID
+case, {keyword_case, keyword_case}, EXPR_VALUE
+class, {keyword_class, keyword_class}, EXPR_CLASS
+def, {keyword_def, keyword_def}, EXPR_FNAME
+do, {keyword_do, keyword_do}, EXPR_BEG
+else, {keyword_else, keyword_else}, EXPR_BEG
+elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE
+end, {keyword_end, keyword_end}, EXPR_END
+ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG
+false, {keyword_false, keyword_false}, EXPR_END
+for, {keyword_for, keyword_for}, EXPR_VALUE
+if, {keyword_if, modifier_if}, EXPR_VALUE
+in, {keyword_in, keyword_in}, EXPR_VALUE
+module, {keyword_module, keyword_module}, EXPR_VALUE
+next, {keyword_next, keyword_next}, EXPR_MID
+nil, {keyword_nil, keyword_nil}, EXPR_END
+not, {keyword_not, keyword_not}, EXPR_ARG
+or, {keyword_or, keyword_or}, EXPR_VALUE
+redo, {keyword_redo, keyword_redo}, EXPR_END
+rescue, {keyword_rescue, modifier_rescue}, EXPR_MID
+retry, {keyword_retry, keyword_retry}, EXPR_END
+return, {keyword_return, keyword_return}, EXPR_MID
+self, {keyword_self, keyword_self}, EXPR_END
+super, {keyword_super, keyword_super}, EXPR_ARG
+then, {keyword_then, keyword_then}, EXPR_BEG
+true, {keyword_true, keyword_true}, EXPR_END
+undef, {keyword_undef, keyword_undef}, EXPR_FNAME
+unless, {keyword_unless, modifier_unless}, EXPR_VALUE
+until, {keyword_until, modifier_until}, EXPR_VALUE
+when, {keyword_when, keyword_when}, EXPR_VALUE
+while, {keyword_while, modifier_while}, EXPR_VALUE
+yield, {keyword_yield, keyword_yield}, EXPR_ARG
%%
diff --git a/src/lex.def b/src/lex.def
index 5223aac1b..ea456a843 100644
--- a/src/lex.def
+++ b/src/lex.def
@@ -1,4 +1,4 @@
-/* ANSI-C code produced by gperf version 3.0.4 */
+/* ANSI-C code produced by gperf version 3.0.3 */
/* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' src/keywords */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
@@ -44,10 +44,12 @@ struct kwtable;
#define MAX_HASH_VALUE 50
/* maximum key range = 43, duplicates = 0 */
-#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) || defined(__GNUC_STDC_INLINE__)
-inline
-#elif defined(__GNUC__)
+#ifdef __GNUC__
__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
#endif
static unsigned int
hash (register const char *str, register unsigned int len)
@@ -98,7 +100,7 @@ hash (register const char *str, register unsigned int len)
#ifdef __GNUC__
__inline
-#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#ifdef __GNUC_STDC_INLINE__
__attribute__ ((__gnu_inline__))
#endif
#endif
@@ -109,87 +111,87 @@ mrb_reserved_word (register const char *str, register unsigned int len)
{
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 18 "src/keywords"
- {"break", {keyword_break, keyword_break}, EXPR_MID},
+ {"break", {keyword_break, keyword_break}, EXPR_MID},
#line 23 "src/keywords"
- {"else", {keyword_else, keyword_else}, EXPR_BEG},
+ {"else", {keyword_else, keyword_else}, EXPR_BEG},
#line 33 "src/keywords"
- {"nil", {keyword_nil, keyword_nil}, EXPR_END},
+ {"nil", {keyword_nil, keyword_nil}, EXPR_END},
#line 26 "src/keywords"
- {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
+ {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
#line 25 "src/keywords"
- {"end", {keyword_end, keyword_end}, EXPR_END},
+ {"end", {keyword_end, keyword_end}, EXPR_END},
#line 42 "src/keywords"
- {"then", {keyword_then, keyword_then}, EXPR_BEG},
+ {"then", {keyword_then, keyword_then}, EXPR_BEG},
#line 34 "src/keywords"
- {"not", {keyword_not, keyword_not}, EXPR_ARG},
+ {"not", {keyword_not, keyword_not}, EXPR_ARG},
#line 27 "src/keywords"
- {"false", {keyword_false, keyword_false}, EXPR_END},
+ {"false", {keyword_false, keyword_false}, EXPR_END},
#line 40 "src/keywords"
- {"self", {keyword_self, keyword_self}, EXPR_END},
+ {"self", {keyword_self, keyword_self}, EXPR_END},
#line 24 "src/keywords"
- {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
+ {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
#line 37 "src/keywords"
- {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
+ {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
#line 43 "src/keywords"
- {"true", {keyword_true, keyword_true}, EXPR_END},
+ {"true", {keyword_true, keyword_true}, EXPR_END},
#line 46 "src/keywords"
- {"until", {keyword_until, modifier_until}, EXPR_VALUE},
+ {"until", {keyword_until, modifier_until}, EXPR_VALUE},
#line 45 "src/keywords"
- {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
+ {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
#line 39 "src/keywords"
- {"return", {keyword_return, keyword_return}, EXPR_MID},
+ {"return", {keyword_return, keyword_return}, EXPR_MID},
#line 21 "src/keywords"
- {"def", {keyword_def, keyword_def}, EXPR_FNAME},
+ {"def", {keyword_def, keyword_def}, EXPR_FNAME},
#line 16 "src/keywords"
- {"and", {keyword_and, keyword_and}, EXPR_VALUE},
+ {"and", {keyword_and, keyword_and}, EXPR_VALUE},
#line 22 "src/keywords"
- {"do", {keyword_do, keyword_do}, EXPR_BEG},
+ {"do", {keyword_do, keyword_do}, EXPR_BEG},
#line 49 "src/keywords"
- {"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
+ {"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
#line 28 "src/keywords"
- {"for", {keyword_for, keyword_for}, EXPR_VALUE},
+ {"for", {keyword_for, keyword_for}, EXPR_VALUE},
#line 44 "src/keywords"
- {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
+ {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
#line 35 "src/keywords"
- {"or", {keyword_or, keyword_or}, EXPR_VALUE},
+ {"or", {keyword_or, keyword_or}, EXPR_VALUE},
#line 30 "src/keywords"
- {"in", {keyword_in, keyword_in}, EXPR_VALUE},
+ {"in", {keyword_in, keyword_in}, EXPR_VALUE},
#line 47 "src/keywords"
- {"when", {keyword_when, keyword_when}, EXPR_VALUE},
+ {"when", {keyword_when, keyword_when}, EXPR_VALUE},
#line 38 "src/keywords"
- {"retry", {keyword_retry, keyword_retry}, EXPR_END},
+ {"retry", {keyword_retry, keyword_retry}, EXPR_END},
#line 29 "src/keywords"
- {"if", {keyword_if, modifier_if}, EXPR_VALUE},
+ {"if", {keyword_if, modifier_if}, EXPR_VALUE},
#line 19 "src/keywords"
- {"case", {keyword_case, keyword_case}, EXPR_VALUE},
+ {"case", {keyword_case, keyword_case}, EXPR_VALUE},
#line 36 "src/keywords"
- {"redo", {keyword_redo, keyword_redo}, EXPR_END},
+ {"redo", {keyword_redo, keyword_redo}, EXPR_END},
#line 32 "src/keywords"
- {"next", {keyword_next, keyword_next}, EXPR_MID},
+ {"next", {keyword_next, keyword_next}, EXPR_MID},
#line 41 "src/keywords"
- {"super", {keyword_super, keyword_super}, EXPR_ARG},
+ {"super", {keyword_super, keyword_super}, EXPR_ARG},
#line 31 "src/keywords"
- {"module", {keyword_module, keyword_module}, EXPR_VALUE},
+ {"module", {keyword_module, keyword_module}, EXPR_VALUE},
#line 17 "src/keywords"
- {"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
-#line 11 "src/keywords"
- {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
+ {"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
#line 12 "src/keywords"
- {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
+ {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
+#line 11 "src/keywords"
+ {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
#line 10 "src/keywords"
{"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
#line 14 "src/keywords"
- {"END", {keyword_END, keyword_END}, EXPR_END},
+ {"END", {keyword_END, keyword_END}, EXPR_END},
#line 15 "src/keywords"
- {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
+ {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
#line 13 "src/keywords"
- {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
+ {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
{""},
#line 20 "src/keywords"
- {"class", {keyword_class, keyword_class}, EXPR_CLASS},
+ {"class", {keyword_class, keyword_class}, EXPR_CLASS},
{""}, {""},
#line 48 "src/keywords"
- {"while", {keyword_while, modifier_while}, EXPR_VALUE}
+ {"while", {keyword_while, modifier_while}, EXPR_VALUE}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/src/load.c b/src/load.c
index 850fa6e8d..c350cb1a3 100644
--- a/src/load.c
+++ b/src/load.c
@@ -4,412 +4,77 @@
** See Copyright Notice in mruby.h
*/
+#ifndef SIZE_MAX
+ /* Some versions of VC++
+ * has SIZE_MAX in stdint.h
+ */
+# include <limits.h>
+#endif
+#include <stdlib.h>
#include <string.h>
#include "mruby/dump.h"
-
-#include "mruby/string.h"
-#include "mruby/proc.h"
#include "mruby/irep.h"
+#include "mruby/proc.h"
+#include "mruby/string.h"
-#ifdef ENABLE_STDIO
-typedef struct _RiteFILE
-{
- FILE* fp;
- unsigned char buf[256];
- int cnt;
- int readlen;
-} RiteFILE;
+#ifndef _WIN32
+# if SIZE_MAX < UINT32_MAX
+# error "It can't be run this code on this environment (SIZE_MAX < UINT32_MAX)"
+# endif
#endif
-const char hex2bin[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //00-0f
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10-1f
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20-2f
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, //30-3f
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40-4f
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //50-5f
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0 //60-6f
- //70-ff
-};
-
-static uint16_t hex_to_bin8(unsigned char*,unsigned char*);
-static uint16_t hex_to_bin16(unsigned char*,unsigned char*);
-static uint16_t hex_to_bin32(unsigned char*,unsigned char*);
-static uint8_t hex_to_uint8(unsigned char*);
-static uint16_t hex_to_uint16(unsigned char*);
-static uint32_t hex_to_uint32(unsigned char*);
-static char* hex_to_str(char*,char*,uint16_t*);
-uint16_t calc_crc_16_ccitt(unsigned char*,int);
-#ifdef ENABLE_STDIO
-static unsigned char rite_fgetcSub(RiteFILE*);
-static unsigned char rite_fgetc(RiteFILE*,int);
-static unsigned char* rite_fgets(RiteFILE*,unsigned char*,int,int);
-static int load_rite_header(FILE*,rite_binary_header*,unsigned char*);
-static int load_rite_irep_record(mrb_state*, RiteFILE*,unsigned char*,uint32_t*);
+#if CHAR_BIT != 8
+# error This code assumes CHAR_BIT == 8
#endif
-static int read_rite_header(mrb_state*,unsigned char*,rite_binary_header*);
-static int read_rite_irep_record(mrb_state*,unsigned char*,uint32_t*);
-
-#ifdef ENABLE_STDIO
-static unsigned char
-rite_fgetcSub(RiteFILE* rfp)
+static size_t
+offset_crc_body()
{
- //only first call
- if (rfp->buf[0] == '\0') {
- rfp->readlen = fread(rfp->buf, 1, sizeof(rfp->buf), rfp->fp);
- rfp->cnt = 0;
- }
-
- if (rfp->readlen == rfp->cnt) {
- rfp->readlen = fread(rfp->buf, 1, sizeof(rfp->buf), rfp->fp);
- rfp->cnt = 0;
- if (rfp->readlen == 0) {
- return '\0';
- }
- }
- return rfp->buf[(rfp->cnt)++];
+ struct rite_binary_header header;
+ return ((uint8_t *)header.binary_crc - (uint8_t *)&header) + sizeof(header.binary_crc);
}
-#endif /* ENABLE_STDIO */
-#ifdef ENABLE_STDIO
-static unsigned char
-rite_fgetc(RiteFILE* rfp, int ignorecomment)
-{
- unsigned char tmp;
-
- for (;;) {
- tmp = rite_fgetcSub(rfp);
- if (tmp == '\n' || tmp == '\r') {
- continue;
- }
- else if (ignorecomment && tmp == '#') {
- while (tmp != '\n' && tmp != '\r' && tmp != '\0')
- tmp = rite_fgetcSub(rfp);
- if (tmp == '\0')
- return '\0';
- }
- else {
- return tmp;
- }
- }
-}
-#endif /* ENABLE_STDIO */
-
-#ifdef ENABLE_STDIO
-static unsigned char*
-rite_fgets(RiteFILE* rfp, unsigned char* dst, int len, int ignorecomment)
-{
- int i;
-
- for (i=0; i<len; i++) {
- if ('\0' == (dst[i] = rite_fgetc(rfp, ignorecomment))) {
- return NULL;
- }
- }
- return dst;
-}
-#endif /* ENABLE_STDIO */
-
-#ifdef ENABLE_STDIO
static int
-load_rite_header(FILE* fp, rite_binary_header* bin_header, unsigned char* hcrc)
+read_rite_irep_record(mrb_state *mrb, const uint8_t *bin, uint32_t *len)
{
- rite_file_header file_header;
-
- if (fread(&file_header, 1, sizeof(file_header), fp) < sizeof(file_header)) {
- return MRB_DUMP_READ_FAULT;
- }
- memcpy(bin_header->rbfi, file_header.rbfi, sizeof(file_header.rbfi));
- if (memcmp(bin_header->rbfi, RITE_FILE_IDENFIFIER, sizeof(bin_header->rbfi)) != 0) {
- return MRB_DUMP_INVALID_FILE_HEADER; //File identifier error
- }
- memcpy(bin_header->rbfv, file_header.rbfv, sizeof(file_header.rbfv));
- if (memcmp(bin_header->rbfv, RITE_FILE_FORMAT_VER, sizeof(bin_header->rbfv)) != 0) {
- return MRB_DUMP_INVALID_FILE_HEADER; //File format version error
- }
- memcpy(bin_header->risv, file_header.risv, sizeof(file_header.risv));
- memcpy(bin_header->rct, file_header.rct, sizeof(file_header.rct));
- memcpy(bin_header->rcv, file_header.rcv, sizeof(file_header.rcv));
- hex_to_bin32(bin_header->rbds, file_header.rbds);
- hex_to_bin16(bin_header->nirep, file_header.nirep);
- hex_to_bin16(bin_header->sirep, file_header.sirep);
- memcpy(bin_header->rsv, file_header.rsv, sizeof(file_header.rsv));
- memcpy(hcrc, file_header.hcrc, sizeof(file_header.hcrc));
-
- return MRB_DUMP_OK;
-}
-#endif /* ENABLE_STDIO */
-
-#ifdef ENABLE_STDIO
-static int
-load_rite_irep_record(mrb_state *mrb, RiteFILE* rfp, unsigned char* dst, uint32_t* len)
-{
- int i;
- uint32_t blocklen;
- uint16_t offset, pdl, snl, clen;
- unsigned char hex2[2] = {0}, hex4[4] = {0}, hex8[8] = {0}, hcrc[4] = {0};
- unsigned char *pStart;
- char *char_buf;
- uint16_t buf_size =0;
- int result;
-
- buf_size = MRB_DUMP_DEFAULT_STR_LEN;
- char_buf = (char *)mrb_malloc(mrb, buf_size);
- if (char_buf == NULL) {
- result = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
-
- pStart = dst;
-
- //IREP HEADER BLOCK
- *dst = rite_fgetc(rfp, TRUE); //record identifier
- if (*dst != RITE_IREP_IDENFIFIER) {
- result = MRB_DUMP_INVALID_IREP;
- goto error_exit;
- }
- dst += sizeof(unsigned char);
- *dst = rite_fgetc(rfp, TRUE); //class or module
- dst += sizeof(unsigned char);
- rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //number of local variable
- dst += hex_to_bin16(dst, hex4);
- rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //number of register variable
- dst += hex_to_bin16(dst, hex4);
- rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //offset of isec block
- offset = hex_to_uint16(hex4);
- rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //header CRC
- memset( char_buf, '\0', buf_size);
- rite_fgets(rfp, (unsigned char*)char_buf, (offset - (MRB_DUMP_SIZE_OF_SHORT * RITE_FILE_HEX_SIZE)), TRUE); //class or module name
- hex_to_str(char_buf, (char*)(dst + MRB_DUMP_SIZE_OF_SHORT + MRB_DUMP_SIZE_OF_SHORT), &clen); //class or module name
- dst += uint16_to_bin((MRB_DUMP_SIZE_OF_SHORT/*crc*/ + clen), (char*)dst); //offset of isec block
- dst += hex_to_bin16(dst, hcrc); //header CRC
- dst += clen;
-
- //ISEQ BLOCK
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //iseq length
- dst += hex_to_bin32(dst, hex8);
- blocklen = hex_to_uint32(hex8);
- for (i=0; i<blocklen; i++) {
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //iseq
- dst += hex_to_bin32(dst, hex8);
- }
- rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //iseq CRC
- dst += hex_to_bin16(dst, hcrc);
-
- //POOL BLOCK
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //pool length
- dst += hex_to_bin32(dst, hex8);
- blocklen = hex_to_uint32(hex8);
- for (i=0; i<blocklen; i++) {
- rite_fgets(rfp, hex2, sizeof(hex2), TRUE); //TT
- dst += hex_to_bin8(dst, hex2);
- rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //pool data length
- pdl = hex_to_uint16(hex4);
-
- if ( pdl > buf_size - 1) {
- buf_size = pdl + 1;
- char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size);
- if (char_buf == NULL) {
- result = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
- }
- memset(char_buf, '\0', buf_size);
- rite_fgets(rfp, (unsigned char*)char_buf, pdl, FALSE); //pool
- hex_to_str(char_buf, (char*)(dst + MRB_DUMP_SIZE_OF_SHORT), &clen);
- dst += uint16_to_bin(clen, (char*)dst);
- dst += clen;
- }
- rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //pool CRC
- dst += hex_to_bin16(dst, hcrc);
-
- //SYMS BLOCK
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //syms length
- dst += hex_to_bin32(dst, hex8);
- blocklen = hex_to_uint32(hex8);
- for (i=0; i<blocklen; i++) {
- rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //symbol name length
- snl = hex_to_uint16(hex4);
-
- if (snl == MRB_DUMP_NULL_SYM_LEN) {
- dst += uint16_to_bin(snl, (char*)dst);
- continue;
- }
-
- if ( snl > buf_size - 1) {
- buf_size = snl + 1;
- char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size);
- if (char_buf == NULL) {
- result = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
- }
- memset(char_buf, '\0', buf_size);
- rite_fgets(rfp, (unsigned char*)char_buf, snl, FALSE); //symbol name
- hex_to_str(char_buf, (char*)(dst + MRB_DUMP_SIZE_OF_SHORT), &clen);
- dst += uint16_to_bin(clen, (char*)dst);
- dst += clen;
- }
- rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //syms CRC
- dst += hex_to_bin16(dst, hcrc);
-
- *len = dst - pStart;
-
- result = MRB_DUMP_OK;
-error_exit:
- mrb_free(mrb, char_buf);
-
- return result;
-}
-#endif /* ENABLE_STDIO */
-
-#ifdef ENABLE_STDIO
-int
-mrb_read_irep_file(mrb_state *mrb, FILE* fp)
-{
- int ret, i;
- uint32_t len, rlen = 0;
- unsigned char hex8[8], hcrc[4];
- unsigned char *dst, *rite_dst = NULL;
- rite_binary_header bin_header;
- RiteFILE ritefp = { 0 };
- RiteFILE *rfp;
-
- if ((mrb == NULL) || (fp == NULL)) {
- return MRB_DUMP_INVALID_ARGUMENT;
- }
- ritefp.fp = fp;
- rfp = &ritefp;
-
- //Read File Header Section
- ret = load_rite_header(fp, &bin_header, hcrc);
- if (ret != MRB_DUMP_OK)
- return ret;
-
- len = sizeof(rite_binary_header) + bin_to_uint32(bin_header.rbds);
- rite_dst = (unsigned char *)mrb_malloc(mrb, len);
- if (rite_dst == NULL)
- return MRB_DUMP_GENERAL_FAILURE;
-
- dst = rite_dst;
- memset(dst, 0x00, len);
- *(rite_binary_header *)dst = bin_header;
- dst += sizeof(rite_binary_header);
- dst += hex_to_bin16(dst, hcrc);
-
- //Read Binary Data Section
- len = bin_to_uint16(bin_header.nirep);
- for (i=0; i<len; i++) {
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //record len
- dst += hex_to_bin32(dst, hex8);
- ret = load_rite_irep_record(mrb, rfp, dst, &rlen);
- if (ret != MRB_DUMP_OK) //irep info
- goto error_exit;
- dst += rlen;
- }
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //dummy record len
- hex_to_bin32(dst, hex8); /* dst += hex_to_bin32(dst, hex8); */
- if (0 != hex_to_uint32(hex8)) {
- ret = MRB_DUMP_INVALID_IREP;
- goto error_exit;
- }
-
- if (ret == MRB_DUMP_OK)
- ret = mrb_read_irep(mrb, (char*)rite_dst);
-
-error_exit:
- mrb_free(mrb, rite_dst);
-
- return ret;
-}
-#endif /* ENABLE_STDIO */
-
-static int
-read_rite_header(mrb_state *mrb, unsigned char *bin, rite_binary_header* bin_header)
-{
- uint16_t crc;
-
- *bin_header = *(rite_binary_header *)bin;
- bin += sizeof(rite_binary_header);
- if (memcmp(bin_header->rbfi, RITE_FILE_IDENFIFIER, sizeof(bin_header->rbfi)) != 0) {
- return MRB_DUMP_INVALID_FILE_HEADER; //File identifier error
- }
- if (memcmp(bin_header->risv, RITE_VM_VER, sizeof(bin_header->risv)) != 0) {
- return MRB_DUMP_INVALID_FILE_HEADER; //Instruction set version check
- }
-
- crc = calc_crc_16_ccitt((unsigned char*)bin_header, sizeof(*bin_header)); //Calculate CRC
- if (crc != bin_to_uint16(bin)) {
- return MRB_DUMP_INVALID_FILE_HEADER; //CRC error
- }
-
- return bin_to_uint16(bin_header->nirep);
-}
-
-static int
-read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len)
-{
- int i, ret = MRB_DUMP_OK;
- char *buf;
- unsigned char *recordStart, *pStart;
- uint16_t crc, tt, pdl, snl, offset, bufsize=MRB_DUMP_DEFAULT_STR_LEN;
- mrb_int fix_num;
- mrb_float f;
- int plen;
+ int ret;
+ size_t i;
+ const uint8_t *src = bin;
+ uint16_t tt, pool_data_len, snl;
+ size_t plen;
int ai = mrb_gc_arena_save(mrb);
mrb_irep *irep = mrb_add_irep(mrb);
- recordStart = src;
- buf = (char *)mrb_malloc(mrb, bufsize);
- if (buf == NULL) {
- ret = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
+ // skip record size
+ src += sizeof(uint32_t);
+
+ // number of local variable
+ irep->nlocals = bin_to_uint16(src);
+ src += sizeof(uint16_t);
- //Header Section
- pStart = src;
- if (*src != RITE_IREP_IDENFIFIER)
- return MRB_DUMP_INVALID_IREP;
- src += (sizeof(unsigned char) * 2);
- irep->nlocals = bin_to_uint16(src); //number of local variable
- src += MRB_DUMP_SIZE_OF_SHORT;
- irep->nregs = bin_to_uint16(src); //number of register variable
- src += MRB_DUMP_SIZE_OF_SHORT;
- offset = bin_to_uint16(src); //offset of isec block
- src += MRB_DUMP_SIZE_OF_SHORT;
- crc = calc_crc_16_ccitt(pStart, src - pStart); //Calculate CRC
- if (crc != bin_to_uint16(src)) //header CRC
- return MRB_DUMP_INVALID_IREP;
- src += offset;
-
- //Binary Data Section
- //ISEQ BLOCK
- pStart = src;
- irep->ilen = bin_to_uint32(src); //iseq length
- src += MRB_DUMP_SIZE_OF_LONG;
+ // number of register variable
+ irep->nregs = bin_to_uint16(src);
+ src += sizeof(uint16_t);
+
+ // Binary Data Section
+ // ISEQ BLOCK
+ irep->ilen = bin_to_uint32(src);
+ src += sizeof(uint32_t);
if (irep->ilen > 0) {
irep->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen);
if (irep->iseq == NULL) {
ret = MRB_DUMP_GENERAL_FAILURE;
goto error_exit;
}
- for (i=0; i<irep->ilen; i++) {
+ for (i = 0; i < irep->ilen; i++) {
irep->iseq[i] = bin_to_uint32(src); //iseq
- src += MRB_DUMP_SIZE_OF_LONG;
+ src += sizeof(uint32_t);
}
}
- crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC
- if (crc != bin_to_uint16(src)) { //iseq CRC
- ret = MRB_DUMP_INVALID_IREP;
- goto error_exit;
- }
- src += MRB_DUMP_SIZE_OF_SHORT;
//POOL BLOCK
- pStart = src;
- plen = bin_to_uint32(src); //pool length
- src += MRB_DUMP_SIZE_OF_LONG;
+ plen = bin_to_uint32(src); /* number of pool */
+ src += sizeof(uint32_t);
if (plen > 0) {
irep->pool = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value) * plen);
if (irep->pool == NULL) {
@@ -417,37 +82,24 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len)
goto error_exit;
}
- for (i=0; i<plen; i++) {
- tt = *src; //pool TT
- src += sizeof(unsigned char);
- pdl = bin_to_uint16(src); //pool data length
- src += MRB_DUMP_SIZE_OF_SHORT;
- if (pdl > bufsize - 1) {
- mrb_free(mrb, buf);
- bufsize = pdl + 1;
- buf = (char *)mrb_malloc(mrb, bufsize);
- if (buf == NULL) {
- ret = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
- }
- memcpy(buf, src, pdl);
- src += pdl;
- buf[pdl] = '\0';
-
- switch (tt) { //pool data
+ for (i = 0; i < plen; i++) {
+ mrb_value s;
+ tt = *src++; //pool TT
+ pool_data_len = bin_to_uint16(src); //pool data length
+ src += sizeof(uint16_t);
+ s = mrb_str_new(mrb, (char *)src, pool_data_len);
+ src += pool_data_len;
+ switch (tt) { //pool data
case MRB_TT_FIXNUM:
- fix_num = str_to_mrb_int(buf);
- irep->pool[i] = mrb_fixnum_value(fix_num);
+ irep->pool[i] = mrb_str_to_inum(mrb, s, 10, FALSE);
break;
case MRB_TT_FLOAT:
- f = str_to_mrb_float(buf);
- irep->pool[i] = mrb_float_value(f);
+ irep->pool[i] = mrb_float_value(mrb_str_to_dbl(mrb, s, FALSE));
break;
case MRB_TT_STRING:
- irep->pool[i] = mrb_str_new(mrb, buf, pdl);
+ irep->pool[i] = s;
break;
default:
@@ -458,17 +110,10 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len)
mrb_gc_arena_restore(mrb, ai);
}
}
- crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC
- if (crc != bin_to_uint16(src)) { //pool CRC
- ret = MRB_DUMP_INVALID_IREP;
- goto error_exit;
- }
- src += MRB_DUMP_SIZE_OF_SHORT;
//SYMS BLOCK
- pStart = src;
- irep->slen = bin_to_uint32(src); //syms length
- src += MRB_DUMP_SIZE_OF_LONG;
+ irep->slen = bin_to_uint32(src); //syms length
+ src += sizeof(uint32_t);
if (irep->slen > 0) {
irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen);
if (irep->syms == NULL) {
@@ -477,83 +122,56 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len)
}
for (i = 0; i < irep->slen; i++) {
- static const mrb_sym mrb_sym_zero = { 0 };
- *irep->syms = mrb_sym_zero;
- }
- for (i=0; i<irep->slen; i++) {
snl = bin_to_uint16(src); //symbol name length
- src += MRB_DUMP_SIZE_OF_SHORT;
+ src += sizeof(uint16_t);
if (snl == MRB_DUMP_NULL_SYM_LEN) {
irep->syms[i] = 0;
continue;
}
- if (snl > bufsize - 1) {
- mrb_free(mrb, buf);
- bufsize = snl + 1;
- buf = (char *)mrb_malloc(mrb, bufsize);
- if (buf == NULL) {
- ret = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
- }
- memcpy(buf, src, snl); //symbol name
- src += snl;
- buf[snl] = '\0';
- irep->syms[i] = mrb_intern2(mrb, buf, snl);
+ irep->syms[i] = mrb_intern2(mrb, (char *)src, snl);
+ src += snl + 1;
+
+ mrb_gc_arena_restore(mrb, ai);
}
}
- crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC
- if (crc != bin_to_uint16(src)) { //syms CRC
- ret = MRB_DUMP_INVALID_IREP;
- goto error_exit;
- }
- src += MRB_DUMP_SIZE_OF_SHORT;
+ *len = src - bin;
- *len = src - recordStart;
+ ret = MRB_DUMP_OK;
error_exit:
- mrb_free(mrb, buf);
-
return ret;
}
-int
-mrb_read_irep(mrb_state *mrb, const char *bin)
+static int
+read_rite_section_irep(mrb_state *mrb, const uint8_t *bin)
{
- int ret = MRB_DUMP_OK, i, n, nirep, sirep;
- uint32_t len = 0;
- unsigned char *src;
- rite_binary_header bin_header;
+ int result;
+ size_t sirep;
+ size_t i;
+ uint32_t len;
+ uint16_t nirep;
+ uint16_t n;
+ const struct rite_section_irep_header *header;
- if ((mrb == NULL) || (bin == NULL)) {
- return MRB_DUMP_INVALID_ARGUMENT;
- }
- src = (unsigned char*)bin;
- sirep = mrb->irep_len;
+ header = (const struct rite_section_irep_header*)bin;
+ bin += sizeof(struct rite_section_irep_header);
- //Read File Header Section
- nirep = read_rite_header(mrb, src, &bin_header);
- if (nirep < 0)
- return nirep;
-
- src += sizeof(bin_header) + MRB_DUMP_SIZE_OF_SHORT; //header + crc
+ sirep = mrb->irep_len;
+ nirep = bin_to_uint16(header->nirep);
//Read Binary Data Section
- for (n=0,i=sirep; n<nirep; n++,i++) {
- src += MRB_DUMP_SIZE_OF_LONG; //record ren
- ret = read_rite_irep_record(mrb, src, &len);
- if (ret != MRB_DUMP_OK)
+ for (n = 0, i = sirep; n < nirep; n++, i++) {
+ result = read_rite_irep_record(mrb, bin, &len);
+ if (result != MRB_DUMP_OK)
goto error_exit;
- src += len;
- }
- if (0 != bin_to_uint32(src)) { //dummy record len
- ret = MRB_DUMP_GENERAL_FAILURE;
+ bin += len;
}
+ result = MRB_DUMP_OK;
error_exit:
- if (ret != MRB_DUMP_OK) {
- for (n=0,i=sirep; i<mrb->irep_len; n++,i++) {
+ if (result != MRB_DUMP_OK) {
+ for (i = sirep; i < mrb->irep_len; i++) {
if (mrb->irep[i]) {
if (mrb->irep[i]->iseq)
mrb_free(mrb, mrb->irep[i]->iseq);
@@ -567,143 +185,385 @@ error_exit:
mrb_free(mrb, mrb->irep[i]);
}
}
- // mrb->irep_len = sirep;
- return ret;
+ return result;
}
- return sirep + hex_to_uint8(bin_header.sirep);
+ return sirep + bin_to_uint16(header->sirep);
}
-static uint16_t
-hex_to_bin8(unsigned char *dst, unsigned char *src)
+static int
+read_rite_lineno_record(mrb_state *mrb, const uint8_t *bin, size_t irepno, uint32_t *len)
{
- dst[0] = (hex2bin[src[0]] << 4) | (hex2bin[src[1]]);
- return 1;
-}
+ int ret;
+ size_t i, fname_len, niseq;
+ char *fname;
+ uint16_t *lines;
+
+ ret = MRB_DUMP_OK;
+ *len = 0;
+ bin += sizeof(uint32_t); // record size
+ *len += sizeof(uint32_t);
+ fname_len = bin_to_uint16(bin);
+ bin += sizeof(uint16_t);
+ *len += sizeof(uint16_t);
+ fname = (char *)mrb_malloc(mrb, fname_len + 1);
+ if (fname == NULL) {
+ ret = MRB_DUMP_GENERAL_FAILURE;
+ goto error_exit;
+ }
+ memcpy(fname, bin, fname_len);
+ fname[fname_len] = '\0';
+ bin += fname_len;
+ *len += fname_len;
-static uint16_t
-hex_to_bin16(unsigned char *dst, unsigned char *src)
-{
- dst[0] = (hex2bin[src[0]] << 4) | (hex2bin[src[1]]);
- dst[1] = (hex2bin[src[2]] << 4) | (hex2bin[src[3]]);
- return 2;
-}
+ niseq = bin_to_uint32(bin);
+ bin += sizeof(uint32_t); // niseq
+ *len += sizeof(uint32_t);
-static uint16_t
-hex_to_bin32(unsigned char *dst, unsigned char *src)
-{
- dst[0] = (hex2bin[src[0]] << 4) | (hex2bin[src[1]]);
- dst[1] = (hex2bin[src[2]] << 4) | (hex2bin[src[3]]);
- dst[2] = (hex2bin[src[4]] << 4) | (hex2bin[src[5]]);
- dst[3] = (hex2bin[src[6]] << 4) | (hex2bin[src[7]]);
- return 4;
-}
+ lines = (uint16_t *)mrb_malloc(mrb, niseq * sizeof(uint16_t));
+ for (i = 0; i < niseq; i++) {
+ lines[i] = bin_to_uint16(bin);
+ bin += sizeof(uint16_t); // niseq
+ *len += sizeof(uint16_t);
+ }
-static uint8_t
-hex_to_uint8(unsigned char *hex)
-{
- return (unsigned char)hex2bin[hex[0]] << 4 |
- (unsigned char)hex2bin[hex[1]];
+ mrb->irep[irepno]->filename = fname;
+ mrb->irep[irepno]->lines = lines;
+
+error_exit:
+ return ret;
}
-static uint16_t
-hex_to_uint16(unsigned char *hex)
+static int
+read_rite_section_lineno(mrb_state *mrb, const uint8_t *bin, size_t sirep)
{
- return (uint16_t)hex2bin[hex[0]] << 12 |
- (uint16_t)hex2bin[hex[1]] << 8 |
- (uint16_t)hex2bin[hex[2]] << 4 |
- (uint16_t)hex2bin[hex[3]];
+ int result;
+ size_t i;
+ uint32_t len;
+ uint16_t nirep;
+ uint16_t n;
+ const struct rite_section_lineno_header *header;
+
+ len = 0;
+ header = (const struct rite_section_lineno_header*)bin;
+ bin += sizeof(struct rite_section_lineno_header);
+
+ nirep = bin_to_uint16(header->nirep);
+
+ //Read Binary Data Section
+ for (n = 0, i = sirep; n < nirep; n++, i++) {
+ result = read_rite_lineno_record(mrb, bin, i, &len);
+ if (result != MRB_DUMP_OK)
+ goto error_exit;
+ bin += len;
+ }
+
+ result = MRB_DUMP_OK;
+error_exit:
+ if (result != MRB_DUMP_OK) {
+ return result;
+ }
+ return sirep + bin_to_uint16(header->sirep);
}
-static uint32_t
-hex_to_uint32(unsigned char *hex)
+
+static int
+read_rite_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc)
{
- return (uint32_t)hex2bin[hex[0]] << 28 |
- (uint32_t)hex2bin[hex[1]] << 24 |
- (uint32_t)hex2bin[hex[2]] << 20 |
- (uint32_t)hex2bin[hex[3]] << 16 |
- (uint32_t)hex2bin[hex[4]] << 12 |
- (uint32_t)hex2bin[hex[5]] << 8 |
- (uint32_t)hex2bin[hex[6]] << 4 |
- (uint32_t)hex2bin[hex[7]];
+ const struct rite_binary_header *header = (const struct rite_binary_header *)bin;
+
+ if(memcmp(header->binary_identify, RITE_BINARY_IDENFIFIER, sizeof(header->binary_identify)) != 0) {
+ return MRB_DUMP_INVALID_FILE_HEADER;
+ }
+
+ if(memcmp(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)) != 0) {
+ return MRB_DUMP_INVALID_FILE_HEADER;
+ }
+
+ *crc = bin_to_uint16(header->binary_crc);
+ if (bin_size) {
+ *bin_size = bin_to_uint32(header->binary_size);
+ }
+
+ return MRB_DUMP_OK;
}
-static char*
-hex_to_str(char *hex, char *str, uint16_t *str_len)
+int32_t
+mrb_read_irep(mrb_state *mrb, const uint8_t *bin)
{
- char *src, *dst, buf[4];
- int escape = 0, base = 0;
- char *err_ptr;
-
- *str_len = 0;
- for (src = hex, dst = str; *src != '\0'; src++) {
- if (escape) {
- switch(*src) {
- case 'a': *dst++ = '\a'/* BEL */; break;
- case 'b': *dst++ = '\b'/* BS */; break;
- case 't': *dst++ = '\t'/* HT */; break;
- case 'n': *dst++ = '\n'/* LF */; break;
- case 'v': *dst++ = '\v'/* VT */; break;
- case 'f': *dst++ = '\f'/* FF */; break;
- case 'r': *dst++ = '\r'/* CR */; break;
- case '\"': /* fall through */
- case '\'': /* fall through */
- case '\?': /* fall through */
- case '\\': *dst++ = *src; break;
- default:
- if (*src >= '0' && *src <= '7') {
- base = 8;
- strncpy(buf, src, 3);
- } else if (*src == 'x' || *src == 'X') {
- base = 16;
- src++;
- strncpy(buf, src, 2);
- }
-
- *dst++ = (unsigned char) strtol(buf, &err_ptr, base) & 0xff;
- src += (err_ptr - buf - 1);
- break;
- }
- escape = 0;
- } else {
- if (*src == '\\') {
- escape = 1;
- } else {
- escape = 0;
- *dst++ = *src;
+ int result;
+ int32_t total_nirep = 0;
+ const struct rite_section_header *section_header;
+ uint16_t crc;
+ size_t bin_size = 0;
+ size_t n;
+ size_t sirep;
+
+ if ((mrb == NULL) || (bin == NULL)) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
+
+ result = read_rite_binary_header(bin, &bin_size, &crc);
+ if(result != MRB_DUMP_OK) {
+ return result;
+ }
+
+ n = offset_crc_body();
+ if(crc != calc_crc_16_ccitt(bin + n, bin_size - n, 0)) {
+ return MRB_DUMP_INVALID_FILE_HEADER;
+ }
+
+ bin += sizeof(struct rite_binary_header);
+ sirep = mrb->irep_len;
+
+ do {
+ section_header = (const struct rite_section_header *)bin;
+ if(memcmp(section_header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(section_header->section_identify)) == 0) {
+ result = read_rite_section_irep(mrb, bin);
+ if(result < MRB_DUMP_OK) {
+ return result;
}
+ total_nirep += result;
}
- if (!escape) {
- (*str_len)++;
+ else if(memcmp(section_header->section_identify, RITE_SECTION_LIENO_IDENTIFIER, sizeof(section_header->section_identify)) == 0) {
+ result = read_rite_section_lineno(mrb, bin, sirep);
+ if(result < MRB_DUMP_OK) {
+ return result;
+ }
}
- }
- return str;
+ bin += bin_to_uint32(section_header->section_size);
+ } while(memcmp(section_header->section_identify, RITE_BINARY_EOF, sizeof(section_header->section_identify)) != 0);
+
+ return total_nirep;
}
static void
irep_error(mrb_state *mrb, int n)
{
static const char msg[] = "irep load error";
- mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1));
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1));
}
-#ifdef ENABLE_STDIO
mrb_value
-mrb_load_irep_file(mrb_state *mrb, FILE* fp)
+mrb_load_irep(mrb_state *mrb, const uint8_t *bin)
{
- int n = mrb_read_irep_file(mrb, fp);
+ int32_t n;
+ n = mrb_read_irep(mrb, bin);
if (n < 0) {
irep_error(mrb, n);
return mrb_nil_value();
}
return mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
}
-#endif
+
+#ifdef ENABLE_STDIO
+
+static int32_t
+read_rite_section_lineno_file(mrb_state *mrb, FILE *fp, size_t sirep)
+{
+ int32_t result;
+ size_t i;
+ uint16_t nirep;
+ uint16_t n;
+ uint32_t len, buf_size;
+ uint8_t *buf = NULL;
+ const size_t record_header_size = 4;
+
+ struct rite_section_lineno_header header;
+ if (fread(&header, sizeof(struct rite_section_lineno_header), 1, fp) == 0) {
+ return MRB_DUMP_READ_FAULT;
+ }
+
+ nirep = bin_to_uint16(header.nirep);
+
+ buf_size = record_header_size;
+ buf = (uint8_t *)mrb_malloc(mrb, buf_size);
+
+ //Read Binary Data Section
+ for (n = 0, i = sirep; n < nirep; n++, i++) {
+ if (fread(buf, record_header_size, 1, fp) == 0) {
+ result = MRB_DUMP_READ_FAULT;
+ goto error_exit;
+ }
+ buf_size = bin_to_uint32(&buf[0]);
+ buf = (uint8_t *)mrb_realloc(mrb, buf, buf_size);
+
+ if (fread(&buf[record_header_size], buf_size - record_header_size, 1, fp) == 0) {
+ result = MRB_DUMP_READ_FAULT;
+ goto error_exit;
+ }
+ result = read_rite_lineno_record(mrb, buf, i, &len);
+ if (result != MRB_DUMP_OK)
+ goto error_exit;
+ }
+
+ result = MRB_DUMP_OK;
+error_exit:
+ mrb_free(mrb, buf);
+ if (result != MRB_DUMP_OK) {
+ for (i = sirep; i < mrb->irep_len; i++) {
+ if (mrb->irep[i]) {
+ if (mrb->irep[i]->iseq)
+ mrb_free(mrb, mrb->irep[i]->iseq);
+
+ if (mrb->irep[i]->pool)
+ mrb_free(mrb, mrb->irep[i]->pool);
+
+ if (mrb->irep[i]->syms)
+ mrb_free(mrb, mrb->irep[i]->syms);
+
+ mrb_free(mrb, mrb->irep[i]);
+ }
+ }
+ return result;
+ }
+ return sirep + bin_to_uint16(header.sirep);
+}
+
+static int32_t
+read_rite_section_irep_file(mrb_state *mrb, FILE *fp)
+{
+ int32_t result;
+ size_t sirep;
+ size_t i;
+ uint16_t nirep;
+ uint16_t n;
+ uint32_t len, buf_size;
+ uint8_t *buf = NULL;
+ const size_t record_header_size = 1 + 4;
+ struct rite_section_irep_header header;
+
+ if (fread(&header, sizeof(struct rite_section_irep_header), 1, fp) == 0) {
+ return MRB_DUMP_READ_FAULT;
+ }
+
+ sirep = mrb->irep_len;
+ nirep = bin_to_uint16(header.nirep);
+
+ buf_size = record_header_size;
+ buf = (uint8_t *)mrb_malloc(mrb, buf_size);
+
+ //Read Binary Data Section
+ for (n = 0, i = sirep; n < nirep; n++, i++) {
+ if (fread(buf, record_header_size, 1, fp) == 0) {
+ result = MRB_DUMP_READ_FAULT;
+ goto error_exit;
+ }
+ buf_size = bin_to_uint32(&buf[0]);
+ buf = (uint8_t *)mrb_realloc(mrb, buf, buf_size);
+ if (fread(&buf[record_header_size], buf_size - record_header_size, 1, fp) == 0) {
+ result = MRB_DUMP_READ_FAULT;
+ goto error_exit;
+ }
+ result = read_rite_irep_record(mrb, buf, &len);
+ if (result != MRB_DUMP_OK)
+ goto error_exit;
+ }
+
+ result = MRB_DUMP_OK;
+error_exit:
+ mrb_free(mrb, buf);
+ if (result != MRB_DUMP_OK) {
+ for (i = sirep; i < mrb->irep_len; i++) {
+ if (mrb->irep[i]) {
+ if (mrb->irep[i]->iseq)
+ mrb_free(mrb, mrb->irep[i]->iseq);
+
+ if (mrb->irep[i]->pool)
+ mrb_free(mrb, mrb->irep[i]->pool);
+
+ if (mrb->irep[i]->syms)
+ mrb_free(mrb, mrb->irep[i]->syms);
+
+ mrb_free(mrb, mrb->irep[i]);
+ }
+ }
+ return result;
+ }
+ return sirep + bin_to_uint16(header.sirep);
+}
+
+int32_t
+mrb_read_irep_file(mrb_state *mrb, FILE* fp)
+{
+ int result;
+ int32_t total_nirep = 0;
+ uint8_t *buf;
+ uint16_t crc, crcwk = 0;
+ uint32_t section_size = 0;
+ size_t nbytes;
+ size_t sirep;
+ struct rite_section_header section_header;
+ long fpos;
+ const size_t block_size = 1 << 14;
+ const size_t buf_size = sizeof(struct rite_binary_header);
+
+ if ((mrb == NULL) || (fp == NULL)) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
+
+ buf = mrb_malloc(mrb, buf_size);
+ if (fread(buf, buf_size, 1, fp) == 0) {
+ mrb_free(mrb, buf);
+ return MRB_DUMP_READ_FAULT;
+ }
+ result = read_rite_binary_header(buf, NULL, &crc);
+ mrb_free(mrb, buf);
+ if(result != MRB_DUMP_OK) {
+ return result;
+ }
+
+ /* verify CRC */
+ fpos = ftell(fp);
+ buf = mrb_malloc(mrb, block_size);
+ fseek(fp, offset_crc_body(), SEEK_SET);
+ while((nbytes = fread(buf, 1, block_size, fp)) > 0) {
+ crcwk = calc_crc_16_ccitt(buf, nbytes, crcwk);
+ }
+ mrb_free(mrb, buf);
+ if (nbytes == 0 && ferror(fp)) {
+ return MRB_DUMP_READ_FAULT;
+ }
+ if(crcwk != crc) {
+ return MRB_DUMP_INVALID_FILE_HEADER;
+ }
+ fseek(fp, fpos + section_size, SEEK_SET);
+ sirep = mrb->irep_len;
+
+ // read sections
+ do {
+ fpos = ftell(fp);
+ if (fread(&section_header, sizeof(struct rite_section_header), 1, fp) == 0) {
+ return MRB_DUMP_READ_FAULT;
+ }
+ section_size = bin_to_uint32(section_header.section_size);
+
+ if(memcmp(section_header.section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(section_header.section_identify)) == 0) {
+ fseek(fp, fpos, SEEK_SET);
+ result = read_rite_section_irep_file(mrb, fp);
+ if(result < MRB_DUMP_OK) {
+ return result;
+ }
+ total_nirep += result;
+ }
+ else if(memcmp(section_header.section_identify, RITE_SECTION_LIENO_IDENTIFIER, sizeof(section_header.section_identify)) == 0) {
+ fseek(fp, fpos, SEEK_SET);
+ result = read_rite_section_lineno_file(mrb, fp, sirep);
+ if(result < MRB_DUMP_OK) {
+ return result;
+ }
+ }
+
+ fseek(fp, fpos + section_size, SEEK_SET);
+ } while(memcmp(section_header.section_identify, RITE_BINARY_EOF, sizeof(section_header.section_identify)) != 0);
+
+ return total_nirep;
+}
mrb_value
-mrb_load_irep(mrb_state *mrb, const char *bin)
+mrb_load_irep_file(mrb_state *mrb, FILE* fp)
{
- int n = mrb_read_irep(mrb, bin);
+ int n = mrb_read_irep_file(mrb, fp);
if (n < 0) {
irep_error(mrb, n);
@@ -711,3 +571,4 @@ mrb_load_irep(mrb_state *mrb, const char *bin)
}
return mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
}
+#endif /* ENABLE_STDIO */
diff --git a/src/node.h b/src/node.h
index 284105023..df27c431f 100644
--- a/src/node.h
+++ b/src/node.h
@@ -4,6 +4,9 @@
** See Copyright Notice in mruby.h
*/
+#ifndef NODE_H
+#define NODE_H
+
enum node_type {
NODE_METHOD,
NODE_FBODY,
@@ -62,6 +65,8 @@ enum node_type {
NODE_SYM,
NODE_STR,
NODE_DSTR,
+ NODE_XSTR,
+ NODE_DXSTR,
NODE_REGX,
NODE_DREGX,
NODE_DREGX_ONCE,
@@ -102,5 +107,11 @@ enum node_type {
NODE_IFUNC,
NODE_DSYM,
NODE_ATTRASGN,
+ NODE_HEREDOC,
+ NODE_LITERAL_DELIM,
+ NODE_WORDS,
+ NODE_SYMBOLS,
NODE_LAST
};
+
+#endif /* NODE_H */
diff --git a/src/numeric.c b/src/numeric.c
index b5bff652d..4ada58a34 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -4,26 +4,22 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/numeric.h"
-#include "mruby/string.h"
-#include "mruby/array.h"
-
-#include <math.h>
-#include <stdio.h>
#include <assert.h>
-
-#if defined(__FreeBSD__) && __FreeBSD__ < 4
-#include <floatingpoint.h>
-#endif
-
-#ifdef HAVE_FLOAT_H
#include <float.h>
+#if defined(__FreeBSD__) && __FreeBSD__ < 4
+# include <floatingpoint.h>
#endif
-
#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
+# include <ieeefp.h>
#endif
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "mruby.h"
+#include "mruby/array.h"
+#include "mruby/numeric.h"
+#include "mruby/string.h"
#ifdef MRB_USE_FLOAT
#define floor(f) floorf(f)
@@ -166,6 +162,105 @@ num_abs(mrb_state *mrb, mrb_value num)
* representation.
*/
+mrb_value
+mrb_flo_to_str(mrb_state *mrb, mrb_value flo, int max_digit)
+{
+ mrb_value result;
+ mrb_float n;
+
+ if (max_digit > 40) {
+ mrb_raise(mrb, E_RANGE_ERROR, "Too large max_digit.");
+ }
+ else if (!mrb_float_p(flo)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "non float value");
+ }
+
+ n = mrb_float(flo);
+
+ if (isnan(n)) {
+ result = mrb_str_new(mrb, "NaN", 3);
+ }
+ else if (isinf(n)) {
+ if (n < 0) {
+ result = mrb_str_new(mrb, "-inf", 4);
+ }
+ else {
+ result = mrb_str_new(mrb, "inf", 3);
+ }
+ }
+ else {
+ int digit;
+ int m;
+ int exp;
+ int e = 0;
+ char s[48];
+ char *c = &s[0];
+
+ if (n < 0) {
+ n = -n;
+ *(c++) = '-';
+ }
+
+ exp = log10(n);
+
+ if ((exp < 0 ? -exp : exp) > max_digit) {
+ /* exponent representation */
+ e = 1;
+ m = exp;
+ if (m < 0) {
+ m -= 1;
+ }
+ n = n / pow(10.0, m);
+ m = 0;
+ }
+ else {
+ /* un-exponent (normal) representation */
+ m = exp;
+ if (m < 0) {
+ m = 0;
+ }
+ }
+
+ /* puts digits */
+ while (max_digit >= 0) {
+ mrb_float weight = pow(10.0, m);
+ digit = floor(n / weight + FLT_EPSILON);
+ *(c++) = '0' + digit;
+ n -= (digit * weight);
+ max_digit--;
+ if (m-- == 0) {
+ *(c++) = '.';
+ }
+ else if (m < -1 && n < FLT_EPSILON) {
+ break;
+ }
+ }
+
+ if (e) {
+ *(c++) = 'e';
+ if (exp > 0) {
+ *(c++) = '+';
+ } else {
+ *(c++) = '-';
+ exp = -exp;
+ }
+
+ if (exp >= 100) {
+ mrb_raise(mrb, E_RANGE_ERROR, "Too large expornent.");
+ }
+
+ *(c++) = '0' + exp / 10;
+ *(c++) = '0' + exp % 10;
+ }
+
+ *c = '\0';
+
+ result = mrb_str_new(mrb, &s[0], c - &s[0]);
+ }
+
+ return result;
+}
+
/* 15.2.9.3.16(x) */
/*
* call-seq:
@@ -180,27 +275,11 @@ num_abs(mrb_state *mrb, mrb_value num)
static mrb_value
flo_to_s(mrb_state *mrb, mrb_value flt)
{
- char buf[32];
- int n;
-
- mrb_float value = mrb_float(flt);
-
- if (isinf(value)) {
- static const char s[2][5] = { "-inf", "inf" };
- static const int n[] = { 4, 3 };
- int idx;
- idx = (value < 0) ? 0 : 1;
- return mrb_str_new(mrb, s[idx], n[idx]);
- } else if(isnan(value))
- return mrb_str_new(mrb, "NaN", 3);
-
#ifdef MRB_USE_FLOAT
- n = sprintf(buf, "%.7g", value);
+ return mrb_flo_to_str(mrb, flt, 7);
#else
- n = sprintf(buf, "%.14g", value);
+ return mrb_flo_to_str(mrb, flt, 14);
#endif
- assert(n >= 0);
- return mrb_str_new(mrb, buf, n);
}
/* 15.2.9.3.2 */
@@ -306,15 +385,17 @@ static mrb_value
num_eql(mrb_state *mrb, mrb_value x)
{
mrb_value y;
-
+ mrb_bool eql_p;
+
mrb_get_args(mrb, "o", &y);
- if (mrb_type(x) != mrb_type(y)) return mrb_false_value();
- if (mrb_equal(mrb, x, y)) {
- return mrb_true_value();
+ if (mrb_type(x) != mrb_type(y)) {
+ eql_p = 0;
}
else {
- return mrb_false_value();
+ eql_p = mrb_equal(mrb, x, y);
}
+
+ return mrb_bool_value(eql_p);
}
static mrb_value
@@ -356,7 +437,7 @@ flo_eq(mrb_state *mrb, mrb_value x)
return num_equal(mrb, x, y);
}
a = mrb_float(x);
- return (a == b)?mrb_true_value():mrb_false_value();
+ return mrb_bool_value(a == b);
}
/* 15.2.8.3.18 */
@@ -371,7 +452,8 @@ flo_hash(mrb_state *mrb, mrb_value num)
{
mrb_float d;
char *c;
- int i, hash;
+ size_t i;
+ int hash;
d = (mrb_float)mrb_fixnum(num);
/* normalize -0.0 to 0.0 */
@@ -437,10 +519,11 @@ static mrb_value
flo_finite_p(mrb_state *mrb, mrb_value num)
{
mrb_float value = mrb_float(num);
+ mrb_bool finite_p;
- if (isinf(value) || isnan(value))
- return mrb_false_value();
- return mrb_true_value();
+ finite_p = !(isinf(value) || isnan(value));
+
+ return mrb_bool_value(finite_p);
}
/* 15.2.9.3.10 */
@@ -568,7 +651,6 @@ flo_round(mrb_state *mrb, mrb_value num)
/*
* call-seq:
* flt.to_i -> integer
- * flt.to_int -> integer
* flt.truncate -> integer
*
* Returns <i>flt</i> truncated to an <code>Integer</code>.
@@ -639,7 +721,6 @@ num_round(mrb_state *mrb, mrb_value num)
/*
* call-seq:
* int.to_i -> integer
- * int.to_int -> integer
* int.floor -> integer
* int.ceil -> integer
* int.round -> integer
@@ -699,7 +780,7 @@ mrb_value
mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
{
mrb_int a;
-
+
a = mrb_fixnum(x);
if (a == 0) return x;
if (mrb_fixnum_p(y)) {
@@ -817,7 +898,7 @@ fix_divmod(mrb_state *mrb, mrb_value x)
if (mrb_fixnum(y) == 0) {
return mrb_assoc_new(mrb, mrb_float_value(str_to_mrb_float("inf")),
- mrb_float_value(str_to_mrb_float("nan")));
+ mrb_float_value(str_to_mrb_float("nan")));
}
fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod);
return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod));
@@ -849,19 +930,15 @@ static mrb_value
fix_equal(mrb_state *mrb, mrb_value x)
{
mrb_value y;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &y);
- if (mrb_obj_equal(mrb, x, y)) return mrb_true_value();
- switch (mrb_type(y)) {
- case MRB_TT_FLOAT:
- if ((mrb_float)mrb_fixnum(x) == mrb_float(y))
- return mrb_true_value();
- /* fall through */
- case MRB_TT_FIXNUM:
- default:
- return mrb_false_value();
- }
+ equal_p = mrb_obj_equal(mrb, x, y) ||
+ (mrb_type(y) == MRB_TT_FLOAT &&
+ (mrb_float)mrb_fixnum(x) == mrb_float(y));
+
+ return mrb_bool_value(equal_p);
}
/* 15.2.8.3.8 */
@@ -959,14 +1036,15 @@ fix_xor(mrb_state *mrb, mrb_value x)
return mrb_fixnum_value(val);
}
-#define NUMERIC_SHIFT_WIDTH_MAX (sizeof(mrb_int)*CHAR_BIT-1)
+#define NUMERIC_SHIFT_WIDTH_MAX (sizeof(mrb_int)*CHAR_BIT-1)
static mrb_value
lshift(mrb_state *mrb, mrb_int val, int width)
{
if (width > NUMERIC_SHIFT_WIDTH_MAX) {
- mrb_raisef(mrb, E_RANGE_ERROR, "width(%d) > (%d:sizeof(mrb_int)*CHAR_BIT-1)", width,
- NUMERIC_SHIFT_WIDTH_MAX);
+ mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:sizeof(mrb_int)*CHAR_BIT-1)",
+ mrb_fixnum_value(width),
+ mrb_fixnum_value(NUMERIC_SHIFT_WIDTH_MAX));
}
val = val << width;
return mrb_fixnum_value(val);
@@ -1101,32 +1179,34 @@ fix_to_f(mrb_state *mrb, mrb_value num)
* FloatDomainError: Infinity
*/
/* ------------------------------------------------------------------------*/
-static mrb_int
-flt2big(mrb_state *mrb, mrb_float d)
+mrb_value
+mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x)
{
mrb_int z;
- if (isinf(d)) {
- mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity");
- }
- if (isnan(d)) {
- mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
+ if (mrb_float_p(x)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "non float value");
+ z = 0; /* not reached. just supress warnings. */
}
- z = (mrb_int)d;
- return z;
-}
+ else {
+ mrb_float d = mrb_float(x);
-mrb_value
-mrb_flt2big(mrb_state *mrb, mrb_float d)
-{
- return mrb_fixnum_value(flt2big(mrb, d));
+ if (isinf(d)) {
+ mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity");
+ }
+ if (isnan(d)) {
+ mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
+ }
+ z = (mrb_int)d;
+ }
+ return mrb_fixnum_value(z);
}
mrb_value
mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
{
mrb_int a;
-
+
a = mrb_fixnum(x);
if (a == 0) return y;
if (mrb_fixnum_p(y)) {
@@ -1165,7 +1245,7 @@ mrb_value
mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
{
mrb_int a;
-
+
a = mrb_fixnum(x);
if (mrb_fixnum_p(y)) {
mrb_int b, c;
@@ -1202,14 +1282,14 @@ fix_minus(mrb_state *mrb, mrb_value self)
mrb_value
-mrb_fix2str(mrb_state *mrb, mrb_value x, int base)
+mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base)
{
char buf[sizeof(mrb_int)*CHAR_BIT+1];
char *b = buf + sizeof buf;
mrb_int val = mrb_fixnum(x);
if (base < 2 || 36 < base) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %d", base);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base));
}
if (val == 0) {
@@ -1250,7 +1330,7 @@ fix_to_s(mrb_state *mrb, mrb_value self)
mrb_int base = 10;
mrb_get_args(mrb, "|i", &base);
- return mrb_fix2str(mrb, self, base);
+ return mrb_fixnum_to_str(mrb, self, base);
}
/* 15.2.9.3.6 */
@@ -1330,6 +1410,8 @@ mrb_init_numeric(mrb_state *mrb)
/* Integer Class */
integer = mrb_define_class(mrb, "Integer", numeric);
+ mrb_undef_class_method(mrb, integer, "new");
+ mrb_define_method(mrb, integer, "to_i", int_to_i, ARGS_NONE()); /* 15.2.8.3.24 */
fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer);
mrb_undef_class_method(mrb, fixnum, "new");
@@ -1353,7 +1435,6 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, fixnum, "round", num_round, ARGS_ANY()); /* 15.2.8.3.20 */
mrb_define_method(mrb, fixnum, "succ", fix_succ, ARGS_NONE()); /* 15.2.8.3.21 */
mrb_define_method(mrb, fixnum, "to_f", fix_to_f, ARGS_NONE()); /* 15.2.8.3.23 */
- mrb_define_method(mrb, fixnum, "to_i", int_to_i, ARGS_NONE()); /* 15.2.8.3.24 */
mrb_define_method(mrb, fixnum, "to_s", fix_to_s, ARGS_NONE()); /* 15.2.8.3.25 */
mrb_define_method(mrb, fixnum, "inspect", fix_to_s, ARGS_NONE());
mrb_define_method(mrb, fixnum, "truncate", int_to_i, ARGS_NONE()); /* 15.2.8.3.26 */
diff --git a/src/object.c b/src/object.c
index 6707fc6e4..bc59b615e 100644
--- a/src/object.c
+++ b/src/object.c
@@ -5,11 +5,9 @@
*/
#include "mruby.h"
-#include <string.h>
-#include "mruby/string.h"
-#include <stdio.h>
#include "mruby/class.h"
#include "mruby/numeric.h"
+#include "mruby/string.h"
#include "error.h"
int
@@ -116,7 +114,8 @@ true_and(mrb_state *mrb, mrb_value obj)
int obj2;
mrb_get_args(mrb, "b", &obj2);
- return obj2 ? mrb_true_value() : mrb_false_value();
+
+ return mrb_bool_value(obj2);
}
/* 15.2.5.3.2 */
@@ -135,7 +134,7 @@ true_xor(mrb_state *mrb, mrb_value obj)
int obj2;
mrb_get_args(mrb, "b", &obj2);
- return obj2 ? mrb_false_value() : mrb_true_value();
+ return mrb_bool_value(!obj2);
}
/* 15.2.5.3.3 */
@@ -228,7 +227,7 @@ false_xor(mrb_state *mrb, mrb_value obj)
int obj2;
mrb_get_args(mrb, "b", &obj2);
- return obj2 ? mrb_true_value() : mrb_false_value();
+ return mrb_bool_value(obj2);
}
/* 15.2.4.3.3 */
@@ -248,7 +247,7 @@ false_or(mrb_state *mrb, mrb_value obj)
int obj2;
mrb_get_args(mrb, "b", &obj2);
- return obj2 ? mrb_true_value() : mrb_false_value();
+ return mrb_bool_value(obj2);
}
/* 15.2.6.3.3 */
@@ -306,12 +305,7 @@ convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *metho
m = mrb_intern(mrb, method);
if (!mrb_respond_to(mrb, val, m)) {
if (raise) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %s into %s",
- mrb_nil_p(val) ? "nil" :
- (mrb_type(val) == MRB_TT_TRUE) ? "true" :
- (mrb_type(val) == MRB_TT_FALSE) ? "false" :
- mrb_obj_classname(mrb, val),
- tname);
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", val, mrb_str_new_cstr(mrb, tname));
return mrb_nil_value();
}
else {
@@ -342,8 +336,8 @@ mrb_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char *tname,
if (mrb_type(val) == type) return val;
v = convert_type(mrb, val, tname, method, 1/*Qtrue*/);
if (mrb_type(v) != type) {
- mrb_raisef(mrb, E_TYPE_ERROR, "%s cannot be converted to %s by #%s",
- mrb_obj_classname(mrb, val), tname, method);
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to %S by #%S", val,
+ mrb_str_new_cstr(mrb, tname), mrb_str_new_cstr(mrb, method));
}
return v;
}
@@ -417,12 +411,13 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t)
else {
etype = mrb_obj_classname(mrb, x);
}
- mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s)",
- etype, type->name);
+ mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)",
+ mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->name));
}
type++;
}
- mrb_raisef(mrb, E_TYPE_ERROR, "unknown type 0x%x (0x%x given)", t, mrb_type(x));
+ mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %S (%S given)",
+ mrb_fixnum_value(t), mrb_fixnum_value(mrb_type(x)));
}
}
@@ -440,8 +435,15 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t)
mrb_value
mrb_any_to_s(mrb_state *mrb, mrb_value obj)
{
+ mrb_value str = mrb_str_buf_new(mrb, 20);
const char *cname = mrb_obj_classname(mrb, obj);
- return mrb_sprintf(mrb, "#<%s:%p>", cname, mrb_voidp(obj));
+
+ mrb_str_buf_cat(mrb, str, "#<", 2);
+ mrb_str_cat2(mrb, str, cname);
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_voidp(obj)));
+ mrb_str_buf_cat(mrb, str, ">", 1);
+
+ return str;
}
/*
@@ -501,9 +503,8 @@ mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method)
if (mrb_fixnum_p(val)) return val;
v = convert_type(mrb, val, "Integer", method, TRUE);
if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) {
- const char *cname = mrb_obj_classname(mrb, val);
- mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %s to Integer (%s#%s gives %s)",
- cname, cname, method, mrb_obj_classname(mrb, v));
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)",
+ val, val, mrb_str_new_cstr(mrb, method), v);
}
return v;
}
@@ -529,7 +530,7 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base)
if (FIXABLE(mrb_float(val))) {
break;
}
- return mrb_flt2big(mrb, mrb_float(val));
+ return mrb_flo_to_fixnum(mrb, val);
case MRB_TT_FIXNUM:
if (base != 0) goto arg_error;
diff --git a/src/opcode.h b/src/opcode.h
index d77e2451f..b4f843116 100644
--- a/src/opcode.h
+++ b/src/opcode.h
@@ -7,12 +7,15 @@
#ifndef OPCODE_H
#define OPCODE_H
-#define MAXARG_Bx ((1<<16)-1)
+#define MAXARG_Bx (0xffff)
#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
-/* instructions OP:A:B:C = 7:9:9:7 (32 bits) */
-/* OP:A:Bx = 7:9:16 */
-/* OP:Ax = 7:25 */
+/* instructions: packed 32 bit */
+/* ------------------------------- */
+/* A:B:C:OP = 9: 9: 7: 7 */
+/* A:Bx:OP = 9:16: 7 */
+/* Ax:OP = 25: 7 */
+/* A:Bz:Cz:OP = 9:14: 2: 7 */
#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f))
#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff))
@@ -20,19 +23,19 @@
#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f))
#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff))
#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx))
-#define GETARG_Ax(i) ((int)((((mrb_code)(i)) >> 7) & 0x1ffffff))
-#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+n2)) & (((1<<n1)-1))))
-#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<n2)-1))))
+#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff))
+#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1))))
+#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1))))
#define GETARG_b(i) GETARG_UNPACK_b(i,14,2)
#define GETARG_c(i) GETARG_UNPACK_c(i,14,2)
#define MKOPCODE(op) ((op) & 0x7f)
-#define MKARG_A(c) (((c) & 0x1ff) << 23)
-#define MKARG_B(c) (((c) & 0x1ff) << 14)
+#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23)
+#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14)
#define MKARG_C(c) (((c) & 0x7f) << 7)
-#define MKARG_Bx(v) (((v) & 0xffff) << 7)
+#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7)
#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx)
-#define MKARG_Ax(v) (((v) & 0x1ffffff) << 7)
+#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7)
#define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7))
#define MKARG_bc(b,c) MKARG_PACK(b,14,c,2)
diff --git a/src/parse.y b/src/parse.y
index 7bca4a4d6..1c0170ac9 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -17,20 +17,20 @@
#define YYFREE(o) mrb_free(p->mrb, (o))
#define YYSTACK_USE_ALLOCA 0
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
#include "mruby.h"
#include "mruby/compile.h"
#include "mruby/proc.h"
#include "node.h"
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-#include <string.h>
-
#define YYLEX_PARAM p
typedef mrb_ast_node node;
typedef struct mrb_parser_state parser_state;
+typedef struct mrb_parser_heredoc_info parser_heredoc_info;
static int yylex(void *lval, parser_state *p);
static void yyerror(parser_state *p, const char *s);
@@ -60,13 +60,27 @@ typedef unsigned int stack_type;
#define sym(x) ((mrb_sym)(intptr_t)(x))
#define nsym(x) ((node*)(intptr_t)(x))
-static mrb_sym
+static inline mrb_sym
intern_gen(parser_state *p, const char *s)
{
return mrb_intern(p->mrb, s);
}
#define intern(s) intern_gen(p,(s))
+static inline mrb_sym
+intern_gen2(parser_state *p, const char *s, size_t len)
+{
+ return mrb_intern2(p->mrb, s, len);
+}
+#define intern2(s,len) intern_gen2(p,(s),(len))
+
+static inline mrb_sym
+intern_gen_c(parser_state *p, const char c)
+{
+ return mrb_intern2(p->mrb, &c, 1);
+}
+#define intern_c(c) intern_gen_c(p,(c))
+
static void
cons_free_gen(parser_state *p, node *cons)
{
@@ -380,15 +394,6 @@ new_fcall(parser_state *p, mrb_sym b, node *c)
return list4((node*)NODE_FCALL, new_self(p), nsym(b), c);
}
-#if 0
-// (:vcall self mid)
-static node*
-new_vcall(parser_state *p, mrb_sym b)
-{
- return list3((node*)NODE_VCALL, new_self(p), (node*)b);
-}
-#endif
-
// (:super . c)
static node*
new_super(parser_state *p, node *c)
@@ -701,6 +706,20 @@ new_dstr(parser_state *p, node *a)
return cons((node*)NODE_DSTR, a);
}
+// (:str . (s . len))
+static node*
+new_xstr(parser_state *p, const char *s, int len)
+{
+ return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), (node*)(intptr_t)len));
+}
+
+// (:xstr . a)
+static node*
+new_dxstr(parser_state *p, node *a)
+{
+ return cons((node*)NODE_DXSTR, a);
+}
+
// (:dsym . a)
static node*
new_dsym(parser_state *p, node *a)
@@ -736,11 +755,39 @@ new_nth_ref(parser_state *p, int n)
return cons((node*)NODE_NTH_REF, (node*)(intptr_t)n);
}
+// (:heredoc . a)
+static node*
+new_heredoc(parser_state *p)
+{
+ parser_heredoc_info *inf = parser_palloc(p, sizeof(parser_heredoc_info));
+ return cons((node*)NODE_HEREDOC, (node*)inf);
+}
+
static void
new_bv(parser_state *p, mrb_sym id)
{
}
+static node*
+new_literal_delim(parser_state *p)
+{
+ return cons((node*)NODE_LITERAL_DELIM, 0);
+}
+
+// (:words . a)
+static node*
+new_words(parser_state *p, node *a)
+{
+ return cons((node*)NODE_WORDS, a);
+}
+
+// (:symbols . a)
+static node*
+new_symbols(parser_state *p, node *a)
+{
+ return cons((node*)NODE_SYMBOLS, a);
+}
+
// xxx -----------------------------
// (:call a op)
@@ -757,15 +804,6 @@ call_bin_op(parser_state *p, node *recv, char *m, node *arg1)
return new_call(p, recv, intern(m), list1(list1(arg1)));
}
-/*
-// (:match (a . b))
-static node*
-match_op(parser_state *p, node *a, node *b)
-{
- return cons((node*)NODE_MATCH, cons((node*)a, (node*)b));
-}
-*/
-
static void
args_with_block(parser_state *p, node *a, node *b)
{
@@ -844,6 +882,49 @@ var_reference(parser_state *p, node *lhs)
return lhs;
}
+typedef enum mrb_string_type string_type;
+
+static node*
+new_strterm(parser_state *p, string_type type, int term, int paren)
+{
+ return cons((node*)(intptr_t)type, cons((node*)0, cons((node*)(intptr_t)paren, (node*)(intptr_t)term)));
+}
+
+static void
+end_strterm(parser_state *p)
+{
+ cons_free(p->lex_strterm->cdr->cdr);
+ cons_free(p->lex_strterm->cdr);
+ cons_free(p->lex_strterm);
+ p->lex_strterm = NULL;
+}
+
+parser_heredoc_info *
+parsing_heredoc_inf(parser_state *p)
+{
+ node *nd = p->parsing_heredoc;
+ if (nd == NULL)
+ return NULL;
+ /* assert(nd->car->car == NODE_HEREDOC); */
+ return (parser_heredoc_info*)nd->car->cdr;
+}
+
+static void
+heredoc_end(parser_state *p)
+{
+ p->parsing_heredoc = p->parsing_heredoc->cdr;
+ if (p->parsing_heredoc == NULL) {
+ p->lstate = EXPR_BEG;
+ p->cmd_start = TRUE;
+ end_strterm(p);
+ p->heredoc_end_now = TRUE;
+ } else {
+ /* next heredoc */
+ p->lex_strterm->car = (node*)(intptr_t)parsing_heredoc_inf(p)->type;
+ }
+}
+#define is_strterm_type(p,str_func) ((int)(intptr_t)((p)->lex_strterm->car) & (str_func))
+
// xxx -----------------------------
%}
@@ -910,13 +991,13 @@ var_reference(parser_state *p, node *lhs)
keyword__FILE__
keyword__ENCODING__
-%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
-%token <nd> tINTEGER tFLOAT tCHAR tREGEXP
-%token <nd> tSTRING tSTRING_PART
-%token <nd> tNTH_REF tBACK_REF
-%token <num> tREGEXP_END
+%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
+%token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP
+%token <nd> tSTRING tSTRING_PART tSTRING_MID
+%token <nd> tNTH_REF tBACK_REF
+%token <num> tREGEXP_END
-%type <nd> singleton string string_interp regexp
+%type <nd> singleton string string_rep string_interp xstring regexp
%type <nd> literal numeric cpath symbol
%type <nd> top_compstmt top_stmts top_stmt
%type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
@@ -935,36 +1016,39 @@ var_reference(parser_state *p, node *lhs)
%type <nd> mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner
%type <id> fsym sym basic_symbol operation operation2 operation3
%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg
-
-%token tUPLUS /* unary+ */
-%token tUMINUS /* unary- */
-%token tPOW /* ** */
-%token tCMP /* <=> */
-%token tEQ /* == */
-%token tEQQ /* === */
-%token tNEQ /* != */
-%token tGEQ /* >= */
-%token tLEQ /* <= */
-%token tANDOP tOROP /* && and || */
-%token tMATCH tNMATCH /* =~ and !~ */
-%token tDOT2 tDOT3 /* .. and ... */
-%token tAREF tASET /* [] and []= */
-%token tLSHFT tRSHFT /* << and >> */
-%token tCOLON2 /* :: */
-%token tCOLON3 /* :: at EXPR_BEG */
-%token <id> tOP_ASGN /* +=, -= etc. */
-%token tASSOC /* => */
-%token tLPAREN /* ( */
-%token tLPAREN_ARG /* ( */
-%token tRPAREN /* ) */
-%token tLBRACK /* [ */
-%token tLBRACE /* { */
-%token tLBRACE_ARG /* { */
-%token tSTAR /* * */
-%token tAMPER /* & */
-%token tLAMBDA /* -> */
-%token tSYMBEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
-%token tSTRING_BEG tSTRING_DVAR tLAMBEG
+%type <nd> heredoc words symbols
+
+%token tUPLUS /* unary+ */
+%token tUMINUS /* unary- */
+%token tPOW /* ** */
+%token tCMP /* <=> */
+%token tEQ /* == */
+%token tEQQ /* === */
+%token tNEQ /* != */
+%token tGEQ /* >= */
+%token tLEQ /* <= */
+%token tANDOP tOROP /* && and || */
+%token tMATCH tNMATCH /* =~ and !~ */
+%token tDOT2 tDOT3 /* .. and ... */
+%token tAREF tASET /* [] and []= */
+%token tLSHFT tRSHFT /* << and >> */
+%token tCOLON2 /* :: */
+%token tCOLON3 /* :: at EXPR_BEG */
+%token <id> tOP_ASGN /* +=, -= etc. */
+%token tASSOC /* => */
+%token tLPAREN /* ( */
+%token tLPAREN_ARG /* ( */
+%token tRPAREN /* ) */
+%token tLBRACK /* [ */
+%token tLBRACE /* { */
+%token tLBRACE_ARG /* { */
+%token tSTAR /* * */
+%token tAMPER /* & */
+%token tLAMBDA /* -> */
+%token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG
+%token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG
+%token <nd> tHEREDOC_BEG /* <<, <<- */
+%token tHEREDOC_END tLITERAL_DELIM
/*
* precedence table
@@ -1024,7 +1108,7 @@ top_compstmt : top_stmts opt_terms
;
top_stmts : none
- {
+ {
$$ = new_begin(p, 0);
}
| top_stmt
@@ -1087,7 +1171,7 @@ compstmt : stmts opt_terms
;
stmts : none
- {
+ {
$$ = new_begin(p, 0);
}
| stmt
@@ -1148,7 +1232,7 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym
}
| primary_value '[' opt_call_args rbracket tOP_ASGN command_call
{
- $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6);
+ $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6);
}
| primary_value '.' tIDENTIFIER tOP_ASGN command_call
{
@@ -1387,7 +1471,7 @@ mlhs_node : variable
}
| primary_value '[' opt_call_args rbracket
{
- $$ = new_call(p, $1, intern("[]"), $3);
+ $$ = new_call(p, $1, intern2("[]",2), $3);
}
| primary_value '.' tIDENTIFIER
{
@@ -1426,7 +1510,7 @@ lhs : variable
}
| primary_value '[' opt_call_args rbracket
{
- $$ = new_call(p, $1, intern("[]"), $3);
+ $$ = new_call(p, $1, intern2("[]",2), $3);
}
| primary_value '.' tIDENTIFIER
{
@@ -1509,34 +1593,35 @@ undef_list : fsym
}
;
-op : '|' { $$ = intern("|"); }
- | '^' { $$ = intern("^"); }
- | '&' { $$ = intern("&"); }
- | tCMP { $$ = intern("<=>"); }
- | tEQ { $$ = intern("=="); }
- | tEQQ { $$ = intern("==="); }
- | tMATCH { $$ = intern("=~"); }
- | tNMATCH { $$ = intern("!~"); }
- | '>' { $$ = intern(">"); }
- | tGEQ { $$ = intern(">="); }
- | '<' { $$ = intern("<"); }
- | tLEQ { $$ = intern("<="); }
- | tNEQ { $$ = intern("!="); }
- | tLSHFT { $$ = intern("<<"); }
- | tRSHFT { $$ = intern(">>"); }
- | '+' { $$ = intern("+"); }
- | '-' { $$ = intern("-"); }
- | '*' { $$ = intern("*"); }
- | tSTAR { $$ = intern("*"); }
- | '/' { $$ = intern("/"); }
- | '%' { $$ = intern("%"); }
- | tPOW { $$ = intern("**"); }
- | '!' { $$ = intern("!"); }
- | '~' { $$ = intern("~"); }
- | tUPLUS { $$ = intern("+@"); }
- | tUMINUS { $$ = intern("-@"); }
- | tAREF { $$ = intern("[]"); }
- | tASET { $$ = intern("[]="); }
+op : '|' { $$ = intern_c('|'); }
+ | '^' { $$ = intern_c('^'); }
+ | '&' { $$ = intern_c('&'); }
+ | tCMP { $$ = intern2("<=>",3); }
+ | tEQ { $$ = intern2("==",2); }
+ | tEQQ { $$ = intern2("===",3); }
+ | tMATCH { $$ = intern2("=~",2); }
+ | tNMATCH { $$ = intern2("!~",2); }
+ | '>' { $$ = intern_c('>'); }
+ | tGEQ { $$ = intern2(">=",2); }
+ | '<' { $$ = intern_c('<'); }
+ | tLEQ { $$ = intern2("<=",2); }
+ | tNEQ { $$ = intern2("!=",2); }
+ | tLSHFT { $$ = intern2("<<",2); }
+ | tRSHFT { $$ = intern2(">>",2); }
+ | '+' { $$ = intern_c('+'); }
+ | '-' { $$ = intern_c('-'); }
+ | '*' { $$ = intern_c('*'); }
+ | tSTAR { $$ = intern_c('*'); }
+ | '/' { $$ = intern_c('/'); }
+ | '%' { $$ = intern_c('%'); }
+ | tPOW { $$ = intern2("**",2); }
+ | '!' { $$ = intern_c('!'); }
+ | '~' { $$ = intern_c('~'); }
+ | tUPLUS { $$ = intern2("+@",2); }
+ | tUMINUS { $$ = intern2("-@",2); }
+ | tAREF { $$ = intern2("[]",2); }
+ | tASET { $$ = intern2("[]=",3); }
+ | '`' { $$ = intern_c('`'); }
;
reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
@@ -1571,7 +1656,7 @@ arg : lhs '=' arg
}
| primary_value '[' opt_call_args rbracket tOP_ASGN arg
{
- $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6);
+ $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6);
}
| primary_value '.' tIDENTIFIER tOP_ASGN arg
{
@@ -1695,11 +1780,6 @@ arg : lhs '=' arg
| arg tMATCH arg
{
$$ = call_bin_op(p, $1, "=~", $3);
-#if 0
- if (nd_type($1) == NODE_LIT && TYPE($1->nd_lit) == T_REGEXP) {
- $$ = reg_named_capture_assign($1->nd_lit, $$);
- }
-#endif
}
| arg tNMATCH arg
{
@@ -1870,7 +1950,9 @@ mrhs : args ',' arg_value
primary : literal
| string
+ | xstring
| regexp
+ | heredoc
| var_ref
| backref
| tFID
@@ -2208,7 +2290,7 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
{
$$ = new_args(p, $1, $3, 0, $5, $6);
}
- | f_arg ',' f_rest_arg opt_f_block_arg
+ | f_arg ',' f_rest_arg opt_f_block_arg
{
$$ = new_args(p, $1, 0, $3, 0, $4);
}
@@ -2340,7 +2422,7 @@ block_call : command do_block
yyerror(p, "block given to yield");
}
else {
- call_with_block(p, $1, $2);
+ call_with_block(p, $1, $2);
}
$$ = $1;
}
@@ -2378,11 +2460,11 @@ method_call : operation paren_args
}
| primary_value '.' paren_args
{
- $$ = new_call(p, $1, intern("call"), $3);
+ $$ = new_call(p, $1, intern2("call",4), $3);
}
| primary_value tCOLON2 paren_args
{
- $$ = new_call(p, $1, intern("call"), $3);
+ $$ = new_call(p, $1, intern2("call",4), $3);
}
| keyword_super paren_args
{
@@ -2394,7 +2476,7 @@ method_call : operation paren_args
}
| primary_value '[' opt_call_args rbracket
{
- $$ = new_call(p, $1, intern("[]"), $3);
+ $$ = new_call(p, $1, intern2("[]",2), $3);
}
;
@@ -2474,6 +2556,8 @@ opt_ensure : keyword_ensure compstmt
literal : numeric
| symbol
+ | words
+ | symbols
;
string : tCHAR
@@ -2482,34 +2566,47 @@ string : tCHAR
{
$$ = $2;
}
- | tSTRING_BEG string_interp tSTRING
+ | tSTRING_BEG string_rep tSTRING
{
$$ = new_dstr(p, push($2, $3));
}
;
-string_interp : tSTRING_PART
+string_rep : string_interp
+ | string_rep string_interp
+ {
+ $$ = append($1, $2);
+ }
+ ;
+
+string_interp : tSTRING_MID
+ {
+ $$ = list1($1);
+ }
+ | tSTRING_PART
{
- $<num>$ = p->sterm;
- p->sterm = 0;
+ $<nd>$ = p->lex_strterm;
+ p->lex_strterm = NULL;
}
compstmt
'}'
{
- p->sterm = $<num>2;
+ p->lex_strterm = $<nd>2;
$$ = list2($1, $3);
}
- | string_interp
- tSTRING_PART
+ | tLITERAL_DELIM
{
- $<num>$ = p->sterm;
- p->sterm = 0;
+ $$ = list1(new_literal_delim(p));
}
- compstmt
- '}'
+ ;
+
+xstring : tXSTRING_BEG tXSTRING
{
- p->sterm = $<num>3;
- $$ = push(push($1, $2), $4);
+ $$ = $2;
+ }
+ | tXSTRING_BEG string_rep tXSTRING
+ {
+ $$ = new_dxstr(p, push($2, $3));
}
;
@@ -2517,12 +2614,46 @@ regexp : tREGEXP_BEG tREGEXP
{
$$ = $2;
}
- | tREGEXP_BEG string_interp tREGEXP
+ | tREGEXP_BEG string_rep tREGEXP
{
$$ = new_dregx(p, $2, $3);
}
;
+heredoc : tHEREDOC_BEG
+ ;
+
+opt_heredoc_bodies : none
+ | heredoc_bodies
+ ;
+
+heredoc_bodies : heredoc_body
+ | heredoc_bodies heredoc_body
+ ;
+
+heredoc_body : tHEREDOC_END
+ {
+ parsing_heredoc_inf(p)->doc = list1(new_str(p, "", 0));
+ heredoc_end(p);
+ }
+ | string_rep tHEREDOC_END
+ {
+ parsing_heredoc_inf(p)->doc = $1;
+ heredoc_end(p);
+ }
+ ;
+
+words : tWORDS_BEG tSTRING
+ {
+ $$ = new_words(p, list1($2));
+ }
+ | tWORDS_BEG string_rep tSTRING
+ {
+ $$ = new_words(p, push($2, $3));
+ }
+ ;
+
+
symbol : basic_symbol
{
$$ = new_sym(p, $1);
@@ -2555,6 +2686,16 @@ sym : fname
}
;
+symbols : tSYMBOLS_BEG tSTRING
+ {
+ $$ = new_symbols(p, list1($2));
+ }
+ | tSYMBOLS_BEG string_rep tSTRING
+ {
+ $$ = new_symbols(p, push($2, $3));
+ }
+ ;
+
numeric : tINTEGER
| tFLOAT
| tUMINUS_NUM tINTEGER %prec tLOWEST
@@ -2869,10 +3010,13 @@ singleton : var_ref
switch ((enum node_type)(int)(intptr_t)$3->car) {
case NODE_STR:
case NODE_DSTR:
+ case NODE_XSTR:
+ case NODE_DXSTR:
case NODE_DREGX:
case NODE_MATCH:
case NODE_FLOAT:
case NODE_ARRAY:
+ case NODE_HEREDOC:
yyerror(p, "can't define singleton method for literals");
default:
break;
@@ -2957,6 +3101,7 @@ nl : '\n'
p->lineno++;
p->column = 0;
}
+ opt_heredoc_bodies
terms : term
| terms ';' {yyerrok;}
@@ -3081,20 +3226,20 @@ nextc(parser_state *p)
cons_free(tmp);
}
else {
+#ifdef ENABLE_STDIO
if (p->f) {
if (feof(p->f)) return -1;
c = fgetc(p->f);
if (c == EOF) return -1;
}
- else if (!p->s || p->s >= p->send) {
+ else
+#endif
+ if (!p->s || p->s >= p->send) {
return -1;
}
else {
c = (unsigned char)*p->s++;
}
- if (c == '\n') {
- // must understand heredoc
- }
}
p->column++;
return c;
@@ -3147,6 +3292,7 @@ peeks(parser_state *p, const char *s)
{
int len = strlen(s);
+#ifdef ENABLE_STDIO
if (p->f) {
int n = 0;
while (*s) {
@@ -3154,7 +3300,9 @@ peeks(parser_state *p, const char *s)
}
return TRUE;
}
- else if (p->s && p->s + len >= p->send) {
+ else
+#endif
+ if (p->s && p->s + len >= p->send) {
if (memcmp(p->s, s, len) == 0) return TRUE;
}
return FALSE;
@@ -3177,7 +3325,7 @@ skips(parser_state *p, const char *s)
int len = strlen(s);
while (len--) {
- nextc(p);
+ nextc(p);
}
return TRUE;
}
@@ -3188,23 +3336,6 @@ skips(parser_state *p, const char *s)
return FALSE;
}
-#define STR_FUNC_ESCAPE 0x01
-#define STR_FUNC_EXPAND 0x02
-#define STR_FUNC_REGEXP 0x04
-#define STR_FUNC_QWORDS 0x08
-#define STR_FUNC_SYMBOL 0x10
-#define STR_FUNC_INDENT 0x20
-
-enum string_type {
- str_squote = (0),
- str_dquote = (STR_FUNC_EXPAND),
- str_xquote = (STR_FUNC_EXPAND),
- str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
- str_sword = (STR_FUNC_QWORDS),
- str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
- str_ssym = (STR_FUNC_SYMBOL),
- str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND)
-};
static int
newtok(parser_state *p)
@@ -3216,7 +3347,7 @@ newtok(parser_state *p)
static void
tokadd(parser_state *p, int c)
{
- if (p->bidx < 1024) {
+ if (p->bidx < MRB_PARSER_BUF_SIZE) {
p->buf[p->bidx++] = c;
}
}
@@ -3230,7 +3361,7 @@ toklast(parser_state *p)
static void
tokfix(parser_state *p)
{
- if (p->bidx >= 1024) {
+ if (p->bidx >= MRB_PARSER_BUF_SIZE) {
yyerror(p, "string too long (truncated)");
}
p->buf[p->bidx] = '\0';
@@ -3255,34 +3386,38 @@ toklen(parser_state *p)
#define IS_LABEL_POSSIBLE() ((p->lstate == EXPR_BEG && !cmd_state) || IS_ARG())
#define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1))
-static unsigned long
+static int
scan_oct(const int *start, int len, int *retlen)
{
const int *s = start;
- unsigned long retval = 0;
+ int retval = 0;
+ /* assert(len <= 3) */
while (len-- && *s >= '0' && *s <= '7') {
retval <<= 3;
retval |= *s++ - '0';
}
*retlen = s - start;
+
return retval;
}
-static unsigned long
+static int
scan_hex(const int *start, int len, int *retlen)
{
static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
register const int *s = start;
- register unsigned long retval = 0;
+ register int retval = 0;
char *tmp;
- while (len-- && *s && (tmp = (char *)strchr(hexdigit, *s))) {
+ /* assert(len <= 2) */
+ while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
retval <<= 4;
retval |= (tmp - hexdigit) & 15;
s++;
}
*retlen = s - start;
+
return retval;
}
@@ -3319,19 +3454,19 @@ read_escape(parser_state *p)
case '0': case '1': case '2': case '3': /* octal constant */
case '4': case '5': case '6': case '7':
{
- int buf[3];
- int i;
-
- buf[0] = c;
- for (i=1; i<3; i++) {
- buf[i] = nextc(p);
- if (buf[i] == -1) goto eof;
- if (buf[i] < '0' || '7' < buf[i]) {
- pushback(p, buf[i]);
- break;
- }
- }
- c = scan_oct(buf, i, &i);
+ int buf[3];
+ int i;
+
+ buf[0] = c;
+ for (i=1; i<3; i++) {
+ buf[i] = nextc(p);
+ if (buf[i] == -1) goto eof;
+ if (buf[i] < '0' || '7' < buf[i]) {
+ pushback(p, buf[i]);
+ break;
+ }
+ }
+ c = scan_oct(buf, i, &i);
}
return c;
@@ -3357,17 +3492,9 @@ read_escape(parser_state *p)
return c;
case 'b': /* backspace */
- if (p->regexp) {
- tokadd(p, '\\');
- return 'b';
- }
return '\010';
case 's': /* space */
- if (p->regexp) {
- tokadd(p, '\\');
- return 's';
- }
return ' ';
case 'M':
@@ -3405,57 +3532,154 @@ read_escape(parser_state *p)
return '\0';
default:
- if (p->regexp) {
- tokadd(p, '\\');
- }
return c;
}
}
+
static int
-parse_string(parser_state *p, int term)
+parse_string(parser_state *p)
{
int c;
+ string_type type = (string_type)(intptr_t)p->lex_strterm->car;
+ int nest_level = (intptr_t)p->lex_strterm->cdr->car;
+ int beg = (intptr_t)p->lex_strterm->cdr->cdr->car;
+ int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr;
+ parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
newtok(p);
- while ((c = nextc(p)) != term) {
- if (c == -1) {
+ while ((c = nextc(p)) != end || nest_level != 0) {
+ if (hinf && (c == '\n' || c == -1)) {
+ int line_head;
+ tokadd(p, '\n');
+ tokfix(p);
+ p->lineno++;
+ p->column = 0;
+ line_head = hinf->line_head;
+ hinf->line_head = TRUE;
+ if (line_head) {
+ /* check whether end of heredoc */
+ const char *s = tok(p);
+ int len = toklen(p);
+ if (hinf->allow_indent) {
+ while (ISSPACE(*s) && len > 0) {
+ ++s;
+ --len;
+ }
+ }
+ if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
+ return tHEREDOC_END;
+ }
+ }
+ if (c == -1) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "can't find string \"%s\" anywhere before EOF", hinf->term);
+ yyerror(p, buf);
+ return 0;
+ }
+ yylval.nd = new_str(p, tok(p), toklen(p));
+ return tSTRING_MID;
+ }
+ if (c == -1) {
yyerror(p, "unterminated string meets end of file");
return 0;
}
+ else if (c == beg) {
+ nest_level++;
+ p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
+ }
+ else if (c == end) {
+ nest_level--;
+ p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
+ }
else if (c == '\\') {
c = nextc(p);
- if (c == term) {
+ if (type & STR_FUNC_EXPAND) {
+ if (c == end || c == beg) {
+ tokadd(p, c);
+ }
+ else if ((c == '\n') && (type & STR_FUNC_ARRAY)) {
+ p->lineno++;
+ p->column = 0;
+ tokadd(p, '\n');
+ }
+ else {
+ pushback(p, c);
+
+ if(type & STR_FUNC_REGEXP)
+ tokadd(p, '\\');
+
+ tokadd(p, read_escape(p));
+ if (hinf)
+ hinf->line_head = FALSE;
+ }
+ } else {
+ if (c != beg && c != end) {
+ switch (c) {
+ case '\n':
+ p->lineno++;
+ p->column = 0;
+ break;
+
+ case '\\':
+ break;
+
+ default:
+ if (! ISSPACE(c))
+ tokadd(p, '\\');
+ }
+ }
tokadd(p, c);
}
- else {
- pushback(p, c);
- tokadd(p, read_escape(p));
- }
continue;
}
- if (c == '#') {
+ else if ((c == '#') && (type & STR_FUNC_EXPAND)) {
c = nextc(p);
if (c == '{') {
tokfix(p);
p->lstate = EXPR_BEG;
- p->sterm = term;
p->cmd_start = TRUE;
yylval.nd = new_str(p, tok(p), toklen(p));
+ if (hinf)
+ hinf->line_head = FALSE;
return tSTRING_PART;
}
tokadd(p, '#');
pushback(p, c);
continue;
}
+ if ((type & STR_FUNC_ARRAY) && ISSPACE(c)) {
+ if (toklen(p) == 0) {
+ do {
+ if (c == '\n') {
+ p->lineno++;
+ p->column = 0;
+ }
+ } while (ISSPACE(c = nextc(p)));
+ pushback(p, c);
+ return tLITERAL_DELIM;
+ } else {
+ pushback(p, c);
+ tokfix(p);
+ yylval.nd = new_str(p, tok(p), toklen(p));
+ return tSTRING_MID;
+ }
+ }
+
tokadd(p, c);
- }
+
+ }
tokfix(p);
p->lstate = EXPR_END;
- p->sterm = 0;
+ end_strterm(p);
- if (p->regexp) {
+ if (type & STR_FUNC_XQUOTE) {
+ yylval.nd = new_xstr(p, tok(p), toklen(p));
+ return tXSTRING;
+ }
+
+ if (type & STR_FUNC_REGEXP) {
int f = 0;
int c;
char *s = strndup(tok(p), toklen(p));
@@ -3475,14 +3699,13 @@ parse_string(parser_state *p, int term)
char msg[128];
tokfix(p);
snprintf(msg, sizeof(msg), "unknown regexp option%s - %s",
- toklen(p) > 1 ? "s" : "", tok(p));
+ toklen(p) > 1 ? "s" : "", tok(p));
yyerror(p, msg);
}
if (f & 1) strcat(flag, "i");
if (f & 2) strcat(flag, "x");
if (f & 4) strcat(flag, "m");
yylval.nd = new_regx(p, s, strdup(flag));
- p->regexp = 0;
return tREGEXP;
}
@@ -3490,61 +3713,78 @@ parse_string(parser_state *p, int term)
yylval.nd = new_str(p, tok(p), toklen(p));
return tSTRING;
}
+
-static node*
-qstring_node(parser_state *p, int beg, int end)
+static int
+heredoc_identifier(parser_state *p)
{
int c;
- int nest_level = 0;
-
- newtok(p);
- while ((c = nextc(p)) != end || nest_level != 0) {
- if (c == -1) {
- yyerror(p, "unterminated string meets end of file");
- return 0;
- }
- else if (c == beg) {
- nest_level++;
+ int type = str_heredoc;
+ int indent = FALSE;
+ int quote = FALSE;
+ node *newnode;
+ parser_heredoc_info *info;
+
+ c = nextc(p);
+ if (ISSPACE(c) || c == '=') {
+ pushback(p, c);
+ return 0;
+ }
+ if (c == '-') {
+ indent = TRUE;
+ c = nextc(p);
+ }
+ if (c == '\'' || c == '"') {
+ int term = c;
+ if (c == '\'')
+ quote = TRUE;
+ newtok(p);
+ while ((c = nextc(p)) != -1 && c != term) {
+ if (c == '\n') {
+ c = -1;
+ break;
+ }
+ tokadd(p, c);
}
- else if (c == end) {
- nest_level--;
+ if (c == -1) {
+ yyerror(p, "unterminated here document identifier");
+ return 0;
}
- else if (c == '\\') {
- c = nextc(p);
- if (c != beg && c != end) {
- switch (c) {
- case '\n':
- p->lineno++;
- p->column = 0;
- continue;
-
- case '\\':
- c = '\\';
- break;
-
- default:
- tokadd(p, '\\');
- }
- }
+ } else {
+ if (! identchar(c)) {
+ pushback(p, c);
+ if (indent) pushback(p, '-');
+ return 0;
}
- tokadd(p, c);
+ newtok(p);
+ do {
+ tokadd(p, c);
+ } while ((c = nextc(p)) != -1 && identchar(c));
+ pushback(p, c);
}
-
tokfix(p);
+ newnode = new_heredoc(p);
+ info = (parser_heredoc_info*)newnode->cdr;
+ info->term = strndup(tok(p), toklen(p));
+ info->term_len = toklen(p);
+ if (! quote)
+ type |= STR_FUNC_EXPAND;
+ info->type = type;
+ info->allow_indent = indent;
+ info->line_head = TRUE;
+ info->doc = NULL;
+ p->heredocs = push(p->heredocs, newnode);
+ if (p->parsing_heredoc == NULL) {
+ node *n = p->heredocs;
+ while (n->cdr)
+ n = n->cdr;
+ p->parsing_heredoc = n;
+ }
+ p->heredoc_starts_nextline = TRUE;
p->lstate = EXPR_END;
- return new_str(p, tok(p), toklen(p));
-}
-
-static int
-parse_qstring(parser_state *p, int beg, int end)
-{
- node *nd = qstring_node(p, beg, end);
- if (nd) {
- yylval.nd = nd;
- return tSTRING;
- }
- return 0;
+ yylval.nd = newnode;
+ return tHEREDOC_BEG;
}
static int
@@ -3565,30 +3805,40 @@ parser_yylex(parser_state *p)
enum mrb_lex_state_enum last_state;
int token_column;
- if (p->sterm) {
- return parse_string(p, p->sterm);
+ if (p->lex_strterm) {
+ if (is_strterm_type(p, STR_FUNC_HEREDOC)) {
+ if ((p->parsing_heredoc != NULL) && (! p->heredoc_starts_nextline))
+ return parse_string(p);
+ }
+ else
+ return parse_string(p);
}
cmd_state = p->cmd_start;
p->cmd_start = FALSE;
retry:
last_state = p->lstate;
switch (c = nextc(p)) {
- case '\0': /* NUL */
- case '\004': /* ^D */
- case '\032': /* ^Z */
- case -1: /* end of script. */
+ case '\0': /* NUL */
+ case '\004': /* ^D */
+ case '\032': /* ^Z */
+ case -1: /* end of script. */
return 0;
- /* white spaces */
+ /* white spaces */
case ' ': case '\t': case '\f': case '\r':
- case '\13': /* '\v' */
+ case '\13': /* '\v' */
space_seen = 1;
goto retry;
- case '#': /* it's a comment */
+ case '#': /* it's a comment */
skip(p, '\n');
- /* fall through */
+ /* fall through */
case '\n':
+ p->heredoc_starts_nextline = FALSE;
+ if (p->parsing_heredoc != NULL) {
+ p->lex_strterm = new_strterm(p, parsing_heredoc_inf(p)->type, 0, 0);
+ goto normal_newline;
+ }
switch (p->lstate) {
case EXPR_BEG:
case EXPR_FNAME:
@@ -3628,7 +3878,7 @@ parser_yylex(parser_state *p)
case '*':
if ((c = nextc(p)) == '*') {
if ((c = nextc(p)) == '=') {
- yylval.id = intern("**");
+ yylval.id = intern2("**",2);
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3637,7 +3887,7 @@ parser_yylex(parser_state *p)
}
else {
if (c == '=') {
- yylval.id = intern("*");
+ yylval.id = intern_c('*');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3684,7 +3934,7 @@ parser_yylex(parser_state *p)
if (p->column == 1) {
if (peeks(p, "begin\n")) {
skips(p, "\n=end\n");
- goto retry;
+ goto retry;
}
}
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
@@ -3711,23 +3961,21 @@ parser_yylex(parser_state *p)
case '<':
last_state = p->lstate;
c = nextc(p);
-#if 0
- // no heredoc supported yet
if (c == '<' &&
p->lstate != EXPR_DOT &&
p->lstate != EXPR_CLASS &&
!IS_END() &&
(!IS_ARG() || space_seen)) {
- int token = heredoc_identifier();
- if (token) return token;
+ int token = heredoc_identifier(p);
+ if (token)
+ return token;
}
-#endif
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
p->lstate = EXPR_ARG;
} else {
p->lstate = EXPR_BEG;
if (p->lstate == EXPR_CLASS) {
- p->cmd_start = TRUE;
+ p->cmd_start = TRUE;
}
}
if (c == '=') {
@@ -3739,7 +3987,7 @@ parser_yylex(parser_state *p)
}
if (c == '<') {
if ((c = nextc(p)) == '=') {
- yylval.id = intern("<<");
+ yylval.id = intern2("<<",2);
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3760,7 +4008,7 @@ parser_yylex(parser_state *p)
}
if (c == '>') {
if ((c = nextc(p)) == '=') {
- yylval.id = intern(">>");
+ yylval.id = intern2(">>",2);
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3771,11 +4019,27 @@ parser_yylex(parser_state *p)
return '>';
case '"':
- p->sterm = '"';
+ p->lex_strterm = new_strterm(p, str_dquote, '"', 0);
return tSTRING_BEG;
case '\'':
- return parse_qstring(p, '\'', '\'');
+ p->lex_strterm = new_strterm(p, str_squote, '\'', 0);
+ return parse_string(p);
+
+ case '`':
+ if (p->lstate == EXPR_FNAME) {
+ p->lstate = EXPR_ENDFN;
+ return '`';
+ }
+ if (p->lstate == EXPR_DOT) {
+ if (cmd_state)
+ p->lstate = EXPR_CMDARG;
+ else
+ p->lstate = EXPR_ARG;
+ return '`';
+ }
+ p->lex_strterm = new_strterm(p, str_xquote, '`', 0);
+ return tXSTRING_BEG;
case '?':
if (IS_END()) {
@@ -3858,7 +4122,7 @@ parser_yylex(parser_state *p)
if ((c = nextc(p)) == '&') {
p->lstate = EXPR_BEG;
if ((c = nextc(p)) == '=') {
- yylval.id = intern("&&");
+ yylval.id = intern2("&&",2);
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3866,7 +4130,7 @@ parser_yylex(parser_state *p)
return tANDOP;
}
else if (c == '=') {
- yylval.id = intern("&");
+ yylval.id = intern_c('&');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3892,7 +4156,7 @@ parser_yylex(parser_state *p)
if ((c = nextc(p)) == '|') {
p->lstate = EXPR_BEG;
if ((c = nextc(p)) == '=') {
- yylval.id = intern("||");
+ yylval.id = intern2("||",2);
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3900,7 +4164,7 @@ parser_yylex(parser_state *p)
return tOROP;
}
if (c == '=') {
- yylval.id = intern("|");
+ yylval.id = intern_c('|');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3924,7 +4188,7 @@ parser_yylex(parser_state *p)
return '+';
}
if (c == '=') {
- yylval.id = intern("+");
+ yylval.id = intern_c('+');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3952,7 +4216,7 @@ parser_yylex(parser_state *p)
return '-';
}
if (c == '=') {
- yylval.id = intern("-");
+ yylval.id = intern_c('-');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3993,7 +4257,7 @@ parser_yylex(parser_state *p)
case '5': case '6': case '7': case '8': case '9':
{
int is_float, seen_point, seen_e, nondigit;
-
+
is_float = seen_point = seen_e = nondigit = 0;
p->lstate = EXPR_END;
token_column = newtok(p);
@@ -4181,7 +4445,7 @@ parser_yylex(parser_state *p)
if (nondigit) goto decode_num;
nondigit = c;
break;
-
+
default:
goto decode_num;
}
@@ -4248,26 +4512,17 @@ parser_yylex(parser_state *p)
case '/':
if (IS_BEG()) {
-#if 0
p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
-#endif
- p->regexp = 1;
- p->sterm = '/';
return tREGEXP_BEG;
}
if ((c = nextc(p)) == '=') {
- yylval.id = intern("/");
+ yylval.id = intern_c('/');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
pushback(p, c);
if (IS_SPCARG(c)) {
- arg_ambiguous(p);
-#if 0
p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
-#endif
- p->regexp = 1;
- p->sterm = '/';
return tREGEXP_BEG;
}
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
@@ -4279,7 +4534,7 @@ parser_yylex(parser_state *p)
case '^':
if ((c = nextc(p)) == '=') {
- yylval.id = intern("^");
+ yylval.id = intern_c('^');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -4294,7 +4549,7 @@ parser_yylex(parser_state *p)
case ';':
p->lstate = EXPR_BEG;
return ';';
-
+
case ',':
p->lstate = EXPR_BEG;
return ',';
@@ -4382,10 +4637,8 @@ parser_yylex(parser_state *p)
case '%':
if (IS_BEG()) {
- int beg = 0, term;
-#if 0
+ int term;
int paren;
-#endif
c = nextc(p);
quotation:
@@ -4394,7 +4647,7 @@ parser_yylex(parser_state *p)
c = 'Q';
}
else {
- beg = term = nextc(p);
+ term = nextc(p);
if (isalnum(term)) {
yyerror(p, "unknown type of %string");
return 0;
@@ -4404,70 +4657,57 @@ parser_yylex(parser_state *p)
yyerror(p, "unterminated quoted string meets end of file");
return 0;
}
-#if 0
paren = term;
-#endif
if (term == '(') term = ')';
else if (term == '[') term = ']';
else if (term == '{') term = '}';
else if (term == '<') term = '>';
- p->sterm = term;
-#if 0
else paren = 0;
-#endif
switch (c) {
case 'Q':
-#if 0
p->lex_strterm = new_strterm(p, str_dquote, term, paren);
-#endif
return tSTRING_BEG;
case 'q':
-#if 0
p->lex_strterm = new_strterm(p, str_squote, term, paren);
-#endif
- p->sterm = 0;
- return parse_qstring(p, beg, term);
+ return parse_string(p);
case 'W':
-#if 0
p->lex_strterm = new_strterm(p, str_dword, term, paren);
-#endif
- do {c = nextc(p);} while (isspace(c));
- pushback(p, c);
return tWORDS_BEG;
case 'w':
-#if 0
p->lex_strterm = new_strterm(p, str_sword, term, paren);
-#endif
- do {c = nextc(p);} while (isspace(c));
- pushback(p, c);
- return tQWORDS_BEG;
+ return tWORDS_BEG;
+
+ case 'x':
+ p->lex_strterm = new_strterm(p, str_xquote, term, paren);
+ return tXSTRING_BEG;
case 'r':
-#if 0
p->lex_strterm = new_strterm(p, str_regexp, term, paren);
-#endif
- p->regexp = 1;
- p->sterm = term;
return tREGEXP_BEG;
case 's':
-#if 0
p->lex_strterm = new_strterm(p, str_ssym, term, paren);
-#endif
- p->lstate = EXPR_FNAME;
return tSYMBEG;
+ case 'I':
+ p->lex_strterm = new_strterm(p, str_dsymbols, term, paren);
+ return tSYMBOLS_BEG;
+
+ case 'i':
+ p->lex_strterm = new_strterm(p, str_ssymbols, term, paren);
+ return tSYMBOLS_BEG;
+
default:
yyerror(p, "unknown type of %string");
return 0;
}
}
if ((c = nextc(p)) == '=') {
- yylval.id = intern("%");
+ yylval.id = intern_c('%');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -4487,27 +4727,32 @@ parser_yylex(parser_state *p)
token_column = newtok(p);
c = nextc(p);
switch (c) {
- case '_': /* $_: last read line string */
+ case '_': /* $_: last read line string */
c = nextc(p);
+ if (c != -1 && identchar(c)) { /* if there is more after _ it is a variable */
+ tokadd(p, '$');
+ tokadd(p, c);
+ break;
+ }
pushback(p, c);
c = '_';
/* fall through */
- case '~': /* $~: match-data */
- case '*': /* $*: argv */
- case '$': /* $$: pid */
- case '?': /* $?: last status */
- case '!': /* $!: error string */
- case '@': /* $@: error position */
- case '/': /* $/: input record separator */
- case '\\': /* $\: output record separator */
- case ';': /* $;: field separator */
- case ',': /* $,: output field separator */
- case '.': /* $.: last read line number */
- case '=': /* $=: ignorecase */
- case ':': /* $:: load path */
- case '<': /* $<: reading filename */
- case '>': /* $>: default output handle */
- case '\"': /* $": already loaded files */
+ case '~': /* $~: match-data */
+ case '*': /* $*: argv */
+ case '$': /* $$: pid */
+ case '?': /* $?: last status */
+ case '!': /* $!: error string */
+ case '@': /* $@: error position */
+ case '/': /* $/: input record separator */
+ case '\\': /* $\: output record separator */
+ case ';': /* $;: field separator */
+ case ',': /* $,: output field separator */
+ case '.': /* $.: last read line number */
+ case '=': /* $=: ignorecase */
+ case ':': /* $:: load path */
+ case '<': /* $<: reading filename */
+ case '>': /* $>: default output handle */
+ case '\"': /* $": already loaded files */
tokadd(p, '$');
tokadd(p, c);
tokfix(p);
@@ -4524,10 +4769,10 @@ parser_yylex(parser_state *p)
yylval.id = intern(tok(p));
return tGVAR;
- case '&': /* $&: last match */
- case '`': /* $`: string before last match */
- case '\'': /* $': string after last match */
- case '+': /* $+: string matches last paren. */
+ case '&': /* $&: last match */
+ case '`': /* $`: string before last match */
+ case '\'': /* $': string after last match */
+ case '+': /* $+: string matches last pattern */
if (last_state == EXPR_FNAME) {
tokadd(p, '$');
tokadd(p, c);
@@ -4706,9 +4951,7 @@ parser_yylex(parser_state *p)
}
}
- if (IS_BEG() ||
- p->lstate == EXPR_DOT ||
- IS_ARG()) {
+ if (IS_BEG() || p->lstate == EXPR_DOT || IS_ARG()) {
if (cmd_state) {
p->lstate = EXPR_CMDARG;
}
@@ -4740,12 +4983,12 @@ parser_yylex(parser_state *p)
static int
yylex(void *lval, parser_state *p)
{
- int t;
+ int t;
- p->ylval = lval;
- t = parser_yylex(p);
+ p->ylval = lval;
+ t = parser_yylex(p);
- return t;
+ return t;
}
static void
@@ -4801,7 +5044,7 @@ mrb_parser_parse(parser_state *p, mrbc_context *c)
p->cmd_start = TRUE;
p->in_def = p->in_single = FALSE;
p->nerr = p->nwarn = 0;
- p->sterm = 0;
+ p->lex_strterm = NULL;
parser_init_cxt(p, c);
yyparse(p);
@@ -4832,7 +5075,9 @@ mrb_parser_new(mrb_state *mrb)
p->in_def = p->in_single = 0;
p->s = p->send = NULL;
+#ifdef ENABLE_STDIO
p->f = NULL;
+#endif
p->cmd_start = TRUE;
p->in_def = p->in_single = FALSE;
@@ -4844,6 +5089,9 @@ mrb_parser_new(mrb_state *mrb)
yydebug = 1;
#endif
+ p->lex_strterm = NULL;
+ p->heredocs = p->parsing_heredoc = NULL;
+
return p;
}
@@ -4882,6 +5130,7 @@ mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
return c->filename;
}
+#ifdef ENABLE_STDIO
parser_state*
mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
{
@@ -4895,6 +5144,7 @@ mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
mrb_parser_parse(p, c);
return p;
}
+#endif
parser_state*
mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c)
@@ -4930,14 +5180,14 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
char buf[256];
n = snprintf(buf, sizeof(buf), "line %d: %s\n",
- p->error_buffer[0].lineno, p->error_buffer[0].message);
- mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
+ p->error_buffer[0].lineno, p->error_buffer[0].message);
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
mrb_parser_free(p);
return mrb_undef_value();
}
else {
static const char msg[] = "syntax error";
- mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1));
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1));
mrb_parser_free(p);
return mrb_undef_value();
}
@@ -4946,7 +5196,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
mrb_parser_free(p);
if (n < 0) {
static const char msg[] = "codegen error";
- mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1));
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1));
return mrb_nil_value();
}
if (c) {
@@ -4958,6 +5208,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
return v;
}
+#ifdef ENABLE_STDIO
mrb_value
mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
{
@@ -4969,6 +5220,7 @@ mrb_load_file(mrb_state *mrb, FILE *f)
{
return mrb_load_file_cxt(mrb, f, NULL);
}
+#endif
mrb_value
mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c)
@@ -5269,8 +5521,8 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
parser_dump(mrb, tree->car, offset+1);
dump_prefix(offset+1);
printf("method='%s' (%d)\n",
- mrb_sym2name(mrb, sym(tree->cdr->car)),
- (int)(intptr_t)tree->cdr->car);
+ mrb_sym2name(mrb, sym(tree->cdr->car)),
+ (int)(intptr_t)tree->cdr->car);
tree = tree->cdr->cdr->car;
if (tree) {
dump_prefix(offset+1);
@@ -5359,11 +5611,11 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
if (n2->car) {
dump_prefix(offset+2);
printf("rest:\n");
- if (n2->car == (node*)-1) {
+ if (n2->car == (node*)-1) {
dump_prefix(offset+2);
printf("(empty)\n");
}
- else {
+ else {
parser_dump(mrb, n2->car, offset+3);
}
}
@@ -5509,6 +5761,15 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
dump_recur(mrb, tree, offset+1);
break;
+ case NODE_XSTR:
+ printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
+ break;
+
+ case NODE_DXSTR:
+ printf("NODE_DXSTR\n");
+ dump_recur(mrb, tree, offset+1);
+ break;
+
case NODE_REGX:
printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr);
break;
@@ -5544,8 +5805,8 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
case NODE_ALIAS:
printf("NODE_ALIAS %s %s:\n",
- mrb_sym2name(mrb, sym(tree->car)),
- mrb_sym2name(mrb, sym(tree->cdr)));
+ mrb_sym2name(mrb, sym(tree->car)),
+ mrb_sym2name(mrb, sym(tree->cdr)));
break;
case NODE_UNDEF:
@@ -5553,8 +5814,8 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
{
node *t = tree;
while (t) {
- printf(" %s", mrb_sym2name(mrb, sym(t->car)));
- t = t->cdr;
+ printf(" %s", mrb_sym2name(mrb, sym(t->car)));
+ t = t->cdr;
}
}
printf(":\n");
@@ -5735,6 +5996,11 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
parser_dump(mrb, tree, offset+1);
break;
+ case NODE_HEREDOC:
+ printf("NODE_HEREDOC:\n");
+ parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
+ break;
+
default:
printf("node type: %d (0x%x)\n", (int)n, (int)n);
break;
diff --git a/src/pool.c b/src/pool.c
index 71e4b477d..77ac8a69f 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -4,9 +4,9 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
#include <stddef.h>
#include <string.h>
+#include "mruby.h"
/* configuration section */
/* allocated memory address should be multiple of POOL_ALIGNMENT */
@@ -25,7 +25,7 @@ struct mrb_pool_page {
size_t offset;
size_t len;
void *last;
- char page[1];
+ char page[];
};
struct mrb_pool {
@@ -81,7 +81,7 @@ page_alloc(mrb_pool *pool, size_t len)
if (len < POOL_PAGE_SIZE)
len = POOL_PAGE_SIZE;
- page = (struct mrb_pool_page *)mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len-1);
+ page = (struct mrb_pool_page *)mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len);
if (page) {
page->offset = 0;
page->len = len;
diff --git a/src/print.c b/src/print.c
index 58297ea83..5367781f5 100644
--- a/src/print.c
+++ b/src/print.c
@@ -5,13 +5,12 @@
*/
#include "mruby.h"
-#ifdef ENABLE_STDIO
#include "mruby/string.h"
-#include <stdio.h>
static void
printstr(mrb_state *mrb, mrb_value obj)
{
+#ifdef ENABLE_STDIO
struct RString *str;
char *s;
int len;
@@ -22,64 +21,35 @@ printstr(mrb_state *mrb, mrb_value obj)
len = str->len;
fwrite(s, len, 1, stdout);
}
+#endif
}
void
mrb_p(mrb_state *mrb, mrb_value obj)
{
+#ifdef ENABLE_STDIO
obj = mrb_funcall(mrb, obj, "inspect", 0);
printstr(mrb, obj);
putc('\n', stdout);
+#endif
}
-/* 15.3.1.2.9 */
-/* 15.3.1.3.34 */
-mrb_value
-mrb_printstr(mrb_state *mrb, mrb_value self)
-{
- mrb_value argv;
-
- mrb_get_args(mrb, "o", &argv);
- printstr(mrb, argv);
-
- return argv;
-}
-
-void
-mrb_init_print(mrb_state *mrb)
-{
- struct RClass *krn;
-
- krn = mrb->kernel_module;
-
- mrb_define_method(mrb, krn, "__printstr__", mrb_printstr, ARGS_REQ(1));
-}
-
-
void
mrb_show_version(mrb_state *mrb)
{
- printf("mruby - Embeddable Ruby Copyright (c) 2010-2013 mruby developers\n");
-}
-
-void
-mrb_show_copyright(mrb_state *mrb)
-{
- printf("mruby - Copyright (c) 2010-2013 mruby developers\n");
-}
-#else
-void
-mrb_p(mrb_state *mrb, mrb_value obj)
-{
-}
+ static const char version_msg[] = "mruby - Embeddable Ruby Copyright (c) 2010-2013 mruby developers\n";
+ mrb_value msg;
-void
-mrb_show_version(mrb_state *mrb)
-{
+ msg = mrb_str_new(mrb, version_msg, sizeof(version_msg) - 1);
+ printstr(mrb, msg);
}
void
mrb_show_copyright(mrb_state *mrb)
{
+ static const char copyright_msg[] = "mruby - Copyright (c) 2010-2013 mruby developers\n";
+ mrb_value msg;
+
+ msg = mrb_str_new(mrb, copyright_msg, sizeof(copyright_msg) - 1);
+ printstr(mrb, msg);
}
-#endif
diff --git a/src/proc.c b/src/proc.c
index c4d7ec3ea..c32ce9c7a 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -5,8 +5,8 @@
*/
#include "mruby.h"
-#include "mruby/proc.h"
#include "mruby/class.h"
+#include "mruby/proc.h"
#include "opcode.h"
static mrb_code call_iseq[] = {
diff --git a/src/range.c b/src/range.c
index aac1d830a..fb4d975e7 100644
--- a/src/range.c
+++ b/src/range.c
@@ -8,7 +8,6 @@
#include "mruby/class.h"
#include "mruby/range.h"
#include "mruby/string.h"
-#include <string.h>
#define RANGE_CLASS (mrb_class_obj_get(mrb, "Range"))
@@ -16,8 +15,8 @@ static void
range_check(mrb_state *mrb, mrb_value a, mrb_value b)
{
mrb_value ans;
- int ta;
- int tb;
+ enum mrb_vtype ta;
+ enum mrb_vtype tb;
ta = mrb_type(a);
tb = mrb_type(b);
@@ -92,7 +91,7 @@ mrb_range_excl(mrb_state *mrb, mrb_value range)
{
struct RRange *r = mrb_range_ptr(range);
- return r->excl ? mrb_true_value() : mrb_false_value();
+ return mrb_bool_value(r->excl);
}
static void
@@ -153,25 +152,30 @@ mrb_range_eq(mrb_state *mrb, mrb_value range)
struct RRange *rr;
struct RRange *ro;
mrb_value obj;
+ mrb_bool eq_p;
mrb_get_args(mrb, "o", &obj);
- if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
-
- /* same class? */
- if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range)))
- return mrb_false_value();
-
- rr = mrb_range_ptr(range);
- ro = mrb_range_ptr(obj);
- if (!mrb_obj_equal(mrb, rr->edges->beg, ro->edges->beg))
- return mrb_false_value();
- if (!mrb_obj_equal(mrb, rr->edges->end, ro->edges->end))
- return mrb_false_value();
- if (rr->excl != ro->excl)
- return mrb_false_value();
+ if (mrb_obj_equal(mrb, range, obj)) {
+ eq_p = 1;
+ }
+ else if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */
+ eq_p = 0;
+ }
+ else {
+ rr = mrb_range_ptr(range);
+ ro = mrb_range_ptr(obj);
+ if (!mrb_obj_equal(mrb, rr->edges->beg, ro->edges->beg) ||
+ !mrb_obj_equal(mrb, rr->edges->end, ro->edges->end) ||
+ rr->excl != ro->excl) {
+ eq_p = 0;
+ }
+ else {
+ eq_p = 1;
+ }
+ }
- return mrb_true_value();
+ return mrb_bool_value(eq_p);
}
static int
@@ -181,7 +185,7 @@ r_le(mrb_state *mrb, mrb_value a, mrb_value b)
/* output :a < b => -1, a = b => 0, a > b => +1 */
if (mrb_type(r) == MRB_TT_FIXNUM) {
- int c = mrb_fixnum(r);
+ mrb_int c = mrb_fixnum(r);
if (c == 0 || c == -1) return TRUE;
}
@@ -208,7 +212,7 @@ r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
/* output :a < b => -1, a = b => 0, a > b => +1 */
if (mrb_type(r) == MRB_TT_FIXNUM) {
- int c = mrb_fixnum(r);
+ mrb_int c = mrb_fixnum(r);
if (c == 0 || c == 1) return TRUE;
}
@@ -228,21 +232,17 @@ mrb_range_include(mrb_state *mrb, mrb_value range)
mrb_value val;
struct RRange *r = mrb_range_ptr(range);
mrb_value beg, end;
+ mrb_bool include_p;
mrb_get_args(mrb, "o", &val);
beg = r->edges->beg;
end = r->edges->end;
- if (r_le(mrb, beg, val)) {
- /* beg <= val */
- if (r->excl) {
- if (r_gt(mrb, end, val)) return mrb_true_value(); /* end > val */
- }
- else {
- if (r_ge(mrb, end, val)) return mrb_true_value(); /* end >= val */
- }
- }
- return mrb_false_value();
+ include_p = r_le(mrb, beg, val) && /* beg <= val */
+ ((r->excl && r_gt(mrb, end, val)) || /* end > val */
+ (r_ge(mrb, end, val))); /* end >= val */
+
+ return mrb_bool_value(include_p);
}
/*
@@ -385,23 +385,34 @@ range_eql(mrb_state *mrb, mrb_value range)
{
mrb_value obj;
struct RRange *r, *o;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &obj);
- if (mrb_obj_equal(mrb, range, obj))
- return mrb_true_value();
- if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS))
- return mrb_false_value();
-
- r = mrb_range_ptr(range);
- if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value();
- o = mrb_range_ptr(obj);
- if (!mrb_eql(mrb, r->edges->beg, o->edges->beg))
- return mrb_false_value();
- if (!mrb_eql(mrb, r->edges->end, o->edges->end))
- return mrb_false_value();
- if (r->excl != o->excl)
- return mrb_false_value();
- return mrb_true_value();
+ if (mrb_obj_equal(mrb, range, obj)) {
+ eql_p = 1;
+ }
+ else if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) {
+ eql_p = 0;
+ }
+ else {
+ r = mrb_range_ptr(range);
+ if (mrb_type(obj) != MRB_TT_RANGE) {
+ eql_p = 0;
+ }
+ else {
+ o = mrb_range_ptr(obj);
+ if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) ||
+ !mrb_eql(mrb, r->edges->end, o->edges->end) ||
+ (r->excl != o->excl)) {
+ eql_p = 0;
+ }
+ else {
+ eql_p = 1;
+ }
+ }
+ }
+
+ return mrb_bool_value(eql_p);
}
/* 15.2.14.4.15(x) */
diff --git a/src/state.c b/src/state.c
index 53773ac89..adc7da06b 100644
--- a/src/state.c
+++ b/src/state.c
@@ -4,15 +4,23 @@
** See Copyright Notice in mruby.h
*/
+#include <stdlib.h>
+#include <string.h>
#include "mruby.h"
+#include "mruby/class.h"
#include "mruby/irep.h"
#include "mruby/variable.h"
-#include <string.h>
void mrb_init_heap(mrb_state*);
void mrb_init_core(mrb_state*);
void mrb_final_core(mrb_state*);
+static mrb_value
+inspect_main(mrb_state *mrb, mrb_value mod)
+{
+ return mrb_str_new(mrb, "main", 4);
+}
+
mrb_state*
mrb_open_allocf(mrb_allocf f, void *ud)
{
@@ -44,7 +52,7 @@ allocf(mrb_state *mrb, void *p, size_t size, void *ud)
struct alloca_header {
struct alloca_header *next;
- char buf[0];
+ char buf[];
};
void*
@@ -53,6 +61,7 @@ mrb_alloca(mrb_state *mrb, size_t size)
struct alloca_header *p;
p = (struct alloca_header*) mrb_malloc(mrb, sizeof(struct alloca_header)+size);
+ if (p == NULL) return NULL;
p->next = mrb->mems;
mrb->mems = p;
return (void*)p->buf;
@@ -61,9 +70,12 @@ mrb_alloca(mrb_state *mrb, size_t size)
static void
mrb_alloca_free(mrb_state *mrb)
{
- struct alloca_header *p = mrb->mems;
+ struct alloca_header *p;
struct alloca_header *tmp;
+ if (mrb == NULL) return;
+ p = mrb->mems;
+
while (p) {
tmp = p;
p = p->next;
@@ -72,7 +84,7 @@ mrb_alloca_free(mrb_state *mrb)
}
mrb_state*
-mrb_open()
+mrb_open(void)
{
mrb_state *mrb = mrb_open_allocf(allocf, NULL);
@@ -83,6 +95,17 @@ void mrb_free_symtbl(mrb_state *mrb);
void mrb_free_heap(mrb_state *mrb);
void
+mrb_irep_free(mrb_state *mrb, struct mrb_irep *irep)
+{
+ if (!(irep->flags & MRB_ISEQ_NO_FREE))
+ mrb_free(mrb, irep->iseq);
+ mrb_free(mrb, irep->pool);
+ mrb_free(mrb, irep->syms);
+ mrb_free(mrb, irep->lines);
+ mrb_free(mrb, irep);
+}
+
+void
mrb_close(mrb_state *mrb)
{
size_t i;
@@ -94,12 +117,7 @@ mrb_close(mrb_state *mrb)
mrb_free(mrb, mrb->stbase);
mrb_free(mrb, mrb->cibase);
for (i=0; i<mrb->irep_len; i++) {
- if (!(mrb->irep[i]->flags & MRB_ISEQ_NO_FREE))
- mrb_free(mrb, mrb->irep[i]->iseq);
- mrb_free(mrb, mrb->irep[i]->pool);
- mrb_free(mrb, mrb->irep[i]->syms);
- mrb_free(mrb, mrb->irep[i]->lines);
- mrb_free(mrb, mrb->irep[i]);
+ mrb_irep_free(mrb, mrb->irep[i]);
}
mrb_free(mrb, mrb->irep);
mrb_free(mrb, mrb->rescue);
@@ -110,6 +128,10 @@ mrb_close(mrb_state *mrb)
mrb_free(mrb, mrb);
}
+#ifndef MRB_IREP_ARRAY_INIT_SIZE
+# define MRB_IREP_ARRAY_INIT_SIZE (256u)
+#endif
+
mrb_irep*
mrb_add_irep(mrb_state *mrb)
{
@@ -117,14 +139,14 @@ mrb_add_irep(mrb_state *mrb)
mrb_irep *irep;
if (!mrb->irep) {
- int max = 256;
+ size_t max = MRB_IREP_ARRAY_INIT_SIZE;
if (mrb->irep_len > max) max = mrb->irep_len+1;
mrb->irep = (mrb_irep **)mrb_calloc(mrb, max, sizeof(mrb_irep*));
mrb->irep_capa = max;
}
else if (mrb->irep_capa <= mrb->irep_len) {
- int i;
+ size_t i;
size_t old_capa = mrb->irep_capa;
while (mrb->irep_capa <= mrb->irep_len) {
mrb->irep_capa *= 2;
@@ -145,8 +167,10 @@ mrb_add_irep(mrb_state *mrb)
mrb_value
mrb_top_self(mrb_state *mrb)
{
- mrb_value v;
-
- MRB_SET_VALUE(v, MRB_TT_MAIN, value.i, 0);
- return v;
+ if (!mrb->top_self) {
+ mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class);
+ mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, ARGS_NONE());
+ mrb_define_singleton_method(mrb, mrb->top_self, "to_s", inspect_main, ARGS_NONE());
+ }
+ return mrb_obj_value(mrb->top_self);
}
diff --git a/src/string.c b/src/string.c
index 28cf0ab9a..c4074a64f 100644
--- a/src/string.c
+++ b/src/string.c
@@ -4,36 +4,34 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-
-#include <string.h>
-#include "mruby/string.h"
-#include "mruby/class.h"
#include <ctype.h>
-#include <limits.h>
-#include "mruby/range.h"
+#ifndef SIZE_MAX
+ /* Some versions of VC++
+ * has SIZE_MAX in stdint.h
+ */
+# include <limits.h>
+#endif
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mruby.h"
#include "mruby/array.h"
#include "mruby/class.h"
#include "mruby/numeric.h"
-#include <stdio.h>
+#include "mruby/range.h"
+#include "mruby/string.h"
#include "re.h"
const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2);
-static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len);
+static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
#define RESIZE_CAPA(s,capacity) do {\
s->ptr = (char *)mrb_realloc(mrb, s->ptr, (capacity)+1);\
s->aux.capa = capacity;\
} while (0)
-static const char*
-_obj_classname(mrb_state *mrb, mrb_value obj)
-{
- return mrb_class_name(mrb, mrb_obj_class(mrb, obj));
-}
-
void
mrb_str_decref(mrb_state *mrb, mrb_shared_string *shared)
{
@@ -57,13 +55,13 @@ str_modify(mrb_state *mrb, struct RString *s)
}
else {
char *ptr, *p;
- long len;
+ mrb_int len;
p = s->ptr;
len = s->len;
- ptr = (char *)mrb_malloc(mrb, len+1);
+ ptr = (char *)mrb_malloc(mrb, (size_t)len + 1);
if (p) {
- memcpy(ptr, p, len);
+ memcpy(ptr, p, len);
}
ptr[len] = 0;
s->ptr = ptr;
@@ -88,7 +86,7 @@ mrb_str_resize(mrb_state *mrb, mrb_value str, int len)
}
s->aux.capa = len;
s->len = len;
- s->ptr[len] = '\0'; /* sentinel */
+ s->ptr[len] = '\0'; /* sentinel */
}
return str;
}
@@ -105,21 +103,6 @@ str_mod_check(mrb_state *mrb, mrb_value str, char *p, mrb_int len)
#define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class))
-static struct RString*
-str_alloc(mrb_state *mrb, struct RClass *c)
-{
- struct RString* s;
-
- s = mrb_obj_alloc_string(mrb);
-
- s->c = c;
- s->ptr = 0;
- s->len = 0;
- s->aux.capa = 0;
-
- return s;
-}
-
/* char offset to byte offset */
int
mrb_str_offset(mrb_state *mrb, mrb_value str, int pos)
@@ -130,8 +113,9 @@ mrb_str_offset(mrb_state *mrb, mrb_value str, int pos)
static struct RString*
str_new(mrb_state *mrb, const char *p, int len)
{
- struct RString *s = str_alloc(mrb, mrb->string_class);
+ struct RString *s;
+ s = mrb_obj_alloc_string(mrb);
s->len = len;
s->aux.capa = len;
s->ptr = (char *)mrb_malloc(mrb, len+1);
@@ -157,6 +141,10 @@ mrb_str_new_empty(mrb_state *mrb, mrb_value str)
return mrb_obj_value(s);
}
+#ifndef MRB_STR_BUF_MIN_SIZE
+# define MRB_STR_BUF_MIN_SIZE 128
+#endif
+
mrb_value
mrb_str_buf_new(mrb_state *mrb, int capa)
{
@@ -164,8 +152,8 @@ mrb_str_buf_new(mrb_state *mrb, int capa)
s = mrb_obj_alloc_string(mrb);
- if (capa < STR_BUF_MIN_SIZE) {
- capa = STR_BUF_MIN_SIZE;
+ if (capa < MRB_STR_BUF_MIN_SIZE) {
+ capa = MRB_STR_BUF_MIN_SIZE;
}
s->len = 0;
s->aux.capa = capa;
@@ -176,9 +164,11 @@ mrb_str_buf_new(mrb_state *mrb, int capa)
}
static void
-str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len)
+str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len)
{
- long capa, total, off = -1;
+ mrb_int capa;
+ mrb_int total;
+ ptrdiff_t off = -1;
str_modify(mrb, s);
if (ptr >= s->ptr && ptr <= s->ptr + s->len) {
@@ -186,13 +176,13 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len)
}
if (len == 0) return;
capa = s->aux.capa;
- if (s->len >= INT_MAX - len) {
+ if (s->len >= MRB_INT_MAX - len) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string sizes too big");
}
total = s->len+len;
if (capa <= total) {
while (total > capa) {
- if (capa + 1 >= INT_MAX / 2) {
+ if (capa + 1 >= MRB_INT_MAX / 2) {
capa = (total + 4095) / 4096;
break;
}
@@ -205,11 +195,11 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len)
}
memcpy(s->ptr + s->len, ptr, len);
s->len = total;
- s->ptr[total] = '\0'; /* sentinel */
+ s->ptr[total] = '\0'; /* sentinel */
}
mrb_value
-mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len)
+mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
{
if (len == 0) return str;
str_buf_cat(mrb, mrb_str_ptr(str), ptr, len);
@@ -217,7 +207,7 @@ mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len)
}
mrb_value
-mrb_str_new(mrb_state *mrb, const char *p, int len)
+mrb_str_new(mrb_state *mrb, const char *p, size_t len)
{
struct RString *s;
@@ -225,17 +215,6 @@ mrb_str_new(mrb_state *mrb, const char *p, int len)
return mrb_obj_value(s);
}
-mrb_value
-mrb_str_new2(mrb_state *mrb, const char *ptr)
-{
- struct RString *s;
- if (!ptr) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "NULL pointer given");
- }
- s = str_new(mrb, ptr, strlen(ptr));
- return mrb_obj_value(s);
-}
-
/*
* call-seq: (Caution! NULL string)
* String.new(str="") => new_str
@@ -247,11 +226,23 @@ mrb_value
mrb_str_new_cstr(mrb_state *mrb, const char *p)
{
struct RString *s;
- int len = strlen(p);
+ size_t len;
+
+ if (p) {
+ len = strlen(p);
+ if ((mrb_int)len < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big");
+ }
+ }
+ else {
+ len = 0;
+ }
s = mrb_obj_alloc_string(mrb);
s->ptr = (char *)mrb_malloc(mrb, len+1);
- memcpy(s->ptr, p, len);
+ if (p) {
+ memcpy(s->ptr, p, len);
+ }
s->ptr[len] = 0;
s->len = len;
s->aux.capa = len;
@@ -264,6 +255,10 @@ mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
{
mrb_value str;
+ if (!mrb_string_p(str0)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "expected String");
+ }
+
str = mrb_str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0));
if (strlen(RSTRING_PTR(str)) != RSTRING_LEN(str)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
@@ -303,7 +298,7 @@ mrb_str_literal(mrb_state *mrb, mrb_value str)
struct RString *s, *orig;
mrb_shared_string *shared;
- s = str_alloc(mrb, mrb->string_class);
+ s = mrb_obj_alloc_string(mrb);
orig = mrb_str_ptr(str);
if (!(orig->flags & MRB_STR_SHARED)) {
str_make_shared(mrb, mrb_str_ptr(str));
@@ -312,6 +307,7 @@ mrb_str_literal(mrb_state *mrb, mrb_value str)
shared->refcnt++;
s->ptr = shared->ptr;
s->len = shared->len;
+ s->aux.capa = 0;
s->aux.shared = shared;
s->flags |= MRB_STR_SHARED;
@@ -447,7 +443,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self)
if (times < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
}
- if (times && INT_MAX/times < RSTRING_LEN(self)) {
+ if (times && MRB_INT_MAX / times < RSTRING_LEN(self)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big");
}
@@ -533,10 +529,10 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1)
mrb_get_args(mrb, "o", &str2);
if (!mrb_string_p(str2)) {
- if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "to_s"))) {
+ if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_s", 4))) {
return mrb_nil_value();
}
- else if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "<=>"))) {
+ else if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "<=>", 3))) {
return mrb_nil_value();
}
else {
@@ -558,8 +554,9 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1)
static int
str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2)
{
- const long len = RSTRING_LEN(str1);
+ const size_t len = RSTRING_LEN(str1);
+ /* assert(SIZE_MAX >= MRB_INT_MAX) */
if (len != RSTRING_LEN(str2)) return FALSE;
if (memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len) == 0)
return TRUE;
@@ -572,7 +569,7 @@ mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2)
if (mrb_obj_equal(mrb, str1, str2)) return TRUE;
if (!mrb_string_p(str2)) {
if (mrb_nil_p(str2)) return FALSE;
- if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "to_str"))) {
+ if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_str", 6))) {
return FALSE;
}
str2 = mrb_funcall(mrb, str2, "to_str", 0);
@@ -596,11 +593,12 @@ static mrb_value
mrb_str_equal_m(mrb_state *mrb, mrb_value str1)
{
mrb_value str2;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &str2);
- if (mrb_str_equal(mrb, str1, str2))
- return mrb_true_value();
- return mrb_false_value();
+ equal_p = mrb_str_equal(mrb, str1, str2);
+
+ return mrb_bool_value(equal_p);
}
/* ---------------------------------- */
mrb_value
@@ -618,21 +616,10 @@ mrb_str_to_str(mrb_state *mrb, mrb_value str)
return str;
}
-mrb_value
-mrb_string_value(mrb_state *mrb, mrb_value *ptr)
-{
- mrb_value s = *ptr;
- if (!mrb_string_p(s)) {
- s = mrb_str_to_str(mrb, s);
- *ptr = s;
- }
- return s;
-}
-
char *
mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr)
{
- mrb_value str = mrb_string_value(mrb, &ptr);
+ mrb_value str = mrb_str_to_str(mrb, ptr);
return RSTRING_PTR(str);
}
/* 15.2.10.5.5 */
@@ -658,8 +645,8 @@ mrb_str_match(mrb_state *mrb, mrb_value self/* x */)
return mrb_nil_value();
}
-static inline long
-mrb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long n)
+static inline mrb_int
+mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
{
const unsigned char *x = xs, *xe = xs + m;
const unsigned char *y = ys;
@@ -678,8 +665,8 @@ mrb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long
return -1;
}
-static int
-mrb_memsearch(const void *x0, int m, const void *y0, int n)
+static mrb_int
+mrb_memsearch(const void *x0, mrb_int m, const void *y0, mrb_int n)
{
const unsigned char *x = (const unsigned char *)x0, *y = (const unsigned char *)y0;
@@ -706,7 +693,8 @@ mrb_str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset)
{
mrb_int pos;
char *s, *sptr;
- int len, slen;
+ mrb_int len, slen;
+
len = RSTRING_LEN(str);
slen = RSTRING_LEN(sub);
if (offset < 0) {
@@ -740,9 +728,9 @@ mrb_str_dup(mrb_state *mrb, mrb_value str)
static mrb_value
mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx)
{
- long idx;
+ mrb_int idx;
- if (!strcmp(_obj_classname(mrb, indx), REGEXP_CLASS)) {
+ if (!strcmp(mrb_obj_classname(mrb, indx), REGEXP_CLASS)) {
mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
}
switch (mrb_type(indx)) {
@@ -843,7 +831,7 @@ mrb_str_aref_m(mrb_state *mrb, mrb_value str)
return mrb_str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2));
}
if (argc != 1) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%d for 1)", argc);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(argc));
}
return mrb_str_aref(mrb, str, a1);
}
@@ -921,7 +909,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
mrb_value rs;
mrb_int newline;
char *p, *pp;
- long len, rslen;
+ mrb_int rslen;
+ mrb_int len;
struct RString *s = mrb_str_ptr(str);
str_modify(mrb, s);
@@ -932,8 +921,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
if (s->ptr[len-1] == '\n') {
s->len--;
if (s->len > 0 &&
- s->ptr[s->len-1] == '\r') {
- s->len--;
+ s->ptr[s->len-1] == '\r') {
+ s->len--;
}
}
else if (s->ptr[len-1] == '\r') {
@@ -1132,9 +1121,7 @@ mrb_str_empty_p(mrb_state *mrb, mrb_value self)
{
struct RString *s = mrb_str_ptr(self);
- if (s->len == 0)
- return mrb_true_value();
- return mrb_false_value();
+ return mrb_bool_value(s->len == 0);
}
/* 15.2.10.5.17 */
@@ -1148,17 +1135,16 @@ static mrb_value
mrb_str_eql(mrb_state *mrb, mrb_value self)
{
mrb_value str2;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &str2);
- if (mrb_type(str2) != MRB_TT_STRING)
- return mrb_false_value();
- if (str_eql(mrb, self, str2))
- return mrb_true_value();
- return mrb_false_value();
+ eql_p = (mrb_type(str2) == MRB_TT_STRING) && str_eql(mrb, self, str2);
+
+ return mrb_bool_value(eql_p);
}
static mrb_value
-mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len)
+mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
struct RString *orig, *s;
mrb_shared_string *shared;
@@ -1177,7 +1163,7 @@ mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len)
}
mrb_value
-mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, int len)
+mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
mrb_value str2;
@@ -1268,7 +1254,7 @@ mrb_str_hash(mrb_state *mrb, mrb_value str)
{
/* 1-8-7 */
struct RString *s = mrb_str_ptr(str);
- long len = s->len;
+ mrb_int len = s->len;
char *p = s->ptr;
mrb_int key = 0;
@@ -1312,18 +1298,20 @@ mrb_str_include(mrb_state *mrb, mrb_value self)
{
mrb_int i;
mrb_value str2;
+ mrb_bool include_p;
mrb_get_args(mrb, "o", &str2);
if (mrb_type(str2) == MRB_TT_FIXNUM) {
- if (memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self)))
- return mrb_true_value();
- return mrb_false_value();
+ include_p = memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self));
}
- mrb_string_value(mrb, &str2);
- i = mrb_str_index(mrb, self, str2, 0);
+ else {
+ str2 = mrb_str_to_str(mrb, str2);
+ i = mrb_str_index(mrb, self, str2, 0);
- if (i == -1) return mrb_false_value();
- return mrb_true_value();
+ include_p = (i != -1);
+ }
+
+ return mrb_bool_value(include_p);
}
/* 15.2.10.5.22 */
@@ -1382,7 +1370,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
switch (mrb_type(sub)) {
case MRB_TT_FIXNUM: {
int c = mrb_fixnum(sub);
- long len = RSTRING_LEN(str);
+ mrb_int len = RSTRING_LEN(str);
unsigned char *p = (unsigned char*)RSTRING_PTR(str);
for (;pos<len;pos++) {
@@ -1396,8 +1384,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
tmp = mrb_check_string_type(mrb, sub);
if (mrb_nil_p(tmp)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %s given",
- _obj_classname(mrb, sub));
+ mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub);
}
sub = tmp;
}
@@ -1405,10 +1392,10 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
case MRB_TT_STRING:
pos = mrb_str_index(mrb, str, sub, pos);
break;
- }
+ }
- if (pos == -1) return mrb_nil_value();
- return mrb_fixnum_value(pos);
+ if (pos == -1) return mrb_nil_value();
+ return mrb_fixnum_value(pos);
}
#define STR_REPLACE_SHARED_MIN 10
@@ -1512,9 +1499,8 @@ mrb_value
mrb_str_intern(mrb_state *mrb, mrb_value self)
{
mrb_sym id;
- mrb_value str = RB_GC_GUARD(self);
- id = mrb_intern_str(mrb, str);
+ id = mrb_intern_str(mrb, self);
return mrb_symbol_value(id);
}
@@ -1534,6 +1520,36 @@ mrb_obj_as_string(mrb_state *mrb, mrb_value obj)
}
mrb_value
+mrb_ptr_to_str(mrb_state *mrb, void *p)
+{
+ struct RString *p_str;
+ char *p1;
+ char *p2;
+ intptr_t n = (intptr_t)p;
+
+ p_str = str_new(mrb, NULL, 2 + sizeof(uintptr_t) * CHAR_BIT / 4);
+ p1 = p_str->ptr;
+ *p1++ = '0';
+ *p1++ = 'x';
+ p2 = p1;
+
+ do {
+ *p2++ = mrb_digitmap[n % 16];
+ n /= 16;
+ } while (n > 0);
+ *p2 = '\0';
+ p_str->len = (mrb_int)(p2 - p_str->ptr);
+
+ while (p1 < p2) {
+ const char c = *p1;
+ *p1++ = *--p2;
+ *p2 = c;
+ }
+
+ return mrb_obj_value(p_str);
+}
+
+mrb_value
mrb_check_string_type(mrb_state *mrb, mrb_value str)
{
return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
@@ -1639,7 +1655,7 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
char *s, *sbeg, *t;
struct RString *ps = mrb_str_ptr(str);
struct RString *psub = mrb_str_ptr(sub);
- long len = psub->len;
+ mrb_int len = psub->len;
/* substring longer than string */
if (ps->len < len) return -1;
@@ -1663,15 +1679,6 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
}
}
-#ifdef INCLUDE_ENCODING
-/* byte offset to char offset */
-int
-mrb_str_sublen(mrb_state *mrb, mrb_value str, long pos)
-{
- return pos;
-}
-#endif //INCLUDE_ENCODING
-
/* 15.2.10.5.31 */
/*
* call-seq:
@@ -1730,7 +1737,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
switch (mrb_type(sub)) {
case MRB_TT_FIXNUM: {
int c = mrb_fixnum(sub);
- long len = RSTRING_LEN(str);
+ mrb_int len = RSTRING_LEN(str);
unsigned char *p = (unsigned char*)RSTRING_PTR(str);
for (pos=len;pos>=0;pos--) {
@@ -1744,8 +1751,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
tmp = mrb_check_string_type(mrb, sub);
if (mrb_nil_p(tmp)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %s given",
- mrb_obj_classname(mrb, sub));
+ mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub);
}
sub = tmp;
}
@@ -1867,7 +1873,9 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
int argc;
mrb_value spat = mrb_nil_value();
enum {awk, string, regexp} split_type = string;
- long beg, end, i = 0, lim_p;
+ long i = 0, lim_p;
+ mrb_int beg;
+ mrb_int end;
mrb_int lim = 0;
mrb_value result, tmp;
@@ -1911,24 +1919,24 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
int ai = mrb_gc_arena_save(mrb);
c = (unsigned char)*ptr++;
if (skip) {
- if (ascii_isspace(c)) {
- beg = ptr - bptr;
- }
- else {
- end = ptr - bptr;
- skip = 0;
- if (lim_p && lim <= i) break;
- }
+ if (ascii_isspace(c)) {
+ beg = ptr - bptr;
+ }
+ else {
+ end = ptr - bptr;
+ skip = 0;
+ if (lim_p && lim <= i) break;
+ }
}
else if (ascii_isspace(c)) {
- mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg));
+ mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg));
mrb_gc_arena_restore(mrb, ai);
- skip = 1;
- beg = ptr - bptr;
- if (lim_p) ++i;
+ skip = 1;
+ beg = ptr - bptr;
+ if (lim_p) ++i;
}
else {
- end = ptr - bptr;
+ end = ptr - bptr;
}
}
}
@@ -1936,15 +1944,15 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
char *ptr = RSTRING_PTR(str);
char *temp = ptr;
char *eptr = RSTRING_END(str);
- long slen = RSTRING_LEN(spat);
+ mrb_int slen = RSTRING_LEN(spat);
if (slen == 0) {
int ai = mrb_gc_arena_save(mrb);
while (ptr < eptr) {
- mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr-temp, 1));
+ mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr-temp, 1));
mrb_gc_arena_restore(mrb, ai);
- ptr++;
- if (lim_p && lim <= ++i) break;
+ ptr++;
+ if (lim_p && lim <= ++i) break;
}
}
else {
@@ -1952,11 +1960,11 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
int ai = mrb_gc_arena_save(mrb);
while (ptr < eptr &&
- (end = mrb_memsearch(sptr, slen, ptr, eptr - ptr)) >= 0) {
- mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr - temp, end));
+ (end = mrb_memsearch(sptr, slen, ptr, eptr - ptr)) >= 0) {
+ mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr - temp, end));
mrb_gc_arena_restore(mrb, ai);
- ptr += end + slen;
- if (lim_p && lim <= ++i) break;
+ ptr += end + slen;
+ if (lim_p && lim <= ++i) break;
}
}
beg = ptr - temp;
@@ -1974,7 +1982,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
mrb_ary_push(mrb, result, tmp);
}
if (!lim_p && lim == 0) {
- long len;
+ mrb_int len;
while ((len = RARRAY_LEN(result)) > 0 &&
(tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0))
mrb_ary_pop(mrb, result);
@@ -2050,14 +2058,11 @@ mrb_str_sub(mrb_state *mrb, mrb_value self)
mrb_value
mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
{
- #define BDIGIT unsigned int
- #define BDIGIT_DBL unsigned long
-
char *end;
char sign = 1;
int c;
- long len;
- unsigned long val;
+ unsigned long n;
+ mrb_int val;
#undef ISDIGIT
#define ISDIGIT(c) ('0' <= (c) && (c) <= '9')
@@ -2113,43 +2118,32 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
}
switch (base) {
case 2:
- len = 1;
if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
str += 2;
}
break;
case 3:
- len = 2;
break;
case 8:
if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
str += 2;
}
case 4: case 5: case 6: case 7:
- len = 3;
break;
case 10:
if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
str += 2;
}
case 9: case 11: case 12: case 13: case 14: case 15:
- len = 4;
break;
case 16:
- len = 4;
if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
str += 2;
}
break;
default:
if (base < 2 || 36 < base) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %d", base);
- }
- if (base <= 32) {
- len = 5;
- }
- else {
- len = 6;
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %S", mrb_fixnum_value(base));
}
break;
} /* end of switch (base) { */
@@ -2171,23 +2165,21 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
if (badcheck) goto bad;
return mrb_fixnum_value(0);
}
- len *= strlen(str);
-
- val = strtoul((char*)str, &end, base);
+ n = strtoul((char*)str, &end, base);
+ if (n > MRB_INT_MAX) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str));
+ }
+ val = n;
if (badcheck) {
if (end == str) goto bad; /* no number */
while (*end && ISSPACE(*end)) end++;
if (*end) goto bad; /* trailing garbage */
}
- if (sign) return mrb_fixnum_value(val);
- else {
- long result = -(long)val;
- return mrb_fixnum_value(result);
- }
+ return mrb_fixnum_value(sign ? val : -val);
bad:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%s)", str);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%S)", mrb_str_new_cstr(mrb, str));
/* not reached */
return mrb_fixnum_value(0);
}
@@ -2210,7 +2202,7 @@ mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, int badcheck)
char *s;
int len;
- mrb_string_value(mrb, &str);
+ str = mrb_str_to_str(mrb, str);
if (badcheck) {
s = mrb_string_value_cstr(mrb, &str);
}
@@ -2262,7 +2254,7 @@ mrb_str_to_i(mrb_state *mrb, mrb_value self)
base = mrb_fixnum(argv[0]);
if (base < 0) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %d", base);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %S", mrb_fixnum_value(base));
}
return mrb_str_to_inum(mrb, self, base, 0/*Qfalse*/);
}
@@ -2273,7 +2265,7 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, int badcheck)
char *end;
double d;
#if !defined(DBL_DIG)
- #define DBL_DIG 16
+# define DBL_DIG 16
#endif
enum {max_width = 20};
@@ -2291,7 +2283,7 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, int badcheck)
if (p == end) {
if (badcheck) {
bad:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%s)", p);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%S)", mrb_str_new_cstr(mrb, p));
/* not reached */
}
return d;
@@ -2342,7 +2334,7 @@ mrb_str_to_dbl(mrb_state *mrb, mrb_value str, int badcheck)
char *s;
int len;
- mrb_string_value(mrb, &str);
+ str = mrb_str_to_str(mrb, str);
s = RSTRING_PTR(str);
len = RSTRING_LEN(str);
if (s) {
@@ -2455,7 +2447,7 @@ mrb_str_upcase(mrb_state *mrb, mrb_value self)
mrb_value
mrb_str_dump(mrb_state *mrb, mrb_value str)
{
- long len;
+ mrb_int len;
const char *p, *pend;
char *q;
struct RString *result;
@@ -2545,7 +2537,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str)
const char *ptr;
int len;
chr = mrb_fixnum_value(c & 0xff);
- octstr = mrb_fix2str(mrb, chr, 8);
+ octstr = mrb_fixnum_to_str(mrb, chr, 8);
ptr = mrb_str_body(octstr, &len);
memcpy(q, "\\000", 4);
memcpy(q + 4 - len, ptr, len);
@@ -2557,7 +2549,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str)
}
mrb_value
-mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len)
+mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, mrb_int len)
{
if (len < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)");
@@ -2567,7 +2559,7 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len)
}
mrb_value
-mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr)
+mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr)
{
return mrb_str_cat(mrb, str, ptr, strlen(ptr));
}
@@ -2575,7 +2567,7 @@ mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr)
mrb_value
mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2)
{
- mrb_string_value(mrb, &str2);
+ str2 = mrb_str_to_str(mrb, str2);
return mrb_str_buf_append(mrb, str, str2);
}
@@ -2637,7 +2629,7 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str)
const char *ptr;
int len;
chr = mrb_fixnum_value(c & 0xff);
- octstr = mrb_fix2str(mrb, chr, 8);
+ octstr = mrb_fixnum_to_str(mrb, chr, 8);
ptr = mrb_str_body(octstr, &len);
memcpy(buf, "\\000", 4);
memcpy(buf + 4 - len, ptr, len);
diff --git a/src/symbol.c b/src/symbol.c
index 81c28d265..55bb4885a 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -4,16 +4,16 @@
** See Copyright Notice in mruby.h
*/
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
#include "mruby.h"
#include "mruby/khash.h"
-#include <string.h>
-
#include "mruby/string.h"
-#include <ctype.h>
/* ------------------------------------------------------ */
typedef struct symbol_name {
- int len;
+ size_t len;
const char *name;
} symbol_name;
@@ -35,7 +35,7 @@ KHASH_DECLARE(n2s, symbol_name, mrb_sym, 1)
KHASH_DEFINE (n2s, symbol_name, mrb_sym, 1, sym_hash_func, sym_hash_equal)
/* ------------------------------------------------------ */
mrb_sym
-mrb_intern2(mrb_state *mrb, const char *name, int len)
+mrb_intern2(mrb_state *mrb, const char *name, size_t len)
{
khash_t(n2s) *h = mrb->name2sym;
symbol_name sname;
@@ -61,7 +61,7 @@ mrb_intern2(mrb_state *mrb, const char *name, int len)
}
mrb_sym
-mrb_intern(mrb_state *mrb, const char *name)
+mrb_intern_cstr(mrb_state *mrb, const char *name)
{
return mrb_intern2(mrb, name, strlen(name));
}
@@ -72,8 +72,9 @@ mrb_intern_str(mrb_state *mrb, mrb_value str)
return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
}
+/* lenp must be a pointer to a size_t variable */
const char*
-mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, int *lenp)
+mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp)
{
khash_t(n2s) *h = mrb->name2sym;
khiter_t k;
@@ -81,16 +82,15 @@ mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, int *lenp)
for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)) {
- if (kh_value(h, k) == sym) break;
+ if (kh_value(h, k) == sym) {
+ sname = kh_key(h, k);
+ *lenp = sname.len;
+ return sname.name;
+ }
}
}
- if (k == kh_end(h)) {
- *lenp = 0;
- return NULL; /* missing */
- }
- sname = kh_key(h, k);
- *lenp = sname.len;
- return sname.name;
+ *lenp = 0;
+ return NULL; /* missing */
}
void
@@ -157,10 +157,12 @@ static mrb_value
sym_equal(mrb_state *mrb, mrb_value sym1)
{
mrb_value sym2;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &sym2);
- if (mrb_obj_equal(mrb, sym1, sym2)) return mrb_true_value();
- return mrb_false_value();
+ equal_p = mrb_obj_equal(mrb, sym1, sym2);
+
+ return mrb_bool_value(equal_p);
}
/* 15.2.11.3.2 */
@@ -179,7 +181,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym)
{
mrb_sym id = mrb_symbol(sym);
const char *p;
- int len;
+ size_t len;
p = mrb_sym2name_len(mrb, id, &len);
return mrb_str_new(mrb, p, len);
@@ -199,7 +201,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym)
static mrb_value
sym_to_sym(mrb_state *mrb, mrb_value sym)
{
- return sym;
+ return sym;
}
/* 15.2.11.3.5(x) */
@@ -223,106 +225,107 @@ sym_to_sym(mrb_state *mrb, mrb_value sym)
static int
is_special_global_name(const char* m)
{
- switch (*m) {
- case '~': case '*': case '$': case '?': case '!': case '@':
- case '/': case '\\': case ';': case ',': case '.': case '=':
- case ':': case '<': case '>': case '\"':
- case '&': case '`': case '\'': case '+':
- case '0':
- ++m;
- break;
- case '-':
- ++m;
- if (is_identchar(*m)) m += 1;
- break;
- default:
- if (!ISDIGIT(*m)) return FALSE;
- do ++m; while (ISDIGIT(*m));
- }
- return !*m;
+ switch (*m) {
+ case '~': case '*': case '$': case '?': case '!': case '@':
+ case '/': case '\\': case ';': case ',': case '.': case '=':
+ case ':': case '<': case '>': case '\"':
+ case '&': case '`': case '\'': case '+':
+ case '0':
+ ++m;
+ break;
+ case '-':
+ ++m;
+ if (is_identchar(*m)) m += 1;
+ break;
+ default:
+ if (!ISDIGIT(*m)) return FALSE;
+ do ++m; while (ISDIGIT(*m));
+ break;
+ }
+ return !*m;
}
static int
symname_p(const char *name)
{
- const char *m = name;
- int localid = FALSE;
-
- if (!m) return FALSE;
- switch (*m) {
- case '\0':
- return FALSE;
-
- case '$':
- if (is_special_global_name(++m)) return TRUE;
- goto id;
-
- case '@':
- if (*++m == '@') ++m;
- goto id;
-
- case '<':
- switch (*++m) {
- case '<': ++m; break;
- case '=': if (*++m == '>') ++m; break;
- default: break;
- }
- break;
-
- case '>':
- switch (*++m) {
- case '>': case '=': ++m; break;
- default: break;
- }
- break;
-
- case '=':
- switch (*++m) {
- case '~': ++m; break;
- case '=': if (*++m == '=') ++m; break;
- default: return FALSE;
- }
- break;
-
- case '*':
- if (*++m == '*') ++m;
- break;
- case '!':
- if (*++m == '=') ++m;
- break;
- case '+': case '-':
- if (*++m == '@') ++m;
- break;
- case '|':
- if (*++m == '|') ++m;
- break;
- case '&':
- if (*++m == '&') ++m;
- break;
-
- case '^': case '/': case '%': case '~': case '`':
- ++m;
- break;
-
- case '[':
- if (*++m != ']') return FALSE;
- if (*++m == '=') ++m;
- break;
-
- default:
- localid = !ISUPPER(*m);
+ const char *m = name;
+ int localid = FALSE;
+
+ if (!m) return FALSE;
+ switch (*m) {
+ case '\0':
+ return FALSE;
+
+ case '$':
+ if (is_special_global_name(++m)) return TRUE;
+ goto id;
+
+ case '@':
+ if (*++m == '@') ++m;
+ goto id;
+
+ case '<':
+ switch (*++m) {
+ case '<': ++m; break;
+ case '=': if (*++m == '>') ++m; break;
+ default: break;
+ }
+ break;
+
+ case '>':
+ switch (*++m) {
+ case '>': case '=': ++m; break;
+ default: break;
+ }
+ break;
+
+ case '=':
+ switch (*++m) {
+ case '~': ++m; break;
+ case '=': if (*++m == '=') ++m; break;
+ default: return FALSE;
+ }
+ break;
+
+ case '*':
+ if (*++m == '*') ++m;
+ break;
+ case '!':
+ if (*++m == '=') ++m;
+ break;
+ case '+': case '-':
+ if (*++m == '@') ++m;
+ break;
+ case '|':
+ if (*++m == '|') ++m;
+ break;
+ case '&':
+ if (*++m == '&') ++m;
+ break;
+
+ case '^': case '/': case '%': case '~': case '`':
+ ++m;
+ break;
+
+ case '[':
+ if (*++m != ']') return FALSE;
+ if (*++m == '=') ++m;
+ break;
+
+ default:
+ localid = !ISUPPER(*m);
id:
- if (*m != '_' && !ISALPHA(*m)) return FALSE;
- while (is_identchar(*m)) m += 1;
- if (localid) {
- switch (*m) {
- case '!': case '?': case '=': ++m;
- default: break;
+ if (*m != '_' && !ISALPHA(*m)) return FALSE;
+ while (is_identchar(*m)) m += 1;
+ if (localid) {
+ switch (*m) {
+ case '!': case '?': case '=': ++m;
+ default: break;
}
}
- break;
- }
- return *m ? FALSE : TRUE;
+ break;
+ }
+ return *m ? FALSE : TRUE;
}
static mrb_value
@@ -330,7 +333,7 @@ sym_inspect(mrb_state *mrb, mrb_value sym)
{
mrb_value str;
const char *name;
- int len;
+ size_t len;
mrb_sym id = mrb_symbol(sym);
name = mrb_sym2name_len(mrb, id, &len);
@@ -344,10 +347,25 @@ sym_inspect(mrb_state *mrb, mrb_value sym)
return str;
}
+mrb_value
+mrb_sym2str(mrb_state *mrb, mrb_sym sym)
+{
+ size_t len;
+ const char *name = mrb_sym2name_len(mrb, sym, &len);
+
+ if (!name) return mrb_undef_value(); /* can't happen */
+ if (symname_p(name) && strlen(name) == len) {
+ return mrb_str_new(mrb, name, len);
+ }
+ else {
+ return mrb_str_dump(mrb, mrb_str_new(mrb, name, len));
+ }
+}
+
const char*
mrb_sym2name(mrb_state *mrb, mrb_sym sym)
{
- int len;
+ size_t len;
const char *name = mrb_sym2name_len(mrb, sym, &len);
if (!name) return NULL;
@@ -375,7 +393,8 @@ sym_cmp(mrb_state *mrb, mrb_value s1)
if (sym1 == sym2) return mrb_fixnum_value(0);
else {
const char *p1, *p2;
- int len, len1, len2, retval;
+ int retval;
+ size_t len, len1, len2;
p1 = mrb_sym2name_len(mrb, sym1, &len1);
p2 = mrb_sym2name_len(mrb, sym2, &len2);
diff --git a/src/value_array.h b/src/value_array.h
new file mode 100644
index 000000000..cabd2426d
--- /dev/null
+++ b/src/value_array.h
@@ -0,0 +1,27 @@
+#ifndef MRB_VALUE_ARRAY_H__
+#define MRB_VALUE_ARRAY_H__
+
+#include "mruby.h"
+
+static inline void
+value_move(mrb_value *s1, const mrb_value *s2, size_t n)
+{
+ if (s1 > s2 && s1 < s2 + n)
+ {
+ s1 += n;
+ s2 += n;
+ while (n-- > 0) {
+ *--s1 = *--s2;
+ }
+ }
+ else if (s1 != s2) {
+ while (n-- > 0) {
+ *s1++ = *s2++;
+ }
+ }
+ else {
+ /* nothing to do. */
+ }
+}
+
+#endif /* MRB_VALUE_ARRAY_H__ */
diff --git a/src/variable.c b/src/variable.c
index 5f657e3d7..941aaf83e 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -5,12 +5,12 @@
*/
#include "mruby.h"
+#include "mruby/array.h"
#include "mruby/class.h"
+#include "mruby/proc.h"
+#include "mruby/string.h"
#include "mruby/variable.h"
#include "error.h"
-#include "mruby/array.h"
-#include "mruby/string.h"
-#include "mruby/proc.h"
typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
@@ -28,8 +28,8 @@ typedef struct segment {
typedef struct iv_tbl {
segment *rootseg;
- int size;
- int last_len;
+ size_t size;
+ size_t last_len;
} iv_tbl;
static iv_tbl*
@@ -52,27 +52,27 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
segment *seg = t->rootseg;
segment *prev = NULL;
segment *matched_seg = NULL;
- int matched_idx = 0;
- int i;
+ size_t matched_idx = 0;
+ size_t i;
while (seg) {
for (i=0; i<MRB_SEGMENT_SIZE; i++) {
mrb_sym key = seg->key[i];
/* found room in last segment after last_len */
if (!seg->next && i >= t->last_len) {
- seg->key[i] = sym;
- seg->val[i] = val;
- t->last_len = i+1;
- t->size++;
- return;
+ seg->key[i] = sym;
+ seg->val[i] = val;
+ t->last_len = i+1;
+ t->size++;
+ return;
}
if (!matched_seg && key == 0) {
- matched_seg = seg;
- matched_idx = i;
+ matched_seg = seg;
+ matched_idx = i;
}
else if (key == sym) {
- seg->val[i] = val;
- return;
+ seg->val[i] = val;
+ return;
}
}
prev = seg;
@@ -102,11 +102,11 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
return;
}
-static int
+static mrb_bool
iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
segment *seg;
- int i;
+ size_t i;
seg = t->rootseg;
while (seg) {
@@ -114,11 +114,11 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
mrb_sym key = seg->key[i];
if (!seg->next && i >= t->last_len) {
- return FALSE;
+ return FALSE;
}
if (key == sym) {
- if (vp) *vp = seg->val[i];
- return TRUE;
+ if (vp) *vp = seg->val[i];
+ return TRUE;
}
}
seg = seg->next;
@@ -126,11 +126,11 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
return FALSE;
}
-static int
+static mrb_bool
iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
segment *seg;
- int i;
+ size_t i;
seg = t->rootseg;
while (seg) {
@@ -138,13 +138,13 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
mrb_sym key = seg->key[i];
if (!seg->next && i >= t->last_len) {
- return FALSE;
+ return FALSE;
}
if (key == sym) {
- t->size--;
- seg->key[i] = 0;
- if (vp) *vp = seg->val[i];
- return TRUE;
+ t->size--;
+ seg->key[i] = 0;
+ if (vp) *vp = seg->val[i];
+ return TRUE;
}
}
seg = seg->next;
@@ -152,11 +152,12 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
return FALSE;
}
-static int
+static mrb_bool
iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
{
segment *seg;
- int i, n;
+ size_t i;
+ int n;
seg = t->rootseg;
while (seg) {
@@ -165,15 +166,15 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
/* no value in last segment after last_len */
if (!seg->next && i >= t->last_len) {
- return FALSE;
+ return FALSE;
}
if (key != 0) {
- n =(*func)(mrb, key, seg->val[i], p);
- if (n > 0) return FALSE;
- if (n < 0) {
- t->size--;
- seg->key[i] = 0;
- }
+ n =(*func)(mrb, key, seg->val[i], p);
+ if (n > 0) return FALSE;
+ if (n < 0) {
+ t->size--;
+ seg->key[i] = 0;
+ }
}
}
seg = seg->next;
@@ -181,11 +182,11 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
return TRUE;
}
-static int
+static size_t
iv_size(mrb_state *mrb, iv_tbl *t)
{
segment *seg;
- int size = 0;
+ size_t size = 0;
if (!t) return 0;
if (t->size > 0) return t->size;
@@ -208,7 +209,7 @@ iv_copy(mrb_state *mrb, iv_tbl *t)
segment *seg;
iv_tbl *t2;
- int i;
+ size_t i;
seg = t->rootseg;
t2 = iv_new(mrb);
@@ -273,7 +274,7 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
kh_value(h, k) = val;
}
-static int
+static mrb_bool
iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
khash_t(iv) *h = &t->h;
@@ -287,7 +288,7 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
return FALSE;
}
-static int
+static mrb_bool
iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
khash_t(iv) *h = &t->h;
@@ -305,7 +306,7 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
return FALSE;
}
-static int
+static mrb_bool
iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
{
khash_t(iv) *h = &t->h;
@@ -315,18 +316,18 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
if (h) {
for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)){
- n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p);
- if (n > 0) return FALSE;
- if (n < 0) {
- kh_del(iv, h, k);
- }
+ n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p);
+ if (n > 0) return FALSE;
+ if (n < 0) {
+ kh_del(iv, h, k);
+ }
}
}
}
return TRUE;
}
-static int
+static size_t
iv_size(mrb_state *mrb, iv_tbl *t)
{
khash_t(iv) *h = &t->h;
@@ -408,7 +409,7 @@ mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v)
{
}
-static int
+static mrb_bool
obj_iv_p(mrb_value obj)
{
switch (mrb_type(obj)) {
@@ -481,7 +482,7 @@ mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v)
}
}
-int
+mrb_bool
mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
{
iv_tbl *t;
@@ -493,7 +494,7 @@ mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
return FALSE;
}
-int
+mrb_bool
mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym)
{
if (!obj_iv_p(obj)) return FALSE;
@@ -520,15 +521,15 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
mrb_value str = *(mrb_value*)p;
const char *s;
- int len;
+ size_t len;
/* need not to show internal data */
if (RSTRING_PTR(str)[0] == '-') { /* first element */
RSTRING_PTR(str)[0] = '#';
- mrb_str_cat2(mrb, str, " ");
+ mrb_str_cat(mrb, str, " ", 1);
}
else {
- mrb_str_cat2(mrb, str, ", ");
+ mrb_str_cat(mrb, str, ", ", 2);
}
s = mrb_sym2name_len(mrb, sym, &len);
mrb_str_cat(mrb, str, s, len);
@@ -541,13 +542,19 @@ mrb_value
mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj)
{
iv_tbl *t = obj->iv;
- int len = iv_size(mrb, t);
+ size_t len = iv_size(mrb, t);
if (len > 0) {
const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj));
- mrb_value str = mrb_sprintf(mrb, "-<%s:%p", cn, (void*)obj);
+ mrb_value str = mrb_str_buf_new(mrb, 30);
+
+ mrb_str_buf_cat(mrb, str, "-<", 2);
+ mrb_str_cat2(mrb, str, cn);
+ mrb_str_cat(mrb, str, ":", 1);
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj));
iv_foreach(mrb, t, inspect_i, &str);
+ mrb_str_cat(mrb, str, ">", 1);
return str;
}
return mrb_any_to_s(mrb, mrb_obj_value(obj));
@@ -586,7 +593,7 @@ iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
mrb_value ary;
const char* s;
- int len;
+ size_t len;
ary = *(mrb_value*)p;
s = mrb_sym2name_len(mrb, sym, &len);
@@ -630,7 +637,7 @@ cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
mrb_value ary;
const char* s;
- int len;
+ size_t len;
ary = *(mrb_value*)p;
s = mrb_sym2name_len(mrb, sym, &len);
@@ -683,8 +690,8 @@ mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym)
}
c = c->super;
}
- mrb_raisef(mrb, E_NAME_ERROR, "uninitialized class variable %s in %s",
- mrb_sym2name(mrb, sym), mrb_class_name(mrb, cls));
+ mrb_raisef(mrb, E_NAME_ERROR, "uninitialized class variable %S in %S",
+ mrb_sym2str(mrb, sym), cls);
/* not reached */
return mrb_nil_value();
}
@@ -727,7 +734,7 @@ mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v);
}
-int
+mrb_bool
mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym)
{
while (c) {
@@ -741,7 +748,7 @@ mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym)
return FALSE;
}
-int
+mrb_bool
mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
{
return mrb_mod_cv_defined(mrb, mrb_class_ptr(mod), sym);
@@ -753,7 +760,7 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
struct RClass *c = mrb->ci->proc->target_class;
if (!c) c = mrb->ci->target_class;
-
+
return mrb_mod_cv_get(mrb, c, sym);
}
@@ -769,7 +776,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
if (iv_get(mrb, t, sym, NULL)) {
mrb_write_barrier(mrb, (struct RBasic*)c);
- iv_put(mrb, t, sym, v);
+ iv_put(mrb, t, sym, v);
return;
}
}
@@ -783,7 +790,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
iv_put(mrb, c->iv, sym, v);
}
-int
+mrb_bool
mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
{
struct RClass *m = mrb_class_ptr(mod);
@@ -813,15 +820,15 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
struct RClass *c = base;
mrb_value v;
iv_tbl *t;
- int retry = 0;
+ mrb_bool retry = 0;
mrb_sym cm;
- L_RETRY:
+L_RETRY:
while (c) {
if (c->iv) {
t = c->iv;
if (iv_get(mrb, t, sym, &v))
- return v;
+ return v;
}
c = c->super;
}
@@ -831,7 +838,7 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
goto L_RETRY;
}
c = base;
- cm = mrb_intern(mrb, "const_missing");
+ cm = mrb_intern2(mrb, "const_missing", 13);
while (c) {
if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) {
mrb_value name = mrb_symbol_value(sym);
@@ -839,8 +846,8 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
}
c = c->super;
}
- mrb_raisef(mrb, E_NAME_ERROR, "uninitialized constant %s",
- mrb_sym2name(mrb, sym));
+ mrb_raisef(mrb, E_NAME_ERROR, "uninitialized constant %S",
+ mrb_sym2str(mrb, sym));
/* not reached */
return mrb_nil_value();
}
@@ -870,7 +877,7 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
c2 = mrb_class_outer_module(mrb, c2);
if (!c2) break;
if (c2->iv && iv_get(mrb, c2->iv, sym, &v)) {
- return v;
+ return v;
}
}
}
@@ -964,7 +971,7 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self)
{
iv_tbl *t = mrb->globals;
mrb_value ary = mrb_ary_new(mrb);
- int i;
+ size_t i;
char buf[3];
if (t) {
@@ -979,11 +986,11 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self)
return ary;
}
-static int
-mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, int exclude, int recurse)
+static mrb_bool
+mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, mrb_bool exclude, mrb_bool recurse)
{
struct RClass * tmp;
- int mod_retry = 0;
+ mrb_bool mod_retry = 0;
tmp = klass;
retry:
@@ -1036,7 +1043,7 @@ csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) {
a->sym = sym;
- return 1; /* stop iteration */
+ return 1; /* stop iteration */
}
return 0;
}
@@ -1046,7 +1053,7 @@ mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer)
{
mrb_value name;
- name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__"));
+ name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__classid__", 11));
if (mrb_nil_p(name)) {
if (!outer) return 0;
diff --git a/src/vm.c b/src/vm.c
index 6e15c48a0..596e34961 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -4,24 +4,24 @@
** See Copyright Notice in mruby.h
*/
+#include <string.h>
+#include <setjmp.h>
+#include <stddef.h>
+#include <stdarg.h>
#include "mruby.h"
-#include "opcode.h"
-#include "mruby/irep.h"
-#include "mruby/variable.h"
-#include "mruby/proc.h"
#include "mruby/array.h"
-#include "mruby/string.h"
-#include "mruby/hash.h"
-#include "mruby/range.h"
#include "mruby/class.h"
+#include "mruby/hash.h"
+#include "mruby/irep.h"
#include "mruby/numeric.h"
+#include "mruby/proc.h"
+#include "mruby/range.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
#include "error.h"
+#include "opcode.h"
+#include "value_array.h"
-#include <stdio.h>
-#include <string.h>
-#include <setjmp.h>
-#include <stddef.h>
-#include <stdarg.h>
#define SET_TRUE_VALUE(r) MRB_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
#define SET_FALSE_VALUE(r) MRB_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
@@ -46,7 +46,7 @@
/* Maximum stack depth. Should be set lower on memory constrained systems.
The value below allows about 60000 recursive calls in the simplest case. */
#ifndef MRB_STACK_MAX
-#define MRB_STACK_MAX ((1<<18) - MRB_STACK_GROWTH)
+#define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH)
#endif
#ifdef VM_DEBUG
@@ -56,12 +56,20 @@ The value below allows about 60000 recursive calls in the simplest case. */
#endif
static inline void
-stack_copy(mrb_value *dst, const mrb_value *src, size_t size)
+stack_clear(mrb_value *from, size_t count)
{
- size_t i;
+ const mrb_value mrb_value_zero = { { 0 } };
- for (i = 0; i < size; i++) {
- dst[i] = src[i];
+ while(count-- > 0) {
+ *from++ = mrb_value_zero;
+ }
+}
+
+static inline void
+stack_copy(mrb_value *dst, const mrb_value *src, size_t size)
+{
+ while (size-- > 0) {
+ *dst++ = *src++;
}
}
@@ -80,7 +88,7 @@ stack_init(mrb_state *mrb)
mrb->ci->target_class = mrb->object_class;
}
-static void
+static inline void
envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
{
mrb_callinfo *ci = mrb->cibase;
@@ -88,7 +96,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
while (ci <= mrb->ci) {
struct REnv *e = ci->env;
if (e && e->cioff >= 0) {
- int off = e->stack - oldbase;
+ ptrdiff_t off = e->stack - oldbase;
e->stack = newbase + off;
}
@@ -101,8 +109,9 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
static void
stack_extend(mrb_state *mrb, int room, int keep)
{
- int size, off;
if (mrb->stack + room >= mrb->stend) {
+ int size, off;
+
mrb_value *oldbase = mrb->stbase;
size = mrb->stend - mrb->stbase;
@@ -125,32 +134,24 @@ stack_extend(mrb_state *mrb, int room, int keep)
envadjust(mrb, oldbase, mrb->stbase);
/* Raise an exception if the new stack size will be too large,
to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raisef has stack space to work with. */
- if(size > MRB_STACK_MAX) {
- mrb_raisef(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=%d)", MRB_STACK_MAX);
+ if (size > MRB_STACK_MAX) {
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=%S)", mrb_fixnum_value(MRB_STACK_MAX));
}
}
if (room > keep) {
- int i;
- for (i=keep; i<room; i++) {
#ifndef MRB_NAN_BOXING
- static const mrb_value mrb_value_zero = { { 0 } };
- mrb->stack[i] = mrb_value_zero;
+ stack_clear(&(mrb->stack[keep]), room - keep);
#else
+ int i;
+ for (i=keep; i<room; i++) {
SET_NIL_VALUE(mrb->stack[i]);
-#endif
}
+#endif
}
}
-int
-mrb_checkstack(mrb_state *mrb, int size)
-{
- stack_extend(mrb, size+1, 1);
- return 0;
-}
-
-struct REnv*
+static inline struct REnv*
uvenv(mrb_state *mrb, int up)
{
struct REnv *e = mrb->ci->proc->env;
@@ -162,25 +163,6 @@ uvenv(mrb_state *mrb, int up)
return e;
}
-static mrb_value
-uvget(mrb_state *mrb, int up, int idx)
-{
- struct REnv *e = uvenv(mrb, up);
-
- if (!e) return mrb_nil_value();
- return e->stack[idx];
-}
-
-static void
-uvset(mrb_state *mrb, int up, int idx, mrb_value v)
-{
- struct REnv *e = uvenv(mrb, up);
-
- if (!e) return;
- e->stack[idx] = v;
- mrb_write_barrier(mrb, (struct RBasic*)e);
-}
-
static inline int
is_strict(mrb_state *mrb, struct REnv *e)
{
@@ -193,7 +175,7 @@ is_strict(mrb_state *mrb, struct REnv *e)
return 0;
}
-struct REnv*
+static inline struct REnv*
top_env(mrb_state *mrb, struct RProc *proc)
{
struct REnv *e = proc->env;
@@ -220,7 +202,7 @@ cipush(mrb_state *mrb)
mrb->ciend = mrb->cibase + size * 2;
}
mrb->ci++;
- mrb->ci->nregs = 2; /* protect method_missing arg and block */
+ mrb->ci->nregs = 2; /* protect method_missing arg and block */
mrb->ci->eidx = eidx;
mrb->ci->ridx = ridx;
mrb->ci->env = 0;
@@ -232,7 +214,7 @@ cipop(mrb_state *mrb)
{
if (mrb->ci->env) {
struct REnv *e = mrb->ci->env;
- int len = (int)e->flags;
+ size_t len = (size_t)e->flags;
mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
e->cioff = -1;
@@ -274,14 +256,13 @@ mrb_value
mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...)
{
mrb_sym mid = mrb_intern(mrb, name);
- va_list ap;
- int i;
if (argc == 0) {
return mrb_funcall_argv(mrb, self, mid, 0, 0);
}
else if (argc == 1) {
mrb_value v;
+ va_list ap;
va_start(ap, argc);
v = va_arg(ap, mrb_value);
@@ -290,9 +271,11 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...)
}
else {
mrb_value argv[MRB_FUNCALL_ARGC_MAX];
+ va_list ap;
+ int i;
if (argc > MRB_FUNCALL_ARGC_MAX) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%S)", mrb_fixnum_value(MRB_FUNCALL_ARGC_MAX));
}
va_start(ap, argc);
@@ -307,83 +290,86 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...)
mrb_value
mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv, mrb_value blk)
{
- struct RProc *p;
- struct RClass *c;
- mrb_sym undef = 0;
- mrb_callinfo *ci;
- int n;
mrb_value val;
if (!mrb->jmp) {
jmp_buf c_jmp;
mrb_callinfo *old_ci = mrb->ci;
- if (setjmp(c_jmp) != 0) { /* error */
+ if (setjmp(c_jmp) != 0) { /* error */
while (old_ci != mrb->ci) {
mrb->stack = mrb->stbase + mrb->ci->stackidx;
cipop(mrb);
}
mrb->jmp = 0;
- return mrb_nil_value();
+ val = mrb_nil_value();
+ }
+ else {
+ mrb->jmp = &c_jmp;
+ /* recursive call */
+ val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
+ mrb->jmp = 0;
}
- mrb->jmp = &c_jmp;
- /* recursive call */
- val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
- mrb->jmp = 0;
- return val;
- }
-
- if (!mrb->stack) {
- stack_init(mrb);
- }
- n = mrb->ci->nregs;
- if (argc < 0) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc);
- }
- c = mrb_class(mrb, self);
- p = mrb_method_search_vm(mrb, &c, mid);
- if (!p) {
- undef = mid;
- mid = mrb_intern(mrb, "method_missing");
- p = mrb_method_search_vm(mrb, &c, mid);
- n++; argc++;
- }
- ci = cipush(mrb);
- ci->mid = mid;
- ci->proc = p;
- ci->stackidx = mrb->stack - mrb->stbase;
- ci->argc = argc;
- ci->target_class = p->target_class;
- if (MRB_PROC_CFUNC_P(p)) {
- ci->nregs = argc + 2;
}
else {
- ci->nregs = p->body.irep->nregs + 2;
- }
- ci->acc = -1;
- mrb->stack = mrb->stack + n;
-
- stack_extend(mrb, ci->nregs, 0);
- mrb->stack[0] = self;
- if (undef) {
- mrb->stack[1] = mrb_symbol_value(undef);
- stack_copy(mrb->stack+2, argv, argc-1);
- }
- else if (argc > 0) {
- stack_copy(mrb->stack+1, argv, argc);
- }
- mrb->stack[argc+1] = blk;
+ struct RProc *p;
+ struct RClass *c;
+ mrb_sym undef = 0;
+ mrb_callinfo *ci;
+ int n;
- if (MRB_PROC_CFUNC_P(p)) {
- int ai = mrb_gc_arena_save(mrb);
- val = p->body.func(mrb, self);
- mrb_gc_arena_restore(mrb, ai);
- mrb_gc_protect(mrb, val);
- mrb->stack = mrb->stbase + mrb->ci->stackidx;
- cipop(mrb);
- }
- else {
- val = mrb_run(mrb, p, self);
+ if (!mrb->stack) {
+ stack_init(mrb);
+ }
+ n = mrb->ci->nregs;
+ if (argc < 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc));
+ }
+ c = mrb_class(mrb, self);
+ p = mrb_method_search_vm(mrb, &c, mid);
+ if (!p) {
+ undef = mid;
+ mid = mrb_intern2(mrb, "method_missing", 14);
+ p = mrb_method_search_vm(mrb, &c, mid);
+ n++; argc++;
+ }
+ ci = cipush(mrb);
+ ci->mid = mid;
+ ci->proc = p;
+ ci->stackidx = mrb->stack - mrb->stbase;
+ ci->argc = argc;
+ ci->target_class = p->target_class;
+ if (MRB_PROC_CFUNC_P(p)) {
+ ci->nregs = argc + 2;
+ }
+ else {
+ ci->nregs = p->body.irep->nregs + 2;
+ }
+ ci->acc = -1;
+ mrb->stack = mrb->stack + n;
+
+ stack_extend(mrb, ci->nregs, 0);
+ mrb->stack[0] = self;
+ if (undef) {
+ mrb->stack[1] = mrb_symbol_value(undef);
+ stack_copy(mrb->stack+2, argv, argc-1);
+ }
+ else if (argc > 0) {
+ stack_copy(mrb->stack+1, argv, argc);
+ }
+ mrb->stack[argc+1] = blk;
+
+ if (MRB_PROC_CFUNC_P(p)) {
+ int ai = mrb_gc_arena_save(mrb);
+ val = p->body.func(mrb, self);
+ mrb_gc_arena_restore(mrb, ai);
+ mrb_gc_protect(mrb, val);
+ mrb->stack = mrb->stbase + mrb->ci->stackidx;
+ cipop(mrb);
+ }
+ else {
+ val = mrb_run(mrb, p, self);
+ }
}
return val;
}
@@ -453,36 +439,45 @@ mrb_yield(mrb_state *mrb, mrb_value b, mrb_value v)
return mrb_yield_internal(mrb, b, 1, &v, mrb->stack[0], p->target_class);
}
+typedef enum {
+ LOCALJUMP_ERROR_RETURN = 0,
+ LOCALJUMP_ERROR_BREAK = 1,
+ LOCALJUMP_ERROR_YIELD = 2
+} localjump_error_kind;
+
static void
-localjump_error(mrb_state *mrb, const char *kind)
+localjump_error(mrb_state *mrb, localjump_error_kind kind)
{
- char buf[256];
- int len;
+ char kind_str[3][7] = { "return", "break", "yield" };
+ char kind_str_len[] = { 6, 5, 5 };
+ static const char lead[] = "unexpected ";
+ mrb_value msg;
mrb_value exc;
- len = snprintf(buf, sizeof(buf), "unexpected %s", kind);
- exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, buf, len);
- mrb->exc = (struct RObject*)mrb_object(exc);
+ msg = mrb_str_buf_new(mrb, sizeof(lead) + 7);
+ mrb_str_buf_cat(mrb, msg, lead, sizeof(lead) - 1);
+ mrb_str_buf_cat(mrb, msg, kind_str[kind], kind_str_len[kind]);
+ exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg);
+ mrb->exc = mrb_obj_ptr(exc);
}
static void
argnum_error(mrb_state *mrb, int num)
{
- char buf[256];
- int len;
mrb_value exc;
+ mrb_value str;
if (mrb->ci->mid) {
- len = snprintf(buf, sizeof(buf), "'%s': wrong number of arguments (%d for %d)",
- mrb_sym2name(mrb, mrb->ci->mid),
- mrb->ci->argc, num);
+ str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)",
+ mrb_sym2str(mrb, mrb->ci->mid),
+ mrb_fixnum_value(mrb->ci->argc), mrb_fixnum_value(num));
}
else {
- len = snprintf(buf, sizeof(buf), "wrong number of arguments (%d for %d)",
- mrb->ci->argc, num);
+ str = mrb_format(mrb, "wrong number of arguments (%S for %S)",
+ mrb_fixnum_value(mrb->ci->argc), mrb_fixnum_value(num));
}
- exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, len);
- mrb->exc = (struct RObject*)mrb_object(exc);
+ exc = mrb_exc_new3(mrb, E_ARGUMENT_ERROR, str);
+ mrb->exc = mrb_obj_ptr(exc);
}
#ifdef ENABLE_DEBUG
@@ -700,14 +695,34 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_GETUPVAR) {
/* A B C R(A) := uvget(B,C) */
+ mrb_value *regs_a = regs + GETARG_A(i);
+ int up = GETARG_C(i);
+
+ struct REnv *e = uvenv(mrb, up);
- regs[GETARG_A(i)] = uvget(mrb, GETARG_C(i), GETARG_B(i));
+ if (!e) {
+ *regs_a = mrb_nil_value();
+ }
+ else {
+ int idx = GETARG_B(i);
+ *regs_a = e->stack[idx];
+ }
NEXT;
}
CASE(OP_SETUPVAR) {
/* A B C uvset(B,C,R(A)) */
- uvset(mrb, GETARG_C(i), GETARG_B(i), regs[GETARG_A(i)]);
+ /* A B C R(A) := uvget(B,C) */
+ int up = GETARG_C(i);
+
+ struct REnv *e = uvenv(mrb, up);
+
+ if (e) {
+ mrb_value *regs_a = regs + GETARG_A(i);
+ int idx = GETARG_B(i);
+ e->stack[idx] = *regs_a;
+ mrb_write_barrier(mrb, (struct RBasic*)e);
+ }
NEXT;
}
@@ -764,7 +779,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_RAISE) {
/* A raise(R(A)) */
- mrb->exc = (struct RObject*)mrb_object(regs[GETARG_A(i)]);
+ mrb->exc = mrb_obj_ptr(regs[GETARG_A(i)]);
goto L_RAISE;
}
@@ -833,15 +848,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (!m) {
mrb_value sym = mrb_symbol_value(mid);
- mid = mrb_intern(mrb, "method_missing");
+ mid = mrb_intern2(mrb, "method_missing", 14);
m = mrb_method_search_vm(mrb, &c, mid);
if (n == CALL_MAXARGS) {
mrb_ary_unshift(mrb, regs[a+1], sym);
}
else {
- memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1));
+ value_move(regs+a+2, regs+a+1, ++n);
regs[a+1] = sym;
- n++;
}
}
@@ -850,8 +864,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->mid = mid;
ci->proc = m;
ci->stackidx = mrb->stack - mrb->stbase;
- ci->argc = n;
- if (ci->argc == CALL_MAXARGS) ci->argc = -1;
+ if (n == CALL_MAXARGS) {
+ ci->argc = -1;
+ }
+ else {
+ ci->argc = n;
+ }
ci->target_class = c;
ci->pc = pc + 1;
ci->acc = a;
@@ -972,15 +990,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
c = mrb->ci->target_class->super;
m = mrb_method_search_vm(mrb, &c, mid);
if (!m) {
- mid = mrb_intern(mrb, "method_missing");
+ mid = mrb_intern2(mrb, "method_missing", 14);
m = mrb_method_search_vm(mrb, &c, mid);
if (n == CALL_MAXARGS) {
mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid));
}
else {
- memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1));
+ value_move(regs+a+2, regs+a+1, ++n);
SET_SYM_VALUE(regs[a+1], ci->mid);
- n++;
}
}
@@ -989,8 +1006,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->mid = mid;
ci->proc = m;
ci->stackidx = mrb->stack - mrb->stbase;
- ci->argc = n;
- if (ci->argc == CALL_MAXARGS) ci->argc = -1;
+ if (n == CALL_MAXARGS) {
+ ci->argc = -1;
+ }
+ else {
+ ci->argc = n;
+ }
ci->target_class = m->target_class;
ci->pc = pc + 1;
@@ -1017,7 +1038,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
pool = irep->pool;
syms = irep->syms;
ci->nregs = irep->nregs;
- if (ci->argc < 0) {
+ if (n == CALL_MAXARGS) {
stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
}
else {
@@ -1046,13 +1067,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
mrb_value exc;
static const char m[] = "super called outside of method";
exc = mrb_exc_new(mrb, E_NOMETHOD_ERROR, m, sizeof(m) - 1);
- mrb->exc = (struct RObject*)mrb_object(exc);
+ mrb->exc = mrb_obj_ptr(exc);
goto L_RAISE;
}
stack = e->stack + 1;
}
if (r == 0) {
- regs[a] = mrb_ary_new_elts(mrb, m1+m2, stack);
+ regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack);
}
else {
mrb_value *pp = NULL;
@@ -1084,7 +1105,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_ENTER) {
/* Ax arg setup according to flags (24=5:5:1:5:5:1:1) */
/* number of optional arguments times OP_JMP should follow */
- int ax = GETARG_Ax(i);
+ int32_t ax = GETARG_Ax(i);
int m1 = (ax>>18)&0x1f;
int o = (ax>>13)&0x1f;
int r = (ax>>12)&0x1;
@@ -1122,10 +1143,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (argc < len) {
regs[len+1] = *blk; /* move block */
if (argv0 != argv) {
- memmove(&regs[1], argv, sizeof(mrb_value)*(argc-m2)); /* m1 + o */
+ value_move(&regs[1], argv, argc-m2); /* m1 + o */
}
if (m2) {
- memmove(&regs[len-m2+1], &argv[argc-m2], sizeof(mrb_value)*m2); /* m2 */
+ value_move(&regs[len-m2+1], &argv[argc-m2], m2); /* m2 */
}
if (r) { /* r */
regs[m1+o+1] = mrb_ary_new_capa(mrb, 0);
@@ -1137,13 +1158,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
if (argv0 != argv) {
regs[len+1] = *blk; /* move block */
- memmove(&regs[1], argv, sizeof(mrb_value)*(m1+o)); /* m1 + o */
+ value_move(&regs[1], argv, m1+o); /* m1 + o */
}
if (r) { /* r */
- regs[m1+o+1] = mrb_ary_new_elts(mrb, argc-m1-o-m2, argv+m1+o);
+ regs[m1+o+1] = mrb_ary_new_from_values(mrb, argc-m1-o-m2, argv+m1+o);
}
if (m2) {
- memmove(&regs[m1+o+r+1], &argv[argc-m2], sizeof(mrb_value)*m2);
+ value_move(&regs[m1+o+r+1], &argv[argc-m2], m2);
}
if (argv0 == argv) {
regs[len+1] = *blk; /* move block */
@@ -1174,8 +1195,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
L_RAISE:
ci = mrb->ci;
- mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern(mrb, "lastpc"), mrb_voidp_value(pc));
- mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->cibase));
+ mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(pc));
+ mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase));
eidx = ci->eidx;
if (ci == mrb->cibase) {
if (ci->ridx == 0) goto L_STOP;
@@ -1218,12 +1239,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
struct REnv *e = top_env(mrb, proc);
if (e->cioff < 0) {
- localjump_error(mrb, "return");
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
}
ci = mrb->cibase + e->cioff;
if (ci == mrb->cibase) {
- localjump_error(mrb, "return");
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
}
mrb->ci = ci;
@@ -1231,14 +1252,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
case OP_R_NORMAL:
if (ci == mrb->cibase) {
- localjump_error(mrb, "return");
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
}
ci = mrb->ci;
break;
case OP_R_BREAK:
if (proc->env->cioff < 0) {
- localjump_error(mrb, "break");
+ localjump_error(mrb, LOCALJUMP_ERROR_BREAK);
goto L_RAISE;
}
ci = mrb->ci = mrb->cibase + proc->env->cioff + 1;
@@ -1291,15 +1312,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (!m) {
mrb_value sym = mrb_symbol_value(mid);
- mid = mrb_intern(mrb, "method_missing");
+ mid = mrb_intern2(mrb, "method_missing", 14);
m = mrb_method_search_vm(mrb, &c, mid);
if (n == CALL_MAXARGS) {
mrb_ary_unshift(mrb, regs[a+1], sym);
}
else {
- memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1));
+ value_move(regs+a+2, regs+a+1, ++n);
regs[a+1] = sym;
- n++;
}
}
@@ -1308,11 +1328,15 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci = mrb->ci;
ci->mid = mid;
ci->target_class = m->target_class;
- ci->argc = n;
- if (ci->argc == CALL_MAXARGS) ci->argc = -1;
+ if (n == CALL_MAXARGS) {
+ ci->argc = -1;
+ }
+ else {
+ ci->argc = n;
+ }
/* move stack */
- memmove(mrb->stack, &regs[a], (ci->argc+1)*sizeof(mrb_value));
+ value_move(mrb->stack, &regs[a], ci->argc+1);
if (MRB_PROC_CFUNC_P(m)) {
mrb->stack[0] = m->body.func(mrb, recv);
@@ -1350,7 +1374,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
struct REnv *e = uvenv(mrb, lv-1);
if (!e) {
- localjump_error(mrb, "yield");
+ localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
goto L_RAISE;
}
stack = e->stack + 1;
@@ -1366,7 +1390,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
#define attr_f value.f
#endif
-#define TYPES2(a,b) (((((int)(a))<<8)|((int)(b)))&0xffff)
+#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
#define OP_MATH_BODY(op,v1,v2) do {\
regs[a].v1 = regs[a].v1 op regs[a+1].v2;\
} while(0)
@@ -1380,16 +1404,18 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
{
mrb_int x, y, z;
+ mrb_value *regs_a = regs + a;
- x = mrb_fixnum(regs[a]);
- y = mrb_fixnum(regs[a+1]);
+ x = mrb_fixnum(regs_a[0]);
+ y = mrb_fixnum(regs_a[1]);
z = x + y;
- if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) {
+ if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) == 0) {
/* integer overflow */
- SET_FLT_VALUE(regs[a], (mrb_float)x + (mrb_float)y);
- break;
+ SET_FLT_VALUE(regs_a[0], (mrb_float)x + (mrb_float)y);
+ }
+ else {
+ regs_a[0].attr_i = z;
}
- SET_INT_VALUE(regs[a], z);
}
break;
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
@@ -1561,28 +1587,30 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_SUBI) {
/* A B C R(A) := R(A)-C (Syms[B]=:+)*/
int a = GETARG_A(i);
+ mrb_value *regs_a = regs + a;
/* need to check if + is overridden */
- switch (mrb_type(regs[a])) {
+ switch (mrb_type(regs_a[0])) {
case MRB_TT_FIXNUM:
{
- mrb_int x = regs[a].attr_i;
+ mrb_int x = regs_a[0].attr_i;
mrb_int y = GETARG_C(i);
mrb_int z = x - y;
- if (((x < 0) ^ (y < 0)) != 0 && (x < 0) != (z < 0)) {
+ if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) != 0) {
/* integer overflow */
- SET_FLT_VALUE(regs[a], (mrb_float)x - (mrb_float)y);
- break;
+ SET_FLT_VALUE(regs_a[0], (mrb_float)x - (mrb_float)y);
+ }
+ else {
+ regs_a[0].attr_i = z;
}
- regs[a].attr_i = z;
}
break;
case MRB_TT_FLOAT:
- regs[a].attr_f -= GETARG_C(i);
+ regs_a[0].attr_f -= GETARG_C(i);
break;
default:
- SET_INT_VALUE(regs[a+1], GETARG_C(i));
+ SET_INT_VALUE(regs_a[1], GETARG_C(i));
i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
goto L_SEND;
}
@@ -1722,7 +1750,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int i;
if (len > pre + post) {
- regs[a++] = mrb_ary_new_elts(mrb, len - pre - post, ary->ptr+pre);
+ regs[a++] = mrb_ary_new_from_values(mrb, len - pre - post, ary->ptr+pre);
while (post--) {
regs[a++] = ary->ptr[len-post-1];
}
@@ -1895,7 +1923,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (!mrb->ci->target_class) {
static const char msg[] = "no target class or module";
mrb_value exc = mrb_exc_new(mrb, E_TYPE_ERROR, msg, sizeof(msg) - 1);
- mrb->exc = (struct RObject*)mrb_object(exc);
+ mrb->exc = mrb_obj_ptr(exc);
goto L_RAISE;
}
regs[GETARG_A(i)] = mrb_obj_value(mrb->ci->target_class);
@@ -1948,7 +1976,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg);
}
- mrb->exc = (struct RObject*)mrb_object(exc);
+ mrb->exc = mrb_obj_ptr(exc);
goto L_RAISE;
}
}
diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake
index 224e69e9d..4b2ce6499 100644
--- a/tasks/mrbgem_spec.rake
+++ b/tasks/mrbgem_spec.rake
@@ -17,6 +17,9 @@ module MRuby
alias mruby build
attr_accessor :build_config_initializer
+ attr_accessor :version
+ attr_accessor :description, :summary
+ attr_accessor :homepage
attr_accessor :licenses, :authors
alias :license= :licenses=
alias :author= :authors=
@@ -25,6 +28,8 @@ module MRuby
attr_accessor :test_objs, :test_rbfiles, :test_args
attr_accessor :test_preload
+ attr_accessor :bins
+
attr_block MRuby::Build::COMMANDS
def initialize(name, &block)
@@ -56,6 +61,8 @@ module MRuby
@test_preload = 'test/assert.rb'
@test_args = {}
+ @bins = []
+
instance_eval(&@initializer)
if !name || !licenses || !authors
@@ -73,6 +80,10 @@ module MRuby
define_gem_init_builder
end
+ def self.bin=(bin)
+ @bins = [bin].flatten
+ end
+
def build_dir
"#{build.build_dir}/mrbgems/#{name}"
end
@@ -134,6 +145,7 @@ module MRuby
f.puts %Q[ * This file was generated!]
f.puts %Q[ * All manual changes will get lost.]
f.puts %Q[ */]
+ f.puts %Q[#include <stdlib.h>]
f.puts %Q[#include "mruby.h"]
f.puts %Q[#include "mruby/irep.h"]
f.puts %Q[#include "mruby/dump.h"]
diff --git a/tasks/mrbgems.rake b/tasks/mrbgems.rake
index 17f266105..1f3aa0811 100644
--- a/tasks/mrbgems.rake
+++ b/tasks/mrbgems.rake
@@ -9,7 +9,7 @@ MRuby.each_target do
# loader all gems
self.libmruby << objfile("#{build_dir}/mrbgems/gem_init")
file objfile("#{build_dir}/mrbgems/gem_init") => "#{build_dir}/mrbgems/gem_init.c"
- file "#{build_dir}/mrbgems/gem_init.c" => MRUBY_CONFIGS.flatten do |t|
+ file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG] do |t|
FileUtils.mkdir_p "#{build_dir}/mrbgems"
open(t.name, 'w') do |f|
f.puts %Q[/*]
@@ -40,4 +40,49 @@ MRuby.each_target do
end
end
end
+
+ # legal documents
+ self.libmruby << "#{build_dir}/LEGAL"
+ file "#{build_dir}/LEGAL" => [MRUBY_CONFIG] do |t|
+ open(t.name, 'w+') do |f|
+ f.puts <<LEGAL
+Copyright (c) #{Time.now.year} mruby developers
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+LEGAL
+
+ if enable_gems?
+ f.puts <<GEMS_LEGAL
+
+Additional Licenses
+
+Due to the reason that you choosed additional mruby packages (GEMS),
+please check the following additional licenses too:
+GEMS_LEGAL
+
+ gems.map do |g|
+ f.puts
+ f.puts "GEM: #{g.name}"
+ f.puts "Copyright (c) #{Time.now.year} #{g.authors}"
+ f.puts "License: #{g.licenses}"
+ end
+ end
+ end
+ end
end
diff --git a/tasks/mrbgems_test.rake b/tasks/mrbgems_test.rake
index 6ca5eaef2..7b78c9878 100644
--- a/tasks/mrbgems_test.rake
+++ b/tasks/mrbgems_test.rake
@@ -10,7 +10,11 @@ MRuby.each_target do
file g.test_rbireps => [g.test_rbfiles].flatten + [g.build.mrbcfile, libfile("#{build_dir}/lib/libmruby")] do |t|
open(t.name, 'w') do |f|
g.print_gem_init_header(f)
- g.build.mrbc.run f, g.test_preload, "gem_test_irep_#{g.funcname}_preload"
+ test_preload = [g.dir, MRUBY_ROOT].map {|dir|
+ File.expand_path(g.test_preload, dir)
+ }.find {|file| File.exists?(file) }
+
+ g.build.mrbc.run f, test_preload, "gem_test_irep_#{g.funcname}_preload"
g.test_rbfiles.flatten.each_with_index do |rbfile, i|
g.build.mrbc.run f, rbfile, "gem_test_irep_#{g.funcname}_#{i}"
end
@@ -68,7 +72,7 @@ MRuby.each_target do
f.puts %Q[ ]
f.puts %Q[ while(mrb_test(val2)) {]
f.puts %Q[ char *str = mrb_string_value_cstr(mrb2, &val2);]
- f.puts %Q[ mrb_ary_push(mrb, ary1, mrb_str_new(mrb, str, strlen(str)));]
+ f.puts %Q[ mrb_ary_push(mrb, ary1, mrb_str_new_cstr(mrb, str));]
f.puts %Q[ val2 = mrb_ary_shift(mrb2, ary2);]
f.puts %Q[ }]
f.puts %Q[ }]
diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake
index 812e861a7..e24a8ac61 100644
--- a/tasks/mruby_build.rake
+++ b/tasks/mruby_build.rake
@@ -128,6 +128,14 @@ module MRuby
end
end
+ def cygwin_filename(name)
+ if name.is_a?(Array)
+ name.flatten.map { |n| cygwin_filename(n) }
+ else
+ '"%s"' % `cygpath -w "#{filename(name)}"`.strip
+ end
+ end
+
def exefile(name)
if name.is_a?(Array)
name.flatten.map { |n| exefile(n) }
@@ -174,8 +182,10 @@ module MRuby
puts " Binaries: #{@bins.join(', ')}" unless @bins.empty?
unless @gems.empty?
puts " Included Gems:"
- @gems.map(&:name).each do |name|
- puts " #{name}"
+ @gems.map do |gem|
+ gem_version = "- #{gem.version}" if gem.version
+ puts " #{gem.name} #{gem_version}"
+ puts " - Binaries: #{gem.bins.join(', ')}" unless gem.bins.empty?
end
end
puts "================================================"
diff --git a/tasks/mruby_build_commands.rake b/tasks/mruby_build_commands.rake
index ec8a8d3e3..0effa648b 100644
--- a/tasks/mruby_build_commands.rake
+++ b/tasks/mruby_build_commands.rake
@@ -4,7 +4,7 @@ module MRuby
class Command
include Rake::DSL
extend Forwardable
- def_delegators :@build, :filename, :objfile, :libfile, :exefile
+ def_delegators :@build, :filename, :objfile, :libfile, :exefile, :cygwin_filename
attr_accessor :build, :command
def initialize(build)
@@ -49,7 +49,11 @@ module MRuby
def all_flags(_defineds=[], _include_paths=[], _flags=[])
define_flags = [defines, _defineds].flatten.map{ |d| option_define % d }
include_path_flags = [include_paths, _include_paths].flatten.map do |f|
- option_include_path % filename(f)
+ if MRUBY_BUILD_HOST_IS_CYGWIN
+ option_include_path % cygwin_filename(f)
+ else
+ option_include_path % filename(f)
+ end
end
[flags, define_flags, include_path_flags, _flags].flatten.join(' ')
end
@@ -61,17 +65,22 @@ module MRuby
option_include_path % filename(f)
end
_pp "CC", infile.relative_path, outfile.relative_path
- _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags),
- :infile => filename(infile), :outfile => filename(outfile) }
+ if MRUBY_BUILD_HOST_IS_CYGWIN
+ _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags),
+ :infile => cygwin_filename(infile), :outfile => cygwin_filename(outfile) }
+ else
+ _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags),
+ :infile => filename(infile), :outfile => filename(outfile) }
+ end
end
def define_rules(build_dir, source_dir='')
@out_ext = build.exts.object
if build_dir.include? "mrbgems/"
- generated_file_matcher = Regexp.new("^#{build_dir}/(.*)#{Regexp.escape out_ext}$")
+ generated_file_matcher = Regexp.new("^#{Regexp.escape build_dir}/(.*)#{Regexp.escape out_ext}$")
else
- generated_file_matcher = Regexp.new("^#{build_dir}/(?!mrbgems/.+/)(.*)#{Regexp.escape out_ext}$")
+ generated_file_matcher = Regexp.new("^#{Regexp.escape build_dir}/(?!mrbgems/.+/)(.*)#{Regexp.escape out_ext}$")
end
source_exts.each do |ext, compile|
rule generated_file_matcher => [
@@ -127,7 +136,11 @@ module MRuby
def all_flags(_library_paths=[], _flags=[])
library_path_flags = [library_paths, _library_paths].flatten.map do |f|
- option_library_path % filename(f)
+ if MRUBY_BUILD_HOST_IS_CYGWIN
+ option_library_path % cygwin_filename(f)
+ else
+ option_library_path % filename(f)
+ end
end
[flags, library_path_flags, _flags].flatten.join(' ')
end
@@ -142,11 +155,19 @@ module MRuby
library_path_flags = [library_paths, _library_paths].flatten.map { |f| option_library_path % filename(f) }
_pp "LD", outfile.relative_path
- _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(' ') }
+ if MRUBY_BUILD_HOST_IS_CYGWIN
+ _run link_options, { :flags => all_flags(_library_paths, _flags),
+ :outfile => cygwin_filename(outfile) , :objs => cygwin_filename(objfiles).join(' '),
+ :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '),
+ :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '),
+ :libs => library_flags.join(' ') }
+ else
+ _run link_options, { :flags => all_flags(_library_paths, _flags),
+ :outfile => filename(outfile) , :objs => filename(objfiles).join(' '),
+ :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '),
+ :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '),
+ :libs => library_flags.join(' ') }
+ end
end
end
@@ -162,7 +183,11 @@ module MRuby
def run(outfile, objfiles)
FileUtils.mkdir_p File.dirname(outfile)
_pp "AR", outfile.relative_path
- _run archive_options, { :outfile => filename(outfile), :objs => filename(objfiles).join(' ') }
+ if MRUBY_BUILD_HOST_IS_CYGWIN
+ _run archive_options, { :outfile => cygwin_filename(outfile), :objs => cygwin_filename(objfiles).join(' ') }
+ else
+ _run archive_options, { :outfile => filename(outfile), :objs => filename(objfiles).join(' ') }
+ end
end
end
@@ -224,9 +249,11 @@ module MRuby
def run(out, infiles, funcname)
@command ||= @build.mrbcfile
- IO.popen("#{filename @command} #{@compile_options % {:funcname => funcname}}", 'r+') do |io|
+ commandline = "#{filename @command} #{@compile_options % {:funcname => funcname}}"
+ IO.popen(commandline, 'r+') do |io|
[infiles].flatten.each do |f|
_pp "MRBC", f.relative_path, nil, :indent => 2
+ log "#{commandline} ## #{f}"
io.write IO.read(f)
end
io.close_write
diff --git a/tasks/mruby_build_gem.rake b/tasks/mruby_build_gem.rake
index 69dd4cafc..358df1612 100644
--- a/tasks/mruby_build_gem.rake
+++ b/tasks/mruby_build_gem.rake
@@ -1,7 +1,12 @@
module MRuby
module LoadGems
def gem(gemdir, &block)
- gemdir = load_external_gem(gemdir) if gemdir.is_a?(Hash)
+ caller_dir = File.expand_path(File.dirname(/^(.*?):\d/.match(caller.first).to_a[1]))
+ if gemdir.is_a?(Hash)
+ gemdir = load_external_gem(gemdir)
+ else
+ gemdir = File.expand_path(gemdir, caller_dir)
+ end
gemrake = File.join(gemdir, "mrbgem.rake")
fail "Can't find #{gemrake}" unless File.exists?(gemrake)
@@ -19,6 +24,8 @@ module MRuby
def load_external_gem(params)
if params[:github]
params[:git] = "https://github.com/#{params[:github]}.git"
+ elsif params[:bitbucket]
+ params[:git] = "https://bitbucket.org/#{params[:bitbucket]}.git"
end
if params[:git]
@@ -27,7 +34,7 @@ module MRuby
return gemdir if File.exists?(gemdir)
options = [params[:options]] || []
- options << "--branch \"#{params[:branch]}\"" if params[:tag]
+ options << "--branch \"#{params[:branch]}\"" if params[:branch]
FileUtils.mkdir_p "build/mrbgems"
git.run_clone gemdir, url, options
diff --git a/tasks/toolchains/androideabi.rake b/tasks/toolchains/androideabi.rake
index 9c6d423e2..a69fd1a9d 100644
--- a/tasks/toolchains/androideabi.rake
+++ b/tasks/toolchains/androideabi.rake
@@ -11,13 +11,115 @@
MRuby::Toolchain.new(:androideabi) do |conf|
toolchain :gcc
- ANDROID_STANDALONE_TOOLCHAIN = ENV['ANDROID_STANDALONE_TOOLCHAIN'] + '/bin/arm-linux-androideabi-'
- SYSROOT = ENV['ANDROID_STANDALONE_TOOLCHAIN'] + '/sysroot'
+ DEFAULT_ANDROID_TOOLCHAIN = 'gcc'
+ DEFAULT_ANDROID_TARGET_ARCH = 'arm'
+ DEFAULT_ANDROID_TARGET_ARCH_ABI = 'armeabi'
+ DEFAULT_ANDROID_TARGET_PLATFORM = 'android-14'
+ DEFAULT_GCC_VERSION = '4.6'
+ DEFAULT_CLANG_VERSION = '3.1'
+ GCC_COMMON_CFLAGS = %W(-ffunction-sections -funwind-tables -fstack-protector)
+ GCC_COMMON_LDFLAGS = %W()
+
+ # 'ANDROID_STANDALONE_TOOLCHAIN' or 'ANDROID_NDK_HOME' must be set.
+ ANDROID_STANDALONE_TOOLCHAIN = ENV['ANDROID_STANDALONE_TOOLCHAIN']
+ ANDROID_NDK_HOME = ENV['ANDROID_NDK_HOME']
+
+ ANDROID_TARGET_ARCH = ENV['ANDROID_TARGET_ARCH'] || DEFAULT_ANDROID_TARGET_ARCH
+ ANDROID_TARGET_ARCH_ABI = ENV['ANDROID_TARGET_ARCH_ABI'] || DEFAULT_ANDROID_TARGET_ARCH_ABI
+ ANDROID_TOOLCHAIN = ENV['ANDROID_TOOLCHAIN'] || DEFAULT_ANDROID_TOOLCHAIN
+
+ case ANDROID_TARGET_ARCH.downcase
+ when 'arch-arm', 'arm' then
+ toolchain_prefix = 'arm-linux-androideabi-'
+ when 'arch-x86', 'x86' then
+ toolchain_prefix = 'i686-linux-android-'
+ when 'arch-mips', 'mips' then
+ toolchain_prefix = 'mipsel-linux-android-'
+ else
+ # Any other architectures are not supported by Android NDK.
+ # Notify error.
+ end
+
+ if ANDROID_STANDALONE_TOOLCHAIN == nil then
+ if RUBY_PLATFORM.include?('darwin') then
+ HOST_PLATFORM = 'darwin-x86'
+ elsif RUBY_PLATFORM.include?('linux') then
+ HOST_PLATFORM = 'linux-x86'
+ elsif RUBY_PLATFORM.include?('win') then
+ HOST_PLATFORM = 'windows'
+ else
+ # Unknown host platform.
+ end
+
+ ANDROID_TARGET_PLATFORM = ENV['ANDROID_TARGET_PLATFORM'] || DEFAULT_ANDROID_TARGET_PLATFORM
+
+ path_to_toolchain = ANDROID_NDK_HOME + '/toolchains/'
+ path_to_sysroot = ANDROID_NDK_HOME + '/platforms/' + ANDROID_TARGET_PLATFORM
+ if ANDROID_TOOLCHAIN.downcase == 'gcc' then
+ case ANDROID_TARGET_ARCH.downcase
+ when 'arch-arm', 'arm' then
+ path_to_toolchain += 'arm-linux-androideabi-'
+ path_to_sysroot += '/arch-arm'
+ when 'arch-x86', 'x86' then
+ path_to_toolchain += 'x86-'
+ path_to_sysroot += '/arch-x86'
+ when 'arch-mips', 'mips' then
+ path_to_toolchain += 'mipsel-linux-android-'
+ path_to_sysroot += '/arch-mips'
+ else
+ # Any other architecture are not supported by Android NDK.
+ end
+ path_to_toolchain += DEFAULT_GCC_VERSION + '/prebuilt/' + HOST_PLATFORM
+ else
+ path_to_toolchain += 'llvm-' + DEFAULT_CLANG_VERSION + '/prebuilt/' + HOST_PLATFORM
+ end
+ else
+ path_to_toolchain = ANDROID_STANDALONE_TOOLCHAIN
+ path_to_sysroot = ANDROID_STANDALONE_TOOLCHAIN + '/sysroot'
+ end
+
+ SYSROOT = path_to_sysroot
+
+ case ANDROID_TARGET_ARCH.downcase
+ when 'arch-arm', 'arm' then
+ if ANDROID_TARGET_ARCH_ABI.downcase == 'armeabi-v7a' then
+ ARCH_CFLAGS = %W(-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16)
+ ARCH_LDFLAGS = %W(-march=armv7-a -Wl,--fix-cortex-a8)
+ else
+ ARCH_CFLAGS = %W(-march=armv5te -mtune=xscale -msoft-float)
+ ARCH_LDFLAGS = %W()
+ end
+ when 'arch-x86', 'x86' then
+ ARCH_CFLAGS = %W()
+ ARCH_LDFLAGS = %W()
+ when 'arch-mips', 'mips' then
+ ARCH_CFLAGS = %W(-fpic -fno-strict-aliasing -finline-functions -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers)
+ ARCH_LDFLAGS = %W()
+ else
+ # Notify error
+ end
+
+ case ANDROID_TOOLCHAIN.downcase
+ when 'gcc' then
+ ANDROID_CC = path_to_toolchain + '/bin/' + toolchain_prefix + 'gcc'
+ ANDROID_LD = path_to_toolchain + '/bin/' + toolchain_prefix + 'gcc'
+ ANDROID_AR = path_to_toolchain + '/bin/' + toolchain_prefix + 'ar'
+ ANDROID_CFLAGS = GCC_COMMON_CFLAGS + %W(-mandroid --sysroot="#{SYSROOT}") + ARCH_CFLAGS
+ ANDROID_LDFLAGS = GCC_COMMON_LDFLAGS + %W(-mandroid --sysroot="#{SYSROOT}") + ARCH_LDFLAGS
+ when 'clang' then
+ # clang is not supported yet.
+ when 'clang31', 'clang3.1' then
+ # clang is not supported yet.
+ else
+ # Any other toolchains are not supported by Android NDK.
+ # Notify error.
+ end
[conf.cc, conf.cxx, conf.objc, conf.asm].each do |cc|
- cc.command = ENV['CC'] || ANDROID_STANDALONE_TOOLCHAIN + 'gcc'
- cc.flags = [ENV['CFLAGS'] || ['--sysroot ' + SYSROOT]]
+ cc.command = ENV['CC'] || ANDROID_CC
+ cc.flags = [ENV['CFLAGS'] || ANDROID_CFLAGS]
end
- conf.linker.command = ENV['LD'] || ANDROID_STANDALONE_TOOLCHAIN + 'gcc'
- conf.archiver.command = ENV['AR'] || ANDROID_STANDALONE_TOOLCHAIN + 'ar'
+ conf.linker.command = ENV['LD'] || ANDROID_LD
+ conf.linker.flags = [ENV['LDFLAGS'] || ANDROID_LDFLAGS]
+ conf.archiver.command = ENV['AR'] || ANDROID_AR
end
diff --git a/test/driver.c b/test/driver.c
index 5183145b4..a55e1180f 100644
--- a/test/driver.c
+++ b/test/driver.c
@@ -5,6 +5,9 @@
** against the current mruby implementation.
*/
+
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <mruby.h>
@@ -17,7 +20,8 @@ void
mrb_init_mrbtest(mrb_state *);
/* Print a short remark for the user */
-void print_hint(void)
+static void
+print_hint(void)
{
printf("mrbtest - Embeddable Ruby Test\n");
printf("\nThis is a very early version, please test and report errors.\n");
@@ -35,13 +39,31 @@ check_error(mrb_state *mrb)
return mrb_fixnum_p(ko_test) && mrb_fixnum(ko_test) == 0 && mrb_fixnum_p(kill_test) && mrb_fixnum(kill_test) == 0;
}
+static int
+eval_test(mrb_state *mrb)
+{
+ mrb_value return_value;
+ const char *prog = "report()";
+
+ /* evaluate the test */
+ return_value = mrb_load_string(mrb, prog);
+ /* did an exception occur? */
+ if (mrb->exc) {
+ mrb_p(mrb, return_value);
+ mrb->exc = 0;
+ return EXIT_FAILURE;
+ }
+ else if (!check_error(mrb)) {
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
int
main(int argc, char **argv)
{
mrb_state *mrb;
- mrb_value return_value;
- const char *prog = "report()";
- int ret = EXIT_SUCCESS;
+ int ret;
print_hint();
@@ -52,23 +74,13 @@ main(int argc, char **argv)
return EXIT_FAILURE;
}
- if (argc == 2 && strncmp(argv[1], "-v", 2) == 0) {
+ if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'v') {
printf("verbose mode: enable\n\n");
mrb_gv_set(mrb, mrb_intern(mrb, "$mrbtest_verbose"), mrb_true_value());
}
mrb_init_mrbtest(mrb);
- /* evaluate the test */
- return_value = mrb_load_string(mrb, prog);
- /* did an exception occur? */
- if (mrb->exc) {
- mrb_p(mrb, return_value);
- mrb->exc = 0;
- ret = EXIT_FAILURE;
- }
- else if (!check_error(mrb)) {
- ret = EXIT_FAILURE;
- }
+ ret = eval_test(mrb);
mrb_close(mrb);
return ret;
diff --git a/test/init_mrbtest.c b/test/init_mrbtest.c
index 6b2219b6f..5c80c6e91 100644
--- a/test/init_mrbtest.c
+++ b/test/init_mrbtest.c
@@ -1,10 +1,11 @@
+#include <stdlib.h>
#include "mruby.h"
#include "mruby/irep.h"
#include "mruby/dump.h"
#include "mruby/string.h"
#include "mruby/proc.h"
-extern const char mrbtest_irep[];
+extern const uint8_t mrbtest_irep[];
void mrbgemtest_init(mrb_state* mrb);
diff --git a/test/t/literals.rb b/test/t/literals.rb
index c996af3f3..f40852ff9 100644
--- a/test/t/literals.rb
+++ b/test/t/literals.rb
@@ -59,10 +59,206 @@ assert('Literals Strings Quoted Expanded', '8.7.6.3.5') do
e == 'abc' and f == 'ab/c' and g == 'abc'
end
-# Not Implemented ATM assert('Literals Strings Here documents', '8.7.6.3.6') do
+assert('Literals Strings Here documents', '8.7.6.3.6') do
+ a = <<AAA
+aaa
+AAA
+ b = <<b_b
+bbb
+b_b
+ c = [<<CCC1, <<"CCC2", <<'CCC3']
+c1
+CCC1
+c 2
+CCC2
+c 3
+CCC3
-# Not Implemented ATM assert('Literals Array', '8.7.6.4') do
+ d = <<DDD
+d#{1+2}DDD
+d\t
+DDD\n
+DDD
+ e = <<'EEE'
+e#{1+2}EEE
+e\t
+EEE\n
+EEE
+ f = <<"FFF"
+F
+FF#{"f"}FFF
+F
+FFF
+
+ g = <<-GGG
+ ggg
+ GGG
+ h = <<-"HHH"
+ hhh
+ HHH
+ i = <<-'III'
+ iii
+ III
+ j = [<<-JJJ1 , <<-"JJJ2" , <<-'JJJ3' ]
+ j#{1}j
+ JJJ1
+ j#{2}j
+ JJJ2
+ j#{3}j
+ JJJ3
+
+ k = <<'KKK'.to_i
+123
+KKK
+
+ z = <<'ZZZ'
+ZZZ
+
+ a == "aaa\n" and
+ b == "bbb\n" and
+ c == ["c1\n", "c 2\n", "c 3\n"] and
+ d == "d3DDD\nd\t\nDDD\n\n" and
+ e == "e\#{1+2}EEE\ne\\t\nEEE\\n\n" and
+ f == "F\nFFfFFF\nF\n" and
+ g == " ggg\n" and
+ h == " hhh\n" and
+ i == " iii\n" and
+ j == [" j1j\n", " j2j\n", " j\#{3}j\n"] and
+ k == 123 and
+ z == ""
+end
+
+assert('Literals Array', '8.7.6.4') do
+ a = %W{abc#{1+2}def \}g}
+ b = %W(abc #{2+3} def \(g)
+ c = %W[#{3+4}]
+ d = %W< #{4+5} >
+ e = %W//
+ f = %W[[ab cd][ef]]
+ g = %W{
+ ab
+ #{-1}1
+ 2#{2}
+ }
+ h = %W(a\nb
+ test\ abc
+ c\
+d
+ x\y x\\y x\\\y)
+
+ test1 = (a == ['abc3def', '}g'] and
+ b == ['abc', '5', 'def', '(g'] and
+ c == ['7'] and
+ d == ['9'] and
+ e == [] and
+ f == ['[ab', 'cd][ef]'] and
+ g == ['ab', '-11', '22'] and
+ h == ["a\nb", 'test abc', "c\nd", "xy", "x\\y", "x\\y"]
+ )
+
+ a = %w{abc#{1+2}def \}g}
+ b = %w(abc #{2+3} def \(g)
+ c = %w[#{3+4}]
+ d = %w< #{4+5} >
+ e = %w//
+ f = %w[[ab cd][ef]]
+ g = %w{
+ ab
+ #{-1}1
+ 2#{2}
+ }
+ h = %w(a\nb
+ test\ abc
+ c\
+d
+ x\y x\\y x\\\y)
+
+ test2 = (a == ['abc#{1+2}def', '}g'] and
+ b == ['abc', '#{2+3}', 'def', '(g'] and
+ c == ['#{3+4}'] and
+ d == ['#{4+5}'] and
+ e == [] and
+ f == ['[ab', 'cd][ef]'] and
+ g == ['ab', '#{-1}1', '2#{2}'] and
+ h == ["a\\nb", "test abc", "c\nd", "x\\y", "x\\y", "x\\\\y"]
+ )
+
+ test1 and test2
+end
+
+assert('Literals Array of symbols') do
+ a = %I{abc#{1+2}def \}g}
+ b = %I(abc #{2+3} def \(g)
+ c = %I[#{3+4}]
+ d = %I< #{4+5} >
+ e = %I//
+ f = %I[[ab cd][ef]]
+ g = %I{
+ ab
+ #{-1}1
+ 2#{2}
+ }
+
+ test1 = (a == [:'abc3def', :'}g'] and
+ b == [:'abc', :'5', :'def', :'(g'] and
+ c == [:'7'] and
+ d == [:'9'] and
+ e == [] and
+ f == [:'[ab', :'cd][ef]'] and
+ g == [:'ab', :'-11', :'22']
+ )
+
+ a = %i{abc#{1+2}def \}g}
+ b = %i(abc #{2+3} def \(g)
+ c = %i[#{3+4}]
+ d = %i< #{4+5} >
+ e = %i//
+ f = %i[[ab cd][ef]]
+ g = %i{
+ ab
+ #{-1}1
+ 2#{2}
+ }
+
+ test2 = (a == [:'abc#{1+2}def', :'}g'] and
+ b == [:'abc', :'#{2+3}', :'def', :'(g'] and
+ c == [:'#{3+4}'] and
+ d == [:'#{4+5}'] and
+ e == [] and
+ f == [:'[ab', :'cd][ef]'] and
+ g == [:'ab', :'#{-1}1', :'2#{2}']
+ )
+
+ test1 and test2
+end
+
+assert('Literals Symbol', '8.7.6.6') do
+ # do not compile error
+ :$asd
+ :@asd
+ :@@asd
+ :asd=
+ :asd!
+ :asd?
+ :+
+ :+@
+ :if
+ :BEGIN
+
+ a = :"asd qwe"
+ b = :'foo bar'
+ c = :"a#{1+2}b"
+ d = %s(asd)
+ e = %s( foo \))
+ f = %s[asd \[
+qwe]
+ g = %s/foo#{1+2}bar/
+ h = %s{{foo bar}}
+
+ a == :'asd qwe' and b == :"foo bar" and c == :a3b and d == :asd and
+ e == :' foo )' and f == :"asd [\nqwe" and g == :'foo#{1+2}bar' and
+ h == :'{foo bar}'
+end
# Not Implemented ATM assert('Literals Regular expression', '8.7.6.5') do
-# Not Implemented ATM assert('Literals Symbol', '8.7.6.6') do
diff --git a/tools/mirb/mirb.c b/tools/mirb/mirb.c
index 29685cf28..3f96696a7 100644
--- a/tools/mirb/mirb.c
+++ b/tools/mirb/mirb.c
@@ -6,6 +6,7 @@
** immediately. It's a REPL...
*/
+#include <stdlib.h>
#include <string.h>
#include <mruby.h>
@@ -38,7 +39,14 @@ is_code_block_open(struct mrb_parser_state *parser)
int code_block_open = FALSE;
/* check for unterminated string */
- if (parser->sterm) return TRUE;
+ if (parser->lex_strterm) return TRUE;
+
+ /* check for heredoc */
+ if (parser->heredoc_starts_nextline) return TRUE;
+ if (parser->heredoc_end_now) {
+ parser->heredoc_end_now = FALSE;
+ return FALSE;
+ }
/* check if parser error are available */
if (0 < parser->nerr) {
@@ -124,8 +132,70 @@ is_code_block_open(struct mrb_parser_state *parser)
return code_block_open;
}
+void mrb_show_version(mrb_state *);
+void mrb_show_copyright(mrb_state *);
+
+struct _args {
+ int argc;
+ char** argv;
+};
+
+static void
+usage(const char *name)
+{
+ static const char *const usage_msg[] = {
+ "switches:",
+ "--version print the version",
+ "--copyright print the copyright",
+ NULL
+ };
+ const char *const *p = usage_msg;
+
+ printf("Usage: %s [switches]\n", name);
+ while(*p)
+ printf(" %s\n", *p++);
+}
+
+static int
+parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
+{
+ static const struct _args args_zero = { 0 };
+
+ *args = args_zero;
+
+ for (argc--,argv++; argc > 0; argc--,argv++) {
+ char *item;
+ if (argv[0][0] != '-') break;
+
+ item = argv[0] + 1;
+ switch (*item++) {
+ case '-':
+ if (strcmp((*argv) + 2, "version") == 0) {
+ mrb_show_version(mrb);
+ exit(0);
+ }
+ else if (strcmp((*argv) + 2, "copyright") == 0) {
+ mrb_show_copyright(mrb);
+ exit(0);
+ }
+ else return -3;
+ default:
+ return -4;
+ }
+ }
+
+ return 0;
+}
+
+static void
+cleanup(mrb_state *mrb, struct _args *args)
+{
+ mrb_close(mrb);
+}
+
/* Print a short remark for the user */
-void print_hint(void)
+static void
+print_hint(void)
{
printf("mirb - Embeddable Interactive Ruby Shell\n");
printf("\nThis is a very early version, please test and report errors.\n");
@@ -145,7 +215,7 @@ print_cmdline(int code_block_open)
}
int
-main(void)
+main(int argc, char **argv)
{
char ruby_code[1024] = { 0 };
char last_code_line[1024] = { 0 };
@@ -157,19 +227,27 @@ main(void)
struct mrb_parser_state *parser;
mrb_state *mrb;
mrb_value result;
+ struct _args args;
int n;
int code_block_open = FALSE;
int ai;
- print_hint();
-
/* new interpreter instance */
mrb = mrb_open();
if (mrb == NULL) {
- fprintf(stderr, "Invalid mrb interpreter, exiting mirb");
+ fputs("Invalid mrb interpreter, exiting mirb\n", stderr);
return EXIT_FAILURE;
}
+ n = parse_args(mrb, argc, argv, &args);
+ if (n < 0) {
+ cleanup(mrb, &args);
+ usage(argv[0]);
+ return n;
+ }
+
+ print_hint();
+
cxt = mrbc_context_new(mrb);
cxt->capture_errors = 1;
@@ -184,7 +262,7 @@ main(void)
last_code_line[char_index++] = last_char;
}
if (last_char == EOF) {
- printf("\n");
+ fputs("\n", stdout);
break;
}
@@ -233,28 +311,31 @@ main(void)
}
else {
if (0 < parser->nerr) {
- /* syntax error */
- printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message);
+ /* syntax error */
+ printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message);
}
else {
- /* generate bytecode */
- n = mrb_generate_code(mrb, parser);
+ /* generate bytecode */
+ n = mrb_generate_code(mrb, parser);
- /* evaluate the bytecode */
- result = mrb_run(mrb,
+ /* evaluate the bytecode */
+ result = mrb_run(mrb,
/* pass a proc for evaulation */
mrb_proc_new(mrb, mrb->irep[n]),
mrb_top_self(mrb));
- /* did an exception occur? */
- if (mrb->exc) {
- p(mrb, mrb_obj_value(mrb->exc));
- mrb->exc = 0;
- }
- else {
- /* no */
- printf(" => ");
- p(mrb, result);
- }
+ /* did an exception occur? */
+ if (mrb->exc) {
+ p(mrb, mrb_obj_value(mrb->exc));
+ mrb->exc = 0;
+ }
+ else {
+ /* no */
+ printf(" => ");
+ if (!mrb_respond_to(mrb,result,mrb_intern(mrb,"inspect"))){
+ result = mrb_any_to_s(mrb,result);
+ }
+ p(mrb, result);
+ }
}
ruby_code[0] = '\0';
last_code_line[0] = '\0';
diff --git a/tools/mrbc/mrbc.c b/tools/mrbc/mrbc.c
index bc551fffc..b8c1cf286 100644
--- a/tools/mrbc/mrbc.c
+++ b/tools/mrbc/mrbc.c
@@ -1,10 +1,10 @@
-#include "mruby.h"
-#include "mruby/proc.h"
-#include "mruby/dump.h"
-#include "mruby/compile.h"
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
+#include <string.h>
+#include "mruby.h"
+#include "mruby/compile.h"
+#include "mruby/dump.h"
+#include "mruby/proc.h"
#define RITEBIN_EXT ".mrb"
#define C_EXT ".c"
@@ -19,8 +19,9 @@ struct _args {
char *filename;
char *initname;
char *ext;
- int check_syntax : 1;
- int verbose : 1;
+ mrb_bool check_syntax : 1;
+ mrb_bool verbose : 1;
+ mrb_bool debug_info : 1;
};
static void
@@ -31,6 +32,7 @@ usage(const char *name)
"-c check syntax only",
"-o<outfile> place the output into <outfile>",
"-v print version number, then trun on verbose mode",
+ "-g produce debugging information",
"-B<symbol> binary <symbol> output in C language format",
"--verbose run at verbose mode",
"--version print the version",
@@ -83,6 +85,12 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
switch ((*argv)[1]) {
case 'o':
+ if (outfile) {
+ printf("%s: An output file is already specified. (%s)\n",
+ *origargv, outfile);
+ result = -5;
+ goto exit;
+ }
outfile = get_outfilename((*argv) + 2, "");
break;
case 'B':
@@ -101,6 +109,9 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
mrb_show_version(mrb);
args->verbose = 1;
break;
+ case 'g':
+ args->debug_info = 1;
+ break;
case '-':
if (strcmp((*argv) + 2, "version") == 0) {
mrb_show_version(mrb);
@@ -176,7 +187,7 @@ main(int argc, char **argv)
mrb_value result;
if (mrb == NULL) {
- fprintf(stderr, "Invalid mrb_state, exiting mrbc");
+ fputs("Invalid mrb_state, exiting mrbc\n", stderr);
return EXIT_FAILURE;
}
@@ -198,15 +209,15 @@ main(int argc, char **argv)
return EXIT_FAILURE;
}
if (args.check_syntax) {
- printf("Syntax OK\n");
+ puts("Syntax OK");
cleanup(mrb, &args);
return EXIT_SUCCESS;
}
if (args.initname) {
- n = mrb_bdump_irep(mrb, n, args.wfp, args.initname);
+ n = mrb_dump_irep_cfunc(mrb, n, args.debug_info, args.wfp, args.initname);
}
else {
- n = mrb_dump_irep(mrb, n, args.wfp);
+ n = mrb_dump_irep_binary(mrb, n, args.debug_info, args.wfp);
}
cleanup(mrb, &args);
diff --git a/tools/mruby/mruby.c b/tools/mruby/mruby.c
index 9d6182238..47727e67b 100644
--- a/tools/mruby/mruby.c
+++ b/tools/mruby/mruby.c
@@ -6,6 +6,7 @@
#include "mruby/dump.h"
#include "mruby/variable.h"
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#ifndef ENABLE_STDIO
@@ -26,10 +27,10 @@ void mrb_show_copyright(mrb_state *);
struct _args {
FILE *rfp;
char* cmdline;
- int fname : 1;
- int mrbfile : 1;
- int check_syntax : 1;
- int verbose : 1;
+ mrb_bool fname : 1;
+ mrb_bool mrbfile : 1;
+ mrb_bool check_syntax : 1;
+ mrb_bool verbose : 1;
int argc;
char** argv;
};
@@ -52,7 +53,7 @@ usage(const char *name)
printf("Usage: %s [switches] programfile\n", name);
while(*p)
- printf(" %s\n", *p++);
+ printf(" %s\n", *p++);
}
static int
@@ -125,7 +126,6 @@ append_cmdline:
exit(0);
}
else return -3;
- return 0;
default:
return -4;
}
@@ -189,14 +189,14 @@ showcallinfo(mrb_state *mrb)
if (irep->filename != NULL)
filename = irep->filename;
if (irep->lines != NULL) {
- mrb_code *pc;
+ mrb_code *pc;
- if (i+1 <= ciidx) {
- pc = mrb->cibase[i+1].pc;
- }
- else {
- pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "lastpc")));
- }
+ if (i+1 <= ciidx) {
+ pc = mrb->cibase[i+1].pc;
+ }
+ else {
+ pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "lastpc")));
+ }
if (irep->iseq <= pc && pc < irep->iseq + irep->ilen) {
line = irep->lines[pc - irep->iseq - 1];
}
@@ -211,19 +211,16 @@ showcallinfo(mrb_state *mrb)
method = mrb_sym2name(mrb, ci->mid);
if (method) {
const char *cn = mrb_class_name(mrb, ci->proc->target_class);
-
+
if (cn) {
- printf("\t[%d] %s:%d:in %s%s%s\n",
- i, filename, line, cn, sep, method);
+ printf("\t[%d] %s:%d:in %s%s%s\n", i, filename, line, cn, sep, method);
}
else {
- printf("\t[%d] %s:%d:in %s\n",
- i, filename, line, method);
+ printf("\t[%d] %s:%d:in %s\n", i, filename, line, method);
}
}
else {
- printf("\t[%d] %s:%d\n",
- i, filename, line);
+ printf("\t[%d] %s:%d\n", i, filename, line);
}
}
}
@@ -238,7 +235,7 @@ main(int argc, char **argv)
mrb_value ARGV;
if (mrb == NULL) {
- fprintf(stderr, "Invalid mrb_state, exiting mruby\n");
+ fputs("Invalid mrb_state, exiting mruby\n", stderr);
return EXIT_FAILURE;
}
diff --git a/travis_config.rb b/travis_config.rb
new file mode 100644
index 000000000..0ba2c38f1
--- /dev/null
+++ b/travis_config.rb
@@ -0,0 +1,10 @@
+MRuby::Build.new do |conf|
+ toolchain :gcc
+
+ conf.gem "#{root}/mrbgems/mruby-sprintf"
+ conf.gem "#{root}/mrbgems/mruby-print"
+
+ Dir.glob("#{root}/mrbgems/mruby-*") do |x|
+ conf.gem x unless x =~ /\/mruby-(print|sprintf)$/
+ end
+end