diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 11 | ||||
| -rw-r--r-- | src/class.c | 2 | ||||
| -rw-r--r-- | src/object.c | 2 | ||||
| -rw-r--r-- | src/proc.c | 2 | ||||
| -rw-r--r-- | src/range.c | 39 | ||||
| -rw-r--r-- | src/string.c | 242 | ||||
| -rw-r--r-- | src/vm.c | 47 |
7 files changed, 313 insertions, 32 deletions
diff --git a/src/array.c b/src/array.c index 9013492fb..f6599bd5b 100644 --- a/src/array.c +++ b/src/array.c @@ -173,11 +173,13 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len) capa = ARY_DEFAULT_LEN; } while (capa < len) { - capa *= 2; + if (capa <= ARY_MAX_SIZE / 2) { + capa *= 2; + } else { + capa = ARY_MAX_SIZE; + } } - if (capa > ARY_MAX_SIZE) capa = ARY_MAX_SIZE; /* len <= capa <= ARY_MAX_SIZE */ - if (capa > a->aux.capa) { mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa); @@ -503,6 +505,9 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self) mrb_int len; mrb_get_args(mrb, "*", &vals, &len); + if (len > ARY_MAX_SIZE - a->len) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); + } if (ARY_SHARED_P(a) && a->aux.shared->refcnt == 1 /* shared only referenced from this array */ && a->ptr - a->aux.shared->ptr >= len) /* there's room for unshifted item */ { diff --git a/src/class.c b/src/class.c index bac1d2984..e724dbb91 100644 --- a/src/class.c +++ b/src/class.c @@ -1817,7 +1817,7 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "*", &argv, &argc); while (argc--) { - undef_method(mrb, c, mrb_symbol(*argv)); + undef_method(mrb, c, to_sym(mrb, *argv)); argv++; } return mrb_nil_value(); diff --git a/src/object.c b/src/object.c index f76ee68a2..eb2c23e63 100644 --- a/src/object.c +++ b/src/object.c @@ -444,7 +444,7 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj) mrb_str_cat_lit(mrb, str, "#<"); mrb_str_cat_cstr(mrb, str, cname); mrb_str_cat_lit(mrb, str, ":"); - mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(obj))); + mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_ptr(obj))); mrb_str_cat_lit(mrb, str, ">"); return str; diff --git a/src/proc.c b/src/proc.c index 4f770932b..470547094 100644 --- a/src/proc.c +++ b/src/proc.c @@ -140,7 +140,7 @@ mrb_proc_copy(struct RProc *a, struct RProc *b) { a->flags = b->flags; a->body = b->body; - if (!MRB_PROC_CFUNC_P(a)) { + if (!MRB_PROC_CFUNC_P(a) && a->body.irep) { a->body.irep->refcnt++; } a->target_class = b->target_class; diff --git a/src/range.c b/src/range.c index f0a976e53..417957420 100644 --- a/src/range.c +++ b/src/range.c @@ -12,6 +12,17 @@ #define RANGE_CLASS (mrb_class_get(mrb, "Range")) +MRB_API struct RRange* +mrb_range_ptr(mrb_state *mrb, mrb_value v) +{ + struct RRange *r = (struct RRange*)mrb_ptr(v); + + if (r->edges == NULL) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range"); + } + return r; +} + static void range_check(mrb_state *mrb, mrb_value a, mrb_value b) { @@ -57,7 +68,7 @@ mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl) mrb_value mrb_range_beg(mrb_state *mrb, mrb_value range) { - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); return r->edges->beg; } @@ -76,7 +87,7 @@ mrb_range_beg(mrb_state *mrb, mrb_value range) mrb_value mrb_range_end(mrb_state *mrb, mrb_value range) { - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); return r->edges->end; } @@ -90,7 +101,7 @@ mrb_range_end(mrb_state *mrb, mrb_value range) mrb_value mrb_range_excl(mrb_state *mrb, mrb_value range) { - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); return mrb_bool_value(r->excl); } @@ -98,7 +109,7 @@ mrb_range_excl(mrb_state *mrb, mrb_value range) static void range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_bool exclude_end) { - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_raw_ptr(range); range_check(mrb, beg, end); r->excl = exclude_end; @@ -129,7 +140,7 @@ mrb_range_initialize(mrb_state *mrb, mrb_value range) exclusive = FALSE; } /* Ranges are immutable, so that they should be initialized only once. */ - if (mrb_range_ptr(range)->edges) { + if (mrb_range_raw_ptr(range)->edges) { mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "`initialize' called twice"); } range_init(mrb, range, beg, end, exclusive); @@ -164,8 +175,8 @@ mrb_range_eq(mrb_state *mrb, mrb_value range) return mrb_false_value(); } - rr = mrb_range_ptr(range); - ro = mrb_range_ptr(obj); + rr = mrb_range_ptr(mrb, range); + ro = mrb_range_ptr(mrb, obj); v1 = mrb_funcall(mrb, rr->edges->beg, "==", 1, ro->edges->beg); v2 = mrb_funcall(mrb, rr->edges->end, "==", 1, ro->edges->end); if (!mrb_bool(v1) || !mrb_bool(v2) || rr->excl != ro->excl) { @@ -222,7 +233,7 @@ mrb_value mrb_range_include(mrb_state *mrb, mrb_value range) { mrb_value val; - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); mrb_value beg, end; mrb_bool include_p; @@ -241,7 +252,7 @@ static mrb_bool range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc) { mrb_int beg, end; - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); if (mrb_type(range) != MRB_TT_RANGE) return FALSE; @@ -287,7 +298,7 @@ static mrb_value range_to_s(mrb_state *mrb, mrb_value range) { mrb_value str, str2; - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); str = mrb_obj_as_string(mrb, r->edges->beg); str2 = mrb_obj_as_string(mrb, r->edges->end); @@ -312,7 +323,7 @@ static mrb_value range_inspect(mrb_state *mrb, mrb_value range) { mrb_value str, str2; - struct RRange *r = mrb_range_ptr(range); + struct RRange *r = mrb_range_ptr(mrb, range); str = mrb_inspect(mrb, r->edges->beg); str2 = mrb_inspect(mrb, r->edges->end); @@ -352,8 +363,8 @@ range_eql(mrb_state *mrb, mrb_value range) } if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value(); - r = mrb_range_ptr(range); - o = mrb_range_ptr(obj); + r = mrb_range_ptr(mrb, range); + o = mrb_range_ptr(mrb, obj); if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) || !mrb_eql(mrb, r->edges->end, o->edges->end) || (r->excl != o->excl)) { @@ -376,7 +387,7 @@ range_initialize_copy(mrb_state *mrb, mrb_value copy) mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class"); } - r = mrb_range_ptr(src); + r = mrb_range_ptr(mrb, src); range_init(mrb, copy, r->edges->beg, r->edges->end, r->excl); return copy; diff --git a/src/string.c b/src/string.c index f47294291..4f722b273 100644 --- a/src/string.c +++ b/src/string.c @@ -2286,7 +2286,7 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, mrb_bool badcheck) if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { return 0.0; } - d = strtod(p, &end); + d = mrb_float_read(p, &end); if (p == end) { if (badcheck) { bad: @@ -2324,7 +2324,7 @@ bad: return 0.0; } - d = strtod(p, &end); + d = mrb_float_read(p, &end); if (badcheck) { if (!end || p == end) goto bad; while (*end && ISSPACE(*end)) end++; @@ -2749,3 +2749,241 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); } + +/* + * Source code for the "strtod" library procedure. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * RCS: @(#) $Id: strtod.c 11708 2007-02-12 23:01:19Z shyouhei $ + */ + +#include <ctype.h> +#include <errno.h> +extern int errno; + +#ifndef __STDC__ +# ifdef __GNUC__ +# define const __const__ +# else +# define const +# endif +#endif + +static const int maxExponent = 511; /* Largest possible base 10 exponent. Any + * exponent larger than this will already + * produce underflow or overflow, so there's + * no need to worry about additional digits. + */ +static const double powersOf10[] = {/* Table giving binary powers of 10. Entry */ + 10., /* is 10^2^i. Used to convert decimal */ + 100., /* exponents into floating-point numbers. */ + 1.0e4, + 1.0e8, + 1.0e16, + 1.0e32, + 1.0e64, + 1.0e128, + 1.0e256 +}; + +MRB_API double +mrb_float_read(const char *string, char **endPtr) +/* const char *string; A decimal ASCII floating-point number, + * optionally preceded by white space. + * Must have form "-I.FE-X", where I is the + * integer part of the mantissa, F is the + * fractional part of the mantissa, and X + * is the exponent. Either of the signs + * may be "+", "-", or omitted. Either I + * or F may be omitted, or both. The decimal + * point isn't necessary unless F is present. + * The "E" may actually be an "e". E and X + * may both be omitted (but not just one). + */ +/* char **endPtr; If non-NULL, store terminating character's + * address here. */ +{ + int sign, expSign = FALSE; + double fraction, dblExp; + const double *d; + register const char *p; + register int c; + int exp = 0; /* Exponent read from "EX" field. */ + int fracExp = 0; /* Exponent that derives from the fractional + * part. Under normal circumstatnces, it is + * the negative of the number of digits in F. + * However, if I is very long, the last digits + * of I get dropped (otherwise a long I with a + * large negative exponent could cause an + * unnecessary overflow on I alone). In this + * case, fracExp is incremented one for each + * dropped digit. */ + int mantSize; /* Number of digits in mantissa. */ + int decPt; /* Number of mantissa digits BEFORE decimal + * point. */ + const char *pExp; /* Temporarily holds location of exponent + * in string. */ + + /* + * Strip off leading blanks and check for a sign. + */ + + p = string; + while (isspace(*p)) { + p += 1; + } + if (*p == '-') { + sign = TRUE; + p += 1; + } else { + if (*p == '+') { + p += 1; + } + sign = FALSE; + } + + /* + * Count the number of digits in the mantissa (including the decimal + * point), and also locate the decimal point. + */ + + decPt = -1; + for (mantSize = 0; ; mantSize += 1) + { + c = *p; + if (!isdigit(c)) { + if ((c != '.') || (decPt >= 0)) { + break; + } + decPt = mantSize; + } + p += 1; + } + + /* + * Now suck up the digits in the mantissa. Use two integers to + * collect 9 digits each (this is faster than using floating-point). + * If the mantissa has more than 18 digits, ignore the extras, since + * they can't affect the value anyway. + */ + + pExp = p; + p -= mantSize; + if (decPt < 0) { + decPt = mantSize; + } else { + mantSize -= 1; /* One of the digits was the point. */ + } + if (mantSize > 18) { + fracExp = decPt - 18; + mantSize = 18; + } else { + fracExp = decPt - mantSize; + } + if (mantSize == 0) { + fraction = 0.0; + p = string; + goto done; + } else { + int frac1, frac2; + frac1 = 0; + for ( ; mantSize > 9; mantSize -= 1) + { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac1 = 10*frac1 + (c - '0'); + } + frac2 = 0; + for (; mantSize > 0; mantSize -= 1) + { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac2 = 10*frac2 + (c - '0'); + } + fraction = (1.0e9 * frac1) + frac2; + } + + /* + * Skim off the exponent. + */ + + p = pExp; + if ((*p == 'E') || (*p == 'e')) { + p += 1; + if (*p == '-') { + expSign = TRUE; + p += 1; + } else { + if (*p == '+') { + p += 1; + } + expSign = FALSE; + } + while (isdigit(*p)) { + exp = exp * 10 + (*p - '0'); + p += 1; + } + } + if (expSign) { + exp = fracExp - exp; + } else { + exp = fracExp + exp; + } + + /* + * Generate a floating-point number that represents the exponent. + * Do this by processing the exponent one bit at a time to combine + * many powers of 2 of 10. Then combine the exponent with the + * fraction. + */ + + if (exp < 0) { + expSign = TRUE; + exp = -exp; + } else { + expSign = FALSE; + } + if (exp > maxExponent) { + exp = maxExponent; + errno = ERANGE; + } + dblExp = 1.0; + for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { + if (exp & 01) { + dblExp *= *d; + } + } + if (expSign) { + fraction /= dblExp; + } else { + fraction *= dblExp; + } + +done: + if (endPtr != NULL) { + *endPtr = (char *) p; + } + + if (sign) { + return -fraction; + } + return fraction; +} @@ -54,6 +54,10 @@ The value below allows about 60000 recursive calls in the simplest case. */ #define ARENA_RESTORE(mrb,ai) (mrb)->gc.arena_idx = (ai) +#define CALL_MAXARGS 127 + +void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); + static inline void stack_clear(mrb_value *from, size_t count) { @@ -362,9 +366,13 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc c = mrb_class(mrb, self); p = mrb_method_search_vm(mrb, &c, mid); if (!p) { + mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); + p = mrb_method_search_vm(mrb, &c, missing); + if (!p) { + mrb_value args = mrb_ary_new_from_values(mrb, argc, argv); + mrb_method_missing(mrb, mid, self, args); + } undef = mid; - mid = mrb_intern_lit(mrb, "method_missing"); - p = mrb_method_search_vm(mrb, &c, mid); n++; argc++; } ci = cipush(mrb); @@ -749,10 +757,6 @@ argnum_error(mrb_state *mrb, mrb_int num) #endif -#define CALL_MAXARGS 127 - -void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); - MRB_API mrb_value mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) { @@ -1290,8 +1294,20 @@ RETRY_TRY_BLOCK: c = mrb->c->ci->target_class->super; m = mrb_method_search_vm(mrb, &c, mid); if (!m) { - mid = mrb_intern_lit(mrb, "method_missing"); - m = mrb_method_search_vm(mrb, &c, mid); + mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); + m = mrb_method_search_vm(mrb, &c, missing); + if (!m) { + mrb_value args; + + if (n == CALL_MAXARGS) { + args = regs[a+1]; + } + else { + args = mrb_ary_new_from_values(mrb, n, regs+a+1); + } + mrb_method_missing(mrb, mid, recv, args); + } + mid = missing; if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); } @@ -1681,9 +1697,20 @@ RETRY_TRY_BLOCK: m = mrb_method_search_vm(mrb, &c, mid); if (!m) { mrb_value sym = mrb_symbol_value(mid); + mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); + m = mrb_method_search_vm(mrb, &c, missing); + if (!m) { + mrb_value args; - mid = mrb_intern_lit(mrb, "method_missing"); - m = mrb_method_search_vm(mrb, &c, mid); + if (n == CALL_MAXARGS) { + args = regs[a+1]; + } + else { + args = mrb_ary_new_from_values(mrb, n, regs+a+1); + } + mrb_method_missing(mrb, mid, recv, args); + } + mid = missing; if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); } |
