diff options
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" @@ -10,3 +10,4 @@ Original Authors "mruby developers" are: Masamitsu MURASE Masaki Muranaka Internet Initiative Japan Inc. + Tadashi FUKUZAWA @@ -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. @@ -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. @@ -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 @@ -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 @@ -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); @@ -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 */ @@ -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(§ion_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; @@ -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(®s[1], argv, sizeof(mrb_value)*(argc-m2)); /* m1 + o */ + value_move(®s[1], argv, argc-m2); /* m1 + o */ } if (m2) { - memmove(®s[len-m2+1], &argv[argc-m2], sizeof(mrb_value)*m2); /* m2 */ + value_move(®s[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(®s[1], argv, sizeof(mrb_value)*(m1+o)); /* m1 + o */ + value_move(®s[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(®s[m1+o+r+1], &argv[argc-m2], sizeof(mrb_value)*m2); + value_move(®s[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, ®s[a], (ci->argc+1)*sizeof(mrb_value)); + value_move(mrb->stack, ®s[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 |
