diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/class.c | 52 | ||||
| -rw-r--r-- | src/codegen.c | 141 | ||||
| -rw-r--r-- | src/debug.c | 26 | ||||
| -rw-r--r-- | src/dump.c | 237 | ||||
| -rw-r--r-- | src/etc.c | 8 | ||||
| -rw-r--r-- | src/gc.c | 4 | ||||
| -rw-r--r-- | src/hash.c | 61 | ||||
| -rw-r--r-- | src/kernel.c | 34 | ||||
| -rw-r--r-- | src/load.c | 121 | ||||
| -rw-r--r-- | src/mrb_throw.h | 2 | ||||
| -rw-r--r-- | src/node.h | 208 | ||||
| -rw-r--r-- | src/numeric.c | 33 | ||||
| -rw-r--r-- | src/object.c | 14 | ||||
| -rw-r--r-- | src/parse.y | 19 | ||||
| -rw-r--r-- | src/pool.c | 9 | ||||
| -rw-r--r-- | src/print.c | 9 | ||||
| -rw-r--r-- | src/re.h | 2 | ||||
| -rw-r--r-- | src/state.c | 23 | ||||
| -rw-r--r-- | src/string.c | 465 | ||||
| -rw-r--r-- | src/symbol.c | 44 | ||||
| -rw-r--r-- | src/variable.c | 10 | ||||
| -rw-r--r-- | src/vm.c | 16 |
22 files changed, 874 insertions, 664 deletions
diff --git a/src/class.c b/src/class.c index 8188db131..1a55009e4 100644 --- a/src/class.c +++ b/src/class.c @@ -411,6 +411,7 @@ to_hash(mrb_state *mrb, mrb_value val) &: Block [mrb_value] *: rest argument [mrb_value*,int] Receive the rest of the arguments as an array. |: optional Next argument of '|' and later are optional. + ?: optional given [mrb_bool] true if preceding argument (optional) is given. */ int mrb_get_args(mrb_state *mrb, const char *format, ...) @@ -420,7 +421,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *sp = mrb->c->stack + 1; va_list ap; int argc = mrb->c->ci->argc; - int opt = 0; + mrb_bool opt = 0; + mrb_bool given = 1; va_start(ap, format); if (argc < 0) { @@ -431,11 +433,16 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } while ((c = *format++)) { switch (c) { - case '|': case '*': case '&': + case '|': case '*': case '&': case '?': break; default: - if (argc <= i && !opt) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + if (argc <= i) { + if (opt) { + given = 0; + } + else { + mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + } } break; } @@ -511,7 +518,6 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) case 's': { mrb_value ss; - struct RString *s; char **ps = 0; int *pl = 0; @@ -519,9 +525,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) pl = va_arg(ap, int*); if (i < argc) { ss = to_str(mrb, *sp++); - s = mrb_str_ptr(ss); - *ps = s->ptr; - *pl = s->len; + *ps = RSTRING_PTR(ss); + *pl = RSTRING_LEN(ss); i++; } } @@ -529,22 +534,12 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) case 'z': { mrb_value ss; - struct RString *s; char **ps; - mrb_int len; ps = va_arg(ap, char**); if (i < argc) { ss = to_str(mrb, *sp++); - s = mrb_str_ptr(ss); - len = (mrb_int)strlen(s->ptr); - if (len < s->len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); - } - else if (len > s->len) { - mrb_str_modify(mrb, s); - } - *ps = s->ptr; + *ps = mrb_string_value_cstr(mrb, &ss); i++; } } @@ -691,6 +686,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) case '|': opt = 1; break; + case '?': + { + mrb_bool *p; + + p = va_arg(ap, mrb_bool*); + *p = given; + } + break; case '*': { @@ -1255,7 +1258,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) { mrb_value path; const char *name; - size_t len; + mrb_int len; mrb_sym classpath = mrb_intern_lit(mrb, "__classpath__"); path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath); @@ -1298,7 +1301,7 @@ mrb_class_name(mrb_state *mrb, struct RClass* c) mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c)); mrb_str_cat_lit(mrb, path, ">"); } - return mrb_str_ptr(path)->ptr; + return RSTRING_PTR(path); } const char* @@ -1542,7 +1545,7 @@ static void check_cv_name_sym(mrb_state *mrb, mrb_sym id) { const char *s; - size_t len; + mrb_int len; s = mrb_sym2name_len(mrb, id, &len); if (len < 3 || !(s[0] == '@' && s[1] == '@')) { @@ -1554,7 +1557,8 @@ static void check_cv_name_str(mrb_state *mrb, mrb_value str) { const char *s = RSTRING_PTR(str); - size_t const len = RSTRING_LEN(str); + mrb_int len = RSTRING_LEN(str); + if (len < 3 || !(s[0] == '@' && s[1] == '@')) { mrb_name_error(mrb, mrb_intern_str(mrb, str), "`%S' is not allowed as a class variable name", str); } @@ -1814,7 +1818,7 @@ static void check_const_name_sym(mrb_state *mrb, mrb_sym id) { const char *s; - size_t len; + mrb_int len; s = mrb_sym2name_len(mrb, id, &len); if (len < 1 || !ISUPPER(*s)) { diff --git a/src/codegen.c b/src/codegen.c index 77bc5e34e..60da17f2b 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -5,6 +5,7 @@ */ #include <ctype.h> +#include <limits.h> #include <stdlib.h> #include <string.h> #include "mruby.h" @@ -139,7 +140,7 @@ new_label(codegen_scope *s) return s->pc; } -static inline void +static inline int genop(codegen_scope *s, mrb_code i) { if (s->pc == s->icapa) { @@ -154,13 +155,13 @@ genop(codegen_scope *s, mrb_code i) if (s->lines) { s->lines[s->pc] = s->lineno; } - s->pc++; + return s->pc++; } #define NOVAL 0 #define VAL 1 -static void +static int genop_peep(codegen_scope *s, mrb_code i, int val) { /* peephole optimization */ @@ -173,24 +174,24 @@ genop_peep(codegen_scope *s, mrb_code i, int val) case OP_MOVE: if (GETARG_A(i) == GETARG_B(i)) { /* skip useless OP_MOVE */ - return; + return 0; } if (val) break; switch (c0) { case OP_MOVE: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0) && GETARG_A(i) >= s->nlocals) { /* skip swapping OP_MOVE */ - return; + return 0; } if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { s->iseq[s->pc-1] = MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)); - return; + return 0; } break; case OP_LOADI: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0)); - return; + return 0; } break; case OP_ARRAY: @@ -200,7 +201,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val) case OP_GETUPVAR: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0)); - return; + return 0; } break; case OP_LOADSYM: @@ -213,13 +214,13 @@ genop_peep(codegen_scope *s, mrb_code i, int val) case OP_STRING: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0)); - return; + return 0; } break; case OP_SCLASS: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0)); - return; + return 0; } break; case OP_LOADNIL: @@ -229,7 +230,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val) case OP_OCLASS: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i)); - return; + return 0; } break; default: @@ -245,7 +246,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val) if (c0 == OP_MOVE) { if (GETARG_A(i) == GETARG_A(i0)) { s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i)); - return; + return 0; } } break; @@ -254,29 +255,29 @@ genop_peep(codegen_scope *s, mrb_code i, int val) if (c0 == OP_MOVE) { if (GETARG_A(i) == GETARG_A(i0)) { s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i)); - return; + return 0; } } break; case OP_EPOP: if (c0 == OP_EPOP) { s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i)); - return; + return 0; } break; case OP_POPERR: if (c0 == OP_POPERR) { s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i)); - return; + return 0; } break; case OP_RETURN: switch (c0) { case OP_RETURN: - return; + return 0; case OP_MOVE: s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL); - return; + return 0; case OP_SETIV: case OP_SETCV: case OP_SETCONST: @@ -286,8 +287,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val) s->pc--; genop_peep(s, i0, NOVAL); i0 = s->iseq[s->pc-1]; - genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL)); - return; + return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL)); #if 0 case OP_SEND: if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) { @@ -311,7 +311,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val) 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; + return 0; } case OP_STRCAT: if (c0 == OP_STRING) { @@ -320,15 +320,22 @@ genop_peep(codegen_scope *s, mrb_code i, int val) if (mrb_type(s->irep->pool[i]) == MRB_TT_STRING && RSTRING_LEN(s->irep->pool[i]) == 0) { s->pc--; - return; + return 0; } } break; + case OP_JMPIF: + case OP_JMPNOT: + if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) { + s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i)); + return s->pc-1; + } + break; default: break; } } - genop(s, i); + return genop(s, i); } static void @@ -700,12 +707,16 @@ static mrb_sym attrsym(codegen_scope *s, mrb_sym a) { const char *name; - size_t len; + mrb_int len; char *name2; name = mrb_sym2name_len(s->mrb, a, &len); - name2 = (char *)codegen_palloc(s, len+1); - memcpy(name2, name, len); + name2 = (char *)codegen_palloc(s, + (size_t)len + + 1 /* '=' */ + + 1 /* '\0' */ + ); + memcpy(name2, name, (size_t)len); name2[len] = '='; name2[len+1] = '\0'; @@ -806,7 +817,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) } pop_n(n+1); { - size_t len; + mrb_int len; const char *name = mrb_sym2name_len(s->mrb, sym, &len); if (!noop && len == 1 && name[0] == '+') { @@ -1146,8 +1157,7 @@ codegen(codegen_scope *s, node *tree, int val) int onerr, noexc, exend, pos1, pos2, tmp; struct loopinfo *lp; - onerr = new_label(s); - genop(s, MKOP_Bx(OP_ONERR, 0)); + onerr = genop(s, MKOP_Bx(OP_ONERR, 0)); lp = loop_push(s, LOOP_BEGIN); lp->pc1 = onerr; if (tree->car) { @@ -1155,8 +1165,7 @@ codegen(codegen_scope *s, node *tree, int val) if (val) pop(); } lp->type = LOOP_RESCUE; - noexc = new_label(s); - genop(s, MKOP_Bx(OP_JMP, 0)); + noexc = genop(s, MKOP_Bx(OP_JMP, 0)); dispatch(s, onerr); tree = tree->cdr; exend = 0; @@ -1183,16 +1192,19 @@ codegen(codegen_scope *s, node *tree, int val) } genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); - tmp = new_label(s); - genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); + if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) { + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1)); + } + else { + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); + } + tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); pos2 = tmp; if (n4) { n4 = n4->cdr; } } while (n4); - pos1 = new_label(s); - genop(s, MKOP_sBx(OP_JMP, 0)); + pos1 = genop(s, MKOP_sBx(OP_JMP, 0)); dispatch_linked(s, pos2); pop(); @@ -1203,8 +1215,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, n3->cdr->cdr->car, val); if (val) pop(); } - tmp = new_label(s); - genop(s, MKOP_sBx(OP_JMP, exend)); + tmp = genop(s, MKOP_sBx(OP_JMP, exend)); exend = tmp; n2 = n2->cdr; push(); @@ -1269,8 +1280,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car, VAL); pop(); - pos1 = new_label(s); - genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0)); + pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL); codegen(s, tree->cdr->car, val); if (val && !(tree->cdr->car)) { @@ -1279,17 +1289,15 @@ codegen(codegen_scope *s, node *tree, int val) } if (e) { if (val) pop(); - pos2 = new_label(s); - genop(s, MKOP_sBx(OP_JMP, 0)); - dispatch(s, pos1); + pos2 = genop(s, MKOP_sBx(OP_JMP, 0)); + dispatch(s, pos1); codegen(s, e, val); dispatch(s, pos2); } else { if (val) { pop(); - pos2 = new_label(s); - genop(s, MKOP_sBx(OP_JMP, 0)); + pos2 = genop(s, MKOP_sBx(OP_JMP, 0)); dispatch(s, pos1); genop(s, MKOP_A(OP_LOADNIL, cursp())); dispatch(s, pos2); @@ -1307,9 +1315,8 @@ codegen(codegen_scope *s, node *tree, int val) int pos; codegen(s, tree->car, VAL); - pos = new_label(s); pop(); - genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0)); + pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0)); codegen(s, tree->cdr, val); dispatch(s, pos); } @@ -1320,9 +1327,8 @@ codegen(codegen_scope *s, node *tree, int val) int pos; codegen(s, tree->car, VAL); - pos = new_label(s); pop(); - genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0)); + pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0)); codegen(s, tree->cdr, val); dispatch(s, pos); } @@ -1332,8 +1338,7 @@ codegen(codegen_scope *s, node *tree, int val) { struct loopinfo *lp = loop_push(s, LOOP_NORMAL); - lp->pc1 = new_label(s); - genop(s, MKOP_sBx(OP_JMP, 0)); + lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0)); lp->pc2 = new_label(s); codegen(s, tree->cdr, NOVAL); dispatch(s, lp->pc1); @@ -1349,8 +1354,7 @@ codegen(codegen_scope *s, node *tree, int val) { struct loopinfo *lp = loop_push(s, LOOP_NORMAL); - lp->pc1 = new_label(s); - genop(s, MKOP_sBx(OP_JMP, 0)); + lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0)); lp->pc2 = new_label(s); codegen(s, tree->cdr, NOVAL); dispatch(s, lp->pc1); @@ -1397,20 +1401,17 @@ codegen(codegen_scope *s, node *tree, int val) else { pop(); } - tmp = new_label(s); - genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); + tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); pos2 = tmp; n = n->cdr; } if (tree->car->car) { - pos1 = new_label(s); - genop(s, MKOP_sBx(OP_JMP, 0)); + pos1 = genop(s, MKOP_sBx(OP_JMP, 0)); dispatch_linked(s, pos2); } codegen(s, tree->car->cdr, val); if (val) pop(); - tmp = new_label(s); - genop(s, MKOP_sBx(OP_JMP, pos3)); + tmp = genop(s, MKOP_sBx(OP_JMP, pos3)); pos3 = tmp; if (pos1) dispatch(s, pos1); tree = tree->cdr; @@ -1591,7 +1592,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_OP_ASGN: { mrb_sym sym = sym(tree->cdr->car); - size_t len; + mrb_int len; const char *name = mrb_sym2name_len(s->mrb, sym, &len); int idx; @@ -1602,8 +1603,7 @@ codegen(codegen_scope *s, node *tree, int val) int pos; pop(); - pos = new_label(s); - genop(s, MKOP_AsBx(name[0] == '|' ? OP_JMPIF : OP_JMPNOT, cursp(), 0)); + pos = genop_peep(s, MKOP_AsBx(name[0] == '|' ? OP_JMPIF : OP_JMPNOT, cursp(), 0), NOVAL); codegen(s, tree->cdr->cdr->car, VAL); pop(); gen_assignment(s, tree->car, cursp(), val); @@ -1905,7 +1905,7 @@ codegen(codegen_scope *s, node *tree, int val) mrb_value fix = mrb_fixnum_value((intptr_t)tree); mrb_value str = mrb_str_buf_new(mrb, 4); - mrb_str_buf_cat(mrb, str, "$", 1); + mrb_str_cat_lit(mrb, str, "$"); 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)); @@ -2097,7 +2097,7 @@ codegen(codegen_scope *s, node *tree, int val) char *p2 = (char*)tree->cdr; int ai = mrb_gc_arena_save(s->mrb); int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); - int off = new_lit(s, mrb_str_new(s->mrb, p1, strlen(p1))); + int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1)); int argc = 1; genop(s, MKOP_A(OP_OCLASS, cursp())); @@ -2106,7 +2106,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_ABx(OP_STRING, cursp(), off)); if (p2) { push(); - off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2))); + off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); argc++; pop(); @@ -2143,7 +2143,7 @@ codegen(codegen_scope *s, node *tree, int val) n = tree->cdr->cdr; if (n->car) { p = (char*)n->car; - off = new_lit(s, mrb_str_new(s->mrb, p, strlen(p))); + off = new_lit(s, mrb_str_new_cstr(s->mrb, p)); codegen(s, tree->car, VAL); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); pop(); @@ -2154,7 +2154,7 @@ codegen(codegen_scope *s, node *tree, int val) int off; push(); - off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2))); + off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); argc++; pop(); @@ -2548,8 +2548,7 @@ loop_break(codegen_scope *s, node *tree) if (tree) { genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL); } - tmp = new_label(s); - genop(s, MKOP_sBx(OP_JMP, loop->pc3)); + tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3)); loop->pc3 = tmp; } else { @@ -2573,14 +2572,16 @@ static void codedump(mrb_state *mrb, mrb_irep *irep) { #ifdef ENABLE_STDIO - uint32_t i; + int i; int ai; mrb_code c; if (!irep) return; printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", irep, irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen); - for (i=0; i<irep->ilen; i++) { + + mrb_assert(irep->ilen <= INT_MAX); + for (i = 0; i < (int)(irep->ilen); i++) { ai = mrb_gc_arena_save(mrb); printf("%03d ", i); c = irep->iseq[i]; diff --git a/src/debug.c b/src/debug.c index cdb0aa9e8..ae7705610 100644 --- a/src/debug.c +++ b/src/debug.c @@ -74,11 +74,11 @@ mrb_debug_get_line(mrb_irep *irep, uint32_t pc) switch(f->line_type) { case mrb_debug_line_ary: mrb_assert(f->start_pos <= pc && pc < (f->start_pos + f->line_entry_count)); - return f->line_ary[pc - f->start_pos]; + return f->lines.ary[pc - f->start_pos]; case mrb_debug_line_flat_map: { /* get upper bound */ - mrb_irep_debug_info_line *ret = f->line_flat_map; + mrb_irep_debug_info_line *ret = f->lines.flat_map; uint32_t count = f->line_entry_count; while (count > 0) { int32_t step = count / 2; @@ -92,10 +92,10 @@ mrb_debug_get_line(mrb_irep *irep, uint32_t pc) --ret; /* check line entry pointer range */ - mrb_assert(f->line_flat_map <= ret && ret < (f->line_flat_map + f->line_entry_count)); + mrb_assert(f->lines.flat_map <= ret && ret < (f->lines.flat_map + f->line_entry_count)); /* check pc range */ mrb_assert(ret->start_pos <= pc && - pc < (((ret + 1 - f->line_flat_map) < f->line_entry_count) + pc < (((ret + 1 - f->lines.flat_map) < f->line_entry_count) ? (ret+1)->start_pos : irep->debug_info->pc_count)); return ret->line; @@ -127,7 +127,7 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep, mrb_irep_debug_info_file *ret; uint32_t file_pc_count; size_t fn_len; - size_t len; + mrb_int len; uint32_t i; if (!irep->debug_info) { return NULL; } @@ -160,31 +160,31 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep, ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len); ret->line_type = select_line_type(irep->lines + start_pos, end_pos - start_pos); - ret->line_ptr = NULL; + ret->lines.ptr = NULL; switch(ret->line_type) { case mrb_debug_line_ary: ret->line_entry_count = file_pc_count; - ret->line_ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count); + ret->lines.ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count); for(i = 0; i < file_pc_count; ++i) { - ret->line_ary[i] = irep->lines[start_pos + i]; + ret->lines.ary[i] = irep->lines[start_pos + i]; } break; case mrb_debug_line_flat_map: { uint16_t prev_line = 0; mrb_irep_debug_info_line m; - ret->line_flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1); + ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1); ret->line_entry_count = 0; for(i = 0; i < file_pc_count; ++i) { if(irep->lines[start_pos + i] == prev_line) { continue; } - ret->line_flat_map = (mrb_irep_debug_info_line*)mrb_realloc( - mrb, ret->line_flat_map, + ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_realloc( + mrb, ret->lines.flat_map, sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1)); m.start_pos = start_pos + i; m.line = irep->lines[start_pos + i]; - ret->line_flat_map[ret->line_entry_count] = m; + ret->lines.flat_map[ret->line_entry_count] = m; /* update */ ++ret->line_entry_count; @@ -207,7 +207,7 @@ mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d) for(i = 0; i < d->flen; ++i) { mrb_assert(d->files[i]); - mrb_free(mrb, d->files[i]->line_ptr); + mrb_free(mrb, d->files[i]->lines.ptr); mrb_free(mrb, d->files[i]); } mrb_free(mrb, d->files); diff --git a/src/dump.c b/src/dump.c index ca53abe3d..559d26030 100644 --- a/src/dump.c +++ b/src/dump.c @@ -6,6 +6,7 @@ #include <ctype.h> #include <string.h> +#include <limits.h> #include "mruby/dump.h" #include "mruby/string.h" #include "mruby/irep.h" @@ -14,10 +15,14 @@ static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep); -static uint32_t +#if UINT32_MAX > SIZE_MAX +# error This code cannot be built on your environment. +#endif + +static size_t get_irep_header_size(mrb_state *mrb) { - uint32_t size = 0; + size_t size = 0; size += sizeof(uint32_t) * 1; size += sizeof(uint16_t) * 3; @@ -25,7 +30,7 @@ get_irep_header_size(mrb_state *mrb) return size; } -static size_t +static ptrdiff_t write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { uint8_t *cur = buf; @@ -35,31 +40,33 @@ write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */ cur += uint16_to_bin((uint16_t)irep->rlen, cur); /* number of child irep */ - return (cur - buf); + return cur - buf; } -static uint32_t +static size_t get_iseq_block_size(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; + size_t size = 0; + size += sizeof(uint32_t); /* ilen */ size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */ + return size; } -static int +static ptrdiff_t write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { uint8_t *cur = buf; - size_t iseq_no; + uint32_t iseq_no; 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 (cur - buf); + return cur - buf; } @@ -68,7 +75,6 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) { size_t size = 0; size_t pool_no; - int len; mrb_value str; char buf[32]; @@ -81,16 +87,31 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) switch (mrb_type(irep->pool[pool_no])) { case MRB_TT_FIXNUM: str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); - size += RSTRING_LEN(str); + { + mrb_int len = RSTRING_LEN(str); + mrb_assert(len >= 0); + mrb_assert((size_t)len <= SIZE_MAX); + size += (size_t)len; + } break; case MRB_TT_FLOAT: - len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no])); - size += len; + { + int len; + len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no])); + mrb_assert(len >= 0); + mrb_assert((size_t)len <= SIZE_MAX); + size += (size_t)len; + } break; case MRB_TT_STRING: - size += RSTRING_LEN(irep->pool[pool_no]); + { + mrb_int len = RSTRING_LEN(irep->pool[pool_no]); + mrb_assert(len >= 0); + mrb_assert((size_t)len <= SIZE_MAX); + size += (size_t)len; + } break; default: @@ -102,12 +123,12 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) return size; } -static int +static ptrdiff_t write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { size_t pool_no; uint8_t *cur = buf; - size_t len; + uint16_t len; mrb_value str; const char *char_ptr; char char_buf[30]; @@ -122,19 +143,37 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) cur += uint8_to_bin(IREP_TT_FIXNUM, cur); /* data type */ str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); char_ptr = RSTRING_PTR(str); - len = RSTRING_LEN(str); + { + mrb_int tlen; + tlen = RSTRING_LEN(str); + mrb_assert(tlen >= 0); + mrb_assert(tlen <= INT16_MAX); + len = (uint16_t)tlen; + } break; case MRB_TT_FLOAT: cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */ - len = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no])); + { + int tlen; + tlen = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no])); + mrb_assert(tlen >= 0); + mrb_assert(tlen <= INT16_MAX); + len = (uint16_t)tlen; + } char_ptr = &char_buf[0]; break; case MRB_TT_STRING: cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */ char_ptr = RSTRING_PTR(irep->pool[pool_no]); - len = RSTRING_LEN(irep->pool[pool_no]); + { + mrb_int tlen; + tlen = RSTRING_LEN(irep->pool[pool_no]); + mrb_assert(tlen >= 0); + mrb_assert(tlen <= INT16_MAX); + len = (uint16_t)tlen; + } break; default: @@ -142,13 +181,13 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) } cur += uint16_to_bin(len, cur); /* data length */ - memcpy(cur, char_ptr, len); + memcpy(cur, char_ptr, (size_t)len); cur += len; mrb_gc_arena_restore(mrb, ai); } - return (int)(cur - buf); + return cur - buf; } @@ -156,8 +195,8 @@ static size_t get_syms_block_size(mrb_state *mrb, mrb_irep *irep) { size_t size = 0; - size_t sym_no; - size_t len; + uint32_t sym_no; + mrb_int len; size += sizeof(uint32_t); /* slen */ for (sym_no = 0; sym_no < irep->slen; sym_no++) { @@ -171,10 +210,10 @@ get_syms_block_size(mrb_state *mrb, mrb_irep *irep) return size; } -static int +static ptrdiff_t write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { - size_t sym_no; + uint32_t sym_no; uint8_t *cur = buf; const char *name; @@ -182,13 +221,11 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) for (sym_no = 0; sym_no < irep->slen; sym_no++) { if (irep->syms[sym_no] != 0) { - size_t len; + mrb_int len; name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); - if (len > UINT16_MAX) { - return MRB_DUMP_GENERAL_FAILURE; - } + mrb_assert(len <= UINT16_MAX); cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */ memcpy(cur, name, len); /* symbol name */ cur += (uint16_t)len; @@ -199,13 +236,13 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) } } - return (int)(cur - buf); + return cur - buf; } static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; + size_t size = 0; size += get_irep_header_size(mrb); size += get_iseq_block_size(mrb, irep); @@ -217,7 +254,7 @@ get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep) static size_t get_irep_record_size(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; + size_t size = 0; size_t irep_no; size = get_irep_record_size_1(mrb, irep); @@ -228,9 +265,9 @@ get_irep_record_size(mrb_state *mrb, mrb_irep *irep) } static int -write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, uint32_t *irep_record_size) +write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, size_t *irep_record_size) { - size_t i; + uint32_t i; if (irep == NULL) { return MRB_DUMP_INVALID_IREP; @@ -250,19 +287,19 @@ write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, uint32_t *irep_r for (i = 0; i < irep->rlen; i++) { int result; - uint32_t rlen; + size_t rsize; - result = write_irep_record(mrb, irep->reps[i], bin, &rlen); + result = write_irep_record(mrb, irep->reps[i], bin, &rsize); if (result != MRB_DUMP_OK) { return result; } - *irep_record_size += rlen; - bin += rlen; + *irep_record_size += rsize; + bin += rsize; } return MRB_DUMP_OK; } -static size_t +static uint32_t write_footer(mrb_state *mrb, uint8_t *bin) { struct rite_binary_footer footer; @@ -276,12 +313,13 @@ write_footer(mrb_state *mrb, uint8_t *bin) static int -write_section_irep_header(mrb_state *mrb, uint32_t section_size, uint8_t *bin) +write_section_irep_header(mrb_state *mrb, size_t section_size, uint8_t *bin) { struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin; memcpy(header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(header->section_identify)); - uint32_to_bin(section_size, header->section_size); + mrb_assert(section_size <= UINT32_MAX); + uint32_to_bin((uint32_t)section_size, header->section_size); memcpy(header->rite_version, RITE_VM_VER, sizeof(header->rite_version)); return MRB_DUMP_OK; @@ -291,7 +329,8 @@ static int write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) { int result; - uint32_t section_size = 0, rlen = 0; /* size of irep record */ + size_t section_size = 0; /* size of irep record */ + size_t rsize = 0; uint8_t *cur = bin; if (mrb == NULL || bin == NULL) { @@ -301,25 +340,24 @@ write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) cur += sizeof(struct rite_section_irep_header); section_size += sizeof(struct rite_section_irep_header); - result = write_irep_record(mrb, irep, cur, &rlen); + result = write_irep_record(mrb, irep, cur, &rsize); if (result != MRB_DUMP_OK) { return result; } - cur += rlen; - section_size += rlen; + cur += rsize; + section_size += rsize; write_section_irep_header(mrb, section_size, bin); return MRB_DUMP_OK; } static int -write_section_lineno_header(mrb_state *mrb, uint32_t section_size, uint8_t *bin) +write_section_lineno_header(mrb_state *mrb, size_t section_size, uint8_t *bin) { struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin; - /* TODO */ memcpy(header->section_identify, RITE_SECTION_LINENO_IDENTIFIER, sizeof(header->section_identify)); - uint32_to_bin(section_size, header->section_size); + uint32_to_bin((uint32_t)section_size, header->section_size); return MRB_DUMP_OK; } @@ -338,21 +376,27 @@ get_lineno_record_size(mrb_state *mrb, mrb_irep *irep) if (irep->lines) { size += sizeof(uint16_t) * irep->ilen; /* lineno */ } + return size; } -static int +static size_t write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) { uint8_t *cur = bin; - size_t filename_len = 0, iseq_no; + size_t iseq_no; + size_t filename_len; + ptrdiff_t diff; cur += sizeof(uint32_t); /* record size */ if (irep->filename) { filename_len = strlen(irep->filename); + } else { + filename_len = 0; } - cur += uint16_to_bin(filename_len, cur); /* filename size */ + mrb_assert(filename_len <= UINT16_MAX); + cur += uint16_to_bin((uint16_t)filename_len, cur); /* filename size */ if (filename_len) { memcpy(cur, irep->filename, filename_len); @@ -360,7 +404,8 @@ write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) } if (irep->lines) { - cur += uint32_to_bin(irep->ilen, cur); /* niseq */ + mrb_assert(irep->ilen <= UINT32_MAX); + cur += uint32_to_bin((uint32_t)(irep->ilen), cur); /* niseq */ for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) { cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */ } @@ -369,16 +414,21 @@ write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) cur += uint32_to_bin(0, cur); /* niseq */ } - uint32_to_bin(cur - bin, bin); /* record size */ + diff = cur - bin; + mrb_assert(diff >= 0); + mrb_assert(diff <= UINT32_MAX); - return (cur - bin); + uint32_to_bin((uint32_t)diff, bin); /* record size */ + + mrb_assert((size_t)diff <= SIZE_MAX); + return (size_t)diff; } -static int +static size_t write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) { size_t i; - uint32_t rlen, size = 0; + size_t rlen, size = 0; rlen = write_lineno_record_1(mrb, irep, bin); bin += rlen; @@ -394,7 +444,8 @@ write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) static int write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) { - uint32_t section_size = 0, rlen = 0; /* size of irep record */ + size_t section_size = 0; + size_t rlen = 0; /* size of irep record */ uint8_t *cur = bin; if (mrb == NULL || bin == NULL) { @@ -416,7 +467,7 @@ static size_t get_debug_record_size(mrb_state *mrb, mrb_irep *irep) { size_t ret = 0; - uint32_t f_idx; + uint16_t f_idx; size_t i; ret += sizeof(uint32_t); /* record size */ @@ -433,11 +484,11 @@ get_debug_record_size(mrb_state *mrb, mrb_irep *irep) ret += sizeof(uint8_t); /* line type */ switch(file->line_type) { case mrb_debug_line_ary: - ret += sizeof(uint16_t) * file->line_entry_count; + ret += sizeof(uint16_t) * (size_t)(file->line_entry_count); break; case mrb_debug_line_flat_map: - ret += (sizeof(uint32_t) + sizeof(uint16_t)) * file->line_entry_count; + ret += (sizeof(uint32_t) + sizeof(uint16_t)) * (size_t)(file->line_entry_count); break; default: mrb_assert(0); break; @@ -451,9 +502,9 @@ get_debug_record_size(mrb_state *mrb, mrb_irep *irep) } static int -find_filename_index(const mrb_sym *ary, size_t ary_len, mrb_sym s) +find_filename_index(const mrb_sym *ary, uint16_t ary_len, mrb_sym s) { - size_t i; + int i; for (i = 0; i < ary_len; ++i) { if (ary[i] == s) { return i; } @@ -462,11 +513,11 @@ find_filename_index(const mrb_sym *ary, size_t ary_len, mrb_sym s) } static size_t -get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, size_t *lp) +get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint16_t *lp) { mrb_sym *filenames = *fp; - size_t tsize = 0; - size_t file_i; + uint16_t tsize = 0; + uint32_t file_i; size_t size = 0; mrb_irep_debug_info *di = irep->debug_info; @@ -475,7 +526,7 @@ get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, size_t *lp } for (file_i = 0; file_i < di->flen; ++file_i) { mrb_irep_debug_info_file *file; - size_t filename_len; + mrb_int filename_len; size_t i; file = di->files[file_i]; @@ -487,7 +538,7 @@ get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, size_t *lp /* filename */ mrb_sym2name_len(mrb, file->filename_sym, &filename_len); - size += sizeof(uint16_t) + filename_len; + size += sizeof(uint16_t) + (size_t)filename_len; } for (i=0; i<irep->rlen; i++) { size += get_filename_table_size(mrb, irep->reps[i], fp, lp); @@ -497,12 +548,12 @@ get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, size_t *lp return size; } -static int -write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, size_t filenames_len) +static size_t +write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) { uint8_t *cur; - uint32_t f_idx; - size_t ret; + uint16_t f_idx; + ptrdiff_t ret; cur = bin + sizeof(uint32_t); /* skip record size */ cur += uint16_to_bin(irep->debug_info->flen, cur); /* file count */ @@ -517,25 +568,26 @@ write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const /* filename index */ filename_idx = find_filename_index(filenames, filenames_len, file->filename_sym); - mrb_assert(filename_idx != -1); - cur += uint16_to_bin(filename_idx, cur); + mrb_assert(filename_idx >= 0); + mrb_assert(filename_idx <= UINT16_MAX); + cur += uint16_to_bin((uint16_t)filename_idx, cur); /* lines */ cur += uint32_to_bin(file->line_entry_count, cur); cur += uint8_to_bin(file->line_type, cur); switch(file->line_type) { case mrb_debug_line_ary: { - size_t l; + uint32_t l; for (l = 0; l < file->line_entry_count; ++l) { - cur += uint16_to_bin(file->line_ary[l], cur); + cur += uint16_to_bin(file->lines.ary[l], cur); } } break; case mrb_debug_line_flat_map: { uint32_t line; for (line = 0; line < file->line_entry_count; ++line) { - cur += uint32_to_bin(file->line_flat_map[line].start_pos, cur); - cur += uint16_to_bin(file->line_flat_map[line].line, cur); + cur += uint32_to_bin(file->lines.flat_map[line].start_pos, cur); + cur += uint16_to_bin(file->lines.flat_map[line].line, cur); } } break; @@ -544,15 +596,18 @@ write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const } ret = cur - bin; + mrb_assert(ret >= 0); + mrb_assert(ret <= UINT32_MAX); uint32_to_bin(ret, bin); - return ret; + mrb_assert((size_t)ret <= SIZE_MAX); + return (size_t)ret; } -static int -write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, size_t filenames_len) +static size_t +write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) { - uint32_t size, len; + size_t size, len; size_t irep_no; size = len = write_debug_record_1(mrb, irep, bin, filenames, filenames_len); @@ -563,16 +618,16 @@ write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* size += len; } - mrb_assert(size == (int)get_debug_record_size(mrb, irep)); + mrb_assert(size == get_debug_record_size(mrb, irep)); return size; } -static int -write_filename_table(mrb_state *mrb, mrb_irep *irep, uint8_t **cp, mrb_sym **fp, size_t *lp) +static size_t +write_filename_table(mrb_state *mrb, mrb_irep *irep, uint8_t **cp, mrb_sym **fp, uint16_t *lp) { uint8_t *cur = *cp; mrb_sym *filenames = *fp; - size_t file_i; + uint32_t file_i; uint16_t fn_len; size_t size = 0; mrb_irep_debug_info *debug_info = irep->debug_info; @@ -604,13 +659,13 @@ write_filename_table(mrb_state *mrb, mrb_irep *irep, uint8_t **cp, mrb_sym **fp, static int write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur) { - uint32_t section_size = 0; + size_t section_size = 0; const uint8_t *bin = cur; struct rite_section_debug_header *header; mrb_sym *filenames; - size_t filenames_len = 0; + uint16_t filenames_len = 0; uint8_t *filenames_len_out; - uint32_t dlen; + size_t dlen; if (mrb == NULL || cur == NULL) { return MRB_DUMP_INVALID_ARGUMENT; @@ -633,6 +688,7 @@ write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur) section_size += dlen; memcpy(header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(header->section_identify)); + mrb_assert(section_size <= INT32_MAX); uint32_to_bin(section_size, header->section_size); mrb_free(mrb, filenames); @@ -645,13 +701,14 @@ 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; + uint32_t offset; memcpy(header->binary_identify, RITE_BINARY_IDENTIFIER, 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); + mrb_assert(binary_size <= UINT32_MAX); + uint32_to_bin((uint32_t)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); @@ -86,8 +86,8 @@ mrb_obj_to_sym(mrb_state *mrb, mrb_value name) return id; } -static mrb_int -float_id(mrb_float f) +mrb_int +mrb_float_id(mrb_float f) { const char *p = (const char*)&f; int len = sizeof(f); @@ -123,9 +123,9 @@ mrb_obj_id(mrb_value obj) case MRB_TT_SYMBOL: return MakeID(mrb_symbol(obj)); case MRB_TT_FIXNUM: - return MakeID2(float_id((mrb_float)mrb_fixnum(obj)), MRB_TT_FLOAT); + return MakeID2(mrb_float_id((mrb_float)mrb_fixnum(obj)), MRB_TT_FLOAT); case MRB_TT_FLOAT: - return MakeID(float_id(mrb_float(obj))); + return MakeID(mrb_float_id(mrb_float(obj))); case MRB_TT_STRING: case MRB_TT_OBJECT: case MRB_TT_CLASS: @@ -1589,5 +1589,5 @@ gc_test(mrb_state *mrb, mrb_value self) test_incremental_sweep_phase(); return mrb_nil_value(); } -#endif -#endif +#endif /* GC_DEBUG */ +#endif /* GC_TEST */ diff --git a/src/hash.c b/src/hash.c index 9d7927bb9..ed71d6ee2 100644 --- a/src/hash.c +++ b/src/hash.c @@ -12,14 +12,43 @@ #include "mruby/string.h" #include "mruby/variable.h" +/* a function to get hash value of a float number */ +mrb_int mrb_float_id(mrb_float f); + static inline khint_t mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key) { - khint_t h = (khint_t)mrb_type(key) << 24; - mrb_value h2; + enum mrb_vtype t = mrb_type(key); + mrb_value hv; + const char *p; + mrb_int i, len; + khint_t h; + + switch (t) { + case MRB_TT_STRING: + p = RSTRING_PTR(key); + len = RSTRING_LEN(key); + break; + + case MRB_TT_SYMBOL: + p = mrb_sym2name_len(mrb, mrb_symbol(key), &len); + break; + + case MRB_TT_FIXNUM: + return (khint_t)mrb_float_id((mrb_float)mrb_fixnum(key)); + + case MRB_TT_FLOAT: + return (khint_t)mrb_float_id(mrb_float(key)); + + default: + hv = mrb_funcall(mrb, key, "hash", 0); + return (khint_t)t ^ mrb_fixnum(hv); + } - h2 = mrb_funcall(mrb, key, "hash", 0, 0); - h ^= h2.value.i; + h = 0; + for (i=0; i<len; i++) { + h = (h << 5) - h + *p++; + } return h; } @@ -676,14 +705,14 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) str2 = mrb_inspect(mrb, kh_key(h,k)); mrb_str_append(mrb, str, str2); - mrb_str_buf_cat(mrb, str, "=>", 2); + mrb_str_cat_lit(mrb, str, "=>"); str2 = mrb_inspect(mrb, kh_value(h,k)); mrb_str_append(mrb, str, str2); mrb_gc_arena_restore(mrb, ai); } } - mrb_str_buf_cat(mrb, str, "}", 1); + mrb_str_cat_lit(mrb, str, "}"); return str; } @@ -874,16 +903,22 @@ static mrb_value hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, mrb_bool eql) { khash_t(ht) *h1, *h2; + mrb_bool eq; if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (!mrb_hash_p(hash2)) { if (!mrb_respond_to(mrb, hash2, mrb_intern_lit(mrb, "to_hash"))) { return mrb_false_value(); } - if (eql) - return mrb_fixnum_value(mrb_eql(mrb, hash2, hash1)); - else - return mrb_fixnum_value(mrb_equal(mrb, hash2, hash1)); + else { + if (eql) { + eq = mrb_eql(mrb, hash2, hash1); + } + else { + eq = mrb_equal(mrb, hash2, hash1); + } + return mrb_bool_value(eq); + } } h1 = RHASH_TBL(hash1); h2 = RHASH_TBL(hash2); @@ -901,7 +936,11 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, mrb_bool eql) key = kh_key(h1,k1); k2 = kh_get(ht, mrb, h2, key); if (k2 != kh_end(h2)) { - if (mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2))) { + if (eql) + eq = mrb_eql(mrb, kh_value(h1,k1), kh_value(h2,k2)); + else + eq = mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2)); + if (eq) { continue; /* next key */ } } diff --git a/src/kernel.c b/src/kernel.c index 45cc299d2..b805c3c47 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -13,26 +13,26 @@ #include "mruby/error.h" typedef enum { - NOEX_PUBLIC = 0x00, - NOEX_NOSUPER = 0x01, - NOEX_PRIVATE = 0x02, - NOEX_PROTECTED = 0x04, - NOEX_MASK = 0x06, - NOEX_BASIC = 0x08, - NOEX_UNDEF = NOEX_NOSUPER, - NOEX_MODFUNC = 0x12, - NOEX_SUPER = 0x20, - NOEX_VCALL = 0x40, - NOEX_RESPONDS = 0x80 + NOEX_PUBLIC = 0x00, + NOEX_NOSUPER = 0x01, + NOEX_PRIVATE = 0x02, + NOEX_PROTECTED = 0x04, + NOEX_MASK = 0x06, + NOEX_BASIC = 0x08, + NOEX_UNDEF = NOEX_NOSUPER, + NOEX_MODFUNC = 0x12, + NOEX_SUPER = 0x20, + NOEX_VCALL = 0x40, + NOEX_RESPONDS = 0x80 } mrb_method_flag_t; mrb_bool 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_lit(mrb, "to_s")); - if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) - return TRUE; - return FALSE; + struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern_lit(mrb, "to_s")); + if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) + return TRUE; + return FALSE; } /* 15.3.1.3.17 */ @@ -530,7 +530,7 @@ obj_is_instance_of(mrb_state *mrb, mrb_value self) } static void -valid_iv_name(mrb_state *mrb, mrb_sym iv_name_id, const char* s, size_t len) +valid_iv_name(mrb_state *mrb, mrb_sym iv_name_id, const char* s, mrb_int len) { if (len < 2 || !(s[0] == '@' && s[1] != '@')) { mrb_name_error(mrb, iv_name_id, "`%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name_id)); @@ -541,7 +541,7 @@ static void check_iv_name(mrb_state *mrb, mrb_sym iv_name_id) { const char *s; - size_t len; + mrb_int len; s = mrb_sym2name_len(mrb, iv_name_id, &len); valid_iv_name(mrb, iv_name_id, s, len); diff --git a/src/load.c b/src/load.c index 857dd7740..badd76a1c 100644 --- a/src/load.c +++ b/src/load.c @@ -12,6 +12,7 @@ #include "mruby/proc.h" #include "mruby/string.h" #include "mruby/debug.h" +#include "mruby/error.h" #if !defined(_WIN32) && SIZE_MAX < UINT32_MAX # define SIZE_ERROR_MUL(x, y) ((x) > SIZE_MAX / (y)) @@ -25,6 +26,10 @@ # error This code assumes CHAR_BIT == 8 #endif +#if UINT32_MAX > SIZE_MAX +# error This code cannot be built on your environment. +#endif + static size_t offset_crc_body(void) { @@ -33,10 +38,11 @@ offset_crc_body(void) } static mrb_irep* -read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool alloc) +read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, mrb_bool alloc) { size_t i; const uint8_t *src = bin; + ptrdiff_t diff; uint16_t tt, pool_data_len, snl; size_t plen; int ai = mrb_gc_arena_save(mrb); @@ -54,12 +60,12 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool a src += sizeof(uint16_t); /* number of child irep */ - irep->rlen = bin_to_uint16(src); + irep->rlen = (size_t)bin_to_uint16(src); src += sizeof(uint16_t); /* Binary Data Section */ /* ISEQ BLOCK */ - irep->ilen = bin_to_uint32(src); + irep->ilen = (size_t)bin_to_uint32(src); src += sizeof(uint32_t); if (irep->ilen > 0) { if (SIZE_ERROR_MUL(sizeof(mrb_code), irep->ilen)) { @@ -70,13 +76,13 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool a return NULL; } for (i = 0; i < irep->ilen; i++) { - irep->iseq[i] = bin_to_uint32(src); /* iseq */ + irep->iseq[i] = (size_t)bin_to_uint32(src); /* iseq */ src += sizeof(uint32_t); } } /* POOL BLOCK */ - plen = bin_to_uint32(src); /* number of pool */ + plen = (size_t)bin_to_uint32(src); /* number of pool */ src += sizeof(uint32_t); if (plen > 0) { if (SIZE_ERROR_MUL(sizeof(mrb_value), plen)) { @@ -124,7 +130,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool a } /* SYMS BLOCK */ - irep->slen = bin_to_uint32(src); /* syms length */ + irep->slen = (size_t)bin_to_uint32(src); /* syms length */ src += sizeof(uint32_t); if (irep->slen > 0) { if (SIZE_ERROR_MUL(sizeof(mrb_sym), irep->slen)) { @@ -157,20 +163,24 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool a } irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*irep->rlen); - *len = src - bin; + + diff = src - bin; + mrb_assert(diff >= 0); + mrb_assert((size_t)diff <= SIZE_MAX); + *len = (size_t)diff; return irep; } static mrb_irep* -read_irep_record(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool alloc) +read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, mrb_bool alloc) { mrb_irep *irep = read_irep_record_1(mrb, bin, len, alloc); size_t i; bin += *len; for (i=0; i<irep->rlen; i++) { - uint32_t rlen; + size_t rlen; irep->reps[i] = read_irep_record(mrb, bin, &rlen, alloc); bin += rlen; @@ -182,14 +192,14 @@ read_irep_record(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool all static mrb_irep* read_section_irep(mrb_state *mrb, const uint8_t *bin, mrb_bool alloc) { - uint32_t len; + size_t len; bin += sizeof(struct rite_section_irep_header); return read_irep_record(mrb, bin, &len, alloc); } static int -read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, uint32_t *len) +read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *len) { int ret; size_t i, fname_len, niseq; @@ -215,7 +225,7 @@ read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, uint32_ bin += fname_len; *len += fname_len; - niseq = bin_to_uint32(bin); + niseq = (size_t)bin_to_uint32(bin); bin += sizeof(uint32_t); /* niseq */ *len += sizeof(uint32_t); @@ -238,14 +248,14 @@ read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, uint32_ } static int -read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, uint32_t *lenp) +read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *lenp) { int result = read_lineno_record_1(mrb, bin, irep, lenp); size_t i; if (result != MRB_DUMP_OK) return result; for (i = 0; i < irep->rlen; i++) { - uint32_t len; + size_t len; result = read_lineno_record(mrb, bin, irep->reps[i], &len); if (result != MRB_DUMP_OK) break; @@ -258,7 +268,7 @@ read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, uint32_t static int read_section_lineno(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep) { - uint32_t len; + size_t len; len = 0; bin += sizeof(struct rite_section_lineno_header); @@ -268,9 +278,10 @@ read_section_lineno(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep) } static int -read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t *len, const mrb_sym *filenames, size_t filenames_len) +read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *record_len, const mrb_sym *filenames, size_t filenames_len) { const uint8_t *bin = start; + ptrdiff_t diff; size_t record_size, i; uint16_t f_idx; @@ -279,7 +290,7 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info)); irep->debug_info->pc_count = irep->ilen; - record_size = bin_to_uint32(bin); + record_size = (size_t)bin_to_uint32(bin); bin += sizeof(uint32_t); irep->debug_info->flen = bin_to_uint16(bin); @@ -289,12 +300,13 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { mrb_irep_debug_info_file *file; uint16_t filename_idx; - size_t len; + mrb_int len; file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file)); irep->debug_info->files[f_idx] = file; - file->start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); + file->start_pos = bin_to_uint32(bin); + bin += sizeof(uint32_t); /* filename */ filename_idx = bin_to_uint16(bin); @@ -304,26 +316,31 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t len = 0; file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len); - file->line_entry_count = bin_to_uint32(bin); bin += sizeof(uint32_t); - file->line_type = (mrb_debug_line_type)bin_to_uint8(bin); bin += sizeof(uint8_t); + file->line_entry_count = bin_to_uint32(bin); + bin += sizeof(uint32_t); + file->line_type = (mrb_debug_line_type)bin_to_uint8(bin); + bin += sizeof(uint8_t); switch(file->line_type) { case mrb_debug_line_ary: { - size_t l; + uint32_t l; - file->line_ary = (uint16_t *)mrb_malloc(mrb, sizeof(uint16_t) * file->line_entry_count); + file->lines.ary = (uint16_t *)mrb_malloc(mrb, sizeof(uint16_t) * (size_t)(file->line_entry_count)); for(l = 0; l < file->line_entry_count; ++l) { - file->line_ary[l] = bin_to_uint16(bin); bin += sizeof(uint16_t); + file->lines.ary[l] = bin_to_uint16(bin); + bin += sizeof(uint16_t); } } break; case mrb_debug_line_flat_map: { - size_t l; + uint32_t l; - file->line_flat_map = (mrb_irep_debug_info_line*)mrb_malloc( - mrb, sizeof(mrb_irep_debug_info_line) * file->line_entry_count); + file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc( + mrb, sizeof(mrb_irep_debug_info_line) * (size_t)(file->line_entry_count)); for(l = 0; l < file->line_entry_count; ++l) { - file->line_flat_map[l].start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); - file->line_flat_map[l].line = bin_to_uint16(bin); bin += sizeof(uint16_t); + file->lines.flat_map[l].start_pos = bin_to_uint32(bin); + bin += sizeof(uint32_t); + file->lines.flat_map[l].line = bin_to_uint16(bin); + bin += sizeof(uint16_t); } } break; @@ -331,12 +348,16 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t } } - if((long)record_size != (bin - start)) { + diff = bin - start; + mrb_assert(diff >= 0); + mrb_assert((size_t)diff <= SIZE_MAX); + + if(record_size != (size_t)diff) { return MRB_DUMP_GENERAL_FAILURE; } for (i = 0; i < irep->rlen; i++) { - uint32_t len; + size_t len; int ret; ret =read_debug_record(mrb, bin, irep->reps[i], &len, filenames, filenames_len); @@ -344,7 +365,10 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t bin += len; } - *len = bin - start; + diff = bin - start; + mrb_assert(diff >= 0); + mrb_assert((size_t)diff <= SIZE_MAX); + *record_len = (size_t)diff; return MRB_DUMP_OK; } @@ -353,11 +377,12 @@ static int read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, mrb_bool alloc) { const uint8_t *bin; + ptrdiff_t diff; struct rite_section_debug_header *header; uint16_t i; - uint32_t len = 0; + size_t len = 0; int result; - size_t filenames_len; + uint16_t filenames_len; mrb_sym *filenames; bin = start; @@ -366,15 +391,15 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, mrb_boo filenames_len = bin_to_uint16(bin); bin += sizeof(uint16_t); - filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * filenames_len); + filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)filenames_len); for(i = 0; i < filenames_len; ++i) { uint16_t f_len = bin_to_uint16(bin); bin += sizeof(uint16_t); if (alloc) { - filenames[i] = mrb_intern(mrb, (const char *)bin, f_len); + filenames[i] = mrb_intern(mrb, (const char *)bin, (size_t)f_len); } else { - filenames[i] = mrb_intern_static(mrb, (const char *)bin, f_len); + filenames[i] = mrb_intern_static(mrb, (const char *)bin, (size_t)f_len); } bin += f_len; } @@ -383,7 +408,10 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, mrb_boo if (result != MRB_DUMP_OK) goto debug_exit; bin += len; - if ((bin - start) != bin_to_uint32(header->section_size)) { + diff = bin - start; + mrb_assert(diff >= 0); + mrb_assert(diff <= UINT32_MAX); + if ((uint32_t)diff != bin_to_uint32(header->section_size)) { result = MRB_DUMP_GENERAL_FAILURE; } @@ -407,7 +435,7 @@ read_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc) *crc = bin_to_uint16(header->binary_crc); if (bin_size) { - *bin_size = bin_to_uint32(header->binary_size); + *bin_size = (size_t)bin_to_uint32(header->binary_size); } return MRB_DUMP_OK; @@ -467,8 +495,7 @@ mrb_read_irep(mrb_state *mrb, const uint8_t *bin) static void irep_error(mrb_state *mrb) { - static const char msg[] = "irep load error"; - mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); + mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "irep load error")); } mrb_value @@ -504,14 +531,14 @@ read_lineno_record_file(mrb_state *mrb, FILE *fp, mrb_irep *irep) const size_t record_header_size = sizeof(header); int result; size_t i, buf_size; - uint32_t len; + size_t len; void *ptr; uint8_t *buf; if (fread(header, record_header_size, 1, fp) == 0) { return MRB_DUMP_READ_FAULT; } - buf_size = bin_to_uint32(&header[0]); + buf_size = (size_t)bin_to_uint32(&header[0]); if (SIZE_ERROR(buf_size)) { return MRB_DUMP_GENERAL_FAILURE; } @@ -553,7 +580,7 @@ read_irep_record_file(mrb_state *mrb, FILE *fp) uint8_t header[1 + 4]; const size_t record_header_size = sizeof(header); size_t buf_size, i; - uint32_t len; + size_t len; mrb_irep *irep = NULL; void *ptr; uint8_t *buf; @@ -561,7 +588,7 @@ read_irep_record_file(mrb_state *mrb, FILE *fp) if (fread(header, record_header_size, 1, fp) == 0) { return NULL; } - buf_size = bin_to_uint32(&header[0]); + buf_size = (size_t)bin_to_uint32(&header[0]); if (SIZE_ERROR(buf_size)) { return NULL; } @@ -600,7 +627,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) int result; uint8_t *buf; uint16_t crc, crcwk = 0; - uint32_t section_size = 0; + size_t section_size = 0; size_t nbytes; struct rite_section_header section_header; long fpos; @@ -657,7 +684,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) if (fread(§ion_header, sizeof(struct rite_section_header), 1, fp) == 0) { return NULL; } - section_size = bin_to_uint32(section_header.section_size); + section_size = (size_t)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); diff --git a/src/mrb_throw.h b/src/mrb_throw.h index 859729be6..3c7407a8d 100644 --- a/src/mrb_throw.h +++ b/src/mrb_throw.h @@ -38,4 +38,4 @@ struct mrb_jmpbuf { #endif }; -#endif +#endif /* MRB_THROW_H */ diff --git a/src/node.h b/src/node.h index df27c431f..532a8323a 100644 --- a/src/node.h +++ b/src/node.h @@ -8,110 +8,110 @@ #define NODE_H enum node_type { - NODE_METHOD, - NODE_FBODY, - NODE_CFUNC, - NODE_SCOPE, - NODE_BLOCK, - NODE_IF, - NODE_CASE, - NODE_WHEN, - NODE_OPT_N, - NODE_WHILE, - NODE_UNTIL, - NODE_ITER, - NODE_FOR, - NODE_BREAK, - NODE_NEXT, - NODE_REDO, - NODE_RETRY, - NODE_BEGIN, - NODE_RESCUE, - NODE_ENSURE, - NODE_AND, - NODE_OR, - NODE_NOT, - NODE_MASGN, - NODE_ASGN, - NODE_CDECL, - NODE_CVASGN, - NODE_CVDECL, - NODE_OP_ASGN, - NODE_CALL, - NODE_FCALL, - NODE_VCALL, - NODE_SUPER, - NODE_ZSUPER, - NODE_ARRAY, - NODE_ZARRAY, - NODE_HASH, - NODE_RETURN, - NODE_YIELD, - NODE_LVAR, - NODE_DVAR, - NODE_GVAR, - NODE_IVAR, - NODE_CONST, - NODE_CVAR, - NODE_NTH_REF, - NODE_BACK_REF, - NODE_MATCH, - NODE_MATCH2, - NODE_MATCH3, - NODE_INT, - NODE_FLOAT, - NODE_NEGATE, - NODE_LAMBDA, - NODE_SYM, - NODE_STR, - NODE_DSTR, - NODE_XSTR, - NODE_DXSTR, - NODE_REGX, - NODE_DREGX, - NODE_DREGX_ONCE, - NODE_LIST, - NODE_ARG, - NODE_ARGSCAT, - NODE_ARGSPUSH, - NODE_SPLAT, - NODE_TO_ARY, - NODE_SVALUE, - NODE_BLOCK_ARG, - NODE_DEF, - NODE_SDEF, - NODE_ALIAS, - NODE_UNDEF, - NODE_CLASS, - NODE_MODULE, - NODE_SCLASS, - NODE_COLON2, - NODE_COLON3, - NODE_CREF, - NODE_DOT2, - NODE_DOT3, - NODE_FLIP2, - NODE_FLIP3, - NODE_ATTRSET, - NODE_SELF, - NODE_NIL, - NODE_TRUE, - NODE_FALSE, - NODE_DEFINED, - NODE_NEWLINE, - NODE_POSTEXE, - NODE_ALLOCA, - NODE_DMETHOD, - NODE_BMETHOD, - NODE_MEMO, - NODE_IFUNC, - NODE_DSYM, - NODE_ATTRASGN, - NODE_HEREDOC, - NODE_LITERAL_DELIM, - NODE_WORDS, - NODE_SYMBOLS, - NODE_LAST + NODE_METHOD, + NODE_FBODY, + NODE_CFUNC, + NODE_SCOPE, + NODE_BLOCK, + NODE_IF, + NODE_CASE, + NODE_WHEN, + NODE_OPT_N, + NODE_WHILE, + NODE_UNTIL, + NODE_ITER, + NODE_FOR, + NODE_BREAK, + NODE_NEXT, + NODE_REDO, + NODE_RETRY, + NODE_BEGIN, + NODE_RESCUE, + NODE_ENSURE, + NODE_AND, + NODE_OR, + NODE_NOT, + NODE_MASGN, + NODE_ASGN, + NODE_CDECL, + NODE_CVASGN, + NODE_CVDECL, + NODE_OP_ASGN, + NODE_CALL, + NODE_FCALL, + NODE_VCALL, + NODE_SUPER, + NODE_ZSUPER, + NODE_ARRAY, + NODE_ZARRAY, + NODE_HASH, + NODE_RETURN, + NODE_YIELD, + NODE_LVAR, + NODE_DVAR, + NODE_GVAR, + NODE_IVAR, + NODE_CONST, + NODE_CVAR, + NODE_NTH_REF, + NODE_BACK_REF, + NODE_MATCH, + NODE_MATCH2, + NODE_MATCH3, + NODE_INT, + NODE_FLOAT, + NODE_NEGATE, + NODE_LAMBDA, + NODE_SYM, + NODE_STR, + NODE_DSTR, + NODE_XSTR, + NODE_DXSTR, + NODE_REGX, + NODE_DREGX, + NODE_DREGX_ONCE, + NODE_LIST, + NODE_ARG, + NODE_ARGSCAT, + NODE_ARGSPUSH, + NODE_SPLAT, + NODE_TO_ARY, + NODE_SVALUE, + NODE_BLOCK_ARG, + NODE_DEF, + NODE_SDEF, + NODE_ALIAS, + NODE_UNDEF, + NODE_CLASS, + NODE_MODULE, + NODE_SCLASS, + NODE_COLON2, + NODE_COLON3, + NODE_CREF, + NODE_DOT2, + NODE_DOT3, + NODE_FLIP2, + NODE_FLIP3, + NODE_ATTRSET, + NODE_SELF, + NODE_NIL, + NODE_TRUE, + NODE_FALSE, + NODE_DEFINED, + NODE_NEWLINE, + NODE_POSTEXE, + NODE_ALLOCA, + NODE_DMETHOD, + NODE_BMETHOD, + NODE_MEMO, + 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 5f23b2461..b0b80c523 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -304,8 +304,8 @@ flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float * mrb_float mod; if (y == 0.0) { - div = str_to_mrb_float("inf"); - mod = str_to_mrb_float("nan"); + div = INFINITY; + mod = NAN; } else { mod = fmod(x, y); @@ -680,7 +680,7 @@ int_to_i(mrb_state *mrb, mrb_value num) return num; } -#define SQRT_INT_MAX ((mrb_int)1<<((sizeof(mrb_int)*CHAR_BIT-1)/2)) +#define SQRT_INT_MAX ((mrb_int)1<<((MRB_INT_BIT-1)/2)) /*tests if N*N would overflow*/ #define FIT_SQRT_INT(n) (((n)<SQRT_INT_MAX)&&((n)>=-SQRT_INT_MAX)) @@ -690,10 +690,10 @@ 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)) { mrb_int b, c; + if (a == 0) return x; b = mrb_fixnum(y); if (FIT_SQRT_INT(a) && FIT_SQRT_INT(b)) return mrb_fixnum_value(a*b); @@ -775,7 +775,7 @@ fix_mod(mrb_state *mrb, mrb_value x) mrb_int mod; if (mrb_fixnum(y) == 0) { - return mrb_float_value(mrb, str_to_mrb_float("nan")); + return mrb_float_value(mrb, NAN); } fixdivmod(mrb, a, mrb_fixnum(y), 0, &mod); return mrb_fixnum_value(mod); @@ -805,8 +805,8 @@ fix_divmod(mrb_state *mrb, mrb_value x) mrb_int div, mod; if (mrb_fixnum(y) == 0) { - return mrb_assoc_new(mrb, mrb_float_value(mrb, str_to_mrb_float("inf")), - mrb_float_value(mrb, str_to_mrb_float("nan"))); + return mrb_assoc_new(mrb, mrb_float_value(mrb, INFINITY), + mrb_float_value(mrb, NAN)); } fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod); return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod)); @@ -959,13 +959,13 @@ 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 (MRB_INT_BIT-1) static mrb_value lshift(mrb_state *mrb, mrb_int val, size_t width) { if (width > NUMERIC_SHIFT_WIDTH_MAX) { - mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:sizeof(mrb_int)*CHAR_BIT-1)", + mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:MRB_INT_BIT-1)", mrb_fixnum_value(width), mrb_fixnum_value(NUMERIC_SHIFT_WIDTH_MAX)); } @@ -1131,10 +1131,10 @@ 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)) { mrb_int b, c; + if (a == 0) return y; b = mrb_fixnum(y); c = a + b; if (((a < 0) ^ (b < 0)) == 0 && (a < 0) != (c < 0)) { @@ -1207,7 +1207,7 @@ fix_minus(mrb_state *mrb, mrb_value self) mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base) { - char buf[sizeof(mrb_int)*CHAR_BIT+1]; + char buf[MRB_INT_BIT+1]; char *b = buf + sizeof buf; mrb_int val = mrb_fixnum(x); @@ -1306,15 +1306,14 @@ num_cmp(mrb_state *mrb, mrb_value self) * and <code>other</code>. */ static mrb_value -flo_plus(mrb_state *mrb, mrb_value self) +flo_plus(mrb_state *mrb, mrb_value x) { - mrb_float x, y; - - x = mrb_float(self); - mrb_get_args(mrb, "f", &y); + mrb_value y; - return mrb_float_value(mrb, x + y); + mrb_get_args(mrb, "o", &y); + return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y)); } + /* ------------------------------------------------------------------------*/ void mrb_init_numeric(mrb_state *mrb) diff --git a/src/object.c b/src/object.c index 1f0d903f2..6d39254dd 100644 --- a/src/object.c +++ b/src/object.c @@ -338,7 +338,7 @@ mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char mrb_value v; if (mrb_type(val) == type) return val; - v = convert_type(mrb, val, tname, method, 1/*Qtrue*/); + v = convert_type(mrb, val, tname, method, TRUE); if (mrb_type(v) != type) { 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)); @@ -352,7 +352,7 @@ mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const mrb_value v; if (mrb_type(val) == type && type != MRB_TT_DATA) return val; - v = convert_type(mrb, val, tname, method, 0/*Qfalse*/); + v = convert_type(mrb, val, tname, method, FALSE); if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value(); return v; } @@ -390,7 +390,6 @@ void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) { const struct types *type = builtin_types; - struct RString *s; enum mrb_vtype xt; xt = mrb_type(x); @@ -409,8 +408,7 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) etype = "Symbol"; } else if (mrb_special_const_p(x)) { - s = mrb_str_ptr(mrb_obj_as_string(mrb, x)); - etype = s->ptr; + etype = RSTRING_PTR(mrb_obj_as_string(mrb, x)); } else { etype = mrb_obj_classname(mrb, x); @@ -442,11 +440,11 @@ 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); - mrb_str_buf_cat(mrb, str, "#<", 2); + 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_buf_cat(mrb, str, ">", 1); + mrb_str_cat_lit(mrb, str, ">"); return str; } @@ -590,7 +588,7 @@ mrb_Float(mrb_state *mrb, mrb_value val) mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj) { - return mrb_obj_as_string(mrb, mrb_funcall(mrb, obj, "inspect", 0, 0)); + return mrb_obj_as_string(mrb, mrb_funcall(mrb, obj, "inspect", 0)); } mrb_bool diff --git a/src/parse.y b/src/parse.y index 5e81e5536..52bb06e73 100644 --- a/src/parse.y +++ b/src/parse.y @@ -24,6 +24,7 @@ #include "mruby.h" #include "mruby/compile.h" #include "mruby/proc.h" +#include "mruby/error.h" #include "node.h" #include "mrb_throw.h" @@ -3525,8 +3526,8 @@ static int scan_hex(const int *start, int len, int *retlen) { static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF"; - register const int *s = start; - register int retval = 0; + const int *s = start; + int retval = 0; char *tmp; /* mrb_assert(len <= 2) */ @@ -3931,7 +3932,7 @@ arg_ambiguous(parser_state *p) static int parser_yylex(parser_state *p) { - register int c; + int c; int space_seen = 0; int cmd_state; enum mrb_lex_state_enum last_state; @@ -5307,12 +5308,11 @@ void mrb_parser_set_filename(struct mrb_parser_state *p, const char *f) { mrb_sym sym; - size_t len; size_t i; mrb_sym* new_table; sym = mrb_intern_cstr(p->mrb, f); - p->filename = mrb_sym2name_len(p->mrb, sym, &len); + p->filename = mrb_sym2name_len(p->mrb, sym, NULL); p->lineno = (p->filename_table_length > 0)? 0 : 1; for(i = 0; i < p->filename_table_length; ++i) { @@ -5335,8 +5335,7 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f) char const* mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) { if (idx >= p->filename_table_length) { return NULL; } else { - size_t len; - return mrb_sym2name_len(p->mrb, p->filename_table[idx], &len); + return mrb_sym2name_len(p->mrb, p->filename_table[idx], NULL); } } @@ -5398,8 +5397,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) return mrb_undef_value(); } else { - static const char msg[] = "syntax error"; - mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1)); + mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SYNTAX_ERROR, "syntax error")); mrb_parser_free(p); return mrb_undef_value(); } @@ -5407,8 +5405,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) proc = mrb_generate_code(mrb, p); mrb_parser_free(p); if (proc == NULL) { - static const char msg[] = "codegen error"; - mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); + mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "codegen error")); return mrb_undef_value(); } if (c) { diff --git a/src/pool.c b/src/pool.c index f09df92c5..4d8c42dd1 100644 --- a/src/pool.c +++ b/src/pool.c @@ -5,6 +5,7 @@ */ #include <stddef.h> +#include <stdint.h> #include <string.h> #include "mruby.h" @@ -36,12 +37,12 @@ struct mrb_pool { #undef TEST_POOL #ifdef TEST_POOL -#define mrb_malloc(m,s) malloc(s) +#define mrb_malloc_simple(m,s) malloc(s) #define mrb_free(m,p) free(p) #endif #ifdef POOL_ALIGNMENT -# define ALIGN_PADDING(x) ((-x) & (POOL_ALIGNMENT - 1)) +# define ALIGN_PADDING(x) ((SIZE_MAX - (x) + 1) & (POOL_ALIGNMENT - 1)) #else # define ALIGN_PADDING(x) (0) #endif @@ -49,7 +50,7 @@ struct mrb_pool { mrb_pool* mrb_pool_open(mrb_state *mrb) { - mrb_pool *pool = (mrb_pool *)mrb_malloc(mrb, sizeof(mrb_pool)); + mrb_pool *pool = (mrb_pool *)mrb_malloc_simple(mrb, sizeof(mrb_pool)); if (pool) { pool->mrb = mrb; @@ -81,7 +82,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); + page = (struct mrb_pool_page *)mrb_malloc_simple(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 9d59aa4ff..6472a4675 100644 --- a/src/print.c +++ b/src/print.c @@ -12,14 +12,12 @@ static void printstr(mrb_state *mrb, mrb_value obj) { #ifdef ENABLE_STDIO - struct RString *str; char *s; int len; if (mrb_string_p(obj)) { - str = mrb_str_ptr(obj); - s = str->ptr; - len = str->len; + s = RSTRING_PTR(obj); + len = RSTRING_LEN(obj); fwrite(s, len, 1, stdout); } #endif @@ -44,8 +42,7 @@ mrb_print_error(mrb_state *mrb) mrb_print_backtrace(mrb); s = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0); if (mrb_string_p(s)) { - struct RString *str = mrb_str_ptr(s); - fwrite(str->ptr, str->len, 1, stderr); + fwrite(RSTRING_PTR(s), RSTRING_LEN(s), 1, stderr); putc('\n', stderr); } #endif @@ -9,4 +9,4 @@ #define REGEXP_CLASS "Regexp" -#endif +#endif /* RE_H */ diff --git a/src/state.c b/src/state.c index 9b7ad1c5a..f05dbda34 100644 --- a/src/state.c +++ b/src/state.c @@ -135,8 +135,8 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) mrb_free(mrb, irep->iseq); for (i=0; i<irep->plen; i++) { if (mrb_type(irep->pool[i]) == MRB_TT_STRING) { - if ((mrb_str_ptr(irep->pool[i])->flags & MRB_STR_NOFREE) == 0) { - mrb_free(mrb, mrb_str_ptr(irep->pool[i])->ptr); + if ((mrb_str_ptr(irep->pool[i])->flags & (MRB_STR_NOFREE|MRB_STR_EMBED)) == 0) { + mrb_free(mrb, RSTRING_PTR(irep->pool[i])); } mrb_free(mrb, mrb_obj_ptr(irep->pool[i])); } @@ -163,25 +163,30 @@ mrb_str_pool(mrb_state *mrb, mrb_value str) { struct RString *s = mrb_str_ptr(str); struct RString *ns; + char *ptr; mrb_int len; ns = (struct RString *)mrb_malloc(mrb, sizeof(struct RString)); ns->tt = MRB_TT_STRING; ns->c = mrb->string_class; - len = s->len; - ns->len = len; + if (s->flags & MRB_STR_EMBED) + len = (mrb_int)((s->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT); + else + len = s->as.heap.len; + ns->as.heap.len = len; if (s->flags & MRB_STR_NOFREE) { - ns->ptr = s->ptr; + ns->as.heap.ptr = s->as.heap.ptr; ns->flags = MRB_STR_NOFREE; } else { ns->flags = 0; - ns->ptr = (char *)mrb_malloc(mrb, (size_t)len+1); - if (s->ptr) { - memcpy(ns->ptr, s->ptr, len); + ns->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1); + ptr = (s->flags & MRB_STR_EMBED) ? s->as.ary : s->as.heap.ptr; + if (ptr) { + memcpy(ns->as.heap.ptr, ptr, len); } - ns->ptr[len] = '\0'; + ns->as.heap.ptr[len] = '\0'; } return mrb_obj_value(ns); } diff --git a/src/string.c b/src/string.c index aa1afec47..0f057ef24 100644 --- a/src/string.c +++ b/src/string.c @@ -16,21 +16,74 @@ #include "mruby/string.h" #include "re.h" +#define STR_EMBED_P(s) ((s)->flags & MRB_STR_EMBED) +#define STR_SET_EMBED_FLAG(s) ((s)->flags |= MRB_STR_EMBED) +#define STR_UNSET_EMBED_FLAG(s) ((s)->flags &= ~(MRB_STR_EMBED|MRB_STR_EMBED_LEN_MASK)) +#define STR_SET_EMBED_LEN(s, n) do {\ + mrb_int tmp_n = (n);\ + s->flags &= ~MRB_STR_EMBED_LEN_MASK;\ + s->flags |= (tmp_n) << MRB_STR_EMBED_LEN_SHIFT;\ +} while (0) +#define STR_SET_LEN(s, n) do {\ + if (STR_EMBED_P(s)) {\ + STR_SET_EMBED_LEN((s),(n));\ + } else {\ + s->as.heap.len = (n);\ + }\ +} while (0) +#define RSTRING_EMBED_LEN(s) \ + (mrb_int)((RSTRING(s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT) +#define STR_EMBED_LEN(s)\ + (mrb_int)(((s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT) +#define STR_PTR(s) ((STR_EMBED_P(s)) ? (s)->as.ary : (s)->as.heap.ptr) +#define STR_LEN(s) ((STR_EMBED_P(s)) ? STR_EMBED_LEN(s) : (s)->as.heap.len) + const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; typedef struct mrb_shared_string { - mrb_bool nofree; + mrb_bool nofree : 1; int refcnt; char *ptr; mrb_int len; } mrb_shared_string; +#define STR_SHARED_P(s) ((s)->flags & MRB_STR_SHARED) +#define STR_SET_SHARED_FLAG(s) ((s)->flags |= MRB_STR_SHARED) +#define STR_UNSET_SHARED_FLAG(s) ((s)->flags &= ~MRB_STR_SHARED) + 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, mrb_int beg, mrb_int len); +mrb_int +mrb_str_strlen(mrb_state *mrb, struct RString *s) +{ + mrb_int i, max = STR_LEN(s); + char *p = STR_PTR(s); + + if (!p) return 0; + for (i=0; i<max; i++) { + if (p[i] == '\0') { + mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); + } + } + return max; +} + #define RESIZE_CAPA(s,capacity) do {\ - s->ptr = (char *)mrb_realloc(mrb, s->ptr, (capacity)+1);\ - s->aux.capa = capacity;\ + if (STR_EMBED_P(s)) {\ + if (RSTRING_EMBED_LEN_MAX < (capacity)) {\ + char *const tmp = (char *)mrb_malloc(mrb, (capacity)+1);\ + const mrb_int len = STR_EMBED_LEN(s);\ + memcpy(tmp, s->as.ary, len);\ + STR_UNSET_EMBED_FLAG(s);\ + s->as.heap.ptr = tmp;\ + s->as.heap.len = len;\ + s->as.heap.aux.capa = (capacity);\ + }\ + } else {\ + s->as.heap.ptr = (char *)mrb_realloc(mrb, STR_PTR(s), (capacity)+1);\ + s->as.heap.aux.capa = capacity;\ + }\ } while(0) static void @@ -48,42 +101,42 @@ str_decref(mrb_state *mrb, mrb_shared_string *shared) void mrb_str_modify(mrb_state *mrb, struct RString *s) { - if (s->flags & MRB_STR_SHARED) { - mrb_shared_string *shared = s->aux.shared; + if (STR_SHARED_P(s)) { + mrb_shared_string *shared = s->as.heap.aux.shared; - if (shared->refcnt == 1 && s->ptr == shared->ptr) { - s->ptr = shared->ptr; - s->aux.capa = shared->len; - s->ptr[s->len] = '\0'; + if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) { + s->as.heap.ptr = shared->ptr; + s->as.heap.aux.capa = shared->len; + STR_PTR(s)[s->as.heap.len] = '\0'; mrb_free(mrb, shared); } else { char *ptr, *p; mrb_int len; - p = s->ptr; - len = s->len; + p = STR_PTR(s); + len = s->as.heap.len; ptr = (char *)mrb_malloc(mrb, (size_t)len + 1); if (p) { memcpy(ptr, p, len); } - ptr[len] = '\0'; - s->ptr = ptr; - s->aux.capa = len; + ptr[len] = '\0'; + s->as.heap.ptr = ptr; + s->as.heap.aux.capa = len; str_decref(mrb, shared); } - s->flags &= ~MRB_STR_SHARED; + STR_UNSET_SHARED_FLAG(s); return; } if (s->flags & MRB_STR_NOFREE) { - char *p = s->ptr; + char *p = STR_PTR(s); - s->ptr = (char *)mrb_malloc(mrb, (size_t)s->len+1); + s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)s->as.heap.len+1); if (p) { - memcpy(s->ptr, p, s->len); + memcpy(STR_PTR(s), p, s->as.heap.len); } - s->ptr[s->len] = '\0'; - s->aux.capa = s->len; + STR_PTR(s)[s->as.heap.len] = '\0'; + s->as.heap.aux.capa = s->as.heap.len; s->flags &= ~MRB_STR_NOFREE; return; } @@ -96,13 +149,13 @@ mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) struct RString *s = mrb_str_ptr(str); mrb_str_modify(mrb, s); - slen = s->len; + slen = STR_LEN(s); if (len != slen) { if (slen < len || slen - len > 256) { RESIZE_CAPA(s, len); } - s->len = len; - s->ptr[len] = '\0'; /* sentinel */ + STR_SET_LEN(s, len); + STR_PTR(s)[len] = '\0'; /* sentinel */ } return str; } @@ -122,13 +175,21 @@ str_new(mrb_state *mrb, const char *p, mrb_int len) struct RString *s; s = mrb_obj_alloc_string(mrb); - s->len = len; - s->aux.capa = len; - s->ptr = (char *)mrb_malloc(mrb, (size_t)len+1); - if (p) { - memcpy(s->ptr, p, len); + if (len < RSTRING_EMBED_LEN_MAX) { + STR_SET_EMBED_FLAG(s); + STR_SET_EMBED_LEN(s,len); + if (p) { + memcpy(s->as.ary, p, len); + } + } else { + s->as.heap.len = len; + s->as.heap.aux.capa = len; + s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1); + if (p) { + memcpy(s->as.heap.ptr, p, len); + } } - s->ptr[len] = '\0'; + STR_PTR(s)[len] = '\0'; return s; } @@ -161,31 +222,36 @@ mrb_str_buf_new(mrb_state *mrb, mrb_int capa) if (capa < MRB_STR_BUF_MIN_SIZE) { capa = MRB_STR_BUF_MIN_SIZE; } - s->len = 0; - s->aux.capa = capa; - s->ptr = (char *)mrb_malloc(mrb, capa+1); - s->ptr[0] = '\0'; + s->as.heap.len = 0; + s->as.heap.aux.capa = capa; + s->as.heap.ptr = (char *)mrb_malloc(mrb, capa+1); + STR_PTR(s)[0] = '\0'; return mrb_obj_value(s); } static void -str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) +str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, mrb_int len) { mrb_int capa; mrb_int total; ptrdiff_t off = -1; mrb_str_modify(mrb, s); - if (ptr >= s->ptr && ptr <= s->ptr + s->len) { - off = ptr - s->ptr; + if (ptr >= STR_PTR(s) && ptr <= STR_PTR(s) + STR_LEN(s)) { + off = ptr - STR_PTR(s); } if (len == 0) return; - capa = s->aux.capa; - if (s->len >= MRB_INT_MAX - (mrb_int)len) { + + if (STR_EMBED_P(s)) + capa = RSTRING_EMBED_LEN_MAX; + else + capa = s->as.heap.aux.capa; + + if (STR_LEN(s) >= MRB_INT_MAX - (mrb_int)len) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string sizes too big"); } - total = s->len+len; + total = STR_LEN(s)+len; if (capa <= total) { while (total > capa) { if (capa + 1 >= MRB_INT_MAX / 2) { @@ -197,15 +263,15 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) RESIZE_CAPA(s, capa); } if (off != -1) { - ptr = s->ptr + off; + ptr = STR_PTR(s) + off; } - memcpy(s->ptr + s->len, ptr, len); - s->len = total; - s->ptr[total] = '\0'; /* sentinel */ + memcpy(STR_PTR(s) + STR_LEN(s), ptr, len); + STR_SET_LEN(s, total); + STR_PTR(s)[total] = '\0'; /* sentinel */ } mrb_value -mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len) +mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, mrb_int len) { if (len == 0) return str; str_buf_cat(mrb, mrb_str_ptr(str), ptr, len); @@ -213,10 +279,10 @@ mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len) } mrb_value -mrb_str_new(mrb_state *mrb, const char *p, size_t len) +mrb_str_new(mrb_state *mrb, const char *p, mrb_int len) { struct RString *s; - if ((mrb_int)len < 0) { + if (len < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)"); } @@ -247,23 +313,24 @@ mrb_str_new_cstr(mrb_state *mrb, const char *p) len = 0; } - s = str_new(mrb, p, len); + s = str_new(mrb, p, (mrb_int)len); return mrb_obj_value(s); } mrb_value -mrb_str_new_static(mrb_state *mrb, const char *p, size_t len) +mrb_str_new_static(mrb_state *mrb, const char *p, mrb_int len) { struct RString *s; - if ((mrb_int)len < 0) { + + if (len < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)"); } s = mrb_obj_alloc_string(mrb); - s->len = len; - s->aux.capa = 0; /* nofree */ - s->ptr = (char *)p; + s->as.heap.len = len; + s->as.heap.aux.capa = 0; /* nofree */ + s->as.heap.ptr = (char *)p; s->flags = MRB_STR_NOFREE; return mrb_obj_value(s); } @@ -271,10 +338,12 @@ mrb_str_new_static(mrb_state *mrb, const char *p, size_t len) void mrb_gc_free_str(mrb_state *mrb, struct RString *str) { - if (str->flags & MRB_STR_SHARED) - str_decref(mrb, str->aux.shared); + if (STR_EMBED_P(str)) + /* no code */; + else if (STR_SHARED_P(str)) + str_decref(mrb, str->as.heap.aux.shared); else if ((str->flags & MRB_STR_NOFREE) == 0) - mrb_free(mrb, str->ptr); + mrb_free(mrb, str->as.heap.ptr); } char * @@ -287,36 +356,47 @@ mrb_str_to_cstr(mrb_state *mrb, mrb_value str0) } s = str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0)); - if ((strlen(s->ptr) ^ s->len) != 0) { + if ((strlen(STR_PTR(s)) ^ STR_LEN(s)) != 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); } - return s->ptr; + return STR_PTR(s); } static void str_make_shared(mrb_state *mrb, struct RString *s) { - if (!(s->flags & MRB_STR_SHARED)) { + if (!STR_SHARED_P(s)) { mrb_shared_string *shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string)); shared->refcnt = 1; - if (s->flags & MRB_STR_NOFREE) { + if (STR_EMBED_P(s)) { + const mrb_int len = STR_EMBED_LEN(s); + char *const tmp = (char *)mrb_malloc(mrb, len+1); + memcpy(tmp, s->as.ary, len); + tmp[len] = '\0'; + STR_UNSET_EMBED_FLAG(s); + s->as.heap.ptr = tmp; + s->as.heap.len = len; + shared->nofree = FALSE; + shared->ptr = s->as.heap.ptr; + } + else if (s->flags & MRB_STR_NOFREE) { shared->nofree = TRUE; - shared->ptr = s->ptr; + shared->ptr = STR_PTR(s); s->flags &= ~MRB_STR_NOFREE; } else { shared->nofree = FALSE; - if (s->aux.capa > s->len) { - s->ptr = shared->ptr = (char *)mrb_realloc(mrb, s->ptr, s->len+1); + if (s->as.heap.aux.capa > s->as.heap.len) { + s->as.heap.ptr = shared->ptr = (char *)mrb_realloc(mrb, STR_PTR(s), s->as.heap.len+1); } else { - shared->ptr = s->ptr; + shared->ptr = STR_PTR(s); } } - shared->len = s->len; - s->aux.shared = shared; - s->flags |= MRB_STR_SHARED; + shared->len = s->as.heap.len; + s->as.heap.aux.shared = shared; + STR_SET_SHARED_FLAG(s); } } @@ -331,8 +411,8 @@ mrb_str_body(mrb_value str, int *len_p) { struct RString *s = mrb_str_ptr(str); - *len_p = s->len; - return s->ptr; + *len_p = STR_LEN(s); + return STR_PTR(s); } /* @@ -352,15 +432,14 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other) other = mrb_str_to_str(mrb, other); } s2 = mrb_str_ptr(other); - len = s1->len + s2->len; + len = STR_LEN(s1) + STR_LEN(s2); - if (s1->aux.capa < len) { - s1->aux.capa = len; - s1->ptr = (char *)mrb_realloc(mrb, s1->ptr, len+1); + if (RSTRING_CAPA(self) < len) { + RESIZE_CAPA(s1, len); } - memcpy(s1->ptr+s1->len, s2->ptr, s2->len); - s1->len = len; - s1->ptr[len] = '\0'; + memcpy(STR_PTR(s1)+STR_LEN(s1), STR_PTR(s2), STR_LEN(s2)); + STR_SET_LEN(s1, len); + STR_PTR(s1)[len] = '\0'; } /* @@ -376,9 +455,9 @@ mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b) struct RString *s2 = mrb_str_ptr(b); struct RString *t; - t = str_new(mrb, 0, s->len + s2->len); - memcpy(t->ptr, s->ptr, s->len); - memcpy(t->ptr + s->len, s2->ptr, s2->len); + t = str_new(mrb, 0, STR_LEN(s) + STR_LEN(s2)); + memcpy(STR_PTR(t), STR_PTR(s), STR_LEN(s)); + memcpy(STR_PTR(t) + STR_LEN(s), STR_PTR(s2), STR_LEN(s2)); return mrb_obj_value(t); } @@ -410,7 +489,7 @@ static mrb_value mrb_str_bytesize(mrb_state *mrb, mrb_value self) { struct RString *s = mrb_str_ptr(self); - return mrb_fixnum_value(s->len); + return mrb_fixnum_value(STR_LEN(s)); } /* 15.2.10.5.26 */ @@ -425,7 +504,7 @@ mrb_value mrb_str_size(mrb_state *mrb, mrb_value self) { struct RString *s = mrb_str_ptr(self); - return mrb_fixnum_value(s->len); + return mrb_fixnum_value(STR_LEN(s)); } /* 15.2.10.5.1 */ @@ -456,7 +535,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self) len = RSTRING_LEN(self)*times; str2 = str_new(mrb, 0, len); str_with_class(mrb, str2, self); - p = str2->ptr; + p = STR_PTR(str2); if (len > 0) { n = RSTRING_LEN(self); memcpy(p, RSTRING_PTR(self), n); @@ -466,7 +545,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self) } memcpy(p + n, p, len-n); } - p[str2->len] = '\0'; + p[STR_LEN(str2)] = '\0'; return mrb_obj_value(str2); } @@ -490,11 +569,11 @@ mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2) struct RString *s1 = mrb_str_ptr(str1); struct RString *s2 = mrb_str_ptr(str2); - len = lesser(s1->len, s2->len); - retval = memcmp(s1->ptr, s2->ptr, len); + len = lesser(STR_LEN(s1), STR_LEN(s2)); + retval = memcmp(STR_PTR(s1), STR_PTR(s2), len); if (retval == 0) { - if (s1->len == s2->len) return 0; - if (s1->len > s2->len) return 1; + if (STR_LEN(s1) == STR_LEN(s2)) return 0; + if (STR_LEN(s1) > STR_LEN(s2)) return 1; return -1; } if (retval > 0) return 1; @@ -720,7 +799,7 @@ mrb_str_dup(mrb_state *mrb, mrb_value str) /* should return shared string */ struct RString *s = mrb_str_ptr(str); - return mrb_str_new(mrb, s->ptr, s->len); + return mrb_str_new(mrb, STR_PTR(s), STR_LEN(s)); } static mrb_value @@ -849,8 +928,8 @@ mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str) struct RString *s = mrb_str_ptr(str); mrb_str_modify(mrb, s); - if (s->len == 0 || !s->ptr) return mrb_nil_value(); - p = s->ptr; pend = s->ptr + s->len; + if (STR_LEN(s) == 0 || !STR_PTR(s)) return mrb_nil_value(); + p = STR_PTR(s); pend = STR_PTR(s) + STR_LEN(s); if (ISLOWER(*p)) { *p = TOUPPER(*p); modify = 1; @@ -906,29 +985,29 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) struct RString *s = mrb_str_ptr(str); mrb_str_modify(mrb, s); - len = s->len; + len = STR_LEN(s); if (mrb_get_args(mrb, "|S", &rs) == 0) { if (len == 0) return mrb_nil_value(); smart_chomp: - if (s->ptr[len-1] == '\n') { - s->len--; - if (s->len > 0 && - s->ptr[s->len-1] == '\r') { - s->len--; + if (STR_PTR(s)[len-1] == '\n') { + STR_SET_LEN(s, STR_LEN(s) - 1); + if (STR_LEN(s) > 0 && + STR_PTR(s)[STR_LEN(s)-1] == '\r') { + STR_SET_LEN(s, STR_LEN(s) - 1); } } - else if (s->ptr[len-1] == '\r') { - s->len--; + else if (STR_PTR(s)[len-1] == '\r') { + STR_SET_LEN(s, STR_LEN(s) - 1); } else { return mrb_nil_value(); } - s->ptr[s->len] = '\0'; + STR_PTR(s)[STR_LEN(s)] = '\0'; return str; } if (len == 0 || mrb_nil_p(rs)) return mrb_nil_value(); - p = s->ptr; + p = STR_PTR(s); rslen = RSTRING_LEN(rs); if (rslen == 0) { while (len>0 && p[len-1] == '\n') { @@ -936,8 +1015,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) if (len>0 && p[len-1] == '\r') len--; } - if (len < s->len) { - s->len = len; + if (len < STR_LEN(s)) { + STR_SET_LEN(s, len); p[len] = '\0'; return str; } @@ -954,8 +1033,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) if (p[len-1] == newline && (rslen <= 1 || memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) { - s->len = len - rslen; - p[s->len] = '\0'; + STR_SET_LEN(s, len - rslen); + p[STR_LEN(s)] = '\0'; return str; } return mrb_nil_value(); @@ -1005,17 +1084,17 @@ mrb_str_chop_bang(mrb_state *mrb, mrb_value str) struct RString *s = mrb_str_ptr(str); mrb_str_modify(mrb, s); - if (s->len > 0) { + if (STR_LEN(s) > 0) { int len; - len = s->len - 1; - if (s->ptr[len] == '\n') { + len = STR_LEN(s) - 1; + if (STR_PTR(s)[len] == '\n') { if (len > 0 && - s->ptr[len-1] == '\r') { + STR_PTR(s)[len-1] == '\r') { len--; } } - s->len = len; - s->ptr[len] = '\0'; + STR_SET_LEN(s, len); + STR_PTR(s)[len] = '\0'; return str; } return mrb_nil_value(); @@ -1063,8 +1142,8 @@ mrb_str_downcase_bang(mrb_state *mrb, mrb_value str) struct RString *s = mrb_str_ptr(str); mrb_str_modify(mrb, s); - p = s->ptr; - pend = s->ptr + s->len; + p = STR_PTR(s); + pend = STR_PTR(s) + STR_LEN(s); while (p < pend) { if (ISUPPER(*p)) { *p = TOLOWER(*p); @@ -1113,7 +1192,7 @@ mrb_str_empty_p(mrb_state *mrb, mrb_value self) { struct RString *s = mrb_str_ptr(self); - return mrb_bool_value(s->len == 0); + return mrb_bool_value(STR_LEN(s) == 0); } /* 15.2.10.5.17 */ @@ -1142,14 +1221,18 @@ mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) mrb_shared_string *shared; orig = mrb_str_ptr(str); - str_make_shared(mrb, orig); - shared = orig->aux.shared; - s = mrb_obj_alloc_string(mrb); - s->ptr = orig->ptr + beg; - s->len = len; - s->aux.shared = shared; - s->flags |= MRB_STR_SHARED; - shared->refcnt++; + if (STR_EMBED_P(orig)) { + s = str_new(mrb, orig->as.ary+beg, len); + } else { + str_make_shared(mrb, orig); + shared = orig->as.heap.aux.shared; + s = mrb_obj_alloc_string(mrb); + s->as.heap.ptr = orig->as.heap.ptr + beg; + s->as.heap.len = len; + s->as.heap.aux.shared = shared; + STR_SET_SHARED_FLAG(s); + shared->refcnt++; + } return mrb_obj_value(s); } @@ -1190,8 +1273,8 @@ mrb_str_hash(mrb_state *mrb, mrb_value str) { /* 1-8-7 */ struct RString *s = mrb_str_ptr(str); - mrb_int len = s->len; - char *p = s->ptr; + mrb_int len = STR_LEN(s); + char *p = STR_PTR(s); mrb_int key = 0; while (len--) { @@ -1337,38 +1420,36 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) { - if (s2->flags & MRB_STR_SHARED) { + long len; + + len = STR_LEN(s2); + if (STR_SHARED_P(s2)) { L_SHARE: - if (s1->flags & MRB_STR_SHARED){ - str_decref(mrb, s1->aux.shared); + if (STR_SHARED_P(s1)) { + str_decref(mrb, s1->as.heap.aux.shared); } - else { - mrb_free(mrb, s1->ptr); + else if (!STR_EMBED_P(s1) && !(s1->flags & MRB_STR_NOFREE)) { + mrb_free(mrb, s1->as.heap.ptr); } - s1->ptr = s2->ptr; - s1->len = s2->len; - s1->aux.shared = s2->aux.shared; - s1->flags |= MRB_STR_SHARED; - s1->aux.shared->refcnt++; - } - else if (s2->len > STR_REPLACE_SHARED_MIN) { - str_make_shared(mrb, s2); - goto L_SHARE; + STR_UNSET_EMBED_FLAG(s1); + s1->as.heap.ptr = s2->as.heap.ptr; + s1->as.heap.len = len; + s1->as.heap.aux.shared = s2->as.heap.aux.shared; + STR_SET_SHARED_FLAG(s1); + s1->as.heap.aux.shared->refcnt++; } else { - if (s1->flags & MRB_STR_SHARED) { - str_decref(mrb, s1->aux.shared); - s1->flags &= ~MRB_STR_SHARED; - s1->ptr = (char *)mrb_malloc(mrb, s2->len+1); + if (len <= RSTRING_EMBED_LEN_MAX) { + STR_SET_EMBED_FLAG(s1); + memcpy(STR_PTR(s1), STR_PTR(s2), len); + STR_SET_EMBED_LEN(s1, len); } else { - s1->ptr = (char *)mrb_realloc(mrb, s1->ptr, s2->len+1); + str_make_shared(mrb, s2); + goto L_SHARE; } - memcpy(s1->ptr, s2->ptr, s2->len); - s1->ptr[s2->len] = 0; - s1->len = s2->len; - s1->aux.capa = s2->len; } + return mrb_obj_value(s1); } @@ -1462,7 +1543,7 @@ mrb_ptr_to_str(mrb_state *mrb, void *p) uintptr_t n = (uintptr_t)p; p_str = str_new(mrb, NULL, 2 + sizeof(uintptr_t) * CHAR_BIT / 4); - p1 = p_str->ptr; + p1 = STR_PTR(p_str); *p1++ = '0'; *p1++ = 'x'; p2 = p1; @@ -1472,7 +1553,7 @@ mrb_ptr_to_str(mrb_state *mrb, void *p) n /= 16; } while (n > 0); *p2 = '\0'; - p_str->len = (mrb_int)(p2 - p_str->ptr); + STR_SET_LEN(p_str, (mrb_int)(p2 - STR_PTR(p_str))); while (p1 < p2) { const char c = *p1; @@ -1511,12 +1592,12 @@ mrb_str_reverse(mrb_state *mrb, mrb_value str) struct RString *s2; char *s, *e, *p; - if (RSTRING(str)->len <= 1) return mrb_str_dup(mrb, str); + if (RSTRING_LEN(str) <= 1) return mrb_str_dup(mrb, str); - s2 = str_new(mrb, 0, RSTRING(str)->len); + s2 = str_new(mrb, 0, RSTRING_LEN(str)); str_with_class(mrb, s2, str); s = RSTRING_PTR(str); e = RSTRING_END(str) - 1; - p = s2->ptr; + p = STR_PTR(s2); while (e >= s) { *p++ = *e--; @@ -1539,9 +1620,9 @@ mrb_str_reverse_bang(mrb_state *mrb, mrb_value str) char c; mrb_str_modify(mrb, s); - if (s->len > 1) { - p = s->ptr; - e = p + s->len - 1; + if (STR_LEN(s) > 1) { + p = STR_PTR(s); + e = p + STR_LEN(s) - 1; while (p < e) { c = *p; *p++ = *e; @@ -1574,21 +1655,20 @@ 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); - mrb_int len = psub->len; + mrb_int len = RSTRING_LEN(sub); /* substring longer than string */ - if (ps->len < len) return -1; - if (ps->len - pos < len) { - pos = ps->len - len; + if (STR_LEN(ps) < len) return -1; + if (STR_LEN(ps) - pos < len) { + pos = STR_LEN(ps) - len; } - sbeg = ps->ptr; - s = ps->ptr + pos; - t = psub->ptr; + sbeg = STR_PTR(ps); + s = STR_PTR(ps) + pos; + t = RSTRING_PTR(sub); if (len) { while (sbeg <= s) { if (memcmp(s, t, len) == 0) { - return s - ps->ptr; + return s - STR_PTR(ps); } s--; } @@ -1656,7 +1736,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) mrb_int len = RSTRING_LEN(str); unsigned char *p = (unsigned char*)RSTRING_PTR(str); - for (pos=len;pos>=0;pos--) { + for (pos=len-1;pos>=0;pos--) { if (p[pos] == c) return mrb_fixnum_value(pos); } return mrb_nil_value(); @@ -1682,22 +1762,22 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) } static const char isspacetable[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #define ascii_isspace(c) isspacetable[(unsigned char)(c)] @@ -1819,7 +1899,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) } } else if (split_type == string) { - char *ptr = RSTRING_PTR(str); + char *ptr = RSTRING_PTR(str); // s->as.ary char *temp = ptr; char *eptr = RSTRING_END(str); mrb_int slen = RSTRING_LEN(spat); @@ -2002,12 +2082,14 @@ char * mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) { struct RString *ps = mrb_str_ptr(*ptr); - char *s = ps->ptr; + mrb_int len = mrb_str_strlen(mrb, ps); + char *p = STR_PTR(ps); - if (!s || ps->len != strlen(s)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); + if (!p || p[len] != '\0') { + mrb_str_modify(mrb, ps); + return STR_PTR(ps); } - return s; + return p; } mrb_value @@ -2027,7 +2109,7 @@ mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, mrb_bool badcheck) len = RSTRING_LEN(str); if (s[len]) { /* no sentinel somehow */ struct RString *temp_str = str_new(mrb, s, len); - s = temp_str->ptr; + s = STR_PTR(temp_str); } } return mrb_cstr_to_inum(mrb, s, base, badcheck); @@ -2157,7 +2239,7 @@ mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck) } if (s[len]) { /* no sentinel somehow */ struct RString *temp_str = str_new(mrb, s, len); - s = temp_str->ptr; + s = STR_PTR(temp_str); } } return mrb_cstr_to_dbl(mrb, s, badcheck); @@ -2296,8 +2378,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str) result = str_new(mrb, 0, len); str_with_class(mrb, result, str); p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str); - q = result->ptr; - + q = STR_PTR(result); *q++ = '"'; while (p < pend) { unsigned char c = *p++; @@ -2372,7 +2453,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str) } mrb_value -mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len) +mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, mrb_int len) { if ((mrb_int)len < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)"); @@ -2455,7 +2536,7 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str) continue; } } - mrb_str_buf_cat(mrb, result, "\"", 1); + mrb_str_cat_lit(mrb, result, "\""); return result; } @@ -2473,8 +2554,8 @@ static mrb_value mrb_str_bytes(mrb_state *mrb, mrb_value str) { struct RString *s = mrb_str_ptr(str); - mrb_value a = mrb_ary_new_capa(mrb, s->len); - unsigned char *p = (unsigned char *)(s->ptr), *pend = p + s->len; + mrb_value a = mrb_ary_new_capa(mrb, STR_LEN(s)); + unsigned char *p = (unsigned char *)(STR_PTR(s)), *pend = p + STR_LEN(s); while (p < pend) { mrb_ary_push(mrb, a, mrb_fixnum_value(p[0])); diff --git a/src/symbol.c b/src/symbol.c index 7971f71ca..deb6155d0 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -12,7 +12,7 @@ /* ------------------------------------------------------ */ typedef struct symbol_name { - mrb_bool lit; + mrb_bool lit : 1; uint16_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) /* ------------------------------------------------------ */ static mrb_sym -sym_intern(mrb_state *mrb, const char *name, size_t len, int lit) +sym_intern(mrb_state *mrb, const char *name, mrb_int len, mrb_bool lit) { khash_t(n2s) *h = mrb->name2sym; symbol_name sname; @@ -70,21 +70,21 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, int lit) } mrb_sym -mrb_intern(mrb_state *mrb, const char *name, size_t len) +mrb_intern(mrb_state *mrb, const char *name, mrb_int len) { - return sym_intern(mrb, name, len, 0); + return sym_intern(mrb, name, len, FALSE); } mrb_sym -mrb_intern_static(mrb_state *mrb, const char *name, size_t len) +mrb_intern_static(mrb_state *mrb, const char *name, mrb_int len) { - return sym_intern(mrb, name, len, 1); + return sym_intern(mrb, name, len, TRUE); } mrb_sym mrb_intern_cstr(mrb_state *mrb, const char *name) { - return mrb_intern(mrb, name, strlen(name)); + return mrb_intern(mrb, name, (mrb_int)strlen(name)); } mrb_sym @@ -94,7 +94,7 @@ mrb_intern_str(mrb_state *mrb, mrb_value str) } mrb_value -mrb_check_intern(mrb_state *mrb, const char *name, size_t len) +mrb_check_intern(mrb_state *mrb, const char *name, mrb_int len) { khash_t(n2s) *h = mrb->name2sym; symbol_name sname = { 0 }; @@ -116,7 +116,7 @@ mrb_check_intern(mrb_state *mrb, const char *name, size_t len) mrb_value mrb_check_intern_cstr(mrb_state *mrb, const char *name) { - return mrb_check_intern(mrb, name, strlen(name)); + return mrb_check_intern(mrb, name, (mrb_int)strlen(name)); } mrb_value @@ -127,7 +127,7 @@ mrb_check_intern_str(mrb_state *mrb, mrb_value str) /* lenp must be a pointer to a size_t variable */ const char* -mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp) +mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp) { khash_t(n2s) *h = mrb->name2sym; khiter_t k; @@ -137,12 +137,12 @@ mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp) if (kh_exist(h, k)) { if (kh_value(h, k) == sym) { sname = kh_key(h, k); - *lenp = sname.len; + if (lenp) *lenp = sname.len; return sname.name; } } } - *lenp = 0; + if (lenp) *lenp = 0; return NULL; /* missing */ } @@ -240,7 +240,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym) { mrb_sym id = mrb_symbol(sym); const char *p; - size_t len; + mrb_int len; p = mrb_sym2name_len(mrb, id, &len); return mrb_str_new_static(mrb, p, len); @@ -392,16 +392,16 @@ sym_inspect(mrb_state *mrb, mrb_value sym) { mrb_value str; const char *name; - size_t len; + mrb_int len; mrb_sym id = mrb_symbol(sym); name = mrb_sym2name_len(mrb, id, &len); str = mrb_str_new(mrb, 0, len+1); - RSTRING(str)->ptr[0] = ':'; - memcpy(RSTRING(str)->ptr+1, name, len); + RSTRING_PTR(str)[0] = ':'; + memcpy(RSTRING_PTR(str)+1, name, len); if (!symname_p(name) || strlen(name) != len) { str = mrb_str_dump(mrb, str); - memcpy(RSTRING(str)->ptr, ":\"", 2); + memcpy(RSTRING_PTR(str), ":\"", 2); } return str; } @@ -409,7 +409,7 @@ sym_inspect(mrb_state *mrb, mrb_value sym) mrb_value mrb_sym2str(mrb_state *mrb, mrb_sym sym) { - size_t len; + mrb_int len; const char *name = mrb_sym2name_len(mrb, sym, &len); if (!name) return mrb_undef_value(); /* can't happen */ @@ -419,16 +419,16 @@ mrb_sym2str(mrb_state *mrb, mrb_sym sym) const char* mrb_sym2name(mrb_state *mrb, mrb_sym sym) { - size_t len; + mrb_int len; const char *name = mrb_sym2name_len(mrb, sym, &len); if (!name) return NULL; - if (symname_p(name) && strlen(name) == len) { + if (symname_p(name) && strlen(name) == (size_t)len) { return name; } else { mrb_value str = mrb_str_dump(mrb, mrb_str_new_static(mrb, name, len)); - return RSTRING(str)->ptr; + return RSTRING_PTR(str); } } @@ -448,7 +448,7 @@ sym_cmp(mrb_state *mrb, mrb_value s1) else { const char *p1, *p2; int retval; - size_t len, len1, len2; + mrb_int len, len1, len2; p1 = mrb_sym2name_len(mrb, sym1, &len1); p2 = mrb_sym2name_len(mrb, sym2, &len2); diff --git a/src/variable.c b/src/variable.c index c313a8f14..8e427829a 100644 --- a/src/variable.c +++ b/src/variable.c @@ -562,7 +562,7 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { mrb_value str = *(mrb_value*)p; const char *s; - size_t len; + mrb_int len; mrb_value ins; /* need not to show internal data */ @@ -596,7 +596,7 @@ mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj) const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj)); mrb_value str = mrb_str_buf_new(mrb, 30); - mrb_str_buf_cat(mrb, str, "-<", 2); + mrb_str_cat_lit(mrb, str, "-<"); mrb_str_cat_cstr(mrb, str, cn); mrb_str_cat_lit(mrb, str, ":"); mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj)); @@ -641,7 +641,7 @@ iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { mrb_value ary; const char* s; - size_t len; + mrb_int len; ary = *(mrb_value*)p; s = mrb_sym2name_len(mrb, sym, &len); @@ -685,7 +685,7 @@ cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { mrb_value ary; const char* s; - size_t len; + mrb_int len; ary = *(mrb_value*)p; s = mrb_sym2name_len(mrb, sym, &len); @@ -949,7 +949,7 @@ const_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { mrb_value ary; const char* s; - size_t len; + mrb_int len; ary = *(mrb_value*)p; s = mrb_sym2name_len(mrb, sym, &len); @@ -451,7 +451,8 @@ mrb_f_send(mrb_state *mrb, mrb_value self) c = mrb_class(mrb, self); p = mrb_method_search_vm(mrb, &c, name); - if (!p || MRB_PROC_CFUNC_P(p)) { + + if (!p) { /* call method_mising */ return mrb_funcall_with_block(mrb, self, name, argc, argv, block); } @@ -470,6 +471,11 @@ mrb_f_send(mrb_state *mrb, mrb_value self) else { /* variable length arguments */ mrb_ary_shift(mrb, regs[0]); } + + if (MRB_PROC_CFUNC_P(p)) { + return p->body.func(mrb, self); + } + cipush(mrb); ci = mrb->c->ci; ci->target_class = 0; @@ -1203,8 +1209,7 @@ RETRY_TRY_BLOCK: struct REnv *e = uvenv(mrb, lv-1); if (!e) { mrb_value exc; - static const char m[] = "super called outside of method"; - exc = mrb_exc_new(mrb, E_NOMETHOD_ERROR, m, sizeof(m) - 1); + exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } @@ -1418,7 +1423,7 @@ RETRY_TRY_BLOCK: goto L_RAISE; } if (mrb->c->prev->ci == mrb->c->prev->cibase) { - mrb_value exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, mrb_str_new_lit(mrb, "double resume")); + mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "double resume"); mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } @@ -2186,8 +2191,7 @@ RETRY_TRY_BLOCK: CASE(OP_TCLASS) { /* A B R(A) := target_class */ if (!mrb->c->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_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module"); mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } |
