diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/backtrace.c | 85 | ||||
| -rw-r--r-- | src/class.c | 69 | ||||
| -rw-r--r-- | src/error.c | 88 | ||||
| -rw-r--r-- | src/fmt_fp.c | 1 | ||||
| -rw-r--r-- | src/gc.c | 2 | ||||
| -rw-r--r-- | src/hash.c | 2 | ||||
| -rw-r--r-- | src/kernel.c | 2 | ||||
| -rw-r--r-- | src/load.c | 28 | ||||
| -rw-r--r-- | src/print.c | 1 | ||||
| -rw-r--r-- | src/string.c | 131 | ||||
| -rw-r--r-- | src/vm.c | 5 |
11 files changed, 175 insertions, 239 deletions
diff --git a/src/backtrace.c b/src/backtrace.c index 803c5e285..186009523 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -25,6 +25,9 @@ typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location* static const mrb_data_type bt_type = { "Backtrace", mrb_free }; +mrb_value mrb_exc_inspect(mrb_state *mrb, mrb_value exc); +mrb_value mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace); + static void each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtrace_func func, void *data) { @@ -74,66 +77,27 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtr #ifndef MRB_DISABLE_STDIO static void -print_backtrace(mrb_state *mrb, mrb_value backtrace) +print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace) { int i; - mrb_int n; + mrb_int n = RARRAY_LEN(backtrace); + mrb_value *loc, mesg; FILE *stream = stderr; - n = RARRAY_LEN(backtrace) - 1; - if (n == 0) return; - - fprintf(stream, "trace (most recent call last):\n"); - for (i=0; i<n; i++) { - mrb_value entry = RARRAY_PTR(backtrace)[n-i-1]; - - if (mrb_string_p(entry)) { - fprintf(stream, "\t[%d] %.*s\n", i, (int)RSTRING_LEN(entry), RSTRING_PTR(entry)); + if (n != 0) { + fprintf(stream, "trace (most recent call last):\n"); + for (i=n-1,loc=&RARRAY_PTR(backtrace)[i]; i>0; i--,loc--) { + if (mrb_string_p(*loc)) { + fprintf(stream, "\t[%d] %.*s\n", + i, (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc)); + } } - } -} - -static int -packed_bt_len(const struct backtrace_location *bt, int n) -{ - int len = 0; - int i; - - for (i=0; i<n; i++) { - if (!bt[i].filename && !bt[i].lineno && !bt[i].method_id) - continue; - len++; - } - return len; -} - -static void -print_packed_backtrace(mrb_state *mrb, mrb_value packed) -{ - FILE *stream = stderr; - const struct backtrace_location *bt; - int n, i; - int ai = mrb_gc_arena_save(mrb); - - bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, packed, &bt_type); - if (bt == NULL) return; - n = (mrb_int)RDATA(packed)->flags; - - if (packed_bt_len(bt, n) == 0) return; - fprintf(stream, "trace (most recent call last):\n"); - for (i = 0; i<n; i++) { - const struct backtrace_location *entry = &bt[n-i-1]; - if (entry->filename == NULL) continue; - fprintf(stream, "\t[%d] %s:%d", i, entry->filename, entry->lineno); - if (entry->method_id != 0) { - const char *method_name; - - method_name = mrb_sym_name(mrb, entry->method_id); - fprintf(stream, ":in %s", method_name); - mrb_gc_arena_restore(mrb, ai); + if (mrb_string_p(*loc)) { + fprintf(stream, "%.*s: ", (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc)); } - fprintf(stream, "\n"); } + mesg = mrb_exc_inspect(mrb, mrb_obj_value(exc)); + fprintf(stream, "%.*s\n", (int)RSTRING_LEN(mesg), RSTRING_PTR(mesg)); } /* mrb_print_backtrace @@ -152,12 +116,8 @@ mrb_print_backtrace(mrb_state *mrb) backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace")); if (mrb_nil_p(backtrace)) return; - if (mrb_array_p(backtrace)) { - print_backtrace(mrb, backtrace); - } - else { - print_packed_backtrace(mrb, backtrace); - } + if (!mrb_array_p(backtrace)) backtrace = mrb_unpack_backtrace(mrb, backtrace); + print_backtrace(mrb, mrb->exc, backtrace); } #else @@ -175,7 +135,6 @@ count_backtrace_i(mrb_state *mrb, { int *lenp = (int*)data; - if (loc->filename == NULL) return; (*lenp)++; } @@ -187,7 +146,6 @@ pack_backtrace_i(mrb_state *mrb, struct backtrace_location **pptr = (struct backtrace_location**)data; struct backtrace_location *ptr = *pptr; - if (loc->filename == NULL) return; *ptr = *loc; *pptr = ptr+1; } @@ -205,7 +163,7 @@ packed_backtrace(mrb_state *mrb) size = len * sizeof(struct backtrace_location); ptr = mrb_malloc(mrb, size); backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type); - backtrace->flags = (unsigned int)len; + backtrace->flags = (uint32_t)len; each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, &ptr); return mrb_obj_value(backtrace); } @@ -245,8 +203,7 @@ mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace) const struct backtrace_location *entry = &bt[i]; mrb_value btline; - if (entry->filename == NULL) continue; - btline = mrb_format(mrb, "%s:%d", entry->filename, entry->lineno); + btline = mrb_format(mrb, "%s:%d", entry->filename, (int)entry->lineno); if (entry->method_id != 0) { mrb_str_cat_lit(mrb, btline, ":in "); mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id)); diff --git a/src/class.c b/src/class.c index e0196fe0a..c49f0f474 100644 --- a/src/class.c +++ b/src/class.c @@ -285,11 +285,9 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super) static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value); #ifdef MRB_METHOD_CACHE static void mc_clear_all(mrb_state *mrb); -static void mc_clear_by_class(mrb_state *mrb, struct RClass*); static void mc_clear_by_id(mrb_state *mrb, struct RClass*, mrb_sym); #else #define mc_clear_all(mrb) -#define mc_clear_by_class(mrb,c) #define mc_clear_by_id(mrb,c,s) #endif @@ -303,7 +301,7 @@ mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass) super = mrb->object_class; super->flags |= MRB_FL_CLASS_IS_INHERITED; s = mrb_obj_value(super); - mc_clear_by_class(mrb, klass); + mrb_mc_clear_by_class(mrb, klass); mid = mrb_intern_lit(mrb, "inherited"); if (!mrb_func_basic_p(mrb, s, mid, mrb_bob_init)) { mrb_value c = mrb_obj_value(klass); @@ -591,7 +589,6 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) char c; mrb_int i = 0; va_list ap; - mrb_int arg_i = 0; mrb_int argc = mrb->c->ci->argc; mrb_value *array_argv = mrb->c->stack+1; mrb_bool argv_on_stack = argc >= 0; @@ -679,8 +676,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_value*); if (i < argc) { - *p = argv[arg_i++]; - i++; + *p = argv[i++]; } } break; @@ -692,12 +688,11 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) if (i < argc) { mrb_value ss; - ss = argv[arg_i++]; + ss = argv[i++]; if (!class_ptr_p(ss)) { mrb_raisef(mrb, E_TYPE_ERROR, "%v is not class/module", ss); } *p = ss; - i++; } } break; @@ -707,8 +702,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_value*); if (i < argc) { - *p = argv[arg_i++]; - i++; + *p = argv[i++]; if (!(altmode && mrb_nil_p(*p))) { mrb_to_str(mrb, *p); } @@ -721,8 +715,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_value*); if (i < argc) { - *p = argv[arg_i++]; - i++; + *p = argv[i++]; if (!(altmode && mrb_nil_p(*p))) { *p = to_ary(mrb, *p); } @@ -735,8 +728,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_value*); if (i < argc) { - *p = argv[arg_i++]; - i++; + *p = argv[i++]; if (!(altmode && mrb_nil_p(*p))) { *p = to_hash(mrb, *p); } @@ -752,8 +744,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) ps = va_arg(ap, char**); pl = va_arg(ap, mrb_int*); if (i < argc) { - ss = argv[arg_i++]; - i++; + ss = argv[i++]; if (altmode && mrb_nil_p(ss)) { *ps = NULL; *pl = 0; @@ -773,8 +764,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) ps = va_arg(ap, const char**); if (i < argc) { - ss = argv[arg_i++]; - i++; + ss = argv[i++]; if (altmode && mrb_nil_p(ss)) { *ps = NULL; } @@ -795,8 +785,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) pb = va_arg(ap, mrb_value**); pl = va_arg(ap, mrb_int*); if (i < argc) { - aa = argv[arg_i++]; - i++; + aa = argv[i++]; if (altmode && mrb_nil_p(aa)) { *pb = 0; *pl = 0; @@ -817,14 +806,12 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, void**); if (i < argc) { - ss = argv[arg_i]; + ss = argv[i++]; if (!mrb_istruct_p(ss)) { mrb_raisef(mrb, E_TYPE_ERROR, "%v is not inline struct", ss); } *p = mrb_istruct_ptr(ss); - arg_i++; - i++; } } break; @@ -835,9 +822,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_float*); if (i < argc) { - *p = mrb_to_flo(mrb, argv[arg_i]); - arg_i++; - i++; + *p = mrb_to_flo(mrb, argv[i++]); } } break; @@ -848,9 +833,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_int*); if (i < argc) { - *p = mrb_fixnum(mrb_to_int(mrb, argv[arg_i])); - arg_i++; - i++; + *p = mrb_fixnum(mrb_to_int(mrb, argv[i++])); } } break; @@ -859,9 +842,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_bool *boolp = va_arg(ap, mrb_bool*); if (i < argc) { - mrb_value b = argv[arg_i++]; + mrb_value b = argv[i++]; *boolp = mrb_test(b); - i++; } } break; @@ -873,9 +855,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) if (i < argc) { mrb_value ss; - ss = argv[arg_i++]; + ss = argv[i++]; *symp = to_sym(mrb, ss); - i++; } } break; @@ -887,8 +868,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) datap = va_arg(ap, void**); type = va_arg(ap, struct mrb_data_type const*); if (i < argc) { - mrb_value dd = argv[arg_i++]; - i++; + mrb_value dd = argv[i++]; if (altmode && mrb_nil_p(dd)) { *datap = 0; } @@ -917,7 +897,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } break; case '|': - if (opt_skip && i == argc) return argc; + if (opt_skip && i == argc) goto finish; opt = TRUE; break; case '?': @@ -933,7 +913,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) { mrb_value **var; mrb_int *pl; - mrb_bool nocopy = altmode || argv_on_stack ? TRUE : FALSE; + mrb_bool nocopy = (altmode || !argv_on_stack) ? TRUE : FALSE; var = va_arg(ap, mrb_value**); pl = va_arg(ap, mrb_int*); @@ -941,16 +921,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) *pl = argc-i; if (*pl > 0) { if (nocopy) { - *var = argv+arg_i; + *var = argv+i; } else { - mrb_value args = mrb_ary_new_from_values(mrb, *pl, argv+arg_i); + mrb_value args = mrb_ary_new_from_values(mrb, *pl, argv+i); RARRAY(args)->c = NULL; *var = RARRAY_PTR(args); } } i = argc; - arg_i += *pl; } else { *pl = 0; @@ -1025,6 +1004,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) if (!c && argc > i) { mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } + +finish: va_end(ap); return i; } @@ -1109,7 +1090,7 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru m->flags |= MRB_FL_CLASS_IS_INHERITED; ins_pos->super = ic; mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic); - mc_clear_by_class(mrb, ins_pos); + mrb_mc_clear_by_class(mrb, ins_pos); ins_pos = ic; skip: m = m->super; @@ -1322,8 +1303,8 @@ mc_clear_all(mrb_state *mrb) } } -static void -mc_clear_by_class(mrb_state *mrb, struct RClass *c) +void +mrb_mc_clear_by_class(mrb_state *mrb, struct RClass *c) { struct mrb_cache_entry *mc = mrb->cache; int i; @@ -2323,7 +2304,9 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "dup", mrb_mod_dup, MRB_ARGS_NONE()); mrb_undef_method(mrb, cls, "append_features"); + mrb_undef_method(mrb, cls, "prepend_features"); mrb_undef_method(mrb, cls, "extend_object"); + mrb_undef_method(mrb, cls, "module_function"); 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, MRB_ARGS_NONE()); diff --git a/src/error.c b/src/error.c index 43b09ec66..260ca7a3d 100644 --- a/src/error.c +++ b/src/error.c @@ -13,7 +13,6 @@ #include <mruby/proc.h> #include <mruby/string.h> #include <mruby/variable.h> -#include <mruby/debug.h> #include <mruby/error.h> #include <mruby/class.h> #include <mruby/throw.h> @@ -88,7 +87,7 @@ exc_exception(mrb_state *mrb, mrb_value self) * no message is set). */ -static mrb_value +mrb_value exc_to_s(mrb_state *mrb, mrb_value exc) { mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); @@ -128,37 +127,13 @@ exc_message(mrb_state *mrb, mrb_value exc) * returns message and class name. */ -static mrb_value -exc_inspect(mrb_state *mrb, mrb_value exc) +mrb_value +mrb_exc_inspect(mrb_state *mrb, mrb_value exc) { - mrb_value str, mesg, file, line; - mrb_bool append_mesg; - const char *cname; - - mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); - file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file")); - line = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "line")); - - append_mesg = !mrb_nil_p(mesg); - if (append_mesg) { - mesg = mrb_obj_as_string(mrb, mesg); - append_mesg = RSTRING_LEN(mesg) > 0; - } - - cname = mrb_obj_classname(mrb, exc); - str = mrb_str_new_cstr(mrb, cname); - if (mrb_string_p(file) && mrb_fixnum_p(line)) { - if (append_mesg) { - str = mrb_format(mrb, "%v:%v: %v (%v)", file, line, mesg, str); - } - else { - str = mrb_format(mrb, "%v:%v: %v", file, line, str); - } - } - else if (append_mesg) { - str = mrb_format(mrb, "%v: %v", str, mesg); - } - return str; + mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); + mrb_value cname = mrb_mod_to_s(mrb, mrb_obj_value(mrb_obj_class(mrb, exc))); + mesg = mrb_obj_as_string(mrb, mesg); + return RSTRING_LEN(mesg) == 0 ? cname : mrb_format(mrb, "%v (%v)", mesg, cname); } void mrb_keep_backtrace(mrb_state *mrb, mrb_value exc); @@ -192,33 +167,6 @@ exc_set_backtrace(mrb_state *mrb, mrb_value exc) return backtrace; } -static void -exc_debug_info(mrb_state *mrb, struct RObject *exc) -{ - mrb_callinfo *ci = mrb->c->ci; - const mrb_code *pc = ci->pc; - - if (mrb_obj_iv_defined(mrb, exc, mrb_intern_lit(mrb, "file"))) return; - while (ci >= mrb->c->cibase) { - const mrb_code *err = ci->err; - - if (!err && pc) err = pc - 1; - if (err && ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) { - mrb_irep *irep = ci->proc->body.irep; - - int32_t const line = mrb_debug_get_line(mrb, irep, err - irep->iseq); - char const* file = mrb_debug_get_filename(mrb, irep, err - irep->iseq); - if (line != -1 && file) { - mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "file"), mrb_str_new_cstr(mrb, file)); - mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "line"), mrb_fixnum_value(line)); - return; - } - } - pc = ci->pc; - ci--; - } -} - void mrb_exc_set(mrb_state *mrb, mrb_value exc) { @@ -232,7 +180,6 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc) mrb->gc.arena_idx--; } if (!mrb->gc.out_of_memory && !mrb_frozen_p(mrb->exc)) { - exc_debug_info(mrb, mrb->exc); mrb_keep_backtrace(mrb, exc); } } @@ -355,7 +302,11 @@ mrb_vformat(mrb_state *mrb, const char *format, va_list ap) mrb_gc_arena_restore(mrb, ai); break; case 'n': +#if UINT32_MAX < INT_MAX + obj = mrb_symbol_value((mrb_sym)va_arg(ap, int)); +#else obj = mrb_symbol_value(va_arg(ap, mrb_sym)); +#endif goto L_cat_obj; case 's': chars = va_arg(ap, char*); @@ -530,7 +481,7 @@ exception_call: break; default: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%i for 0..3)", argc); + mrb_argnum_error(mrb, argc, 0, 3); break; } if (argc > 0) { @@ -586,6 +537,19 @@ mrb_frozen_error(mrb_state *mrb, void *frozen_obj) mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %t", mrb_obj_value(frozen_obj)); } +MRB_API mrb_noreturn void +mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max) +{ +#define FMT(exp) "wrong number of arguments (given %i, expected " exp ")" + if (min == max) + mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d"), argc, min); + else if (max < 0) + mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d+"), argc, min); + else + mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d..%d"), argc, min, max); +#undef FMT +} + void mrb_init_exception(mrb_state *mrb) { @@ -598,7 +562,7 @@ mrb_init_exception(mrb_state *mrb) mrb_define_method(mrb, exception, "initialize", exc_initialize, MRB_ARGS_OPT(1)); mrb_define_method(mrb, exception, "to_s", exc_to_s, MRB_ARGS_NONE()); mrb_define_method(mrb, exception, "message", exc_message, MRB_ARGS_NONE()); - mrb_define_method(mrb, exception, "inspect", exc_inspect, MRB_ARGS_NONE()); + mrb_define_method(mrb, exception, "inspect", mrb_exc_inspect, MRB_ARGS_NONE()); mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE()); mrb_define_method(mrb, exception, "set_backtrace", exc_set_backtrace, MRB_ARGS_REQ(1)); diff --git a/src/fmt_fp.c b/src/fmt_fp.c index 1f1af6764..b77abe7b5 100644 --- a/src/fmt_fp.c +++ b/src/fmt_fp.c @@ -30,7 +30,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <limits.h> #include <string.h> -#include <stdint.h> #include <math.h> #include <float.h> #include <ctype.h> @@ -807,10 +807,12 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end) case MRB_TT_SCLASS: mrb_gc_free_mt(mrb, (struct RClass*)obj); mrb_gc_free_iv(mrb, (struct RObject*)obj); + mrb_mc_clear_by_class(mrb, (struct RClass*)obj); break; case MRB_TT_ICLASS: if (MRB_FLAG_TEST(obj, MRB_FL_CLASS_IS_ORIGIN)) mrb_gc_free_mt(mrb, (struct RClass*)obj); + mrb_mc_clear_by_class(mrb, (struct RClass*)obj); break; case MRB_TT_ENV: { diff --git a/src/hash.c b/src/hash.c index d94fc23b0..70f437358 100644 --- a/src/hash.c +++ b/src/hash.c @@ -800,7 +800,7 @@ mrb_hash_init(mrb_state *mrb, mrb_value hash) mrb_hash_modify(mrb, hash); if (!mrb_nil_p(block)) { if (ifnone_p) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + mrb_argnum_error(mrb, 1, 0, 0); } RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; ifnone = block; diff --git a/src/kernel.c b/src/kernel.c index 69a7311e0..8bb837eca 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -384,7 +384,7 @@ mrb_obj_extend(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb_value obj) mrb_int i; if (argc == 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (at least 1)"); + mrb_argnum_error(mrb, argc, 1, -1); } for (i = 0; i < argc; i++) { mrb_check_type(mrb, argv[i], MRB_TT_MODULE); diff --git a/src/load.c b/src/load.c index 471ff3841..e624c52d5 100644 --- a/src/load.c +++ b/src/load.c @@ -42,22 +42,22 @@ offset_crc_body(void) } #ifndef MRB_WITHOUT_FLOAT +double mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck); + static double -str_to_double(mrb_state *mrb, mrb_value str) +str_to_double(mrb_state *mrb, const char *p, size_t len) { - const char *p = RSTRING_PTR(str); - mrb_int len = RSTRING_LEN(str); - /* `i`, `inf`, `infinity` */ if (len > 0 && p[0] == 'i') return INFINITY; /* `I`, `-inf`, `-infinity` */ if (p[0] == 'I' || (len > 1 && p[0] == '-' && p[1] == 'i')) return -INFINITY; - - return mrb_str_to_dbl(mrb, str, TRUE); + return mrb_str_len_to_dbl(mrb, p, len, TRUE); } #endif +mrb_value mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck); + static mrb_irep* read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags) { @@ -119,21 +119,17 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * plen); for (i = 0; i < plen; i++) { - mrb_value s; + const char *s; + mrb_bool st = (flags & FLAG_SRC_MALLOC)==0; tt = *src++; /* pool TT */ pool_data_len = bin_to_uint16(src); /* pool data length */ src += sizeof(uint16_t); - if (flags & FLAG_SRC_MALLOC) { - s = mrb_str_new(mrb, (char *)src, pool_data_len); - } - else { - s = mrb_str_new_static(mrb, (char *)src, pool_data_len); - } + s = (const char*)src; src += pool_data_len; switch (tt) { /* pool data */ case IREP_TT_FIXNUM: { - mrb_value num = mrb_str_to_inum(mrb, s, 10, FALSE); + mrb_value num = mrb_str_len_to_inum(mrb, s, pool_data_len, 10, FALSE); #ifdef MRB_WITHOUT_FLOAT irep->pool[i] = num; #else @@ -144,12 +140,12 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag #ifndef MRB_WITHOUT_FLOAT case IREP_TT_FLOAT: - irep->pool[i] = mrb_float_pool(mrb, str_to_double(mrb, s)); + irep->pool[i] = mrb_float_pool(mrb, str_to_double(mrb, s, pool_data_len)); break; #endif case IREP_TT_STRING: - irep->pool[i] = mrb_str_pool(mrb, s); + irep->pool[i] = mrb_str_pool(mrb, s, pool_data_len, st); break; default: diff --git a/src/print.c b/src/print.c index 03b5eadfa..7d2d16086 100644 --- a/src/print.c +++ b/src/print.c @@ -31,7 +31,6 @@ MRB_API void mrb_print_error(mrb_state *mrb) { mrb_print_backtrace(mrb); - printstr(mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0), stderr); } MRB_API void diff --git a/src/string.c b/src/string.c index 5a0a6a233..c7b9db17a 100644 --- a/src/string.c +++ b/src/string.c @@ -10,6 +10,7 @@ #ifndef MRB_WITHOUT_FLOAT #include <float.h> +#include <math.h> #endif #include <limits.h> #include <stddef.h> @@ -553,7 +554,7 @@ str_share(mrb_state *mrb, struct RString *orig, struct RString *s) size_t len = (size_t)orig->as.heap.len; mrb_assert(!RSTR_EMBED_P(orig)); - if (RSTR_NOFREE_P(orig) || RSTR_POOL_P(orig)) { + if (RSTR_NOFREE_P(orig)) { str_init_nofree(s, orig->as.heap.ptr, len); } else if (RSTR_SHARED_P(orig)) { @@ -562,7 +563,7 @@ str_share(mrb_state *mrb, struct RString *orig, struct RString *s) else if (RSTR_FSHARED_P(orig)) { str_init_fshared(orig, s, orig->as.heap.aux.fshared); } - else if (mrb_frozen_p(orig)) { + else if (mrb_frozen_p(orig) && !RSTR_POOL_P(orig)) { str_init_fshared(orig, s, orig); } else { @@ -576,12 +577,9 @@ str_share(mrb_state *mrb, struct RString *orig, struct RString *s) } mrb_value -mrb_str_pool(mrb_state *mrb, mrb_value str) +mrb_str_pool(mrb_state *mrb, const char *p, mrb_int len, mrb_bool nofree) { struct RString *s = (struct RString *)mrb_malloc(mrb, sizeof(struct RString)); - struct RString *orig = mrb_str_ptr(str); - const char *p = RSTR_PTR(orig); - size_t len = (size_t)RSTR_LEN(orig); s->tt = MRB_TT_STRING; s->c = mrb->string_class; @@ -590,7 +588,7 @@ mrb_str_pool(mrb_state *mrb, mrb_value str) if (RSTR_EMBEDDABLE_P(len)) { str_init_embed(s, p, len); } - else if (RSTR_NOFREE_P(orig)) { + else if (nofree) { str_init_nofree(s, p, len); } else { @@ -1095,7 +1093,6 @@ mrb_str_equal_m(mrb_state *mrb, mrb_value str1) return mrb_bool_value(mrb_str_equal(mrb, str1, str2)); } /* ---------------------------------- */ -mrb_value mrb_mod_to_s(mrb_state *mrb, mrb_value klass); MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str) @@ -2243,7 +2240,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) return result; } -static mrb_value +mrb_value mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck) { const char *p = str; @@ -2492,20 +2489,78 @@ mrb_str_to_i(mrb_state *mrb, mrb_value self) } #ifndef MRB_WITHOUT_FLOAT -MRB_API double -mrb_cstr_to_dbl(mrb_state *mrb, const char * s, mrb_bool badcheck) +double +mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck) { - const char *p = s; + char buf[DBL_DIG * 4 + 20]; + const char *p = s, *p2; + const char *pend = p + len; char *end; - char buf[DBL_DIG * 4 + 10]; + char *n; + char prev = 0; double d; + mrb_bool dot = FALSE; if (!p) return 0.0; - while (ISSPACE(*p)) p++; - - if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { - return 0.0; + while (p<pend && ISSPACE(*p)) p++; + p2 = p; + + if (pend - p > 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { + mrb_value x; + + if (!badcheck) return 0.0; + x = mrb_str_len_to_inum(mrb, p, pend-p, 0, badcheck); + if (mrb_fixnum_p(x)) + d = (double)mrb_fixnum(x); + else /* if (mrb_float_p(x)) */ + d = mrb_float(x); + return d; } + while (p < pend) { + if (!*p) { + if (badcheck) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte"); + /* not reached */ + } + pend = p; + p = p2; + goto nocopy; + } + if (!badcheck && *p == ' ') { + pend = p; + p = p2; + goto nocopy; + } + if (*p == '_') break; + p++; + } + p = p2; + n = buf; + while (p < pend) { + char c = *p++; + if (c == '.') dot = TRUE; + if (c == '_') { + /* remove an underscore between digits */ + if (n == buf || !ISDIGIT(prev) || p == pend) { + if (badcheck) goto bad; + break; + } + } + else if (badcheck && prev == '_' && !ISDIGIT(c)) goto bad; + else { + const char *bend = buf+sizeof(buf)-1; + if (n==bend) { /* buffer overflow */ + if (dot) break; /* cut off remaining fractions */ + return INFINITY; + } + *n++ = c; + } + prev = c; + } + *n = '\0'; + p = buf; + pend = n; +nocopy: d = mrb_float_read(p, &end); if (p == end) { if (badcheck) { @@ -2515,44 +2570,24 @@ bad: } return d; } - if (*end) { - char *n = buf; - char *e = buf + sizeof(buf) - 1; - char prev = 0; - - while (p < end && n < e) prev = *n++ = *p++; - while (*p) { - if (*p == '_') { - /* remove an underscore between digits */ - if (n == buf || !ISDIGIT(prev) || (++p, !ISDIGIT(*p))) { - if (badcheck) goto bad; - break; - } - } - prev = *p++; - if (n < e) *n++ = prev; - } - *n = '\0'; - p = buf; - - if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { - return 0.0; - } - - d = mrb_float_read(p, &end); - if (badcheck) { - if (!end || p == end) goto bad; - while (*end && ISSPACE(*end)) end++; - if (*end) goto bad; - } + if (badcheck) { + if (!end || p == end) goto bad; + while (end<pend && ISSPACE(*end)) end++; + if (end<pend) goto bad; } return d; } MRB_API double +mrb_cstr_to_dbl(mrb_state *mrb, const char *s, mrb_bool badcheck) +{ + return mrb_str_len_to_dbl(mrb, s, strlen(s), badcheck); +} + +MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck) { - return mrb_cstr_to_dbl(mrb, RSTRING_CSTR(mrb, str), badcheck); + return mrb_str_len_to_dbl(mrb, RSTRING_PTR(str), RSTRING_LEN(str), badcheck); } /* 15.2.10.5.39 */ @@ -6,7 +6,9 @@ #include <stddef.h> #include <stdarg.h> +#ifndef MRB_WITHOUT_FLOAT #include <math.h> +#endif #include <mruby.h> #include <mruby/array.h> #include <mruby/class.h> @@ -1498,8 +1500,7 @@ RETRY_TRY_BLOCK: mrb_sym mid; struct REnv *e = MRB_PROC_ENV(m); - mid = e->mid; - if (mid) ci->mid = mid; + ci->mid = mid = e->mid; if (!e->stack) { e->stack = mrb->c->stack; } |
