summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backtrace.c85
-rw-r--r--src/class.c69
-rw-r--r--src/error.c88
-rw-r--r--src/fmt_fp.c1
-rw-r--r--src/gc.c2
-rw-r--r--src/hash.c2
-rw-r--r--src/kernel.c2
-rw-r--r--src/load.c28
-rw-r--r--src/print.c1
-rw-r--r--src/string.c131
-rw-r--r--src/vm.c5
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>
diff --git a/src/gc.c b/src/gc.c
index 40c85a373..8d9a1806c 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -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 */
diff --git a/src/vm.c b/src/vm.c
index 54f74907e..09b0c767e 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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;
}