summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c201
-rw-r--r--src/class.c209
-rw-r--r--src/codegen.c241
-rw-r--r--src/crc.c12
-rw-r--r--src/dump.c881
-rw-r--r--src/error.c254
-rw-r--r--src/error.h3
-rw-r--r--src/etc.c8
-rw-r--r--src/gc.c78
-rw-r--r--src/hash.c59
-rw-r--r--src/init.c4
-rw-r--r--src/kernel.c134
-rw-r--r--src/keywords78
-rw-r--r--src/lex.def92
-rw-r--r--src/load.c987
-rw-r--r--src/node.h11
-rw-r--r--src/numeric.c241
-rw-r--r--src/object.c47
-rw-r--r--src/opcode.h25
-rw-r--r--src/parse.y962
-rw-r--r--src/pool.c6
-rw-r--r--src/print.c56
-rw-r--r--src/proc.c2
-rw-r--r--src/range.c103
-rw-r--r--src/sprintf.c1095
-rw-r--r--src/state.c56
-rw-r--r--src/string.c368
-rw-r--r--src/symbol.c247
-rw-r--r--src/value_array.h27
-rw-r--r--src/variable.c165
-rw-r--r--src/vm.c408
31 files changed, 3104 insertions, 3956 deletions
diff --git a/src/array.c b/src/array.c
index c767283aa..88f56f6b4 100644
--- a/src/array.c
+++ b/src/array.c
@@ -4,20 +4,25 @@
** See Copyright Notice in mruby.h
*/
+#ifndef SIZE_MAX
+ /* Some versions of VC++
+ * has SIZE_MAX in stdint.h
+ */
+# include <limits.h>
+#endif
#include "mruby.h"
#include "mruby/array.h"
-#include <string.h>
-#include "mruby/string.h"
#include "mruby/class.h"
+#include "mruby/string.h"
+#include "value_array.h"
#define ARY_DEFAULT_LEN 4
#define ARY_SHRINK_RATIO 5 /* must be larger than 2 */
-#ifdef INT_MAX
-# define ARY_MAX_SIZE (INT_MAX / sizeof(mrb_value))
-#endif
+#define ARY_C_MAX_SIZE (SIZE_MAX / sizeof(mrb_value))
+#define ARY_MAX_SIZE ((ARY_C_MAX_SIZE < (size_t)MRB_INT_MAX) ? (mrb_int)ARY_C_MAX_SIZE : MRB_INT_MAX)
static inline mrb_value
-ary_elt(mrb_value ary, int offset)
+ary_elt(mrb_value ary, mrb_int offset)
{
if (RARRAY_LEN(ary) == 0) return mrb_nil_value();
if (offset < 0 || RARRAY_LEN(ary) <= offset) {
@@ -27,16 +32,14 @@ ary_elt(mrb_value ary, int offset)
}
static struct RArray*
-ary_new_capa(mrb_state *mrb, int capa)
+ary_new_capa(mrb_state *mrb, mrb_int capa)
{
struct RArray *a;
- int blen;
+ mrb_int blen;
-#ifdef INT_MAX
if (capa > ARY_MAX_SIZE) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big");
}
-#endif
blen = capa * sizeof(mrb_value) ;
if (blen < capa) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big");
@@ -51,7 +54,7 @@ ary_new_capa(mrb_state *mrb, int capa)
}
mrb_value
-mrb_ary_new_capa(mrb_state *mrb, int capa)
+mrb_ary_new_capa(mrb_state *mrb, mrb_int capa)
{
struct RArray *a = ary_new_capa(mrb, capa);
return mrb_obj_value(a);
@@ -87,21 +90,6 @@ array_copy(mrb_value *dst, const mrb_value *src, size_t size)
}
}
-
-mrb_value
-mrb_ary_new_from_values(mrb_state *mrb, int size, mrb_value *vals)
-{
- mrb_value ary;
- struct RArray *a;
-
- ary = mrb_ary_new_capa(mrb, size);
- a = mrb_ary_ptr(ary);
- array_copy(a->ptr, vals, size);
- a->len = size;
-
- return ary;
-}
-
mrb_value
mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr)
{
@@ -112,7 +100,7 @@ mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr)
}
static void
-ary_fill_with_nil(mrb_value *ptr, int size)
+ary_fill_with_nil(mrb_value *ptr, mrb_int size)
{
mrb_value nil = mrb_nil_value();
@@ -134,13 +122,13 @@ ary_modify(mrb_state *mrb, struct RArray *a)
}
else {
mrb_value *ptr, *p;
- int len;
+ mrb_int len;
p = a->ptr;
len = a->len * sizeof(mrb_value);
ptr = (mrb_value *)mrb_malloc(mrb, len);
if (p) {
- array_copy(ptr, p, a->len);
+ array_copy(ptr, p, a->len);
}
a->ptr = ptr;
a->aux.capa = a->len;
@@ -170,15 +158,13 @@ ary_make_shared(mrb_state *mrb, struct RArray *a)
}
static void
-ary_expand_capa(mrb_state *mrb, struct RArray *a, int len)
+ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len)
{
- int capa = a->aux.capa;
+ mrb_int capa = a->aux.capa;
-#ifdef INT_MAX
if (len > ARY_MAX_SIZE) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
-#endif
while(capa < len) {
if (capa == 0) {
@@ -189,20 +175,24 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, int len)
}
}
-#ifdef INT_MAX
if (capa > ARY_MAX_SIZE) capa = ARY_MAX_SIZE; /* len <= capa <= ARY_MAX_SIZE */
-#endif
if (capa > a->aux.capa) {
+ mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa);
+
+ if(!expanded_ptr) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "out of memory");
+ }
+
a->aux.capa = capa;
- a->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa);
+ a->ptr = expanded_ptr;
}
}
static void
ary_shrink_capa(mrb_state *mrb, struct RArray *a)
{
- int capa = a->aux.capa;
+ mrb_int capa = a->aux.capa;
if (capa < ARY_DEFAULT_LEN * 2) return;
if (capa <= a->len * ARY_SHRINK_RATIO) return;
@@ -228,13 +218,13 @@ mrb_ary_s_create(mrb_state *mrb, mrb_value self)
int len;
mrb_get_args(mrb, "*", &vals, &len);
- return mrb_ary_new_from_values(mrb, (int)len, vals);
+ return mrb_ary_new_from_values(mrb, len, vals);
}
static void
-ary_concat(mrb_state *mrb, struct RArray *a, mrb_value *ptr, int blen)
+ary_concat(mrb_state *mrb, struct RArray *a, mrb_value *ptr, mrb_int blen)
{
- int len = a->len + blen;
+ mrb_int len = a->len + blen;
ary_modify(mrb, a);
if (a->aux.capa < len) ary_expand_capa(mrb, a, len);
@@ -255,7 +245,7 @@ mrb_value
mrb_ary_concat_m(mrb_state *mrb, mrb_value self)
{
mrb_value *ptr;
- int blen;
+ mrb_int blen;
mrb_get_args(mrb, "a", &ptr, &blen);
ary_concat(mrb, mrb_ary_ptr(self), ptr, blen);
@@ -269,7 +259,7 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self)
struct RArray *a2;
mrb_value ary;
mrb_value *ptr;
- int blen;
+ mrb_int blen;
mrb_get_args(mrb, "a", &ptr, &blen);
ary = mrb_ary_new_capa(mrb, a1->len + blen);
@@ -305,14 +295,14 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
mrb_value ary2;
struct RArray *a1, *a2;
mrb_value r = mrb_nil_value();
- int i, len;
+ mrb_int i, len;
mrb_get_args(mrb, "o", &ary2);
if (!mrb_array_p(ary2)) return mrb_nil_value();
a1 = RARRAY(ary1); a2 = RARRAY(ary2);
if (a1->len == a2->len && a1->ptr == a2->ptr) return mrb_fixnum_value(0);
else {
- mrb_sym cmp = mrb_intern(mrb, "<=>");
+ mrb_sym cmp = mrb_intern2(mrb, "<=>", 3);
len = RARRAY_LEN(ary1);
if (len > RARRAY_LEN(ary2)) {
@@ -329,7 +319,7 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
}
static void
-ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, int len)
+ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, mrb_int len)
{
ary_modify(mrb, a);
if (a->aux.capa < len)
@@ -429,25 +419,19 @@ mrb_ary_reverse(mrb_state *mrb, mrb_value self)
}
mrb_value
-mrb_ary_new4(mrb_state *mrb, int n, const mrb_value *elts)
+mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals)
{
mrb_value ary;
+ struct RArray *a;
- ary = mrb_ary_new_capa(mrb, n);
- if (n > 0 && elts) {
- array_copy(RARRAY_PTR(ary), elts, n);
- RARRAY_LEN(ary) = n;
- }
+ ary = mrb_ary_new_capa(mrb, size);
+ a = mrb_ary_ptr(ary);
+ array_copy(a->ptr, vals, size);
+ a->len = size;
return ary;
}
-mrb_value
-mrb_ary_new_elts(mrb_state *mrb, int n, const mrb_value *elts)
-{
- return mrb_ary_new4(mrb, n, elts);
-}
-
void
mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem) /* mrb_ary_push */
{
@@ -505,7 +489,7 @@ mrb_ary_shift(mrb_state *mrb, mrb_value self)
}
else {
mrb_value *ptr = a->ptr;
- int size = a->len;
+ mrb_int size = a->len;
val = *ptr;
while((int)(--size)) {
@@ -536,7 +520,7 @@ mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item)
ary_modify(mrb, a);
if (a->aux.capa < a->len + 1)
ary_expand_capa(mrb, a, a->len + 1);
- memmove(a->ptr + 1, a->ptr, sizeof(mrb_value)*a->len);
+ value_move(a->ptr + 1, a->ptr, a->len);
a->ptr[0] = item;
}
a->len++;
@@ -563,7 +547,7 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self)
if (len == 0) return self;
if (a->aux.capa < a->len + len)
ary_expand_capa(mrb, a, a->len + len);
- memmove(a->ptr + len, a->ptr, sizeof(mrb_value)*a->len);
+ value_move(a->ptr + len, a->ptr, a->len);
}
array_copy(a->ptr, vals, len);
a->len += len;
@@ -594,7 +578,7 @@ mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) /* rb_ary_s
if (n < 0) {
n += a->len;
if (n < 0) {
- mrb_raisef(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len);
+ mrb_raisef(mrb, E_INDEX_ERROR, "index %S out of array", mrb_fixnum_value(n - a->len));
}
}
if (a->len <= (int)n) {
@@ -612,9 +596,9 @@ mrb_value
mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_value rpl)
{
struct RArray *a = mrb_ary_ptr(ary);
- int tail, size;
+ mrb_int tail, size;
mrb_value *argv;
- int i, argc;
+ mrb_int i, argc;
ary_modify(mrb, a);
/* range check */
@@ -648,7 +632,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
ary_fill_with_nil(a->ptr + a->len, (int)(head - a->len));
}
else if (head < a->len) {
- memmove(a->ptr + head + argc, a->ptr + tail, sizeof(mrb_value)*(a->len - tail));
+ value_move(a->ptr + head + argc, a->ptr + tail, a->len - tail);
}
for(i = 0; i < argc; i++) {
@@ -660,7 +644,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
return ary;
}
-int
+mrb_int
mrb_ary_len(mrb_state *mrb, mrb_value ary)
{
return RARRAY_LEN(ary);
@@ -677,7 +661,7 @@ mrb_ary_decref(mrb_state *mrb, mrb_shared_array *shared)
}
static mrb_value
-ary_subseq(mrb_state *mrb, struct RArray *a, int beg, int len)
+ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len)
{
struct RArray *b;
@@ -714,11 +698,12 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self)
len = mrb_fixnum(argv[0]);
if (len < 0) return mrb_nil_value();
if (a->len == (int)index) return mrb_ary_new(mrb);
- if ((int)len > a->len - index) len = a->len - index;
+ if (len > a->len - index) len = a->len - index;
return ary_subseq(mrb, a, index, len);
default:
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ break;
}
return mrb_nil_value(); /* dummy to avoid warning : not reach here */
@@ -757,7 +742,7 @@ mrb_ary_delete_at(mrb_state *mrb, mrb_value self)
mrb_int index;
mrb_value val;
mrb_value *ptr;
- int len;
+ mrb_int len;
mrb_get_args(mrb, "i", &index);
if (index < 0) index += a->len;
@@ -803,7 +788,7 @@ mrb_value
mrb_ary_last(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
- int size;
+ mrb_int size;
mrb_value *vals;
int len;
@@ -830,7 +815,7 @@ mrb_value
mrb_ary_index_m(mrb_state *mrb, mrb_value self)
{
mrb_value obj;
- int i;
+ mrb_int i;
mrb_get_args(mrb, "o", &obj);
for (i = 0; i < RARRAY_LEN(self); i++) {
@@ -845,7 +830,7 @@ mrb_value
mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
{
mrb_value obj;
- int i;
+ mrb_int i;
mrb_get_args(mrb, "o", &obj);
for (i = RARRAY_LEN(self) - 1; i >= 0; i--) {
@@ -894,7 +879,7 @@ mrb_ary_empty_p(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
- return ((a->len == 0)? mrb_true_value(): mrb_false_value());
+ return mrb_bool_value(a->len == 0);
}
mrb_value
@@ -904,7 +889,7 @@ mrb_check_array_type(mrb_state *mrb, mrb_value ary)
}
mrb_value
-mrb_ary_entry(mrb_value ary, int offset)
+mrb_ary_entry(mrb_value ary, mrb_int offset)
{
if (offset < 0) {
offset += RARRAY_LEN(ary);
@@ -915,7 +900,7 @@ mrb_ary_entry(mrb_value ary, int offset)
static mrb_value
inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
{
- int i;
+ mrb_int i;
mrb_value s, arystr;
char head[] = { '[' };
char sep[] = { ',', ' ' };
@@ -967,17 +952,13 @@ static mrb_value
mrb_ary_inspect(mrb_state *mrb, mrb_value ary)
{
if (RARRAY_LEN(ary) == 0) return mrb_str_new(mrb, "[]", 2);
- #if 0 /* THREAD */
- return mrb_exec_recursive(inspect_ary_r, ary, 0);
- #else
return inspect_ary(mrb, ary, mrb_ary_new(mrb));
- #endif
}
static mrb_value
join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list)
{
- int i;
+ mrb_int i;
mrb_value result, val, tmp;
/* check recursive */
@@ -1075,31 +1056,39 @@ static mrb_value
mrb_ary_equal(mrb_state *mrb, mrb_value ary1)
{
mrb_value ary2;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &ary2);
- if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value();
- if (mrb_special_const_p(ary2)) return mrb_false_value();
- if (!mrb_array_p(ary2)) {
- if (!mrb_respond_to(mrb, ary2, mrb_intern(mrb, "to_ary"))) {
- return mrb_false_value();
- }
- if (mrb_equal(mrb, ary2, ary1)){
- return mrb_true_value();
+ if (mrb_obj_equal(mrb, ary1, ary2)) {
+ equal_p = 1;
+ }
+ else if (mrb_special_const_p(ary2)) {
+ equal_p = 0;
+ }
+ else if (!mrb_array_p(ary2)) {
+ if (!mrb_respond_to(mrb, ary2, mrb_intern2(mrb, "to_ary", 6))) {
+ equal_p = 0;
}
else {
- return mrb_false_value();
+ equal_p = mrb_equal(mrb, ary2, ary1);
}
}
- if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value();
+ else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) {
+ equal_p = 0;
+ }
else {
- int i;
+ mrb_int i;
+ equal_p = 1;
for (i=0; i<RARRAY_LEN(ary1); i++) {
- if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i)))
- return mrb_false_value();
+ if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) {
+ equal_p = 0;
+ break;
+ }
}
- return mrb_true_value();
}
+
+ return mrb_bool_value(equal_p);
}
/* 15.2.12.5.34 (x) */
@@ -1115,20 +1104,30 @@ static mrb_value
mrb_ary_eql(mrb_state *mrb, mrb_value ary1)
{
mrb_value ary2;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &ary2);
- if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value();
- if (!mrb_array_p(ary2)) return mrb_false_value();
- if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value();
+ if (mrb_obj_equal(mrb, ary1, ary2)) {
+ eql_p = 1;
+ }
+ else if (!mrb_array_p(ary2)) {
+ eql_p = 0;
+ }
+ else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) {
+ eql_p = 0;
+ }
else {
- int i;
-
+ mrb_int i;
+ eql_p = 1;
for (i=0; i<RARRAY_LEN(ary1); i++) {
- if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i)))
- return mrb_false_value();
+ if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) {
+ eql_p = 0;
+ break;
+ }
}
- return mrb_true_value();
}
+
+ return mrb_bool_value(eql_p);
}
void
diff --git a/src/class.c b/src/class.c
index c0e71dad7..9dc7b46d6 100644
--- a/src/class.c
+++ b/src/class.c
@@ -6,14 +6,13 @@
#include "mruby.h"
#include <stdarg.h>
-#include <stdio.h>
#include <ctype.h>
+#include "mruby/array.h"
#include "mruby/class.h"
+#include "mruby/numeric.h"
#include "mruby/proc.h"
#include "mruby/string.h"
-#include "mruby/numeric.h"
#include "mruby/variable.h"
-#include "mruby/array.h"
#include "error.h"
KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal)
@@ -29,7 +28,7 @@ mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
if (kh_exist(h, k)){
struct RProc *m = kh_value(h, k);
if (m) {
- mrb_gc_mark(mrb, (struct RBasic*)m);
+ mrb_gc_mark(mrb, (struct RBasic*)m);
}
}
}
@@ -54,7 +53,7 @@ void
mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
{
mrb_obj_iv_set(mrb, (struct RObject*)c,
- mrb_intern(mrb, "__classid__"), mrb_symbol_value(name));
+ mrb_intern2(mrb, "__classid__", 11), mrb_symbol_value(name));
}
#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))
@@ -88,7 +87,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
o->c = sc;
mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc);
mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o);
- mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern(mrb, "__attached__"), mrb_obj_value(o));
+ mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern2(mrb, "__attached__", 12), mrb_obj_value(o));
}
struct RClass*
@@ -115,7 +114,7 @@ setup_class(mrb_state *mrb, mrb_value outer, struct RClass *c, mrb_sym id)
mrb_name_class(mrb, c, id);
mrb_const_set(mrb, outer, id, mrb_obj_value(c));
mrb_obj_iv_set(mrb, (struct RObject*)c,
- mrb_intern(mrb, "__outer__"), outer);
+ mrb_intern2(mrb, "__outer__", 9), outer);
}
struct RClass*
@@ -123,7 +122,7 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c)
{
mrb_value outer;
- outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__outer__"));
+ outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__outer__", 9));
if (mrb_nil_p(outer)) return 0;
return mrb_class_ptr(outer);
}
@@ -177,11 +176,11 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
c = mrb_class_ptr(v);
if (!mrb_nil_p(super)) {
if (mrb_type(super) != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super));
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", super);
}
if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %s", mrb_sym2name(mrb, id));
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", mrb_sym2str(mrb, id));
}
}
return c;
@@ -189,7 +188,7 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
if (!mrb_nil_p(super)) {
if (mrb_type(super) != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super));
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", super);
}
s = mrb_class_ptr(super);
}
@@ -204,13 +203,19 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
return c;
}
+int
+mrb_class_defined(mrb_state *mrb, const char *name)
+{
+ return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_intern(mrb, name));
+}
+
static struct RClass *
class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
{
mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
if (mrb_type(c) != MRB_TT_MODULE && mrb_type(c) != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "%s is not a class/module", mrb_sym2name(mrb, id));
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_sym2str(mrb, id));
}
return mrb_class_ptr(c);
}
@@ -246,13 +251,13 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s
if (mrb_const_defined_at(mrb, outer, id)) {
c = class_from_sym(mrb, outer, id);
if (mrb_class_real(c->super) != super) {
- mrb_name_error(mrb, id, "%s is already defined", mrb_sym2name(mrb, id));
+ mrb_name_error(mrb, id, "%S is already defined", mrb_sym2str(mrb, id));
}
return c;
}
if (!super) {
- mrb_warn("no super class for `%s::%s', Object assumed",
- mrb_obj_classname(mrb, mrb_obj_value(outer)), mrb_sym2name(mrb, id));
+ mrb_warn("no super class for `%S::%S', Object assumed",
+ mrb_obj_value(outer), mrb_sym2str(mrb, id));
}
c = mrb_class_new(mrb, super);
setup_class(mrb, mrb_obj_value(outer), c, id);
@@ -291,17 +296,19 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro
}
void
-mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, int aspec)
+mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec)
{
struct RProc *p;
+ int ai = mrb_gc_arena_save(mrb);
p = mrb_proc_new_cfunc(mrb, func);
p->target_class = c;
mrb_define_method_raw(mrb, c, mid, p);
+ mrb_gc_arena_restore(mrb, ai);
}
void
-mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec)
+mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
{
mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, aspec);
}
@@ -329,7 +336,7 @@ check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const
tmp = mrb_check_convert_type(mrb, val, t, c, m);
if (mrb_nil_p(tmp)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "expected %s", c);
+ mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_cstr(mrb, c));
}
return tmp;
}
@@ -356,7 +363,7 @@ to_hash(mrb_state *mrb, mrb_value val)
retrieve arguments from mrb_state.
mrb_get_args(mrb, format, ...)
-
+
returns number of arguments parsed.
fortmat specifiers:
@@ -367,7 +374,7 @@ to_hash(mrb_state *mrb, mrb_value val)
H: Hash [mrb_value]
s: String [char*,int]
z: String [char*]
- a: Array [mrb_value*,int]
+ a: Array [mrb_value*,mrb_int]
f: Float [mrb_float]
i: Integer [mrb_int]
b: Binary [int]
@@ -401,6 +408,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (argc <= i && !opt) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
}
+ break;
}
switch (c) {
@@ -489,10 +497,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value aa;
struct RArray *a;
mrb_value **pb;
- int *pl;
+ mrb_int *pl;
pb = va_arg(ap, mrb_value**);
- pl = va_arg(ap, int*);
+ pl = va_arg(ap, mrb_int*);
if (i < argc) {
aa = to_ary(mrb, *sp++);
a = mrb_ary_ptr(aa);
@@ -597,8 +605,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
else {
mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0);
- mrb_raisef(mrb, E_TYPE_ERROR, "%s is not a symbol",
- mrb_string_value_ptr(mrb, obj));
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj);
}
i++;
}
@@ -646,7 +653,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
break;
default:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %c", c);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %S", mrb_str_new(mrb, &c, 1));
break;
}
}
@@ -774,7 +781,7 @@ mrb_mod_include_p(mrb_state *mrb, mrb_value mod)
}
return mrb_false_value();
}
-
+
static mrb_value
mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
{
@@ -902,7 +909,6 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
return mrb_obj_value(mrb->false_class);
case MRB_TT_TRUE:
return mrb_obj_value(mrb->true_class);
- case MRB_TT_MAIN:
case MRB_TT_VOIDP:
return mrb_obj_value(mrb->object_class);
case MRB_TT_SYMBOL:
@@ -913,26 +919,26 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
default:
break;
}
- obj = mrb_object(v);
+ obj = mrb_basic_ptr(v);
prepare_singleton_class(mrb, obj);
return mrb_obj_value(obj->c);
}
void
-mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, int aspec)
+mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, mrb_aspec aspec)
{
prepare_singleton_class(mrb, (struct RBasic*)o);
mrb_define_method_id(mrb, o->c, mrb_intern(mrb, name), func, aspec);
}
void
-mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec)
+mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
{
mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec);
}
void
-mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec)
+mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
{
mrb_define_class_method(mrb, c, name, func, aspec);
mrb_define_method(mrb, c, name, func, aspec);
@@ -973,8 +979,8 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
if (RSTRING_LEN(inspect) > 64) {
inspect = mrb_any_to_s(mrb, mrb_obj_value(c));
}
- mrb_raisef(mrb, E_NAME_ERROR, "undefined method '%s' for class %s",
- mrb_sym2name(mrb, mid), RSTRING_PTR(inspect));
+ mrb_raisef(mrb, E_NAME_ERROR, "undefined method '%S' for class %S",
+ mrb_sym2str(mrb, mid), inspect);
}
return m;
}
@@ -1081,9 +1087,7 @@ mrb_bob_init(mrb_state *mrb, mrb_value cv)
static mrb_value
mrb_bob_not(mrb_state *mrb, mrb_value cv)
{
- if (mrb_test(cv))
- return mrb_false_value();
- return mrb_true_value();
+ return mrb_bool_value(!mrb_test(cv));
}
/* 15.3.1.3.30 */
@@ -1131,13 +1135,18 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod)
mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol");
}
- inspect = mrb_funcall(mrb, mod, "inspect", 0);
- if (RSTRING_LEN(inspect) > 64) {
+ if (mrb_respond_to(mrb,mod,mrb_intern2(mrb,"inspect",7))){
+ inspect = mrb_funcall(mrb, mod, "inspect", 0);
+ if (RSTRING_LEN(inspect) > 64) {
+ inspect = mrb_any_to_s(mrb, mod);
+ }
+ }
+ else {
inspect = mrb_any_to_s(mrb, mod);
}
- mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%s' for %s",
- mrb_sym2name(mrb, mrb_symbol(name)), RSTRING_PTR(inspect));
+ mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S",
+ mrb_sym2str(mrb, mrb_symbol(name)), inspect);
/* not reached */
return mrb_nil_value();
}
@@ -1154,16 +1163,16 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid)
k = kh_get(mt, h, mid);
if (k != kh_end(h)) {
if (kh_value(h, k)) {
- return TRUE; /* method exists */
+ return TRUE; /* method exists */
}
else {
- return FALSE; /* undefined method */
+ return FALSE; /* undefined method */
}
}
}
c = c->super;
}
- return FALSE; /* no method */
+ return FALSE; /* no method */
}
int
@@ -1177,9 +1186,10 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
{
mrb_value path;
const char *name;
- int len;
+ size_t len;
+ mrb_sym classpath = mrb_intern2(mrb, "__classpath__", 13);
- path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"));
+ path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath);
if (mrb_nil_p(path)) {
struct RClass *outer = mrb_class_outer_module(mrb, c);
mrb_sym sym = mrb_class_sym(mrb, c, outer);
@@ -1196,7 +1206,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
name = mrb_sym2name_len(mrb, sym, &len);
path = mrb_str_new(mrb, name, len);
}
- mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"), path);
+ mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path);
}
return path;
}
@@ -1215,10 +1225,9 @@ mrb_class_name(mrb_state *mrb, struct RClass* c)
{
mrb_value path = mrb_class_path(mrb, c);
if (mrb_nil_p(path)) {
- char buf[32];
-
- snprintf(buf, 32, "#<Class:%p>", c);
- path = mrb_str_new_cstr(mrb, buf);
+ path = mrb_str_new(mrb, "#<Class:", 8);
+ mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c));
+ mrb_str_cat(mrb, path, ">", 1);
}
return mrb_str_ptr(path)->ptr;
}
@@ -1239,8 +1248,7 @@ void
mrb_check_inheritable(mrb_state *mrb, struct RClass *super)
{
if (super->tt != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)",
- mrb_obj_classname(mrb, mrb_obj_value(super)));
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", mrb_obj_value(super));
}
if (super->tt == MRB_TT_SCLASS) {
mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of singleton class");
@@ -1337,51 +1345,57 @@ mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const
static mrb_value
mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
{
+ mrb_value str;
+
if (mrb_type(klass) == MRB_TT_SCLASS) {
- mrb_value s = mrb_str_new(mrb, "#<", 2);
- mrb_value v = mrb_iv_get(mrb, klass, mrb_intern(mrb, "__attached__"));
+ mrb_value v = mrb_iv_get(mrb, klass, mrb_intern2(mrb, "__attached__", 12));
+
+ str = mrb_str_new(mrb, "#<Class:", 8);
- mrb_str_cat2(mrb, s, "Class:");
switch (mrb_type(v)) {
case MRB_TT_CLASS:
case MRB_TT_MODULE:
case MRB_TT_SCLASS:
- mrb_str_append(mrb, s, mrb_inspect(mrb, v));
+ mrb_str_append(mrb, str, mrb_inspect(mrb, v));
break;
default:
- mrb_str_append(mrb, s, mrb_any_to_s(mrb, v));
+ mrb_str_append(mrb, str, mrb_any_to_s(mrb, v));
break;
}
- mrb_str_cat2(mrb, s, ">");
-
- return s;
+ mrb_str_cat(mrb, str, ">", 1);
}
else {
- struct RClass *c = mrb_class_ptr(klass);
- const char *cn = mrb_class_name(mrb, c);
+ struct RClass *c;
+ mrb_value path;
- if (!cn) {
- char buf[256];
- int n = 0;
+ str = mrb_str_buf_new(mrb, 32);
+ c = mrb_class_ptr(klass);
+ path = mrb_class_path(mrb, c);
+ if (mrb_nil_p(path)) {
switch (mrb_type(klass)) {
case MRB_TT_CLASS:
- n = snprintf(buf, sizeof(buf), "#<Class:%p>", c);
+ mrb_str_cat(mrb, str, "#<Class:", 8);
break;
case MRB_TT_MODULE:
- n = snprintf(buf, sizeof(buf), "#<Module:%p>", c);
+ mrb_str_cat(mrb, str, "#<Module:", 9);
break;
default:
+ /* Shouldn't be happened? */
+ mrb_str_cat(mrb, str, "#<??????:", 9);
break;
}
- return mrb_str_dup(mrb, mrb_str_new(mrb, buf, n));
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c));
+ mrb_str_cat(mrb, str, ">", 1);
}
else {
- return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, cn));
+ str = path;
}
}
+
+ return str;
}
mrb_value
@@ -1454,11 +1468,11 @@ static void
check_cv_name(mrb_state *mrb, mrb_sym id)
{
const char *s;
- int len;
+ size_t len;
s = mrb_sym2name_len(mrb, id, &len);
if (len < 3 || !(s[0] == '@' && s[1] == '@')) {
- mrb_name_error(mrb, id, "`%s' is not allowed as a class variable name", s);
+ mrb_name_error(mrb, id, "`%S' is not allowed as a class variable name", mrb_sym2str(mrb, id));
}
}
@@ -1481,12 +1495,12 @@ static mrb_value
mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod)
{
mrb_sym id;
+ mrb_bool defined_p;
mrb_get_args(mrb, "n", &id);
check_cv_name(mrb, id);
- if(mrb_cv_defined(mrb, mod, id))
- return mrb_true_value();
- return mrb_false_value();
+ defined_p = mrb_cv_defined(mrb, mod, id);
+ return mrb_bool_value(defined_p);
}
/* 15.2.2.4.17 */
@@ -1580,12 +1594,12 @@ mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod)
if (!mrb_undef_p(val)) return val;
if (mrb_cv_defined(mrb, mod, id)){
- mrb_name_error(mrb, id, "cannot remove %s for %s",
- mrb_sym2name(mrb, id), mrb_class_name(mrb, mrb_class_ptr(mod)));
+ mrb_name_error(mrb, id, "cannot remove %S for %S",
+ mrb_sym2str(mrb, id), mod);
}
- mrb_name_error(mrb, id, "class variable %s not defined for %s",
- mrb_sym2name(mrb, id), mrb_class_name(mrb, mrb_class_ptr(mod)));
+ mrb_name_error(mrb, id, "class variable %S not defined for %S",
+ mrb_sym2str(mrb, id), mod);
/* not reached */
return mrb_nil_value();
@@ -1622,17 +1636,17 @@ static mrb_value
mrb_mod_method_defined(mrb_state *mrb, mrb_value mod)
{
mrb_sym id;
+ mrb_bool method_defined_p;
mrb_get_args(mrb, "n", &id);
- if (mrb_obj_respond_to(mrb_class_ptr(mod), id)) {
- return mrb_true_value();
- }
- return mrb_false_value();
+ method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), id);
+ return mrb_bool_value(method_defined_p);
}
static void
-remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid)
+remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid)
{
+ struct RClass *c = mrb_class_ptr(mod);
khash_t(mt) *h = c->mt;
khiter_t k;
@@ -1644,8 +1658,8 @@ remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid)
}
}
- mrb_name_error(mrb, mid, "method `%s' not defined in %s",
- mrb_sym2name(mrb, mid), mrb_class_name(mrb, c));
+ mrb_name_error(mrb, mid, "method `%S' not defined in %S",
+ mrb_sym2str(mrb, mid), mod);
}
/* 15.2.2.4.41 */
@@ -1660,13 +1674,12 @@ remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid)
mrb_value
mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
{
- struct RClass *c = mrb_class_ptr(mod);
int argc;
mrb_value *argv;
mrb_get_args(mrb, "*", &argv, &argc);
while (argc--) {
- remove_method(mrb, c, mrb_symbol(*argv));
+ remove_method(mrb, mod, mrb_symbol(*argv));
argv++;
}
return mod;
@@ -1676,11 +1689,11 @@ static void
check_const_name(mrb_state *mrb, mrb_sym id)
{
const char *s;
- int len;
+ size_t len;
s = mrb_sym2name_len(mrb, id, &len);
if (len < 1 || !ISUPPER(*s)) {
- mrb_name_error(mrb, id, "wrong constant name %s", s);
+ mrb_name_error(mrb, id, "wrong constant name %S", mrb_sym2str(mrb, id));
}
}
@@ -1688,13 +1701,13 @@ mrb_value
mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
{
mrb_sym id;
+ mrb_bool const_defined_p;
mrb_get_args(mrb, "n", &id);
check_const_name(mrb, id);
- if(mrb_const_defined(mrb, mod, id)) {
- return mrb_true_value();
- }
- return mrb_false_value();
+ const_defined_p = mrb_const_defined(mrb, mod, id);
+
+ return mrb_bool_value(const_defined_p);
}
mrb_value
@@ -1729,7 +1742,7 @@ mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
check_const_name(mrb, id);
val = mrb_iv_remove(mrb, mod, id);
if (mrb_undef_p(val)) {
- mrb_name_error(mrb, id, "constant %s not defined", mrb_sym2name(mrb, id));
+ mrb_name_error(mrb, id, "constant %S not defined", mrb_sym2str(mrb, id));
}
return val;
}
@@ -1738,11 +1751,12 @@ static mrb_value
mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
{
mrb_value obj;
+ mrb_bool eqq;
mrb_get_args(mrb, "o", &obj);
- if (!mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod)))
- return mrb_false_value();
- return mrb_true_value();
+ eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod));
+
+ return mrb_bool_value(eqq);
}
void
@@ -1790,6 +1804,7 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, cls, "new", mrb_instance_new, ARGS_ANY()); /* 15.2.3.3.3 */
mrb_define_method(mrb, cls, "inherited", mrb_bob_init, ARGS_REQ(1));
+ MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined, ARGS_REQ(1)); /* 15.2.2.4.16 */
mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, ARGS_REQ(1)); /* 15.2.2.4.17 */
mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, ARGS_REQ(2)); /* 15.2.2.4.18 */
diff --git a/src/codegen.c b/src/codegen.c
index ff7e87c28..b8909e809 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -4,18 +4,16 @@
** See Copyright Notice in mruby.h
*/
-#define CODEGEN_DUMP
-
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
#include "mruby.h"
-#include "mruby/string.h"
-#include "mruby/irep.h"
#include "mruby/compile.h"
+#include "mruby/irep.h"
#include "mruby/numeric.h"
-#include "opcode.h"
+#include "mruby/string.h"
#include "node.h"
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
+#include "opcode.h"
#include "re.h"
typedef mrb_ast_node node;
@@ -49,7 +47,7 @@ typedef struct scope {
int pc;
int lastlabel;
int ainfo:15;
- int mscope:1;
+ mrb_bool mscope:1;
struct loopinfo *loop;
int ensure_level;
@@ -330,12 +328,23 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
if (c1 == OP_SUB) c = -c;
if (c > 127 || c < -127) break;
- if (0 <= c)
+ if (0 <= c)
s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c);
else
s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
return;
}
+ case OP_STRCAT:
+ if (c0 == OP_STRING) {
+ int i = GETARG_Bx(i0);
+
+ if (mrb_type(s->irep->pool[i]) == MRB_TT_STRING &&
+ RSTRING_LEN(s->irep->pool[i]) == 0) {
+ s->pc--;
+ return;
+ }
+ }
+ break;
default:
break;
}
@@ -368,6 +377,7 @@ dispatch(codegen_scope *s, int pc)
fprintf(stderr, "bug: dispatch on non JMP op\n");
#endif
scope_error(s);
+ break;
}
s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
}
@@ -410,9 +420,27 @@ new_lit(codegen_scope *s, mrb_value val)
{
int i;
- for (i=0; i<s->irep->plen; i++) {
- if (mrb_obj_equal(s->mrb, s->irep->pool[i], val)) return i;
+
+ switch (mrb_type(val)) {
+ case MRB_TT_STRING:
+ for (i=0; i<s->irep->plen; i++) {
+ mrb_value pv = s->irep->pool[i];
+ mrb_int len;
+
+ if (mrb_type(pv) != MRB_TT_STRING) continue;
+ if ((len = RSTRING_LEN(pv)) != RSTRING_LEN(val)) continue;
+ if (memcmp(RSTRING_PTR(pv), RSTRING_PTR(val), len) == 0)
+ return i;
+ }
+ break;
+ case MRB_TT_FLOAT:
+ default:
+ for (i=0; i<s->irep->plen; i++) {
+ if (mrb_obj_equal(s->mrb, s->irep->pool[i], val)) return i;
+ }
+ break;
}
+
if (s->irep->plen == s->pcapa) {
s->pcapa *= 2;
s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
@@ -511,11 +539,11 @@ for_body(codegen_scope *s, node *tree)
// generate loop variable
n2 = tree->car;
if (n2->car && !n2->car->cdr && !n2->cdr) {
- genop(s, MKOP_Ax(OP_ENTER, 1<<18));
+ genop(s, MKOP_Ax(OP_ENTER, 0x40000));
gen_assignment(s, n2->car->car, 1, NOVAL);
}
else {
- genop(s, MKOP_Ax(OP_ENTER, 1<<18));
+ genop(s, MKOP_Ax(OP_ENTER, 0x40000));
gen_vmassignment(s, n2, 1, VAL);
}
codegen(s, tree->cdr->cdr->car, VAL);
@@ -530,7 +558,7 @@ for_body(codegen_scope *s, node *tree)
s = prev;
genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx - base, OP_L_BLOCK));
pop();
- idx = new_msym(s, mrb_intern(s->mrb, "each"));
+ idx = new_msym(s, mrb_intern2(s->mrb, "each", 4));
genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
}
@@ -550,7 +578,8 @@ lambda_body(codegen_scope *s, node *tree, int blk)
}
tree = tree->cdr;
if (tree->car) {
- int ma, oa, ra, pa, ka, kd, ba, a;
+ int32_t a;
+ int ma, oa, ra, pa, ka, kd, ba;
int pos, i;
node *n, *opt;
@@ -565,8 +594,8 @@ lambda_body(codegen_scope *s, node *tree, int blk)
ka = kd = 0;
ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
- a = ((ma & 0x1f) << 18)
- | ((oa & 0x1f) << 13)
+ a = ((int32_t)(ma & 0x1f) << 18)
+ | ((int32_t)(oa & 0x1f) << 13)
| ((ra & 1) << 12)
| ((pa & 0x1f) << 7)
| ((ka & 0x1f) << 2)
@@ -661,7 +690,7 @@ static mrb_sym
attrsym(codegen_scope *s, mrb_sym a)
{
const char *name;
- int len;
+ size_t len;
char *name2;
name = mrb_sym2name_len(s->mrb, a, &len);
@@ -679,7 +708,7 @@ gen_values(codegen_scope *s, node *t, int val)
int n = 0;
while (t) {
- if ((intptr_t)t->car->car == NODE_SPLAT) { // splat mode
+ if (n >= 127 || (intptr_t)t->car->car == NODE_SPLAT) { // splat mode
if (val) {
pop_n(n);
genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
@@ -760,7 +789,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val)
}
pop_n(n+1);
{
- int len;
+ size_t len;
const char *name = mrb_sym2name_len(s->mrb, sym, &len);
if (!noop && len == 1 && name[0] == '+') {
@@ -926,6 +955,68 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
}
static void
+gen_send_intern(codegen_scope *s)
+{
+ pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "intern", 6)), 0));
+ push();
+}
+static void
+gen_literal_array(codegen_scope *s, node *tree, int sym, int val)
+{
+ if (val) {
+ int i = 0, j = 0;
+
+ while (tree) {
+ switch ((intptr_t)tree->car->car) {
+ case NODE_STR:
+ if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0))
+ break;
+ /* fall through */
+ case NODE_BEGIN:
+ codegen(s, tree->car, VAL);
+ ++j;
+ break;
+
+ case NODE_LITERAL_DELIM:
+ if (j > 0) {
+ j = 0;
+ ++i;
+ if (sym)
+ gen_send_intern(s);
+ }
+ break;
+ }
+ if (j >= 2) {
+ pop(); pop();
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ push();
+ j = 1;
+ }
+ tree = tree->cdr;
+ }
+ if (j > 0) {
+ j = 0;
+ ++i;
+ if (sym)
+ gen_send_intern(s);
+ }
+ pop_n(i);
+ genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
+ push();
+ }
+ else {
+ while (tree) {
+ switch ((intptr_t)tree->car->car) {
+ case NODE_BEGIN: case NODE_BLOCK:
+ codegen(s, tree->car, NOVAL);
+ }
+ tree = tree->cdr;
+ }
+ }
+}
+
+static void
raise_error(codegen_scope *s, const char *msg)
{
int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
@@ -1059,12 +1150,12 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n4->car, VAL);
}
else {
- genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern(s->mrb, "StandardError"))));
+ genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern2(s->mrb, "StandardError", 13))));
push();
}
genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1));
tmp = new_label(s);
genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
@@ -1161,7 +1252,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (e) {
if (val) pop();
pos2 = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, 0));
+ genop(s, MKOP_sBx(OP_JMP, 0));
dispatch(s, pos1);
codegen(s, e, val);
dispatch(s, pos2);
@@ -1268,7 +1359,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (head) {
genop(s, MKOP_AB(OP_MOVE, cursp(), head));
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1));
}
else {
pop();
@@ -1462,7 +1553,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_OP_ASGN:
{
mrb_sym sym = sym(tree->cdr->car);
- int len;
+ size_t len;
const char *name = mrb_sym2name_len(s->mrb, sym, &len);
int idx;
@@ -1609,7 +1700,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
pop_n(n+1);
if (sendv) n = CALL_MAXARGS;
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "call")), n));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "call", 4)), n));
if (val) push();
}
break;
@@ -1757,12 +1848,13 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_BACK_REF:
{
- char buf[4];
- int len;
+ char buf[2] = { '$' };
+ mrb_value str;
int sym;
- len = snprintf(buf, sizeof(buf), "$%c", (int)(intptr_t)tree);
- sym = new_sym(s, mrb_intern2(s->mrb, buf, len));
+ buf[1] = (char)(intptr_t)tree;
+ str = mrb_str_new(s->mrb, buf, 2);
+ sym = new_sym(s, mrb_intern_str(s->mrb, str));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
}
@@ -1770,12 +1862,14 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_NTH_REF:
{
- char buf[4];
- int len;
int sym;
+ mrb_state *mrb = s->mrb;
+ mrb_value fix = mrb_fixnum_value((intptr_t)tree);
+ mrb_value str = mrb_str_buf_new(mrb, 4);
- len = snprintf(buf, sizeof(buf), "$%d", (int)(intptr_t)tree);
- sym = new_sym(s, mrb_intern2(s->mrb, buf, len));
+ mrb_str_buf_cat(mrb, str, "$", 1);
+ mrb_str_buf_append(mrb, str, mrb_fixnum_to_str(mrb, fix, 10));
+ sym = new_sym(s, mrb_intern_str(mrb, str));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
}
@@ -1876,7 +1970,7 @@ codegen(codegen_scope *s, node *tree, int val)
default:
{
- int sym = new_msym(s, mrb_intern(s->mrb, "-"));
+ int sym = new_msym(s, mrb_intern2(s->mrb, "-", 1));
genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
push();
@@ -1902,6 +1996,9 @@ codegen(codegen_scope *s, node *tree, int val)
}
break;
+ case NODE_HEREDOC:
+ tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
+ /* fall through */
case NODE_DSTR:
if (val) {
node *n = tree;
@@ -1911,7 +2008,7 @@ codegen(codegen_scope *s, node *tree, int val)
while (n) {
codegen(s, n->car, VAL);
pop(); pop();
- genop(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1));
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
push();
n = n->cdr;
}
@@ -1928,6 +2025,34 @@ codegen(codegen_scope *s, node *tree, int val)
}
break;
+ case NODE_WORDS:
+ gen_literal_array(s, tree, FALSE, val);
+ break;
+
+ case NODE_SYMBOLS:
+ gen_literal_array(s, tree, TRUE, val);
+ break;
+
+ case NODE_XSTR:
+ if (val) {
+ char *p = (char*)tree->car;
+ size_t len = (intptr_t)tree->cdr;
+ int ai = mrb_gc_arena_save(s->mrb);
+ int sym = new_sym(s, mrb_intern2(s->mrb, "Kernel", 6));
+ int off = new_lit(s, mrb_str_new(s->mrb, p, len));
+
+ genop(s, MKOP_A(OP_OCLASS, cursp()));
+ genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ push();
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ pop();
+ sym = new_sym(s, mrb_intern2(s->mrb, "`", 1));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
+ mrb_gc_arena_restore(s->mrb, ai);
+ push();
+ }
+ break;
+
case NODE_REGX:
if (val) {
char *p1 = (char*)tree->car;
@@ -1949,9 +2074,9 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
}
pop();
- sym = new_sym(s, mrb_intern(s->mrb, "compile"));
+ sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7));
genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
- mrb_gc_arena_restore(s->mrb, ai);
+ mrb_gc_arena_restore(s->mrb, ai);
push();
}
break;
@@ -1973,22 +2098,22 @@ codegen(codegen_scope *s, node *tree, int val)
while (n) {
codegen(s, n->car, VAL);
pop(); pop();
- genop(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1));
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
push();
n = n->cdr;
}
n = tree->cdr->cdr;
if (n->car) {
- p = (char*)n->car;
- off = new_lit(s, mrb_str_new(s->mrb, p, strlen(p)));
- codegen(s, tree->car, VAL);
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
- pop();
- genop(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1));
+ p = (char*)n->car;
+ off = new_lit(s, mrb_str_new(s->mrb, p, strlen(p)));
+ codegen(s, tree->car, VAL);
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ pop();
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
}
if (n->cdr) {
- char *p2 = (char*)n->cdr;
- int off;
+ char *p2 = (char*)n->cdr;
+ int off;
push();
off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2)));
@@ -1997,9 +2122,9 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
}
pop();
- sym = new_sym(s, mrb_intern(s->mrb, "compile"));
+ sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7));
genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
- mrb_gc_arena_restore(s->mrb, ai);
+ mrb_gc_arena_restore(s->mrb, ai);
push();
}
else {
@@ -2026,9 +2151,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_DSYM:
codegen(s, tree, val);
if (val) {
- pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "intern")), 0));
- push();
+ gen_send_intern(s);
}
break;
@@ -2064,7 +2187,7 @@ codegen(codegen_scope *s, node *tree, int val)
{
int a = new_msym(s, sym(tree->car));
int b = new_msym(s, sym(tree->cdr));
- int c = new_msym(s, mrb_intern(s->mrb, "alias_method"));
+ int c = new_msym(s, mrb_intern2(s->mrb, "alias_method", 12));
genop(s, MKOP_A(OP_TCLASS, cursp()));
push();
@@ -2083,7 +2206,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_UNDEF:
{
- int undef = new_msym(s, mrb_intern(s->mrb, "undef_method"));
+ int undef = new_msym(s, mrb_intern2(s->mrb, "undef_method", 12));
int num = 0;
node *t = tree;
@@ -2278,7 +2401,7 @@ scope_finish(codegen_scope *s)
irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
irep->ilen = s->pc;
if (s->lines) {
- irep->lines = (short *)codegen_realloc(s, s->lines, sizeof(short)*s->pc);
+ irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
}
else {
irep->lines = 0;
@@ -2370,13 +2493,14 @@ codedump(mrb_state *mrb, int n)
{
#ifdef ENABLE_STDIO
mrb_irep *irep = mrb->irep[n];
- int i;
+ int i, ai;
mrb_code c;
if (!irep) return;
printf("irep %d nregs=%d nlocals=%d pools=%d syms=%d\n", n,
- irep->nregs, irep->nlocals, irep->plen, irep->slen);
+ irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen);
for (i=0; i<irep->ilen; i++) {
+ ai = mrb_gc_arena_save(mrb);
printf("%03d ", i);
c = irep->iseq[i];
switch (GET_OPCODE(c)) {
@@ -2677,6 +2801,7 @@ codedump(mrb_state *mrb, int n)
GETARG_A(c), GETARG_B(c), GETARG_C(c));
break;
}
+ mrb_gc_arena_restore(mrb, ai);
}
printf("\n");
#endif
diff --git a/src/crc.c b/src/crc.c
index 0451c363c..463c7abe6 100644
--- a/src/crc.c
+++ b/src/crc.c
@@ -6,6 +6,8 @@
#include <limits.h>
#include <stdint.h>
+#include <sys/types.h>
+
// Calculate CRC (CRC-16-CCITT)
//
// 0000_0000_0000_0000_0000_0000_0000_0000
@@ -13,13 +15,14 @@
// carry
#define CRC_16_CCITT 0x11021ul //x^16+x^12+x^5+1
#define CRC_XOR_PATTERN (CRC_16_CCITT << 8)
-#define CRC_CARRY_BIT (1 << 24)
+#define CRC_CARRY_BIT (0x01000000)
uint16_t
-calc_crc_16_ccitt(unsigned char *src, int nbytes)
+calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc)
{
- uint32_t crcwk = 0ul;
- int ibyte, ibit;
+ size_t ibyte;
+ uint32_t ibit;
+ uint32_t crcwk = crc << 8;
for (ibyte = 0; ibyte < nbytes; ibyte++) {
crcwk |= *src++;
@@ -32,3 +35,4 @@ calc_crc_16_ccitt(unsigned char *src, int nbytes)
}
return (uint16_t)(crcwk >> 8);
}
+
diff --git a/src/dump.c b/src/dump.c
index ba5a69a56..4714278b0 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -1,5 +1,5 @@
/*
-** dump.c - mruby binary dumper (Rite binary format)
+** dump.c - mruby binary dumper (mrbc binary format)
**
** See Copyright Notice in mruby.h
*/
@@ -12,739 +12,516 @@
#include "mruby/irep.h"
#include "mruby/numeric.h"
-static const unsigned char def_rite_binary_header[] =
- RITE_FILE_IDENFIFIER
- RITE_FILE_FORMAT_VER
- RITE_VM_VER
- RITE_COMPILER_TYPE
- RITE_COMPILER_VER
- "0000" //Binary data size
- "00" //Number of ireps
- "00" //Start index
- RITE_RESERVED
-;
-
-static const unsigned char def_rite_file_header[] =
- RITE_FILE_IDENFIFIER
- RITE_FILE_FORMAT_VER
- RITE_VM_VER
- RITE_COMPILER_TYPE
- RITE_COMPILER_VER
- "00000000" //Binary data size
- "0000" //Number of ireps
- "0000" //Start index
- RITE_RESERVED
- "0000" //CRC
-;
-
-const char bin2hex[] = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-#define DUMP_SIZE(size, type) ((type == DUMP_TYPE_BIN) ? size : size * RITE_FILE_HEX_SIZE)
-
-enum {
- DUMP_IREP_HEADER = 0,
- DUMP_ISEQ_BLOCK,
- DUMP_POOL_BLOCK,
- DUMP_SYMS_BLOCK,
- DUMP_SECTION_NUM,
-};
+static size_t
+get_irep_record_size(mrb_state *mrb, mrb_irep *irep);
-#ifdef ENABLE_STDIO
-
-uint16_t calc_crc_16_ccitt(unsigned char*,int);
-static inline int uint8_dump(uint8_t,char*,int);
-static inline int uint16_dump(uint16_t,char*,int);
-static inline int uint32_dump(uint32_t,char*,int);
-static char* str_dump(char*,char*,uint16_t,int);
-static uint16_t str_dump_len(char*,uint16_t, int);
-static uint32_t get_irep_header_size(mrb_state*,int);
-static uint32_t get_iseq_block_size(mrb_state*,mrb_irep*,int);
-static uint32_t get_pool_block_size(mrb_state*,mrb_irep*,int);
-static uint32_t get_syms_block_size(mrb_state*,mrb_irep*,int);
-static uint32_t get_irep_record_size(mrb_state*,int,int);
-static int write_irep_header(mrb_state*,mrb_irep*,char*,int);
-static int write_iseq_block(mrb_state*,mrb_irep*,char*,int);
-static int write_pool_block(mrb_state*,mrb_irep*,char*,int);
-static int write_syms_block(mrb_state*,mrb_irep*,char*,int);
-static int calc_crc_section(mrb_state*,mrb_irep*,uint16_t*,int);
-static int write_rite_header(mrb_state*,int,char*,uint32_t);
-static int dump_rite_header(mrb_state*,int,FILE*,uint32_t);
-static int write_irep_record(mrb_state*,int,char*,uint32_t*,int);
-static int dump_irep_record(mrb_state*,int,FILE*,uint32_t*);
-static int mrb_write_irep(mrb_state*,int,char*);
-
-
-static inline int
-uint8_dump(uint8_t bin, char *hex, int type)
-{
- if (type == DUMP_TYPE_BIN) {
- *hex = bin;
- } else {
- *hex++ = bin2hex[(bin >> 4) & 0x0f];
- *hex = bin2hex[bin & 0x0f];
- }
- return DUMP_SIZE(MRB_DUMP_SIZE_OF_CHAR, type);
-}
-
-static inline int
-uint16_dump(uint16_t bin, char *hex, int type)
-{
- if (type == DUMP_TYPE_BIN) {
- return (uint16_to_bin(bin, hex));
- } else {
- *hex++ = bin2hex[(bin >> 12)& 0x0f];
- *hex++ = bin2hex[(bin >> 8) & 0x0f];
- *hex++ = bin2hex[(bin >> 4) & 0x0f];
- *hex = bin2hex[bin & 0x0f];
- return DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type);
- }
-}
-
-static inline int
-uint32_dump(uint32_t bin, char *hex, int type)
+static uint32_t
+get_irep_header_size(mrb_state *mrb)
{
- if (type == DUMP_TYPE_BIN) {
- return (uint32_to_bin(bin, hex));
- } else {
- *hex++ = bin2hex[(bin >> 28) & 0x0f];
- *hex++ = bin2hex[(bin >> 24) & 0x0f];
- *hex++ = bin2hex[(bin >> 20) & 0x0f];
- *hex++ = bin2hex[(bin >> 16) & 0x0f];
- *hex++ = bin2hex[(bin >> 12) & 0x0f];
- *hex++ = bin2hex[(bin >> 8) & 0x0f];
- *hex++ = bin2hex[(bin >> 4) & 0x0f];
- *hex = bin2hex[bin & 0x0f];
- return DUMP_SIZE(MRB_DUMP_SIZE_OF_LONG, type);
- }
-}
-
-#define CHAR_ESC_LEN 13 /* sizeof(\x{ hex of 32bit unsigned int } \0) */
+ uint32_t size = 0;
-static char*
-str_dump(char *str, char *hex, uint16_t len, int type)
-{
- if (type == DUMP_TYPE_BIN)
- memcpy(hex, str, len);
- else {
- char *src, *dst, buf[CHAR_ESC_LEN + 1];
- int n;
-
- for (src = str, dst = hex; len > 0; src++, dst++, len--) {
- switch (*src) {
- case 0x07:/* BEL */ *dst++ = '\\'; *dst = 'a'; break;
- case 0x08:/* BS */ *dst++ = '\\'; *dst = 'b'; break;
- case 0x09:/* HT */ *dst++ = '\\'; *dst = 't'; break;
- case 0x0A:/* LF */ *dst++ = '\\'; *dst = 'n'; break;
- case 0x0B:/* VT */ *dst++ = '\\'; *dst = 'v'; break;
- case 0x0C:/* FF */ *dst++ = '\\'; *dst = 'f'; break;
- case 0x0D:/* CR */ *dst++ = '\\'; *dst = 'r'; break;
- case 0x5C:/* \ */ *dst++ = '\\'; *dst = '\\'; break;
- case 0x22:/* " */ /* fall through */
- case 0x27:/* ' */ /* fall through */
- // case 0x3F:/* ? */ /* fall through */
- default:
- if (*src >= ' ' && *src <= '~') {
- *dst = *src;
- } else {
- n = sprintf(buf, "\\%03o", *src & 0377);
- memcpy(dst, buf, n);
- dst += (n-1);
- }
- break;
- }
- }
- }
+ size += sizeof(uint32_t) * 1;
+ size += sizeof(uint16_t) * 2;
- return hex;
+ return size;
}
-static uint16_t
-str_dump_len(char *str, uint16_t len, int type)
+static size_t
+write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
{
- uint16_t dump_len = 0;
+ uint8_t *cur = buf;
- if (type == DUMP_TYPE_BIN)
- dump_len = len;
- else {
- char *src;
-
- for (src = str; len > 0; src++, len--) {
- switch (*src) {
- case 0x07:/* BEL */ /* fall through */
- case 0x08:/* BS */ /* fall through */
- case 0x09:/* HT */ /* fall through */
- case 0x0A:/* LF */ /* fall through */
- case 0x0B:/* VT */ /* fall through */
- case 0x0C:/* FF */ /* fall through */
- case 0x0D:/* CR */ /* fall through */
- case 0x5C:/* \ */ /* fall through */
- dump_len += 2;
- break;
-
- case 0x22:/* " */ /* fall through */
- case 0x27:/* ' */ /* fall through */
- // case 0x3F:/* ? */ /* fall through */
- default:
- if (*src >= ' ' && *src <= '~') {
- dump_len++;
- } else {
- dump_len += 4; /* octet "\\nnn" */
- }
- break;
- }
- }
- }
+ cur += uint32_to_bin(get_irep_record_size(mrb, irep), cur); /* record size */
+ cur += uint16_to_bin((uint16_t)irep->nlocals, cur); /* number of local variable */
+ cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */
- return dump_len;
+ return (cur - buf);
}
+
static uint32_t
-get_irep_header_size(mrb_state *mrb, int type)
+get_iseq_block_size(mrb_state *mrb, mrb_irep *irep)
{
uint32_t size = 0;
-
- size += 2;
- size += DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type) * 4;
-
+ size += sizeof(uint32_t); /* ilen */
+ size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */
return size;
}
-static uint32_t
-get_iseq_block_size(mrb_state *mrb, mrb_irep *irep, int type)
+static int
+write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
{
- uint32_t size = 0;
+ uint8_t *cur = buf;
+ size_t iseq_no;
- size += MRB_DUMP_SIZE_OF_LONG; /* ilen */
- size += irep->ilen * MRB_DUMP_SIZE_OF_LONG; /* iseq(n) */
- size += MRB_DUMP_SIZE_OF_SHORT; /* crc */
+ cur += uint32_to_bin(irep->ilen, cur); /* number of opcode */
+ for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
+ cur += uint32_to_bin(irep->iseq[iseq_no], cur); /* opcode */
+ }
- return DUMP_SIZE(size, type);
+ return (cur - buf);
}
-static uint32_t
-get_pool_block_size(mrb_state *mrb, mrb_irep *irep, int type)
+
+static size_t
+get_pool_block_size(mrb_state *mrb, mrb_irep *irep)
{
- uint32_t size = 0;
- int pool_no;
+ size_t size = 0;
+ size_t pool_no;
+ int len;
mrb_value str;
char buf[32];
- size += MRB_DUMP_SIZE_OF_LONG; /* plen */
- size += irep->plen; /* tt(n) */
- size += irep->plen * MRB_DUMP_SIZE_OF_SHORT; /* len(n) */
- size += MRB_DUMP_SIZE_OF_SHORT; /* crc */
- size = DUMP_SIZE(size, type);
+ size += sizeof(uint32_t); /* plen */
+ size += irep->plen * (sizeof(uint8_t) + sizeof(uint16_t)); /* len(n) */
for (pool_no = 0; pool_no < irep->plen; pool_no++) {
- uint16_t nlen =0;
- int len;
+ int ai = mrb_gc_arena_save(mrb);
switch (mrb_type(irep->pool[pool_no])) {
case MRB_TT_FIXNUM:
- str = mrb_fix2str(mrb, irep->pool[pool_no], 10);
- size += (uint32_t)RSTRING_LEN(str);
+ str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10);
+ size += RSTRING_LEN(str);
break;
+
case MRB_TT_FLOAT:
- len = mrb_float_to_str( buf, mrb_float(irep->pool[pool_no]));
- size += (uint32_t)len;
+ len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no]));
+ size += len;
break;
+
case MRB_TT_STRING:
- str = mrb_string_value( mrb, &irep->pool[pool_no]);
- nlen = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type);
- size += nlen;
+ str = mrb_str_to_str(mrb, irep->pool[pool_no]);
+ size += RSTRING_LEN(str);
break;
+
default:
break;
}
- }
-
- return size;
-}
-
-static uint32_t
-get_syms_block_size(mrb_state *mrb, mrb_irep *irep, int type)
-{
- uint32_t size = 0;
- int sym_no;
-
- size += MRB_DUMP_SIZE_OF_LONG; /* slen */
- size += MRB_DUMP_SIZE_OF_SHORT; /* crc */
- size = DUMP_SIZE(size, type);
-
- for (sym_no = 0; sym_no < irep->slen; sym_no++) {
- const char * name;
- uint16_t nlen =0;
- size += DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type); /* snl(n) */
- if (irep->syms[sym_no] != 0) {
- int len;
-
- name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
- nlen = str_dump_len((char*)name, len, type);
- size += nlen; /* sn(n) */
- }
+ mrb_gc_arena_restore(mrb, ai);
}
return size;
}
-static uint32_t
-get_irep_record_size(mrb_state *mrb, int irep_no, int type)
-{
- uint32_t size = 0;
- mrb_irep *irep = mrb->irep[irep_no];
-
- size += DUMP_SIZE(MRB_DUMP_SIZE_OF_LONG, type); /* rlen */
- size += get_irep_header_size(mrb, type);
- size += get_iseq_block_size(mrb, irep, type);
- size += get_pool_block_size(mrb, irep, type);
- size += get_syms_block_size(mrb, irep, type);
-
- return size;
-}
-
-static int
-write_irep_header(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
-{
- char *buf_top = buf;
-
- *buf++ = RITE_IREP_IDENFIFIER; /* record identifier */
- *buf++ = RITE_IREP_TYPE_CLASS; /* class or module */
- buf += uint16_dump((uint16_t)irep->nlocals, buf, type); /* number of local variable */
- buf += uint16_dump((uint16_t)irep->nregs, buf, type); /* number of register variable */
- buf += uint16_dump(DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type)/* crc */, buf, type); /* offset of isec block */
-
- return (int)(buf - buf_top);
-}
-
-static int
-write_iseq_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
-{
- char *buf_top = buf;
- int iseq_no;
-
- buf += uint32_dump((uint32_t)irep->ilen, buf, type); /* number of opcode */
-
- for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
- buf += uint32_dump((uint32_t)irep->iseq[iseq_no], buf, type); /* opcode */
- }
-
- return (int)(buf - buf_top);
-}
-
static int
-write_pool_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
+write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
{
- int pool_no;
+ size_t pool_no;
+ uint8_t *cur = buf;
+ size_t len;
mrb_value str;
- char *buf_top = buf;
- char *char_buf;
- uint16_t buf_size =0;
- uint16_t len =0;
- int result;
-
- buf_size = MRB_DUMP_DEFAULT_STR_LEN;
- char_buf = (char *)mrb_malloc(mrb, buf_size);
- if (char_buf == NULL) {
- result = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
+ const char *char_ptr;
+ char char_buf[30];
- buf += uint32_dump((uint32_t)irep->plen, buf, type); /* number of pool */
+ cur += uint32_to_bin(irep->plen, cur); /* number of pool */
for (pool_no = 0; pool_no < irep->plen; pool_no++) {
- buf += uint8_dump(mrb_type(irep->pool[pool_no]), buf, type); /* data type */
- memset(char_buf, 0, buf_size);
+ int ai = mrb_gc_arena_save(mrb);
+
+ cur += uint8_to_bin(mrb_type(irep->pool[pool_no]), cur); /* data type */
switch (mrb_type(irep->pool[pool_no])) {
case MRB_TT_FIXNUM:
- str = mrb_fix2str(mrb, irep->pool[pool_no], 10);
- memcpy(char_buf, RSTRING_PTR(str), RSTRING_LEN(str));
+ str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10);
+ char_ptr = RSTRING_PTR(str);
len = RSTRING_LEN(str);
break;
case MRB_TT_FLOAT:
len = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no]));
+ char_ptr = &char_buf[0];
break;
case MRB_TT_STRING:
str = irep->pool[pool_no];
- len = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type);
- if (len > buf_size - 1) {
- buf_size = len + 1;
- char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size);
- if (char_buf == NULL) {
- result = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
- memset(char_buf, 0, buf_size);
- }
- str_dump(RSTRING_PTR(str), char_buf, RSTRING_LEN(str), type);
+ char_ptr = RSTRING_PTR(str);
+ len = RSTRING_LEN(str);
break;
default:
- buf += uint16_dump(0, buf, type); /* data length = 0 */
continue;
}
- buf += uint16_dump(len, buf, type); /* data length */
+ cur += uint16_to_bin(len, cur); /* data length */
+ memcpy(cur, char_ptr, len);
+ cur += len;
- memcpy(buf, char_buf, len);
- buf += len;
+ mrb_gc_arena_restore(mrb, ai);
}
- result = (int)(buf - buf_top);
-error_exit:
- mrb_free(mrb, char_buf);
- return result;
+ return (int)(cur - buf);
+}
+
+
+static size_t
+get_syms_block_size(mrb_state *mrb, mrb_irep *irep)
+{
+ size_t size = 0;
+ size_t sym_no;
+ size_t len;
+
+ size += sizeof(uint32_t); /* slen */
+ for (sym_no = 0; sym_no < irep->slen; sym_no++) {
+ size += sizeof(uint16_t); /* snl(n) */
+ if (irep->syms[sym_no] != 0) {
+ mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
+ size += len + 1; /* sn(n) + null char */
+ }
+ }
+
+ return size;
}
static int
-write_syms_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
+write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
{
- int sym_no;
- char *buf_top = buf;
- char *char_buf;
- uint16_t buf_size =0;
-
- buf_size = MRB_DUMP_DEFAULT_STR_LEN;
- char_buf = (char *)mrb_malloc(mrb, buf_size);
- if (char_buf == NULL)
- goto error_exit;
+ size_t sym_no;
+ uint8_t *cur = buf;
+ const char *name;
- buf += uint32_dump((uint32_t)irep->slen, buf, type); /* number of symbol */
+ cur += uint32_to_bin(irep->slen, cur); /* number of symbol */
for (sym_no = 0; sym_no < irep->slen; sym_no++) {
- const char * name;
- uint16_t nlen =0;
-
if (irep->syms[sym_no] != 0) {
- int len;
+ size_t len;
name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
- nlen = str_dump_len((char*)name, len, type);
- if ( nlen > buf_size - 1) {
- buf_size = nlen + 1;
- char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size);
- if (char_buf == NULL)
- goto error_exit;
+ if (len > UINT16_MAX) {
+ return MRB_DUMP_GENERAL_FAILURE;
}
- memset(char_buf, 0, buf_size);
- str_dump((char*)name, char_buf, len, type);
- buf += uint16_dump(nlen, buf, type); /* length of symbol name */
- memcpy(buf, char_buf, nlen); /* symbol name */
- buf += nlen;
+ cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */
+ memcpy(cur, name, len); /* symbol name */
+ cur += (uint16_t)len;
+ *cur++ = '\0';
}
else {
- buf += uint16_dump(MRB_DUMP_NULL_SYM_LEN, buf, type); /* length of symbol name */
+ cur += uint16_to_bin(MRB_DUMP_NULL_SYM_LEN, cur); /* length of symbol name */
}
}
-error_exit:
- mrb_free(mrb, char_buf);
- return (int)(buf - buf_top);
+ return (int)(cur - buf);
}
-static int
-calc_crc_section(mrb_state *mrb, mrb_irep *irep, uint16_t *crc, int section)
+
+
+static size_t
+get_irep_record_size(mrb_state *mrb, mrb_irep *irep)
{
- char *buf, *buf_top;
- uint32_t buf_size;
- int type = DUMP_TYPE_BIN;
- int result;
+ uint32_t size = 0;
- switch (section) {
- case DUMP_IREP_HEADER: buf_size = get_irep_header_size(mrb, type); break;
- case DUMP_ISEQ_BLOCK: buf_size = get_iseq_block_size(mrb, irep, type); break;
- case DUMP_POOL_BLOCK: buf_size = get_pool_block_size(mrb, irep, type); break;
- case DUMP_SYMS_BLOCK: buf_size = get_syms_block_size(mrb, irep, type); break;
- default: return MRB_DUMP_GENERAL_FAILURE;
- }
+ //size += sizeof(uint16_t); /* rlen */
+ size += get_irep_header_size(mrb);
+ size += get_iseq_block_size(mrb, irep);
+ size += get_pool_block_size(mrb, irep);
+ size += get_syms_block_size(mrb, irep);
- buf = (char *)mrb_calloc(mrb, 1, buf_size);
- if (buf == NULL)
- return MRB_DUMP_GENERAL_FAILURE;
+ return size;
+}
- buf_top = buf;
-
- switch (section) {
- case DUMP_IREP_HEADER:
- result = write_irep_header(mrb, irep, buf, type);
- break;
- case DUMP_ISEQ_BLOCK:
- result = write_iseq_block(mrb, irep, buf, type);
- break;
- case DUMP_POOL_BLOCK:
- result = write_pool_block(mrb, irep, buf, type);
- break;
- case DUMP_SYMS_BLOCK:
- result = write_syms_block(mrb, irep, buf, type);
- break;
- default:
- result = MRB_DUMP_GENERAL_FAILURE;
- break; /* Already checked above. */
+static int
+write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, uint32_t *irep_record_size)
+{
+ if (irep == NULL) {
+ return MRB_DUMP_INVALID_IREP;
}
- if (result < 0) {
- goto error_exit;
+
+ *irep_record_size = get_irep_record_size(mrb, irep);
+ if (*irep_record_size == 0) {
+ return MRB_DUMP_GENERAL_FAILURE;
}
- buf += result;
- *crc = calc_crc_16_ccitt((unsigned char*)buf_top, (int)(buf - buf_top));
+ memset(bin, 0, *irep_record_size);
- mrb_free(mrb, buf_top);
+ //bin += uint16_to_bin(*irep_record_size, bin);
+ bin += write_irep_header(mrb, irep, bin);
+ bin += write_iseq_block(mrb, irep, bin);
+ bin += write_pool_block(mrb, irep, bin);
+ bin += write_syms_block(mrb, irep, bin);
- result = MRB_DUMP_OK;
- error_exit:
- return result;
+ return MRB_DUMP_OK;
}
-static uint16_t
-calc_rite_header_crc(mrb_state *mrb, int top, rite_binary_header *binary_header, uint32_t rbds, int type)
+static size_t
+mrb_write_eof(mrb_state *mrb, uint8_t *bin)
{
- memcpy( binary_header, def_rite_binary_header, sizeof(*binary_header));
+ struct rite_binary_footer footer;
- uint32_dump(rbds, (char*)binary_header->rbds, type);
- uint16_dump((uint16_t)mrb->irep_len, (char*)binary_header->nirep, type);
- uint16_dump((uint16_t)top, (char*)binary_header->sirep, type);
+ memcpy(footer.section_identify, RITE_BINARY_EOF, sizeof(footer.section_identify));
+ uint32_to_bin(sizeof(struct rite_binary_footer), footer.section_size);
+ memcpy(bin, &footer, sizeof(struct rite_binary_footer));
- return calc_crc_16_ccitt((unsigned char*)binary_header, sizeof(*binary_header));
+ return sizeof(struct rite_binary_footer);
}
+
static int
-write_rite_header(mrb_state *mrb, int top, char* bin, uint32_t rbds)
-{
- rite_binary_header *binary_header;
- uint16_t crc;
- int type = DUMP_TYPE_BIN;
+mrb_write_section_irep_header(mrb_state *mrb, uint32_t section_size, uint16_t nirep, uint16_t sirep, uint8_t *bin)
+{
+ struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin;
- binary_header = (rite_binary_header*)bin;
- crc = calc_rite_header_crc(mrb, top, binary_header, rbds, type);
- bin += sizeof(*binary_header);
- uint16_dump(crc, bin, type);
+ memcpy(header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(header->section_identify));
+ uint32_to_bin(section_size, header->section_size);
+ memcpy(header->rite_version, RITE_VM_VER, sizeof(header->rite_version));
+ uint16_to_bin(nirep, header->nirep);
+ uint16_to_bin(sirep, header->sirep);
return MRB_DUMP_OK;
}
static int
-calc_rite_file_header(mrb_state *mrb, int top, uint32_t rbds, rite_file_header *file_header)
+mrb_write_section_irep(mrb_state *mrb, size_t start_index, uint8_t *bin)
{
- rite_binary_header *binary_header, b_header;
- uint16_t crc;
- int type;
+ int result;
+ size_t irep_no;
+ uint32_t section_size = 0, rlen = 0; /* size of irep record */
+ uint8_t *cur = bin;
+
+ if (mrb == NULL || start_index >= mrb->irep_len || bin == NULL) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
- /* calc crc */
- type = DUMP_TYPE_BIN;
- binary_header = &b_header;
- crc = calc_rite_header_crc(mrb, top, binary_header, rbds, type);
+ cur += sizeof(struct rite_section_irep_header);
+ section_size += sizeof(struct rite_section_irep_header);
- /* dump rbc header */
- memcpy( file_header, def_rite_file_header, sizeof(*file_header));
+ for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) {
+ result = write_irep_record(mrb, mrb->irep[irep_no], cur, &rlen);
+ if (result != MRB_DUMP_OK) {
+ return result;
+ }
+ cur += rlen;
+ section_size += rlen;
+ }
- type = DUMP_TYPE_HEX;
- uint32_dump(rbds, (char*)file_header->rbds, type);
- uint16_dump((uint16_t)mrb->irep_len, (char*)file_header->nirep, type);
- uint16_dump((uint16_t)top, (char*)file_header->sirep, type);
- uint16_dump(crc, (char*)file_header->hcrc, type);
+ mrb_write_section_irep_header(mrb, section_size, mrb->irep_len - start_index, start_index, bin);
return MRB_DUMP_OK;
}
static int
-dump_rite_header(mrb_state *mrb, int top, FILE* fp, uint32_t rbds)
-{
- int rc = MRB_DUMP_OK;
- rite_file_header file_header;
-
- if (fseek(fp, 0, SEEK_SET) != 0)
- return MRB_DUMP_GENERAL_FAILURE;
-
- rc = calc_rite_file_header(mrb, top, rbds, &file_header);
- if (rc != MRB_DUMP_OK)
- return rc;
+mrb_write_section_lineno_header(mrb_state *mrb, uint32_t section_size, uint16_t nirep, uint16_t sirep, uint8_t *bin)
+{
+ struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin;
- if (fwrite(&file_header, sizeof(file_header), 1, fp) != 1)
- return MRB_DUMP_WRITE_FAULT;
+ // TODO
+ memcpy(header->section_identify, RITE_SECTION_LIENO_IDENTIFIER, sizeof(header->section_identify));
+ uint32_to_bin(section_size, header->section_size);
+ uint16_to_bin(nirep, header->nirep);
+ uint16_to_bin(sirep, header->sirep);
return MRB_DUMP_OK;
}
-static int
-write_irep_record(mrb_state *mrb, int irep_no, char* bin, uint32_t *rlen, int type)
+static size_t
+get_debug_record_size(mrb_state *mrb, mrb_irep *irep)
{
- uint32_t irep_record_size;
- mrb_irep *irep = mrb->irep[irep_no];
- int section;
+ size_t size = 0;
- if (irep == NULL)
- return MRB_DUMP_INVALID_IREP;
+ size += sizeof(uint32_t); // record size
+ size += sizeof(uint16_t); // filename size
+ if(irep->filename) {
+ size += strlen(irep->filename); // filename
+ }
+ size += sizeof(uint32_t); // niseq
+ if(irep->lines) {
+ size += sizeof(uint16_t) * irep->ilen; // lineno
+ }
- /* buf alloc */
- irep_record_size = get_irep_record_size(mrb, irep_no, type);
- if (irep_record_size == 0)
- return MRB_DUMP_GENERAL_FAILURE;
+ return size;
+}
- memset( bin, 0, irep_record_size);
+static int
+write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin)
+{
+ uint8_t *cur = bin;
+ size_t filename_len = 0;
+ int iseq_no;
- /* rlen */
- *rlen = irep_record_size - DUMP_SIZE(MRB_DUMP_SIZE_OF_LONG, type);
+ cur += sizeof(uint32_t); /* record size */
- bin += uint32_dump(*rlen, bin, type);
+ if(irep->filename) {
+ filename_len = strlen(irep->filename);
+ }
+ cur += uint16_to_bin(filename_len, cur); /* filename size */
- for (section = 0; section < DUMP_SECTION_NUM; section++) {
- int rc;
- uint16_t crc;
+ if(filename_len) {
+ memcpy(cur, irep->filename, filename_len);
+ cur += filename_len; /* filename */
+ }
- switch (section) {
- case DUMP_IREP_HEADER: bin += write_irep_header(mrb, irep, bin, type); break;
- case DUMP_ISEQ_BLOCK: bin += write_iseq_block(mrb, irep, bin, type); break;
- case DUMP_POOL_BLOCK: bin += write_pool_block(mrb, irep, bin, type); break;
- case DUMP_SYMS_BLOCK: bin += write_syms_block(mrb, irep, bin, type); break;
- default: break;
+ if(irep->lines) {
+ cur += uint32_to_bin(irep->ilen, cur); /* niseq */
+ for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
+ cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */
}
-
- rc = calc_crc_section(mrb, irep, &crc, section);
- if (rc != MRB_DUMP_OK)
- return rc;
-
- bin += uint16_dump(crc, bin, type); /* crc */
+ }
+ else {
+ cur += uint32_to_bin(0, cur); /* niseq */
}
- return MRB_DUMP_OK;
+ uint32_to_bin(cur - bin, bin); /* record size */
+
+ return (cur - bin);
}
static int
-dump_irep_record(mrb_state *mrb, int irep_no, FILE* fp, uint32_t *rlen)
+mrb_write_section_lineno(mrb_state *mrb, int start_index, uint8_t *bin)
{
- int rc = MRB_DUMP_OK;
- uint32_t irep_record_size;
- char *buf;
- mrb_irep *irep = mrb->irep[irep_no];
-
- if (irep == NULL)
- return MRB_DUMP_INVALID_IREP;
+ int irep_no;
+ uint32_t section_size = 0, rlen = 0; /* size of irep record */
+ uint8_t *cur = bin;
- /* buf alloc */
- irep_record_size = get_irep_record_size(mrb, irep_no, DUMP_TYPE_HEX);
- if (irep_record_size == 0)
- return MRB_DUMP_GENERAL_FAILURE;
+ if (mrb == NULL || start_index < 0 || start_index >= mrb->irep_len || bin == NULL) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
- buf = (char *)mrb_calloc(mrb, 1, irep_record_size);
- if (buf == NULL)
- return MRB_DUMP_GENERAL_FAILURE;
+ cur += sizeof(struct rite_section_lineno_header);
+ section_size += sizeof(struct rite_section_lineno_header);
- rc = write_irep_record(mrb, irep_no, buf, rlen, DUMP_TYPE_HEX);
- if (rc != MRB_DUMP_OK) {
- rc = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
+ for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) {
+ rlen = write_lineno_record(mrb, mrb->irep[irep_no], cur);
+ cur += rlen;
+ section_size += rlen;
}
+ mrb_write_section_lineno_header(mrb, section_size, mrb->irep_len - start_index, start_index, bin);
- if (fwrite(buf, irep_record_size, 1, fp) != 1)
- rc = MRB_DUMP_WRITE_FAULT;
+ return MRB_DUMP_OK;
+}
-error_exit:
- mrb_free(mrb, buf);
+static int
+write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t* bin)
+{
+ struct rite_binary_header *header = (struct rite_binary_header*)bin;
+ uint16_t crc;
+ size_t offset;
+
+ memcpy(header->binary_identify, RITE_BINARY_IDENFIFIER, sizeof(header->binary_identify));
+ memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version));
+ memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name));
+ memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version));
+ uint32_to_bin(binary_size, header->binary_size);
+
+ offset = (&(header->binary_crc[0]) - bin) + sizeof(uint16_t);
+ crc = calc_crc_16_ccitt(bin + offset, binary_size - offset, 0);
+ uint16_to_bin(crc, header->binary_crc);
- return rc;
+ return MRB_DUMP_OK;
}
static int
-mrb_write_irep(mrb_state *mrb, int top, char *bin)
+mrb_dump_irep(mrb_state *mrb, size_t start_index, int debug_info, uint8_t **bin, size_t *bin_size)
{
- int rc;
- uint32_t rlen=0; /* size of irep record */
- int irep_no;
- char *bin_top;
+ int result = MRB_DUMP_GENERAL_FAILURE;
+ size_t section_size = 0;
+ size_t section_irep_size;
+ size_t section_lineno_size = 0;
+ size_t irep_no;
+ uint8_t *cur = NULL;
+
+ if (mrb == NULL || start_index >= mrb->irep_len) {
+ *bin = NULL;
+ return MRB_DUMP_GENERAL_FAILURE;
+ }
- if (mrb == NULL || top < 0 || top >= mrb->irep_len || bin == NULL)
- return MRB_DUMP_INVALID_ARGUMENT;
+ section_irep_size = sizeof(struct rite_section_irep_header);
+ for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) {
+ section_irep_size += get_irep_record_size(mrb, mrb->irep[irep_no]);
+ }
+ section_size += section_irep_size;
- bin_top = bin;
- bin += sizeof(rite_binary_header) + MRB_DUMP_SIZE_OF_SHORT/* crc */;
+ /* DEBUG section size */
+ if(debug_info) {
+ section_lineno_size += sizeof(struct rite_section_lineno_header);
+ for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) {
+ section_lineno_size += get_debug_record_size(mrb, mrb->irep[irep_no]);
+ }
+ section_size += section_lineno_size;
+ }
+
+ *bin_size += sizeof(struct rite_binary_header) + section_size + sizeof(struct rite_binary_footer);
+ cur = *bin = (uint8_t *)mrb_malloc(mrb, *bin_size);
+ if(cur == NULL) {
+ goto error_exit;
+ }
- for (irep_no=top; irep_no<mrb->irep_len; irep_no++) {
- rc = write_irep_record(mrb, irep_no, bin, &rlen, DUMP_TYPE_BIN);
- if (rc != MRB_DUMP_OK)
- return rc;
+ cur += sizeof(struct rite_binary_header);
- bin += (rlen + DUMP_SIZE(MRB_DUMP_SIZE_OF_LONG, DUMP_TYPE_BIN));
+ result = mrb_write_section_irep(mrb, start_index, cur);
+ if (result != MRB_DUMP_OK) {
+ goto error_exit;
+ }
+
+ cur += section_irep_size;
+
+ /* write DEBUG section */
+ if(debug_info) {
+ result = mrb_write_section_lineno(mrb, start_index, cur);
+ if (result != MRB_DUMP_OK) {
+ goto error_exit;
+ }
+ cur += section_lineno_size;
}
- bin += uint32_dump(0, bin, DUMP_TYPE_BIN); /* end of file */
+ mrb_write_eof(mrb, cur);
- rc = write_rite_header(mrb, top, bin_top, (bin - bin_top)); //TODO: Remove top(SIREP)
+ result = write_rite_binary_header(mrb, *bin_size, *bin);
- return rc;
+error_exit:
+ if (result != MRB_DUMP_OK) {
+ mrb_free(mrb, *bin);
+ *bin = NULL;
+ }
+ return result;
}
+
+#ifdef ENABLE_STDIO
+
int
-mrb_dump_irep(mrb_state *mrb, int top, FILE* fp)
+mrb_dump_irep_binary(mrb_state *mrb, size_t start_index, int debug_info, FILE* fp)
{
- int rc;
- uint32_t rbds=0; /* size of Rite Binary Data */
- uint32_t rlen=0; /* size of irep record */
- int irep_no;
+ uint8_t *bin = NULL;
+ size_t bin_size = 0;
+ int result;
- if (mrb == NULL || top < 0 || top >= mrb->irep_len || fp == NULL)
+ if (fp == NULL) {
return MRB_DUMP_INVALID_ARGUMENT;
-
- if (fwrite(&def_rite_file_header, sizeof(rite_file_header), 1, fp) != 1) /* dummy write */
- return MRB_DUMP_WRITE_FAULT;
-
- for (irep_no=top; irep_no<mrb->irep_len; irep_no++) {
- rc = dump_irep_record(mrb, irep_no, fp, &rlen);
- if (rc != MRB_DUMP_OK)
- return rc;
-
- rbds += rlen;
}
- if (fwrite("00000000"/* end of file */, 8, 1, fp) != 1)
- return MRB_DUMP_WRITE_FAULT;
-
- rc = dump_rite_header(mrb, top, fp, rbds); //TODO: Remove top(SIREP)
+ result = mrb_dump_irep(mrb, start_index, debug_info, &bin, &bin_size);
+ if (result == MRB_DUMP_OK) {
+ fwrite(bin, bin_size, 1, fp);
+ }
- return rc;
+ mrb_free(mrb, bin);
+ return result;
}
int
-mrb_bdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname)
+mrb_dump_irep_cfunc(mrb_state *mrb, size_t start_index, int debug_info, FILE *fp, const char *initname)
{
- int rc;
- int irep_no;
- char *buf;
- int buf_size = 0;
- int buf_idx = 0;
+ uint8_t *bin = NULL;
+ size_t bin_size = 0, bin_idx = 0;
+ int result;
- if (mrb == NULL || n < 0 || n >= mrb->irep_len || f == NULL || initname == NULL)
+ if (fp == NULL || initname == NULL) {
return MRB_DUMP_INVALID_ARGUMENT;
+ }
- buf_size = sizeof(rite_binary_header) + MRB_DUMP_SIZE_OF_SHORT/* crc */;
- for (irep_no=n; irep_no<mrb->irep_len; irep_no++)
- buf_size += get_irep_record_size(mrb, irep_no, DUMP_TYPE_BIN);
- buf_size += MRB_DUMP_SIZE_OF_LONG; /* end of file */
-
- buf = (char *)mrb_malloc(mrb, buf_size);
- if (buf == NULL)
- return MRB_DUMP_GENERAL_FAILURE;
-
- rc = mrb_write_irep(mrb, n, buf);
-
- if (rc == MRB_DUMP_OK) {
- fprintf(f, "const char %s[] = {", initname);
- while (buf_idx < buf_size ) {
- if (buf_idx % 16 == 0 ) fputs("\n", f);
- fprintf(f, "0x%02x,", (unsigned char)buf[buf_idx++]);
+ result = mrb_dump_irep(mrb, start_index, debug_info, &bin, &bin_size);
+ if (result == MRB_DUMP_OK) {
+ fprintf(fp, "const uint8_t %s[] = {", initname);
+ while (bin_idx < bin_size) {
+ if (bin_idx % 16 == 0 ) fputs("\n", fp);
+ fprintf(fp, "0x%02x,", bin[bin_idx++]);
}
- fputs("\n};\n", f);
+ fputs("\n};\n", fp);
}
- mrb_free(mrb, buf);
-
- return rc;
+ mrb_free(mrb, bin);
+ return result;
}
#endif /* ENABLE_STDIO */
diff --git a/src/error.c b/src/error.c
index 70a84455f..5f1476115 100644
--- a/src/error.c
+++ b/src/error.c
@@ -4,17 +4,19 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include <stdarg.h>
-#include <stdio.h>
+#include <errno.h>
#include <setjmp.h>
+#include <stdarg.h>
+#include <stdlib.h>
#include <string.h>
-#include "error.h"
-#include "mruby/variable.h"
-#include "mruby/string.h"
+#include "mruby.h"
+#include "mruby/array.h"
#include "mruby/class.h"
-#include "mruby/proc.h"
#include "mruby/irep.h"
+#include "mruby/proc.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
+#include "error.h"
mrb_value
mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len)
@@ -25,7 +27,7 @@ mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len)
mrb_value
mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str)
{
- mrb_string_value(mrb, &str);
+ str = mrb_str_to_str(mrb, str);
return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, str);
}
@@ -43,7 +45,7 @@ exc_initialize(mrb_state *mrb, mrb_value exc)
mrb_value mesg;
if (mrb_get_args(mrb, "|o", &mesg) == 1) {
- mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), mesg);
+ mrb_iv_set(mrb, exc, mrb_intern2(mrb, "mesg", 4), mesg);
}
return exc;
}
@@ -72,7 +74,7 @@ exc_exception(mrb_state *mrb, mrb_value self)
if (argc == 0) return self;
if (mrb_obj_equal(mrb, self, a)) return self;
exc = mrb_obj_clone(mrb, self);
- mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), a);
+ mrb_iv_set(mrb, exc, mrb_intern2(mrb, "mesg", 4), a);
return exc;
}
@@ -88,9 +90,9 @@ exc_exception(mrb_state *mrb, mrb_value self)
static mrb_value
exc_to_s(mrb_state *mrb, mrb_value exc)
{
- mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg"));
+ mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4));
- if (mrb_nil_p(mesg)) return mrb_str_new2(mrb, mrb_obj_classname(mrb, exc));
+ if (mrb_nil_p(mesg)) return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc));
return mesg;
}
@@ -122,32 +124,32 @@ exc_inspect(mrb_state *mrb, mrb_value exc)
{
mrb_value str, mesg, file, line;
- mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg"));
- file = mrb_attr_get(mrb, exc, mrb_intern(mrb, "file"));
- line = mrb_attr_get(mrb, exc, mrb_intern(mrb, "line"));
-
+ mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4));
+ file = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "file", 4));
+ line = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "line", 4));
+
if (!mrb_nil_p(file) && !mrb_nil_p(line)) {
str = file;
- mrb_str_cat2(mrb, str, ":");
+ mrb_str_cat(mrb, str, ":", 1);
mrb_str_append(mrb, str, line);
- mrb_str_cat2(mrb, str, ": ");
+ mrb_str_cat(mrb, str, ": ", 2);
if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
mrb_str_append(mrb, str, mesg);
- mrb_str_cat2(mrb, str, " (");
+ mrb_str_cat(mrb, str, " (", 2);
}
- mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc));
+ mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc));
if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
- mrb_str_cat2(mrb, str, ")");
+ mrb_str_cat(mrb, str, ")", 1);
}
}
else {
- str = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc));
+ str = mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc));
if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
- mrb_str_cat2(mrb, str, ": ");
+ mrb_str_cat(mrb, str, ": ", 2);
mrb_str_append(mrb, str, mesg);
} else {
- mrb_str_cat2(mrb, str, ": ");
- mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc));
+ mrb_str_cat(mrb, str, ": ", 2);
+ mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc));
}
}
return str;
@@ -159,25 +161,29 @@ exc_equal(mrb_state *mrb, mrb_value exc)
{
mrb_value obj;
mrb_value mesg;
- mrb_sym id_mesg = mrb_intern(mrb, "mesg");
+ mrb_bool equal_p;
+ mrb_sym id_mesg = mrb_intern2(mrb, "mesg", 4);
mrb_get_args(mrb, "o", &obj);
- if (mrb_obj_equal(mrb, exc, obj)) return mrb_true_value();
-
- if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) {
- if (mrb_respond_to(mrb, obj, mrb_intern(mrb, "message"))) {
- mesg = mrb_funcall(mrb, obj, "message", 0);
- }
- else
- return mrb_false_value();
+ if (mrb_obj_equal(mrb, exc, obj)) {
+ equal_p = 1;
}
else {
- mesg = mrb_attr_get(mrb, obj, id_mesg);
+ if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) {
+ if (mrb_respond_to(mrb, obj, mrb_intern2(mrb, "message", 7))) {
+ mesg = mrb_funcall(mrb, obj, "message", 0);
+ }
+ else
+ return mrb_false_value();
+ }
+ else {
+ mesg = mrb_attr_get(mrb, obj, id_mesg);
+ }
+
+ equal_p = mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg);
}
- if (!mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg))
- return mrb_false_value();
- return mrb_true_value();
+ return mrb_bool_value(equal_p);
}
static void
@@ -186,16 +192,16 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
mrb_callinfo *ci = mrb->ci;
mrb_code *pc = ci->pc;
- mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->cibase));
+ mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase));
ci--;
while (ci >= mrb->cibase) {
if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
- mrb_irep *irep = ci->proc->body.irep;
+ mrb_irep *irep = ci->proc->body.irep;
if (irep->filename && irep->lines && irep->iseq <= pc && pc < irep->iseq + irep->ilen) {
- mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "file"), mrb_str_new_cstr(mrb, irep->filename));
- mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "line"), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1]));
- return;
+ mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, irep->filename));
+ mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1]));
+ return;
}
}
pc = ci->pc;
@@ -206,12 +212,10 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
void
mrb_exc_raise(mrb_state *mrb, mrb_value exc)
{
- mrb->exc = (struct RObject*)mrb_object(exc);
+ mrb->exc = mrb_obj_ptr(exc);
exc_debug_info(mrb, mrb->exc);
if (!mrb->jmp) {
-#ifdef ENABLE_STDIO
mrb_p(mrb, exc);
-#endif
abort();
}
longjmp(*(jmp_buf*)mrb->jmp, 1);
@@ -221,114 +225,123 @@ void
mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg)
{
mrb_value mesg;
- mesg = mrb_str_new2(mrb, msg);
+ mesg = mrb_str_new_cstr(mrb, msg);
mrb_exc_raise(mrb, mrb_exc_new3(mrb, c, mesg));
}
+mrb_value
+mrb_vformat(mrb_state *mrb, const char *format, va_list ap)
+{
+ const char *p = format;
+ const char *b = p;
+ ptrdiff_t size;
+ mrb_value ary = mrb_ary_new_capa(mrb, 4);
+
+ while (*p) {
+ const char c = *p++;
+
+ if (c == '%') {
+ if (*p == 'S') {
+ size = p - b - 1;
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
+ mrb_ary_push(mrb, ary, va_arg(ap, mrb_value));
+ b = p + 1;
+ }
+ }
+ else if (c == '\\') {
+ if (*p) {
+ size = p - b - 1;
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, p, 1));
+ b = ++p;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ if (b == format) {
+ return mrb_str_new_cstr(mrb, format);
+ }
+ else {
+ size = p - b;
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
+ return mrb_ary_join(mrb, ary, mrb_str_new(mrb,NULL,0));
+ }
+}
+
+mrb_value
+mrb_format(mrb_state *mrb, const char *format, ...)
+{
+ va_list ap;
+ mrb_value str;
+
+ va_start(ap, format);
+ str = mrb_vformat(mrb, format, ap);
+ va_end(ap);
+
+ return str;
+}
+
void
mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...)
{
va_list args;
- char buf[256];
- int n;
+ mrb_value mesg;
va_start(args, fmt);
- n = vsnprintf(buf, sizeof(buf), fmt, args);
+ mesg = mrb_vformat(mrb, fmt, args);
va_end(args);
- if (n < 0) {
- n = 0;
- }
- mrb_exc_raise(mrb, mrb_exc_new(mrb, c, buf, n));
+ mrb_exc_raise(mrb, mrb_exc_new3(mrb, c, mesg));
}
void
mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...)
{
- mrb_value exc, argv[2];
+ mrb_value exc;
+ mrb_value argv[2];
va_list args;
- char buf[256];
- int n;
va_start(args, fmt);
- n = vsnprintf(buf, sizeof(buf), fmt, args);
+ argv[0] = mrb_vformat(mrb, fmt, args);
va_end(args);
- if (n < 0) {
- n = 0;
- }
- argv[0] = mrb_str_new(mrb, buf, n);
+
argv[1] = mrb_symbol_value(id); /* ignore now */
exc = mrb_class_new_instance(mrb, 1, argv, E_NAME_ERROR);
mrb_exc_raise(mrb, exc);
}
-mrb_value
-mrb_sprintf(mrb_state *mrb, const char *fmt, ...)
-{
- va_list args;
- char buf[256];
- int n;
-
- va_start(args, fmt);
- n = vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- if (n < 0) {
- n = 0;
- }
- return mrb_str_new(mrb, buf, n);
-}
-
void
mrb_warn(const char *fmt, ...)
{
+#ifdef ENABLE_STDIO
va_list args;
va_start(args, fmt);
printf("warning: ");
vprintf(fmt, args);
va_end(args);
+#endif
}
void
mrb_bug(const char *fmt, ...)
{
+#ifdef ENABLE_STDIO
va_list args;
va_start(args, fmt);
printf("bug: ");
vprintf(fmt, args);
va_end(args);
+#endif
exit(EXIT_FAILURE);
}
-static const char *
-mrb_strerrno(int err)
-{
-#define defined_error(name, num) if (err == num) return name;
-#define undefined_error(name)
-//#include "known_errors.inc"
-#undef defined_error
-#undef undefined_error
- return NULL;
-}
-
-void
-mrb_bug_errno(const char *mesg, int errno_arg)
-{
- if (errno_arg == 0)
- mrb_bug("%s: errno == 0 (NOERROR)", mesg);
- else {
- const char *errno_str = mrb_strerrno(errno_arg);
- if (errno_str)
- mrb_bug("%s: %s (%s)", mesg, strerror(errno_arg), errno_str);
- else
- mrb_bug("%s: %s (%d)", mesg, strerror(errno_arg), errno_arg);
- }
-}
-
int
sysexit_status(mrb_state *mrb, mrb_value err)
{
- mrb_value st = mrb_iv_get(mrb, err, mrb_intern(mrb, "status"));
+ mrb_value st = mrb_iv_get(mrb, err, mrb_intern2(mrb, "status", 6));
return mrb_fixnum(st);
}
@@ -366,19 +379,19 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr)
n = 1;
exception_call:
{
- mrb_sym exc = mrb_intern(mrb, "exception");
- if (mrb_respond_to(mrb, argv[0], exc)) {
- mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1);
- }
- else {
- /* undef */
- mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected");
- }
+ mrb_sym exc = mrb_intern2(mrb, "exception", 9);
+ if (mrb_respond_to(mrb, argv[0], exc)) {
+ mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1);
+ }
+ else {
+ /* undef */
+ mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected");
+ }
}
break;
default:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%d for 0..3)", argc);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 0..3)", mrb_fixnum_value(argc));
break;
}
if (argc > 0) {
@@ -400,7 +413,20 @@ mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv)
void
mrb_sys_fail(mrb_state *mrb, const char *mesg)
{
- mrb_raise(mrb, E_RUNTIME_ERROR, mesg);
+ struct RClass *sce;
+ mrb_int no;
+
+ no = (mrb_int)errno;
+ if (mrb_class_defined(mrb, "SystemCallError")) {
+ sce = mrb_class_get(mrb, "SystemCallError");
+ if (mesg != NULL) {
+ mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 2, mrb_fixnum_value(no), mrb_str_new_cstr(mrb, mesg));
+ } else {
+ mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 1, mrb_fixnum_value(no));
+ }
+ } else {
+ mrb_raise(mrb, E_RUNTIME_ERROR, mesg);
+ }
}
void
diff --git a/src/error.h b/src/error.h
index ba3fdac6c..83d0938aa 100644
--- a/src/error.h
+++ b/src/error.h
@@ -8,12 +8,11 @@
#define MRUBY_ERROR_H
void mrb_sys_fail(mrb_state *mrb, const char *mesg);
-void mrb_bug_errno(const char*, int);
int sysexit_status(mrb_state *mrb, mrb_value err);
mrb_value mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str);
mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr);
mrb_value mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv);
-mrb_value mrb_sprintf(mrb_state *mrb, const char *fmt, ...);
+mrb_value mrb_format(mrb_state *mrb, const char *format, ...);
void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...);
void mrb_exc_print(mrb_state *mrb, struct RObject *exc);
diff --git a/src/etc.c b/src/etc.c
index 5d2c836e7..0b58ad67c 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -37,14 +37,13 @@ mrb_get_datatype(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
void *
mrb_check_datatype(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
{
- static const char mesg[] = "wrong argument type %s (expected %s)";
-
if (mrb_special_const_p(obj) || (mrb_type(obj) != MRB_TT_DATA)) {
mrb_check_type(mrb, obj, MRB_TT_DATA);
}
if (DATA_TYPE(obj) != type) {
const char *etype = DATA_TYPE(obj)->struct_name;
- mrb_raisef(mrb, E_TYPE_ERROR, mesg, etype, type->struct_name);
+ mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)",
+ mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->struct_name));
}
return DATA_PTR(obj);
}
@@ -93,8 +92,7 @@ mrb_to_id(mrb_state *mrb, mrb_value name)
tmp = mrb_check_string_type(mrb, name);
if (mrb_nil_p(tmp)) {
tmp = mrb_inspect(mrb, name);
- mrb_raisef(mrb, E_TYPE_ERROR, "%s is not a symbol",
- RSTRING_PTR(tmp));
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp);
}
name = tmp;
/* fall through */
diff --git a/src/gc.c b/src/gc.c
index ae47de025..c90e00c89 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -4,21 +4,23 @@
** See Copyright Notice in mruby.h
*/
+#ifndef SIZE_MAX
+ /* Some versions of VC++
+ * has SIZE_MAX in stdint.h
+ */
+# include <limits.h>
+#endif
+#include <string.h>
#include "mruby.h"
-#include "mruby/class.h"
#include "mruby/array.h"
-#include "mruby/string.h"
+#include "mruby/class.h"
+#include "mruby/data.h"
#include "mruby/hash.h"
-#include "mruby/range.h"
-#include <string.h>
#include "mruby/proc.h"
-#include "mruby/data.h"
+#include "mruby/range.h"
+#include "mruby/string.h"
#include "mruby/variable.h"
-#ifndef SIZE_MAX
-#include <limits.h> // for SIZE_MAX
-#endif
-
/*
= Tri-color Incremental Garbage Collection
@@ -197,7 +199,7 @@ struct heap_page {
struct heap_page *next;
struct heap_page *free_next;
struct heap_page *free_prev;
- unsigned int old:1;
+ mrb_bool old:1;
RVALUE objects[MRB_HEAP_PAGE_SIZE];
};
@@ -301,7 +303,7 @@ mrb_free_heap(mrb_state *mrb)
page = page->next;
for (p = tmp->objects, e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
if (p->as.free.tt != MRB_TT_FREE)
- obj_free(mrb, &p->as.basic);
+ obj_free(mrb, &p->as.basic);
}
mrb_free(mrb, tmp);
}
@@ -322,7 +324,7 @@ void
mrb_gc_protect(mrb_state *mrb, mrb_value obj)
{
if (mrb_special_const_p(obj)) return;
- gc_protect(mrb, mrb_basic(obj));
+ gc_protect(mrb, mrb_basic_ptr(obj));
}
struct RBasic*
@@ -542,7 +544,9 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
static void
root_scan_phase(mrb_state *mrb)
{
- int i, j, e;
+ int j;
+ size_t i;
+ size_t e;
mrb_callinfo *ci;
if (!is_minor_gc(mrb)) {
@@ -557,6 +561,8 @@ root_scan_phase(mrb_state *mrb)
}
/* mark class hierarchy */
mrb_gc_mark(mrb, (struct RBasic*)mrb->object_class);
+ /* mark top_self */
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self);
/* mark exception */
mrb_gc_mark(mrb, (struct RBasic*)mrb->exc);
/* mark stack */
@@ -586,7 +592,7 @@ root_scan_phase(mrb_state *mrb)
mrb_irep *irep = mrb->irep[i];
if (!irep) continue;
for (j=0; j<irep->plen; j++) {
- mrb_gc_mark_value(mrb, irep->pool[j]);
+ mrb_gc_mark_value(mrb, irep->pool[j]);
}
}
}
@@ -982,8 +988,8 @@ gc_enable(mrb_state *mrb, mrb_value obj)
int old = mrb->gc_disabled;
mrb->gc_disabled = FALSE;
- if (old) return mrb_true_value();
- return mrb_false_value();
+
+ return mrb_bool_value(old);
}
/*
@@ -1004,8 +1010,8 @@ gc_disable(mrb_state *mrb, mrb_value obj)
int old = mrb->gc_disabled;
mrb->gc_disabled = TRUE;
- if (old) return mrb_true_value();
- return mrb_false_value();
+
+ return mrb_bool_value(old);
}
/*
@@ -1101,10 +1107,7 @@ change_gen_gc_mode(mrb_state *mrb, mrb_int enable)
static mrb_value
gc_generational_mode_get(mrb_state *mrb, mrb_value self)
{
- if (mrb->is_generational_gc_mode)
- return mrb_true_value();
- else
- return mrb_false_value();
+ return mrb_bool_value(mrb->is_generational_gc_mode);
}
/*
@@ -1124,10 +1127,7 @@ gc_generational_mode_set(mrb_state *mrb, mrb_value self)
if (mrb->is_generational_gc_mode != enable)
change_gen_gc_mode(mrb, enable);
- if (enable)
- return mrb_true_value();
- else
- return mrb_false_value();
+ return mrb_bool_value(enable);
}
#ifdef GC_TEST
@@ -1168,8 +1168,8 @@ test_mrb_field_write_barrier(void)
puts("test_mrb_field_write_barrier");
mrb->is_generational_gc_mode = FALSE;
- obj = mrb_basic(mrb_ary_new(mrb));
- value = mrb_basic(mrb_str_new_cstr(mrb, "value"));
+ obj = mrb_basic_ptr(mrb_ary_new(mrb));
+ value = mrb_basic_ptr(mrb_str_new_cstr(mrb, "value"));
paint_black(obj);
paint_partial_white(mrb,value);
@@ -1210,15 +1210,15 @@ test_mrb_field_write_barrier(void)
{
puts("test_mrb_field_write_barrier_value");
- obj = mrb_basic(mrb_ary_new(mrb));
+ obj = mrb_basic_ptr(mrb_ary_new(mrb));
mrb_value value = mrb_str_new_cstr(mrb, "value");
paint_black(obj);
- paint_partial_white(mrb, mrb_basic(value));
+ paint_partial_white(mrb, mrb_basic_ptr(value));
mrb->gc_state = GC_STATE_MARK;
mrb_field_write_barrier_value(mrb, obj, value);
- gc_assert(is_gray(mrb_basic(value)));
+ gc_assert(is_gray(mrb_basic_ptr(value)));
}
mrb_close(mrb);
@@ -1231,7 +1231,7 @@ test_mrb_write_barrier(void)
struct RBasic *obj;
puts("test_mrb_write_barrier");
- obj = mrb_basic(mrb_ary_new(mrb));
+ obj = mrb_basic_ptr(mrb_ary_new(mrb));
paint_black(obj);
puts(" in GC_STATE_MARK");
@@ -1260,12 +1260,12 @@ test_add_gray_list(void)
puts("test_add_gray_list");
change_gen_gc_mode(mrb, FALSE);
gc_assert(mrb->gray_list == NULL);
- obj1 = mrb_basic(mrb_str_new_cstr(mrb, "test"));
+ obj1 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test"));
add_gray_list(mrb, obj1);
gc_assert(mrb->gray_list == obj1);
gc_assert(is_gray(obj1));
- obj2 = mrb_basic(mrb_str_new_cstr(mrb, "test"));
+ obj2 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test"));
add_gray_list(mrb, obj2);
gc_assert(mrb->gray_list == obj2);
gc_assert(mrb->gray_list->gcnext == obj1);
@@ -1294,12 +1294,12 @@ test_gc_gray_mark(void)
puts(" in MRB_TT_ARRAY");
obj_v = mrb_ary_new(mrb);
value_v = mrb_str_new_cstr(mrb, "test");
- paint_gray(mrb_basic(obj_v));
- paint_partial_white(mrb, mrb_basic(value_v));
+ paint_gray(mrb_basic_ptr(obj_v));
+ paint_partial_white(mrb, mrb_basic_ptr(value_v));
mrb_ary_push(mrb, obj_v, value_v);
- gray_num = gc_gray_mark(mrb, mrb_basic(obj_v));
- gc_assert(is_black(mrb_basic(obj_v)));
- gc_assert(is_gray(mrb_basic(value_v)));
+ gray_num = gc_gray_mark(mrb, mrb_basic_ptr(obj_v));
+ gc_assert(is_black(mrb_basic_ptr(obj_v)));
+ gc_assert(is_gray(mrb_basic_ptr(value_v)));
gc_assert(gray_num == 1);
mrb_close(mrb);
diff --git a/src/hash.c b/src/hash.c
index 2439a235d..e32ee73e1 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -5,17 +5,17 @@
*/
#include "mruby.h"
+#include "mruby/array.h"
+#include "mruby/class.h"
#include "mruby/hash.h"
#include "mruby/khash.h"
-#include "mruby/class.h"
-#include "mruby/array.h"
#include "mruby/string.h"
#include "mruby/variable.h"
static inline khint_t
mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key)
{
- khint_t h = mrb_type(key) << 24;
+ khint_t h = (khint_t)mrb_type(key) << 24;
mrb_value h2;
h2 = mrb_funcall(mrb, key, "hash", 0, 0);
@@ -52,11 +52,15 @@ mrb_gc_mark_ht(mrb_state *mrb, struct RHash *hash)
khash_t(ht) *h = hash->ht;
if (!h) return;
- for (k = kh_begin(h); k != kh_end(h); k++)
+ for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)) {
- mrb_gc_mark_value(mrb, kh_key(h, k));
- mrb_gc_mark_value(mrb, kh_value(h, k));
+ mrb_value key = kh_key(h, k);
+ mrb_value val = kh_value(h, k);
+
+ mrb_gc_mark_value(mrb, key);
+ mrb_gc_mark_value(mrb, val);
}
+ }
}
size_t
@@ -258,7 +262,7 @@ mrb_hash_init_core(mrb_state *mrb, mrb_value hash)
RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
ifnone = block;
}
- mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
+ mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone);
return hash;
}
@@ -423,7 +427,7 @@ mrb_hash_set_default(mrb_state *mrb, mrb_value hash)
mrb_get_args(mrb, "o", &ifnone);
mrb_hash_modify(mrb, hash);
- mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
+ mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone);
RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT);
return ifnone;
@@ -474,7 +478,7 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash)
mrb_get_args(mrb, "o", &ifnone);
mrb_hash_modify(mrb, hash);
- mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
+ mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone);
RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
return ifnone;
@@ -559,7 +563,7 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash)
delVal = mrb_hash_delete_key(mrb, hash, delKey);
mrb_gc_protect(mrb, delVal);
- return mrb_assoc_new(mrb, delKey, delVal);
+ return mrb_assoc_new(mrb, delKey, delVal);
}
}
}
@@ -755,7 +759,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash)
else {
ifnone = RHASH_IFNONE(hash2);
}
- mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
+ mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone);
return hash;
}
@@ -797,13 +801,16 @@ static mrb_value
mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
{
khash_t(ht) *h = RHASH_TBL(self);
+ mrb_bool empty_p;
if (h) {
- if (kh_size(h) == 0)
- return mrb_true_value();
- return mrb_false_value();
+ empty_p = (kh_size(h) == 0);
}
- return mrb_true_value();
+ else {
+ empty_p = 1;
+ }
+
+ return mrb_bool_value(empty_p);
}
/* 15.2.13.4.11 */
@@ -887,7 +894,7 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur)
ai = mrb_gc_arena_save(mrb);
- if (RSTRING_LEN(str) > 1) mrb_str_cat2(mrb, str, ", ");
+ if (RSTRING_LEN(str) > 1) mrb_str_cat(mrb, str, ", ", 2);
str2 = mrb_inspect(mrb, kh_key(h,k));
mrb_str_append(mrb, str, str2);
@@ -1006,14 +1013,17 @@ mrb_hash_has_keyWithKey(mrb_state *mrb, mrb_value hash, mrb_value key)
{
khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
+ mrb_bool result;
if (h) {
k = kh_get(ht, h, key);
- if (k != kh_end(h))
- return mrb_true_value();
+ result = (k != kh_end(h));
+ }
+ else {
+ result = 0;
}
- return mrb_false_value();
+ return mrb_bool_value(result);
}
/* 15.2.13.4.13 */
@@ -1094,7 +1104,7 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql)
if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value();
if (!mrb_hash_p(hash2)) {
- if (!mrb_respond_to(mrb, hash2, mrb_intern(mrb, "to_hash"))) {
+ if (!mrb_respond_to(mrb, hash2, mrb_intern2(mrb, "to_hash", 7))) {
return mrb_false_value();
}
if (eql)
@@ -1105,8 +1115,7 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql)
h1 = RHASH_TBL(hash1);
h2 = RHASH_TBL(hash2);
if (!h1) {
- if (!h2) return mrb_true_value();
- return mrb_false_value();
+ return mrb_bool_value(!h2);
}
if (!h2) return mrb_false_value();
if (kh_size(h1) != kh_size(h2)) return mrb_false_value();
@@ -1119,9 +1128,9 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql)
key = kh_key(h1,k1);
k2 = kh_get(ht, h2, key);
if (k2 != kh_end(h2)) {
- if (mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2))) {
- continue; /* next key */
- }
+ if (mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2))) {
+ continue; /* next key */
+ }
}
return mrb_false_value();
}
diff --git a/src/init.c b/src/init.c
index 0d1a24881..e97c72d68 100644
--- a/src/init.c
+++ b/src/init.c
@@ -21,7 +21,6 @@ void mrb_init_hash(mrb_state*);
void mrb_init_numeric(mrb_state*);
void mrb_init_range(mrb_state*);
void mrb_init_gc(mrb_state*);
-void mrb_init_print(mrb_state*);
void mrb_init_math(mrb_state*);
void mrb_init_mrblib(mrb_state*);
void mrb_init_mrbgems(mrb_state*);
@@ -48,9 +47,6 @@ mrb_init_core(mrb_state *mrb)
mrb_init_numeric(mrb); DONE;
mrb_init_range(mrb); DONE;
mrb_init_gc(mrb); DONE;
-#ifdef ENABLE_STDIO
- mrb_init_print(mrb); DONE;
-#endif
mrb_init_mrblib(mrb); DONE;
#ifndef DISABLE_GEMS
mrb_init_mrbgems(mrb); DONE;
diff --git a/src/kernel.c b/src/kernel.c
index e45953fd3..f14a94b3a 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -5,10 +5,10 @@
*/
#include "mruby.h"
-#include "mruby/string.h"
-#include "mruby/proc.h"
#include "mruby/array.h"
#include "mruby/class.h"
+#include "mruby/proc.h"
+#include "mruby/string.h"
#include "mruby/variable.h"
#include "error.h"
@@ -29,7 +29,7 @@ typedef enum {
int
mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj)
{
- struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern(mrb, "to_s"));
+ struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern2(mrb, "to_s", 4));
if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s))
return TRUE;
return FALSE;
@@ -55,9 +55,6 @@ mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
if ((mrb_type(obj) == MRB_TT_OBJECT) && mrb_obj_basic_to_s_p(mrb, obj)) {
return mrb_obj_iv_inspect(mrb, mrb_obj_ptr(obj));
}
- else if (mrb_type(obj) == MRB_TT_MAIN) {
- return mrb_str_new(mrb, "main", 4);
- }
return mrb_any_to_s(mrb, obj);
}
@@ -96,28 +93,24 @@ static mrb_value
mrb_obj_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &arg);
- if (mrb_obj_equal(mrb, self, arg)) {
- return mrb_true_value();
- }
- else {
- return mrb_false_value();
- }
+ eql_p = mrb_obj_equal(mrb, self, arg);
+
+ return mrb_bool_value(eql_p);
}
static mrb_value
mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &arg);
- if (mrb_equal(mrb, self, arg)) {
- return mrb_false_value();
- }
- else {
- return mrb_true_value();
- }
+ eql_p = mrb_obj_equal(mrb, self, arg);
+
+ return mrb_bool_value(!eql_p);
}
/* 15.3.1.3.2 */
@@ -133,14 +126,12 @@ static mrb_value
mrb_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &arg);
- if (mrb_equal(mrb, self, arg)){
- return mrb_true_value();
- }
- else {
- return mrb_false_value();
- }
+ equal_p = mrb_equal(mrb, self, arg);
+
+ return mrb_bool_value(equal_p);
}
/* 15.3.1.3.3 */
@@ -191,7 +182,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
mrb_sym name;
mrb_value block, *argv;
int argc;
-
+
mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block);
return mrb_funcall_with_block(mrb,self, name, argc, argv, block);
}
@@ -225,21 +216,28 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
{
mrb_callinfo *ci = mrb->ci;
mrb_value *bp;
+ mrb_bool given_p;
bp = mrb->stbase + ci->stackidx + 1;
ci--;
- if (ci <= mrb->cibase) return mrb_false_value();
- /* block_given? called within block; check upper scope */
- if (ci->proc->env && ci->proc->env->stack) {
- if (ci->proc->env->stack == mrb->stbase || mrb_nil_p(ci->proc->env->stack[1]))
- return mrb_false_value();
- return mrb_true_value();
+ if (ci <= mrb->cibase) {
+ given_p = 0;
}
- if (ci->argc > 0) {
- bp += ci->argc;
+ else {
+ /* block_given? called within block; check upper scope */
+ if (ci->proc->env && ci->proc->env->stack) {
+ given_p = !(ci->proc->env->stack == mrb->stbase ||
+ mrb_nil_p(ci->proc->env->stack[1]));
+ }
+ else {
+ if (ci->argc > 0) {
+ bp += ci->argc;
+ }
+ given_p = !mrb_nil_p(*bp);
+ }
}
- if (mrb_nil_p(*bp)) return mrb_false_value();
- return mrb_true_value();
+
+ return mrb_bool_value(given_p);
}
/* 15.3.1.3.7 */
@@ -263,7 +261,7 @@ mrb_obj_class_m(mrb_state *mrb, mrb_value self)
struct RClass*
mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
{
- struct RClass *klass = mrb_basic(obj)->c;
+ struct RClass *klass = mrb_basic_ptr(obj)->c;
if (klass->tt != MRB_TT_SCLASS)
return klass;
@@ -282,7 +280,7 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
clone->super = klass->super;
if (klass->iv) {
mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass));
- mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern(mrb, "__attached__"), obj);
+ mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern2(mrb, "__attached__", 12), obj);
}
if (klass->mt) {
clone->mt = kh_copy(mt, mrb, klass->mt);
@@ -305,7 +303,7 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
case MRB_TT_SCLASS:
case MRB_TT_HASH:
case MRB_TT_DATA:
- mrb_iv_copy(mrb, dest, obj);
+ mrb_iv_copy(mrb, dest, obj);
break;
default:
@@ -347,7 +345,7 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self)
mrb_value clone;
if (mrb_special_const_p(self)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %s", mrb_obj_classname(mrb, self));
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self);
}
p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self));
p->c = mrb_singleton_class_clone(mrb, self);
@@ -383,7 +381,7 @@ mrb_obj_dup(mrb_state *mrb, mrb_value obj)
mrb_value dup;
if (mrb_special_const_p(obj)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %s", mrb_obj_classname(mrb, obj));
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %S", obj);
}
p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
dup = mrb_obj_value(p);
@@ -483,7 +481,7 @@ mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *a
* call-seq:
* obj.instance_eval {| | block } -> obj
*
- * Evaluates the given block,within the context of the receiver (_obj_).
+ * Evaluates the given block,within the context of the receiver (_obj_).
* In order to set the context, the variable +self+ is set to _obj_ while
* the code is executing, giving the code access to _obj_'s
* instance variables. In the version of <code>instance_eval</code>
@@ -518,6 +516,7 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
default:
cv = mrb_singleton_class(mrb, self);
c = mrb_class_ptr(cv);
+ break;
}
return mrb_yield_internal(mrb, b, 0, 0, self, c);
}
@@ -541,25 +540,23 @@ static mrb_value
obj_is_instance_of(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
+ mrb_bool instance_of_p;
mrb_get_args(mrb, "o", &arg);
- if (mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg))){
- return mrb_true_value();
- }
- else {
- return mrb_false_value();
- }
+ instance_of_p = mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg));
+
+ return mrb_bool_value(instance_of_p);
}
static void
check_iv_name(mrb_state *mrb, mrb_sym id)
{
const char *s;
- int len;
+ size_t len;
s = mrb_sym2name_len(mrb, id, &len);
if (len < 2 || !(s[0] == '@' && s[1] != '@')) {
- mrb_name_error(mrb, id, "`%s' is not allowed as an instance variable name", s);
+ mrb_name_error(mrb, id, "`%S' is not allowed as an instance variable name", mrb_sym2str(mrb, id));
}
}
@@ -585,12 +582,13 @@ mrb_value
mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self)
{
mrb_sym mid;
+ mrb_bool defined_p;
mrb_get_args(mrb, "n", &mid);
check_iv_name(mrb, mid);
- if (mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid))
- return mrb_true_value();
- return mrb_false_value();
+ defined_p = mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid);
+
+ return mrb_bool_value(defined_p);
}
/* 15.3.1.3.21 */
@@ -687,14 +685,12 @@ mrb_value
mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
+ mrb_bool kind_of_p;
mrb_get_args(mrb, "o", &arg);
- if (mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg))) {
- return mrb_true_value();
- }
- else {
- return mrb_false_value();
- }
+ kind_of_p = mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg));
+
+ return mrb_bool_value(kind_of_p);
}
static void
@@ -913,7 +909,7 @@ mrb_f_raise(mrb_state *mrb, mrb_value self)
{
mrb_value a[2], exc;
int argc;
-
+
argc = mrb_get_args(mrb, "|oo", &a[0], &a[1]);
switch (argc) {
@@ -929,8 +925,9 @@ mrb_f_raise(mrb_state *mrb, mrb_value self)
/* fall through */
default:
exc = mrb_make_exception(mrb, argc, a);
- mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern(mrb, "lastpc"), mrb_voidp_value(mrb->ci->pc));
+ mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb->ci->pc));
mrb_exc_raise(mrb, exc);
+ break;
}
return mrb_nil_value(); /* not reached */
}
@@ -967,7 +964,7 @@ mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self)
check_iv_name(mrb, sym);
val = mrb_iv_remove(mrb, self, sym);
if (mrb_undef_p(val)) {
- mrb_name_error(mrb, sym, "instance variable %s not defined", mrb_sym2name(mrb, sym));
+ mrb_name_error(mrb, sym, "instance variable %S not defined", mrb_sym2str(mrb, sym));
}
return val;
}
@@ -1000,15 +997,17 @@ obj_respond_to(mrb_state *mrb, mrb_value self)
int argc;
mrb_value mid, priv;
mrb_sym id;
+ mrb_bool respond_to_p;
mrb_get_args(mrb, "*", &argv, &argc);
mid = argv[0];
if (argc > 1) priv = argv[1];
else priv = mrb_nil_value();
id = mrb_to_id(mrb, mid);
- if (basic_obj_respond_to(mrb, self, id, !mrb_test(priv)))
- return mrb_true_value();
- return mrb_false_value();
+
+ respond_to_p = basic_obj_respond_to(mrb, self, id, !mrb_test(priv));
+
+ return mrb_bool_value(respond_to_p);
}
/* 15.3.1.3.45 */
@@ -1054,8 +1053,6 @@ mrb_obj_singleton_methods_m(mrb_state *mrb, mrb_value self)
return mrb_obj_singleton_methods(mrb, argc, argv, self);
}
-mrb_value mrb_f_sprintf(mrb_state *mrb, mrb_value obj); /* in sprintf.c */
-
void
mrb_init_kernel(mrb_state *mrb)
{
@@ -1108,11 +1105,6 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, ARGS_ANY()); /* 15.3.1.3.45 */
mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, ARGS_NONE()); /* 15.3.1.3.46 */
-#ifdef ENABLE_SPRINTF
- mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, ARGS_ANY()); /* in sprintf.c */
- mrb_define_method(mrb, krn, "format", mrb_f_sprintf, ARGS_ANY()); /* in sprintf.c */
-#endif
-
mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
mrb_alias_method(mrb, mrb->module_class, mrb_intern(mrb, "dup"), mrb_intern(mrb, "clone"));
}
diff --git a/src/keywords b/src/keywords
index be5324875..9cb86608c 100644
--- a/src/keywords
+++ b/src/keywords
@@ -8,43 +8,43 @@ static const struct kwtable *reserved_word(const char *, unsigned int);
struct kwtable;
%%
__ENCODING__, {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END
-__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END
-__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END
-BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END
-END, {keyword_END, keyword_END}, EXPR_END
-alias, {keyword_alias, keyword_alias}, EXPR_FNAME
-and, {keyword_and, keyword_and}, EXPR_VALUE
-begin, {keyword_begin, keyword_begin}, EXPR_BEG
-break, {keyword_break, keyword_break}, EXPR_MID
-case, {keyword_case, keyword_case}, EXPR_VALUE
-class, {keyword_class, keyword_class}, EXPR_CLASS
-def, {keyword_def, keyword_def}, EXPR_FNAME
-do, {keyword_do, keyword_do}, EXPR_BEG
-else, {keyword_else, keyword_else}, EXPR_BEG
-elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE
-end, {keyword_end, keyword_end}, EXPR_END
-ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG
-false, {keyword_false, keyword_false}, EXPR_END
-for, {keyword_for, keyword_for}, EXPR_VALUE
-if, {keyword_if, modifier_if}, EXPR_VALUE
-in, {keyword_in, keyword_in}, EXPR_VALUE
-module, {keyword_module, keyword_module}, EXPR_VALUE
-next, {keyword_next, keyword_next}, EXPR_MID
-nil, {keyword_nil, keyword_nil}, EXPR_END
-not, {keyword_not, keyword_not}, EXPR_ARG
-or, {keyword_or, keyword_or}, EXPR_VALUE
-redo, {keyword_redo, keyword_redo}, EXPR_END
-rescue, {keyword_rescue, modifier_rescue}, EXPR_MID
-retry, {keyword_retry, keyword_retry}, EXPR_END
-return, {keyword_return, keyword_return}, EXPR_MID
-self, {keyword_self, keyword_self}, EXPR_END
-super, {keyword_super, keyword_super}, EXPR_ARG
-then, {keyword_then, keyword_then}, EXPR_BEG
-true, {keyword_true, keyword_true}, EXPR_END
-undef, {keyword_undef, keyword_undef}, EXPR_FNAME
-unless, {keyword_unless, modifier_unless}, EXPR_VALUE
-until, {keyword_until, modifier_until}, EXPR_VALUE
-when, {keyword_when, keyword_when}, EXPR_VALUE
-while, {keyword_while, modifier_while}, EXPR_VALUE
-yield, {keyword_yield, keyword_yield}, EXPR_ARG
+__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END
+__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END
+BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END
+END, {keyword_END, keyword_END}, EXPR_END
+alias, {keyword_alias, keyword_alias}, EXPR_FNAME
+and, {keyword_and, keyword_and}, EXPR_VALUE
+begin, {keyword_begin, keyword_begin}, EXPR_BEG
+break, {keyword_break, keyword_break}, EXPR_MID
+case, {keyword_case, keyword_case}, EXPR_VALUE
+class, {keyword_class, keyword_class}, EXPR_CLASS
+def, {keyword_def, keyword_def}, EXPR_FNAME
+do, {keyword_do, keyword_do}, EXPR_BEG
+else, {keyword_else, keyword_else}, EXPR_BEG
+elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE
+end, {keyword_end, keyword_end}, EXPR_END
+ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG
+false, {keyword_false, keyword_false}, EXPR_END
+for, {keyword_for, keyword_for}, EXPR_VALUE
+if, {keyword_if, modifier_if}, EXPR_VALUE
+in, {keyword_in, keyword_in}, EXPR_VALUE
+module, {keyword_module, keyword_module}, EXPR_VALUE
+next, {keyword_next, keyword_next}, EXPR_MID
+nil, {keyword_nil, keyword_nil}, EXPR_END
+not, {keyword_not, keyword_not}, EXPR_ARG
+or, {keyword_or, keyword_or}, EXPR_VALUE
+redo, {keyword_redo, keyword_redo}, EXPR_END
+rescue, {keyword_rescue, modifier_rescue}, EXPR_MID
+retry, {keyword_retry, keyword_retry}, EXPR_END
+return, {keyword_return, keyword_return}, EXPR_MID
+self, {keyword_self, keyword_self}, EXPR_END
+super, {keyword_super, keyword_super}, EXPR_ARG
+then, {keyword_then, keyword_then}, EXPR_BEG
+true, {keyword_true, keyword_true}, EXPR_END
+undef, {keyword_undef, keyword_undef}, EXPR_FNAME
+unless, {keyword_unless, modifier_unless}, EXPR_VALUE
+until, {keyword_until, modifier_until}, EXPR_VALUE
+when, {keyword_when, keyword_when}, EXPR_VALUE
+while, {keyword_while, modifier_while}, EXPR_VALUE
+yield, {keyword_yield, keyword_yield}, EXPR_ARG
%%
diff --git a/src/lex.def b/src/lex.def
index 5223aac1b..ea456a843 100644
--- a/src/lex.def
+++ b/src/lex.def
@@ -1,4 +1,4 @@
-/* ANSI-C code produced by gperf version 3.0.4 */
+/* ANSI-C code produced by gperf version 3.0.3 */
/* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' src/keywords */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
@@ -44,10 +44,12 @@ struct kwtable;
#define MAX_HASH_VALUE 50
/* maximum key range = 43, duplicates = 0 */
-#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) || defined(__GNUC_STDC_INLINE__)
-inline
-#elif defined(__GNUC__)
+#ifdef __GNUC__
__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
#endif
static unsigned int
hash (register const char *str, register unsigned int len)
@@ -98,7 +100,7 @@ hash (register const char *str, register unsigned int len)
#ifdef __GNUC__
__inline
-#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#ifdef __GNUC_STDC_INLINE__
__attribute__ ((__gnu_inline__))
#endif
#endif
@@ -109,87 +111,87 @@ mrb_reserved_word (register const char *str, register unsigned int len)
{
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 18 "src/keywords"
- {"break", {keyword_break, keyword_break}, EXPR_MID},
+ {"break", {keyword_break, keyword_break}, EXPR_MID},
#line 23 "src/keywords"
- {"else", {keyword_else, keyword_else}, EXPR_BEG},
+ {"else", {keyword_else, keyword_else}, EXPR_BEG},
#line 33 "src/keywords"
- {"nil", {keyword_nil, keyword_nil}, EXPR_END},
+ {"nil", {keyword_nil, keyword_nil}, EXPR_END},
#line 26 "src/keywords"
- {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
+ {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
#line 25 "src/keywords"
- {"end", {keyword_end, keyword_end}, EXPR_END},
+ {"end", {keyword_end, keyword_end}, EXPR_END},
#line 42 "src/keywords"
- {"then", {keyword_then, keyword_then}, EXPR_BEG},
+ {"then", {keyword_then, keyword_then}, EXPR_BEG},
#line 34 "src/keywords"
- {"not", {keyword_not, keyword_not}, EXPR_ARG},
+ {"not", {keyword_not, keyword_not}, EXPR_ARG},
#line 27 "src/keywords"
- {"false", {keyword_false, keyword_false}, EXPR_END},
+ {"false", {keyword_false, keyword_false}, EXPR_END},
#line 40 "src/keywords"
- {"self", {keyword_self, keyword_self}, EXPR_END},
+ {"self", {keyword_self, keyword_self}, EXPR_END},
#line 24 "src/keywords"
- {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
+ {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
#line 37 "src/keywords"
- {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
+ {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
#line 43 "src/keywords"
- {"true", {keyword_true, keyword_true}, EXPR_END},
+ {"true", {keyword_true, keyword_true}, EXPR_END},
#line 46 "src/keywords"
- {"until", {keyword_until, modifier_until}, EXPR_VALUE},
+ {"until", {keyword_until, modifier_until}, EXPR_VALUE},
#line 45 "src/keywords"
- {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
+ {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
#line 39 "src/keywords"
- {"return", {keyword_return, keyword_return}, EXPR_MID},
+ {"return", {keyword_return, keyword_return}, EXPR_MID},
#line 21 "src/keywords"
- {"def", {keyword_def, keyword_def}, EXPR_FNAME},
+ {"def", {keyword_def, keyword_def}, EXPR_FNAME},
#line 16 "src/keywords"
- {"and", {keyword_and, keyword_and}, EXPR_VALUE},
+ {"and", {keyword_and, keyword_and}, EXPR_VALUE},
#line 22 "src/keywords"
- {"do", {keyword_do, keyword_do}, EXPR_BEG},
+ {"do", {keyword_do, keyword_do}, EXPR_BEG},
#line 49 "src/keywords"
- {"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
+ {"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
#line 28 "src/keywords"
- {"for", {keyword_for, keyword_for}, EXPR_VALUE},
+ {"for", {keyword_for, keyword_for}, EXPR_VALUE},
#line 44 "src/keywords"
- {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
+ {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
#line 35 "src/keywords"
- {"or", {keyword_or, keyword_or}, EXPR_VALUE},
+ {"or", {keyword_or, keyword_or}, EXPR_VALUE},
#line 30 "src/keywords"
- {"in", {keyword_in, keyword_in}, EXPR_VALUE},
+ {"in", {keyword_in, keyword_in}, EXPR_VALUE},
#line 47 "src/keywords"
- {"when", {keyword_when, keyword_when}, EXPR_VALUE},
+ {"when", {keyword_when, keyword_when}, EXPR_VALUE},
#line 38 "src/keywords"
- {"retry", {keyword_retry, keyword_retry}, EXPR_END},
+ {"retry", {keyword_retry, keyword_retry}, EXPR_END},
#line 29 "src/keywords"
- {"if", {keyword_if, modifier_if}, EXPR_VALUE},
+ {"if", {keyword_if, modifier_if}, EXPR_VALUE},
#line 19 "src/keywords"
- {"case", {keyword_case, keyword_case}, EXPR_VALUE},
+ {"case", {keyword_case, keyword_case}, EXPR_VALUE},
#line 36 "src/keywords"
- {"redo", {keyword_redo, keyword_redo}, EXPR_END},
+ {"redo", {keyword_redo, keyword_redo}, EXPR_END},
#line 32 "src/keywords"
- {"next", {keyword_next, keyword_next}, EXPR_MID},
+ {"next", {keyword_next, keyword_next}, EXPR_MID},
#line 41 "src/keywords"
- {"super", {keyword_super, keyword_super}, EXPR_ARG},
+ {"super", {keyword_super, keyword_super}, EXPR_ARG},
#line 31 "src/keywords"
- {"module", {keyword_module, keyword_module}, EXPR_VALUE},
+ {"module", {keyword_module, keyword_module}, EXPR_VALUE},
#line 17 "src/keywords"
- {"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
-#line 11 "src/keywords"
- {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
+ {"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
#line 12 "src/keywords"
- {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
+ {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
+#line 11 "src/keywords"
+ {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
#line 10 "src/keywords"
{"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
#line 14 "src/keywords"
- {"END", {keyword_END, keyword_END}, EXPR_END},
+ {"END", {keyword_END, keyword_END}, EXPR_END},
#line 15 "src/keywords"
- {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
+ {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
#line 13 "src/keywords"
- {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
+ {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
{""},
#line 20 "src/keywords"
- {"class", {keyword_class, keyword_class}, EXPR_CLASS},
+ {"class", {keyword_class, keyword_class}, EXPR_CLASS},
{""}, {""},
#line 48 "src/keywords"
- {"while", {keyword_while, modifier_while}, EXPR_VALUE}
+ {"while", {keyword_while, modifier_while}, EXPR_VALUE}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/src/load.c b/src/load.c
index 850fa6e8d..c350cb1a3 100644
--- a/src/load.c
+++ b/src/load.c
@@ -4,412 +4,77 @@
** See Copyright Notice in mruby.h
*/
+#ifndef SIZE_MAX
+ /* Some versions of VC++
+ * has SIZE_MAX in stdint.h
+ */
+# include <limits.h>
+#endif
+#include <stdlib.h>
#include <string.h>
#include "mruby/dump.h"
-
-#include "mruby/string.h"
-#include "mruby/proc.h"
#include "mruby/irep.h"
+#include "mruby/proc.h"
+#include "mruby/string.h"
-#ifdef ENABLE_STDIO
-typedef struct _RiteFILE
-{
- FILE* fp;
- unsigned char buf[256];
- int cnt;
- int readlen;
-} RiteFILE;
+#ifndef _WIN32
+# if SIZE_MAX < UINT32_MAX
+# error "It can't be run this code on this environment (SIZE_MAX < UINT32_MAX)"
+# endif
#endif
-const char hex2bin[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //00-0f
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10-1f
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20-2f
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, //30-3f
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40-4f
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //50-5f
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0 //60-6f
- //70-ff
-};
-
-static uint16_t hex_to_bin8(unsigned char*,unsigned char*);
-static uint16_t hex_to_bin16(unsigned char*,unsigned char*);
-static uint16_t hex_to_bin32(unsigned char*,unsigned char*);
-static uint8_t hex_to_uint8(unsigned char*);
-static uint16_t hex_to_uint16(unsigned char*);
-static uint32_t hex_to_uint32(unsigned char*);
-static char* hex_to_str(char*,char*,uint16_t*);
-uint16_t calc_crc_16_ccitt(unsigned char*,int);
-#ifdef ENABLE_STDIO
-static unsigned char rite_fgetcSub(RiteFILE*);
-static unsigned char rite_fgetc(RiteFILE*,int);
-static unsigned char* rite_fgets(RiteFILE*,unsigned char*,int,int);
-static int load_rite_header(FILE*,rite_binary_header*,unsigned char*);
-static int load_rite_irep_record(mrb_state*, RiteFILE*,unsigned char*,uint32_t*);
+#if CHAR_BIT != 8
+# error This code assumes CHAR_BIT == 8
#endif
-static int read_rite_header(mrb_state*,unsigned char*,rite_binary_header*);
-static int read_rite_irep_record(mrb_state*,unsigned char*,uint32_t*);
-
-#ifdef ENABLE_STDIO
-static unsigned char
-rite_fgetcSub(RiteFILE* rfp)
+static size_t
+offset_crc_body()
{
- //only first call
- if (rfp->buf[0] == '\0') {
- rfp->readlen = fread(rfp->buf, 1, sizeof(rfp->buf), rfp->fp);
- rfp->cnt = 0;
- }
-
- if (rfp->readlen == rfp->cnt) {
- rfp->readlen = fread(rfp->buf, 1, sizeof(rfp->buf), rfp->fp);
- rfp->cnt = 0;
- if (rfp->readlen == 0) {
- return '\0';
- }
- }
- return rfp->buf[(rfp->cnt)++];
+ struct rite_binary_header header;
+ return ((uint8_t *)header.binary_crc - (uint8_t *)&header) + sizeof(header.binary_crc);
}
-#endif /* ENABLE_STDIO */
-#ifdef ENABLE_STDIO
-static unsigned char
-rite_fgetc(RiteFILE* rfp, int ignorecomment)
-{
- unsigned char tmp;
-
- for (;;) {
- tmp = rite_fgetcSub(rfp);
- if (tmp == '\n' || tmp == '\r') {
- continue;
- }
- else if (ignorecomment && tmp == '#') {
- while (tmp != '\n' && tmp != '\r' && tmp != '\0')
- tmp = rite_fgetcSub(rfp);
- if (tmp == '\0')
- return '\0';
- }
- else {
- return tmp;
- }
- }
-}
-#endif /* ENABLE_STDIO */
-
-#ifdef ENABLE_STDIO
-static unsigned char*
-rite_fgets(RiteFILE* rfp, unsigned char* dst, int len, int ignorecomment)
-{
- int i;
-
- for (i=0; i<len; i++) {
- if ('\0' == (dst[i] = rite_fgetc(rfp, ignorecomment))) {
- return NULL;
- }
- }
- return dst;
-}
-#endif /* ENABLE_STDIO */
-
-#ifdef ENABLE_STDIO
static int
-load_rite_header(FILE* fp, rite_binary_header* bin_header, unsigned char* hcrc)
+read_rite_irep_record(mrb_state *mrb, const uint8_t *bin, uint32_t *len)
{
- rite_file_header file_header;
-
- if (fread(&file_header, 1, sizeof(file_header), fp) < sizeof(file_header)) {
- return MRB_DUMP_READ_FAULT;
- }
- memcpy(bin_header->rbfi, file_header.rbfi, sizeof(file_header.rbfi));
- if (memcmp(bin_header->rbfi, RITE_FILE_IDENFIFIER, sizeof(bin_header->rbfi)) != 0) {
- return MRB_DUMP_INVALID_FILE_HEADER; //File identifier error
- }
- memcpy(bin_header->rbfv, file_header.rbfv, sizeof(file_header.rbfv));
- if (memcmp(bin_header->rbfv, RITE_FILE_FORMAT_VER, sizeof(bin_header->rbfv)) != 0) {
- return MRB_DUMP_INVALID_FILE_HEADER; //File format version error
- }
- memcpy(bin_header->risv, file_header.risv, sizeof(file_header.risv));
- memcpy(bin_header->rct, file_header.rct, sizeof(file_header.rct));
- memcpy(bin_header->rcv, file_header.rcv, sizeof(file_header.rcv));
- hex_to_bin32(bin_header->rbds, file_header.rbds);
- hex_to_bin16(bin_header->nirep, file_header.nirep);
- hex_to_bin16(bin_header->sirep, file_header.sirep);
- memcpy(bin_header->rsv, file_header.rsv, sizeof(file_header.rsv));
- memcpy(hcrc, file_header.hcrc, sizeof(file_header.hcrc));
-
- return MRB_DUMP_OK;
-}
-#endif /* ENABLE_STDIO */
-
-#ifdef ENABLE_STDIO
-static int
-load_rite_irep_record(mrb_state *mrb, RiteFILE* rfp, unsigned char* dst, uint32_t* len)
-{
- int i;
- uint32_t blocklen;
- uint16_t offset, pdl, snl, clen;
- unsigned char hex2[2] = {0}, hex4[4] = {0}, hex8[8] = {0}, hcrc[4] = {0};
- unsigned char *pStart;
- char *char_buf;
- uint16_t buf_size =0;
- int result;
-
- buf_size = MRB_DUMP_DEFAULT_STR_LEN;
- char_buf = (char *)mrb_malloc(mrb, buf_size);
- if (char_buf == NULL) {
- result = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
-
- pStart = dst;
-
- //IREP HEADER BLOCK
- *dst = rite_fgetc(rfp, TRUE); //record identifier
- if (*dst != RITE_IREP_IDENFIFIER) {
- result = MRB_DUMP_INVALID_IREP;
- goto error_exit;
- }
- dst += sizeof(unsigned char);
- *dst = rite_fgetc(rfp, TRUE); //class or module
- dst += sizeof(unsigned char);
- rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //number of local variable
- dst += hex_to_bin16(dst, hex4);
- rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //number of register variable
- dst += hex_to_bin16(dst, hex4);
- rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //offset of isec block
- offset = hex_to_uint16(hex4);
- rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //header CRC
- memset( char_buf, '\0', buf_size);
- rite_fgets(rfp, (unsigned char*)char_buf, (offset - (MRB_DUMP_SIZE_OF_SHORT * RITE_FILE_HEX_SIZE)), TRUE); //class or module name
- hex_to_str(char_buf, (char*)(dst + MRB_DUMP_SIZE_OF_SHORT + MRB_DUMP_SIZE_OF_SHORT), &clen); //class or module name
- dst += uint16_to_bin((MRB_DUMP_SIZE_OF_SHORT/*crc*/ + clen), (char*)dst); //offset of isec block
- dst += hex_to_bin16(dst, hcrc); //header CRC
- dst += clen;
-
- //ISEQ BLOCK
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //iseq length
- dst += hex_to_bin32(dst, hex8);
- blocklen = hex_to_uint32(hex8);
- for (i=0; i<blocklen; i++) {
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //iseq
- dst += hex_to_bin32(dst, hex8);
- }
- rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //iseq CRC
- dst += hex_to_bin16(dst, hcrc);
-
- //POOL BLOCK
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //pool length
- dst += hex_to_bin32(dst, hex8);
- blocklen = hex_to_uint32(hex8);
- for (i=0; i<blocklen; i++) {
- rite_fgets(rfp, hex2, sizeof(hex2), TRUE); //TT
- dst += hex_to_bin8(dst, hex2);
- rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //pool data length
- pdl = hex_to_uint16(hex4);
-
- if ( pdl > buf_size - 1) {
- buf_size = pdl + 1;
- char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size);
- if (char_buf == NULL) {
- result = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
- }
- memset(char_buf, '\0', buf_size);
- rite_fgets(rfp, (unsigned char*)char_buf, pdl, FALSE); //pool
- hex_to_str(char_buf, (char*)(dst + MRB_DUMP_SIZE_OF_SHORT), &clen);
- dst += uint16_to_bin(clen, (char*)dst);
- dst += clen;
- }
- rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //pool CRC
- dst += hex_to_bin16(dst, hcrc);
-
- //SYMS BLOCK
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //syms length
- dst += hex_to_bin32(dst, hex8);
- blocklen = hex_to_uint32(hex8);
- for (i=0; i<blocklen; i++) {
- rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //symbol name length
- snl = hex_to_uint16(hex4);
-
- if (snl == MRB_DUMP_NULL_SYM_LEN) {
- dst += uint16_to_bin(snl, (char*)dst);
- continue;
- }
-
- if ( snl > buf_size - 1) {
- buf_size = snl + 1;
- char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size);
- if (char_buf == NULL) {
- result = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
- }
- memset(char_buf, '\0', buf_size);
- rite_fgets(rfp, (unsigned char*)char_buf, snl, FALSE); //symbol name
- hex_to_str(char_buf, (char*)(dst + MRB_DUMP_SIZE_OF_SHORT), &clen);
- dst += uint16_to_bin(clen, (char*)dst);
- dst += clen;
- }
- rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //syms CRC
- dst += hex_to_bin16(dst, hcrc);
-
- *len = dst - pStart;
-
- result = MRB_DUMP_OK;
-error_exit:
- mrb_free(mrb, char_buf);
-
- return result;
-}
-#endif /* ENABLE_STDIO */
-
-#ifdef ENABLE_STDIO
-int
-mrb_read_irep_file(mrb_state *mrb, FILE* fp)
-{
- int ret, i;
- uint32_t len, rlen = 0;
- unsigned char hex8[8], hcrc[4];
- unsigned char *dst, *rite_dst = NULL;
- rite_binary_header bin_header;
- RiteFILE ritefp = { 0 };
- RiteFILE *rfp;
-
- if ((mrb == NULL) || (fp == NULL)) {
- return MRB_DUMP_INVALID_ARGUMENT;
- }
- ritefp.fp = fp;
- rfp = &ritefp;
-
- //Read File Header Section
- ret = load_rite_header(fp, &bin_header, hcrc);
- if (ret != MRB_DUMP_OK)
- return ret;
-
- len = sizeof(rite_binary_header) + bin_to_uint32(bin_header.rbds);
- rite_dst = (unsigned char *)mrb_malloc(mrb, len);
- if (rite_dst == NULL)
- return MRB_DUMP_GENERAL_FAILURE;
-
- dst = rite_dst;
- memset(dst, 0x00, len);
- *(rite_binary_header *)dst = bin_header;
- dst += sizeof(rite_binary_header);
- dst += hex_to_bin16(dst, hcrc);
-
- //Read Binary Data Section
- len = bin_to_uint16(bin_header.nirep);
- for (i=0; i<len; i++) {
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //record len
- dst += hex_to_bin32(dst, hex8);
- ret = load_rite_irep_record(mrb, rfp, dst, &rlen);
- if (ret != MRB_DUMP_OK) //irep info
- goto error_exit;
- dst += rlen;
- }
- rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //dummy record len
- hex_to_bin32(dst, hex8); /* dst += hex_to_bin32(dst, hex8); */
- if (0 != hex_to_uint32(hex8)) {
- ret = MRB_DUMP_INVALID_IREP;
- goto error_exit;
- }
-
- if (ret == MRB_DUMP_OK)
- ret = mrb_read_irep(mrb, (char*)rite_dst);
-
-error_exit:
- mrb_free(mrb, rite_dst);
-
- return ret;
-}
-#endif /* ENABLE_STDIO */
-
-static int
-read_rite_header(mrb_state *mrb, unsigned char *bin, rite_binary_header* bin_header)
-{
- uint16_t crc;
-
- *bin_header = *(rite_binary_header *)bin;
- bin += sizeof(rite_binary_header);
- if (memcmp(bin_header->rbfi, RITE_FILE_IDENFIFIER, sizeof(bin_header->rbfi)) != 0) {
- return MRB_DUMP_INVALID_FILE_HEADER; //File identifier error
- }
- if (memcmp(bin_header->risv, RITE_VM_VER, sizeof(bin_header->risv)) != 0) {
- return MRB_DUMP_INVALID_FILE_HEADER; //Instruction set version check
- }
-
- crc = calc_crc_16_ccitt((unsigned char*)bin_header, sizeof(*bin_header)); //Calculate CRC
- if (crc != bin_to_uint16(bin)) {
- return MRB_DUMP_INVALID_FILE_HEADER; //CRC error
- }
-
- return bin_to_uint16(bin_header->nirep);
-}
-
-static int
-read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len)
-{
- int i, ret = MRB_DUMP_OK;
- char *buf;
- unsigned char *recordStart, *pStart;
- uint16_t crc, tt, pdl, snl, offset, bufsize=MRB_DUMP_DEFAULT_STR_LEN;
- mrb_int fix_num;
- mrb_float f;
- int plen;
+ int ret;
+ size_t i;
+ const uint8_t *src = bin;
+ uint16_t tt, pool_data_len, snl;
+ size_t plen;
int ai = mrb_gc_arena_save(mrb);
mrb_irep *irep = mrb_add_irep(mrb);
- recordStart = src;
- buf = (char *)mrb_malloc(mrb, bufsize);
- if (buf == NULL) {
- ret = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
+ // skip record size
+ src += sizeof(uint32_t);
+
+ // number of local variable
+ irep->nlocals = bin_to_uint16(src);
+ src += sizeof(uint16_t);
- //Header Section
- pStart = src;
- if (*src != RITE_IREP_IDENFIFIER)
- return MRB_DUMP_INVALID_IREP;
- src += (sizeof(unsigned char) * 2);
- irep->nlocals = bin_to_uint16(src); //number of local variable
- src += MRB_DUMP_SIZE_OF_SHORT;
- irep->nregs = bin_to_uint16(src); //number of register variable
- src += MRB_DUMP_SIZE_OF_SHORT;
- offset = bin_to_uint16(src); //offset of isec block
- src += MRB_DUMP_SIZE_OF_SHORT;
- crc = calc_crc_16_ccitt(pStart, src - pStart); //Calculate CRC
- if (crc != bin_to_uint16(src)) //header CRC
- return MRB_DUMP_INVALID_IREP;
- src += offset;
-
- //Binary Data Section
- //ISEQ BLOCK
- pStart = src;
- irep->ilen = bin_to_uint32(src); //iseq length
- src += MRB_DUMP_SIZE_OF_LONG;
+ // number of register variable
+ irep->nregs = bin_to_uint16(src);
+ src += sizeof(uint16_t);
+
+ // Binary Data Section
+ // ISEQ BLOCK
+ irep->ilen = bin_to_uint32(src);
+ src += sizeof(uint32_t);
if (irep->ilen > 0) {
irep->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen);
if (irep->iseq == NULL) {
ret = MRB_DUMP_GENERAL_FAILURE;
goto error_exit;
}
- for (i=0; i<irep->ilen; i++) {
+ for (i = 0; i < irep->ilen; i++) {
irep->iseq[i] = bin_to_uint32(src); //iseq
- src += MRB_DUMP_SIZE_OF_LONG;
+ src += sizeof(uint32_t);
}
}
- crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC
- if (crc != bin_to_uint16(src)) { //iseq CRC
- ret = MRB_DUMP_INVALID_IREP;
- goto error_exit;
- }
- src += MRB_DUMP_SIZE_OF_SHORT;
//POOL BLOCK
- pStart = src;
- plen = bin_to_uint32(src); //pool length
- src += MRB_DUMP_SIZE_OF_LONG;
+ plen = bin_to_uint32(src); /* number of pool */
+ src += sizeof(uint32_t);
if (plen > 0) {
irep->pool = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value) * plen);
if (irep->pool == NULL) {
@@ -417,37 +82,24 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len)
goto error_exit;
}
- for (i=0; i<plen; i++) {
- tt = *src; //pool TT
- src += sizeof(unsigned char);
- pdl = bin_to_uint16(src); //pool data length
- src += MRB_DUMP_SIZE_OF_SHORT;
- if (pdl > bufsize - 1) {
- mrb_free(mrb, buf);
- bufsize = pdl + 1;
- buf = (char *)mrb_malloc(mrb, bufsize);
- if (buf == NULL) {
- ret = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
- }
- memcpy(buf, src, pdl);
- src += pdl;
- buf[pdl] = '\0';
-
- switch (tt) { //pool data
+ for (i = 0; i < plen; i++) {
+ mrb_value s;
+ tt = *src++; //pool TT
+ pool_data_len = bin_to_uint16(src); //pool data length
+ src += sizeof(uint16_t);
+ s = mrb_str_new(mrb, (char *)src, pool_data_len);
+ src += pool_data_len;
+ switch (tt) { //pool data
case MRB_TT_FIXNUM:
- fix_num = str_to_mrb_int(buf);
- irep->pool[i] = mrb_fixnum_value(fix_num);
+ irep->pool[i] = mrb_str_to_inum(mrb, s, 10, FALSE);
break;
case MRB_TT_FLOAT:
- f = str_to_mrb_float(buf);
- irep->pool[i] = mrb_float_value(f);
+ irep->pool[i] = mrb_float_value(mrb_str_to_dbl(mrb, s, FALSE));
break;
case MRB_TT_STRING:
- irep->pool[i] = mrb_str_new(mrb, buf, pdl);
+ irep->pool[i] = s;
break;
default:
@@ -458,17 +110,10 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len)
mrb_gc_arena_restore(mrb, ai);
}
}
- crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC
- if (crc != bin_to_uint16(src)) { //pool CRC
- ret = MRB_DUMP_INVALID_IREP;
- goto error_exit;
- }
- src += MRB_DUMP_SIZE_OF_SHORT;
//SYMS BLOCK
- pStart = src;
- irep->slen = bin_to_uint32(src); //syms length
- src += MRB_DUMP_SIZE_OF_LONG;
+ irep->slen = bin_to_uint32(src); //syms length
+ src += sizeof(uint32_t);
if (irep->slen > 0) {
irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen);
if (irep->syms == NULL) {
@@ -477,83 +122,56 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len)
}
for (i = 0; i < irep->slen; i++) {
- static const mrb_sym mrb_sym_zero = { 0 };
- *irep->syms = mrb_sym_zero;
- }
- for (i=0; i<irep->slen; i++) {
snl = bin_to_uint16(src); //symbol name length
- src += MRB_DUMP_SIZE_OF_SHORT;
+ src += sizeof(uint16_t);
if (snl == MRB_DUMP_NULL_SYM_LEN) {
irep->syms[i] = 0;
continue;
}
- if (snl > bufsize - 1) {
- mrb_free(mrb, buf);
- bufsize = snl + 1;
- buf = (char *)mrb_malloc(mrb, bufsize);
- if (buf == NULL) {
- ret = MRB_DUMP_GENERAL_FAILURE;
- goto error_exit;
- }
- }
- memcpy(buf, src, snl); //symbol name
- src += snl;
- buf[snl] = '\0';
- irep->syms[i] = mrb_intern2(mrb, buf, snl);
+ irep->syms[i] = mrb_intern2(mrb, (char *)src, snl);
+ src += snl + 1;
+
+ mrb_gc_arena_restore(mrb, ai);
}
}
- crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC
- if (crc != bin_to_uint16(src)) { //syms CRC
- ret = MRB_DUMP_INVALID_IREP;
- goto error_exit;
- }
- src += MRB_DUMP_SIZE_OF_SHORT;
+ *len = src - bin;
- *len = src - recordStart;
+ ret = MRB_DUMP_OK;
error_exit:
- mrb_free(mrb, buf);
-
return ret;
}
-int
-mrb_read_irep(mrb_state *mrb, const char *bin)
+static int
+read_rite_section_irep(mrb_state *mrb, const uint8_t *bin)
{
- int ret = MRB_DUMP_OK, i, n, nirep, sirep;
- uint32_t len = 0;
- unsigned char *src;
- rite_binary_header bin_header;
+ int result;
+ size_t sirep;
+ size_t i;
+ uint32_t len;
+ uint16_t nirep;
+ uint16_t n;
+ const struct rite_section_irep_header *header;
- if ((mrb == NULL) || (bin == NULL)) {
- return MRB_DUMP_INVALID_ARGUMENT;
- }
- src = (unsigned char*)bin;
- sirep = mrb->irep_len;
+ header = (const struct rite_section_irep_header*)bin;
+ bin += sizeof(struct rite_section_irep_header);
- //Read File Header Section
- nirep = read_rite_header(mrb, src, &bin_header);
- if (nirep < 0)
- return nirep;
-
- src += sizeof(bin_header) + MRB_DUMP_SIZE_OF_SHORT; //header + crc
+ sirep = mrb->irep_len;
+ nirep = bin_to_uint16(header->nirep);
//Read Binary Data Section
- for (n=0,i=sirep; n<nirep; n++,i++) {
- src += MRB_DUMP_SIZE_OF_LONG; //record ren
- ret = read_rite_irep_record(mrb, src, &len);
- if (ret != MRB_DUMP_OK)
+ for (n = 0, i = sirep; n < nirep; n++, i++) {
+ result = read_rite_irep_record(mrb, bin, &len);
+ if (result != MRB_DUMP_OK)
goto error_exit;
- src += len;
- }
- if (0 != bin_to_uint32(src)) { //dummy record len
- ret = MRB_DUMP_GENERAL_FAILURE;
+ bin += len;
}
+ result = MRB_DUMP_OK;
error_exit:
- if (ret != MRB_DUMP_OK) {
- for (n=0,i=sirep; i<mrb->irep_len; n++,i++) {
+ if (result != MRB_DUMP_OK) {
+ for (i = sirep; i < mrb->irep_len; i++) {
if (mrb->irep[i]) {
if (mrb->irep[i]->iseq)
mrb_free(mrb, mrb->irep[i]->iseq);
@@ -567,143 +185,385 @@ error_exit:
mrb_free(mrb, mrb->irep[i]);
}
}
- // mrb->irep_len = sirep;
- return ret;
+ return result;
}
- return sirep + hex_to_uint8(bin_header.sirep);
+ return sirep + bin_to_uint16(header->sirep);
}
-static uint16_t
-hex_to_bin8(unsigned char *dst, unsigned char *src)
+static int
+read_rite_lineno_record(mrb_state *mrb, const uint8_t *bin, size_t irepno, uint32_t *len)
{
- dst[0] = (hex2bin[src[0]] << 4) | (hex2bin[src[1]]);
- return 1;
-}
+ int ret;
+ size_t i, fname_len, niseq;
+ char *fname;
+ uint16_t *lines;
+
+ ret = MRB_DUMP_OK;
+ *len = 0;
+ bin += sizeof(uint32_t); // record size
+ *len += sizeof(uint32_t);
+ fname_len = bin_to_uint16(bin);
+ bin += sizeof(uint16_t);
+ *len += sizeof(uint16_t);
+ fname = (char *)mrb_malloc(mrb, fname_len + 1);
+ if (fname == NULL) {
+ ret = MRB_DUMP_GENERAL_FAILURE;
+ goto error_exit;
+ }
+ memcpy(fname, bin, fname_len);
+ fname[fname_len] = '\0';
+ bin += fname_len;
+ *len += fname_len;
-static uint16_t
-hex_to_bin16(unsigned char *dst, unsigned char *src)
-{
- dst[0] = (hex2bin[src[0]] << 4) | (hex2bin[src[1]]);
- dst[1] = (hex2bin[src[2]] << 4) | (hex2bin[src[3]]);
- return 2;
-}
+ niseq = bin_to_uint32(bin);
+ bin += sizeof(uint32_t); // niseq
+ *len += sizeof(uint32_t);
-static uint16_t
-hex_to_bin32(unsigned char *dst, unsigned char *src)
-{
- dst[0] = (hex2bin[src[0]] << 4) | (hex2bin[src[1]]);
- dst[1] = (hex2bin[src[2]] << 4) | (hex2bin[src[3]]);
- dst[2] = (hex2bin[src[4]] << 4) | (hex2bin[src[5]]);
- dst[3] = (hex2bin[src[6]] << 4) | (hex2bin[src[7]]);
- return 4;
-}
+ lines = (uint16_t *)mrb_malloc(mrb, niseq * sizeof(uint16_t));
+ for (i = 0; i < niseq; i++) {
+ lines[i] = bin_to_uint16(bin);
+ bin += sizeof(uint16_t); // niseq
+ *len += sizeof(uint16_t);
+ }
-static uint8_t
-hex_to_uint8(unsigned char *hex)
-{
- return (unsigned char)hex2bin[hex[0]] << 4 |
- (unsigned char)hex2bin[hex[1]];
+ mrb->irep[irepno]->filename = fname;
+ mrb->irep[irepno]->lines = lines;
+
+error_exit:
+ return ret;
}
-static uint16_t
-hex_to_uint16(unsigned char *hex)
+static int
+read_rite_section_lineno(mrb_state *mrb, const uint8_t *bin, size_t sirep)
{
- return (uint16_t)hex2bin[hex[0]] << 12 |
- (uint16_t)hex2bin[hex[1]] << 8 |
- (uint16_t)hex2bin[hex[2]] << 4 |
- (uint16_t)hex2bin[hex[3]];
+ int result;
+ size_t i;
+ uint32_t len;
+ uint16_t nirep;
+ uint16_t n;
+ const struct rite_section_lineno_header *header;
+
+ len = 0;
+ header = (const struct rite_section_lineno_header*)bin;
+ bin += sizeof(struct rite_section_lineno_header);
+
+ nirep = bin_to_uint16(header->nirep);
+
+ //Read Binary Data Section
+ for (n = 0, i = sirep; n < nirep; n++, i++) {
+ result = read_rite_lineno_record(mrb, bin, i, &len);
+ if (result != MRB_DUMP_OK)
+ goto error_exit;
+ bin += len;
+ }
+
+ result = MRB_DUMP_OK;
+error_exit:
+ if (result != MRB_DUMP_OK) {
+ return result;
+ }
+ return sirep + bin_to_uint16(header->sirep);
}
-static uint32_t
-hex_to_uint32(unsigned char *hex)
+
+static int
+read_rite_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc)
{
- return (uint32_t)hex2bin[hex[0]] << 28 |
- (uint32_t)hex2bin[hex[1]] << 24 |
- (uint32_t)hex2bin[hex[2]] << 20 |
- (uint32_t)hex2bin[hex[3]] << 16 |
- (uint32_t)hex2bin[hex[4]] << 12 |
- (uint32_t)hex2bin[hex[5]] << 8 |
- (uint32_t)hex2bin[hex[6]] << 4 |
- (uint32_t)hex2bin[hex[7]];
+ const struct rite_binary_header *header = (const struct rite_binary_header *)bin;
+
+ if(memcmp(header->binary_identify, RITE_BINARY_IDENFIFIER, sizeof(header->binary_identify)) != 0) {
+ return MRB_DUMP_INVALID_FILE_HEADER;
+ }
+
+ if(memcmp(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)) != 0) {
+ return MRB_DUMP_INVALID_FILE_HEADER;
+ }
+
+ *crc = bin_to_uint16(header->binary_crc);
+ if (bin_size) {
+ *bin_size = bin_to_uint32(header->binary_size);
+ }
+
+ return MRB_DUMP_OK;
}
-static char*
-hex_to_str(char *hex, char *str, uint16_t *str_len)
+int32_t
+mrb_read_irep(mrb_state *mrb, const uint8_t *bin)
{
- char *src, *dst, buf[4];
- int escape = 0, base = 0;
- char *err_ptr;
-
- *str_len = 0;
- for (src = hex, dst = str; *src != '\0'; src++) {
- if (escape) {
- switch(*src) {
- case 'a': *dst++ = '\a'/* BEL */; break;
- case 'b': *dst++ = '\b'/* BS */; break;
- case 't': *dst++ = '\t'/* HT */; break;
- case 'n': *dst++ = '\n'/* LF */; break;
- case 'v': *dst++ = '\v'/* VT */; break;
- case 'f': *dst++ = '\f'/* FF */; break;
- case 'r': *dst++ = '\r'/* CR */; break;
- case '\"': /* fall through */
- case '\'': /* fall through */
- case '\?': /* fall through */
- case '\\': *dst++ = *src; break;
- default:
- if (*src >= '0' && *src <= '7') {
- base = 8;
- strncpy(buf, src, 3);
- } else if (*src == 'x' || *src == 'X') {
- base = 16;
- src++;
- strncpy(buf, src, 2);
- }
-
- *dst++ = (unsigned char) strtol(buf, &err_ptr, base) & 0xff;
- src += (err_ptr - buf - 1);
- break;
- }
- escape = 0;
- } else {
- if (*src == '\\') {
- escape = 1;
- } else {
- escape = 0;
- *dst++ = *src;
+ int result;
+ int32_t total_nirep = 0;
+ const struct rite_section_header *section_header;
+ uint16_t crc;
+ size_t bin_size = 0;
+ size_t n;
+ size_t sirep;
+
+ if ((mrb == NULL) || (bin == NULL)) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
+
+ result = read_rite_binary_header(bin, &bin_size, &crc);
+ if(result != MRB_DUMP_OK) {
+ return result;
+ }
+
+ n = offset_crc_body();
+ if(crc != calc_crc_16_ccitt(bin + n, bin_size - n, 0)) {
+ return MRB_DUMP_INVALID_FILE_HEADER;
+ }
+
+ bin += sizeof(struct rite_binary_header);
+ sirep = mrb->irep_len;
+
+ do {
+ section_header = (const struct rite_section_header *)bin;
+ if(memcmp(section_header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(section_header->section_identify)) == 0) {
+ result = read_rite_section_irep(mrb, bin);
+ if(result < MRB_DUMP_OK) {
+ return result;
}
+ total_nirep += result;
}
- if (!escape) {
- (*str_len)++;
+ else if(memcmp(section_header->section_identify, RITE_SECTION_LIENO_IDENTIFIER, sizeof(section_header->section_identify)) == 0) {
+ result = read_rite_section_lineno(mrb, bin, sirep);
+ if(result < MRB_DUMP_OK) {
+ return result;
+ }
}
- }
- return str;
+ bin += bin_to_uint32(section_header->section_size);
+ } while(memcmp(section_header->section_identify, RITE_BINARY_EOF, sizeof(section_header->section_identify)) != 0);
+
+ return total_nirep;
}
static void
irep_error(mrb_state *mrb, int n)
{
static const char msg[] = "irep load error";
- mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1));
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1));
}
-#ifdef ENABLE_STDIO
mrb_value
-mrb_load_irep_file(mrb_state *mrb, FILE* fp)
+mrb_load_irep(mrb_state *mrb, const uint8_t *bin)
{
- int n = mrb_read_irep_file(mrb, fp);
+ int32_t n;
+ n = mrb_read_irep(mrb, bin);
if (n < 0) {
irep_error(mrb, n);
return mrb_nil_value();
}
return mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
}
-#endif
+
+#ifdef ENABLE_STDIO
+
+static int32_t
+read_rite_section_lineno_file(mrb_state *mrb, FILE *fp, size_t sirep)
+{
+ int32_t result;
+ size_t i;
+ uint16_t nirep;
+ uint16_t n;
+ uint32_t len, buf_size;
+ uint8_t *buf = NULL;
+ const size_t record_header_size = 4;
+
+ struct rite_section_lineno_header header;
+ if (fread(&header, sizeof(struct rite_section_lineno_header), 1, fp) == 0) {
+ return MRB_DUMP_READ_FAULT;
+ }
+
+ nirep = bin_to_uint16(header.nirep);
+
+ buf_size = record_header_size;
+ buf = (uint8_t *)mrb_malloc(mrb, buf_size);
+
+ //Read Binary Data Section
+ for (n = 0, i = sirep; n < nirep; n++, i++) {
+ if (fread(buf, record_header_size, 1, fp) == 0) {
+ result = MRB_DUMP_READ_FAULT;
+ goto error_exit;
+ }
+ buf_size = bin_to_uint32(&buf[0]);
+ buf = (uint8_t *)mrb_realloc(mrb, buf, buf_size);
+
+ if (fread(&buf[record_header_size], buf_size - record_header_size, 1, fp) == 0) {
+ result = MRB_DUMP_READ_FAULT;
+ goto error_exit;
+ }
+ result = read_rite_lineno_record(mrb, buf, i, &len);
+ if (result != MRB_DUMP_OK)
+ goto error_exit;
+ }
+
+ result = MRB_DUMP_OK;
+error_exit:
+ mrb_free(mrb, buf);
+ if (result != MRB_DUMP_OK) {
+ for (i = sirep; i < mrb->irep_len; i++) {
+ if (mrb->irep[i]) {
+ if (mrb->irep[i]->iseq)
+ mrb_free(mrb, mrb->irep[i]->iseq);
+
+ if (mrb->irep[i]->pool)
+ mrb_free(mrb, mrb->irep[i]->pool);
+
+ if (mrb->irep[i]->syms)
+ mrb_free(mrb, mrb->irep[i]->syms);
+
+ mrb_free(mrb, mrb->irep[i]);
+ }
+ }
+ return result;
+ }
+ return sirep + bin_to_uint16(header.sirep);
+}
+
+static int32_t
+read_rite_section_irep_file(mrb_state *mrb, FILE *fp)
+{
+ int32_t result;
+ size_t sirep;
+ size_t i;
+ uint16_t nirep;
+ uint16_t n;
+ uint32_t len, buf_size;
+ uint8_t *buf = NULL;
+ const size_t record_header_size = 1 + 4;
+ struct rite_section_irep_header header;
+
+ if (fread(&header, sizeof(struct rite_section_irep_header), 1, fp) == 0) {
+ return MRB_DUMP_READ_FAULT;
+ }
+
+ sirep = mrb->irep_len;
+ nirep = bin_to_uint16(header.nirep);
+
+ buf_size = record_header_size;
+ buf = (uint8_t *)mrb_malloc(mrb, buf_size);
+
+ //Read Binary Data Section
+ for (n = 0, i = sirep; n < nirep; n++, i++) {
+ if (fread(buf, record_header_size, 1, fp) == 0) {
+ result = MRB_DUMP_READ_FAULT;
+ goto error_exit;
+ }
+ buf_size = bin_to_uint32(&buf[0]);
+ buf = (uint8_t *)mrb_realloc(mrb, buf, buf_size);
+ if (fread(&buf[record_header_size], buf_size - record_header_size, 1, fp) == 0) {
+ result = MRB_DUMP_READ_FAULT;
+ goto error_exit;
+ }
+ result = read_rite_irep_record(mrb, buf, &len);
+ if (result != MRB_DUMP_OK)
+ goto error_exit;
+ }
+
+ result = MRB_DUMP_OK;
+error_exit:
+ mrb_free(mrb, buf);
+ if (result != MRB_DUMP_OK) {
+ for (i = sirep; i < mrb->irep_len; i++) {
+ if (mrb->irep[i]) {
+ if (mrb->irep[i]->iseq)
+ mrb_free(mrb, mrb->irep[i]->iseq);
+
+ if (mrb->irep[i]->pool)
+ mrb_free(mrb, mrb->irep[i]->pool);
+
+ if (mrb->irep[i]->syms)
+ mrb_free(mrb, mrb->irep[i]->syms);
+
+ mrb_free(mrb, mrb->irep[i]);
+ }
+ }
+ return result;
+ }
+ return sirep + bin_to_uint16(header.sirep);
+}
+
+int32_t
+mrb_read_irep_file(mrb_state *mrb, FILE* fp)
+{
+ int result;
+ int32_t total_nirep = 0;
+ uint8_t *buf;
+ uint16_t crc, crcwk = 0;
+ uint32_t section_size = 0;
+ size_t nbytes;
+ size_t sirep;
+ struct rite_section_header section_header;
+ long fpos;
+ const size_t block_size = 1 << 14;
+ const size_t buf_size = sizeof(struct rite_binary_header);
+
+ if ((mrb == NULL) || (fp == NULL)) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
+
+ buf = mrb_malloc(mrb, buf_size);
+ if (fread(buf, buf_size, 1, fp) == 0) {
+ mrb_free(mrb, buf);
+ return MRB_DUMP_READ_FAULT;
+ }
+ result = read_rite_binary_header(buf, NULL, &crc);
+ mrb_free(mrb, buf);
+ if(result != MRB_DUMP_OK) {
+ return result;
+ }
+
+ /* verify CRC */
+ fpos = ftell(fp);
+ buf = mrb_malloc(mrb, block_size);
+ fseek(fp, offset_crc_body(), SEEK_SET);
+ while((nbytes = fread(buf, 1, block_size, fp)) > 0) {
+ crcwk = calc_crc_16_ccitt(buf, nbytes, crcwk);
+ }
+ mrb_free(mrb, buf);
+ if (nbytes == 0 && ferror(fp)) {
+ return MRB_DUMP_READ_FAULT;
+ }
+ if(crcwk != crc) {
+ return MRB_DUMP_INVALID_FILE_HEADER;
+ }
+ fseek(fp, fpos + section_size, SEEK_SET);
+ sirep = mrb->irep_len;
+
+ // read sections
+ do {
+ fpos = ftell(fp);
+ if (fread(&section_header, sizeof(struct rite_section_header), 1, fp) == 0) {
+ return MRB_DUMP_READ_FAULT;
+ }
+ section_size = bin_to_uint32(section_header.section_size);
+
+ if(memcmp(section_header.section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(section_header.section_identify)) == 0) {
+ fseek(fp, fpos, SEEK_SET);
+ result = read_rite_section_irep_file(mrb, fp);
+ if(result < MRB_DUMP_OK) {
+ return result;
+ }
+ total_nirep += result;
+ }
+ else if(memcmp(section_header.section_identify, RITE_SECTION_LIENO_IDENTIFIER, sizeof(section_header.section_identify)) == 0) {
+ fseek(fp, fpos, SEEK_SET);
+ result = read_rite_section_lineno_file(mrb, fp, sirep);
+ if(result < MRB_DUMP_OK) {
+ return result;
+ }
+ }
+
+ fseek(fp, fpos + section_size, SEEK_SET);
+ } while(memcmp(section_header.section_identify, RITE_BINARY_EOF, sizeof(section_header.section_identify)) != 0);
+
+ return total_nirep;
+}
mrb_value
-mrb_load_irep(mrb_state *mrb, const char *bin)
+mrb_load_irep_file(mrb_state *mrb, FILE* fp)
{
- int n = mrb_read_irep(mrb, bin);
+ int n = mrb_read_irep_file(mrb, fp);
if (n < 0) {
irep_error(mrb, n);
@@ -711,3 +571,4 @@ mrb_load_irep(mrb_state *mrb, const char *bin)
}
return mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
}
+#endif /* ENABLE_STDIO */
diff --git a/src/node.h b/src/node.h
index 284105023..df27c431f 100644
--- a/src/node.h
+++ b/src/node.h
@@ -4,6 +4,9 @@
** See Copyright Notice in mruby.h
*/
+#ifndef NODE_H
+#define NODE_H
+
enum node_type {
NODE_METHOD,
NODE_FBODY,
@@ -62,6 +65,8 @@ enum node_type {
NODE_SYM,
NODE_STR,
NODE_DSTR,
+ NODE_XSTR,
+ NODE_DXSTR,
NODE_REGX,
NODE_DREGX,
NODE_DREGX_ONCE,
@@ -102,5 +107,11 @@ enum node_type {
NODE_IFUNC,
NODE_DSYM,
NODE_ATTRASGN,
+ NODE_HEREDOC,
+ NODE_LITERAL_DELIM,
+ NODE_WORDS,
+ NODE_SYMBOLS,
NODE_LAST
};
+
+#endif /* NODE_H */
diff --git a/src/numeric.c b/src/numeric.c
index b5bff652d..4ada58a34 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -4,26 +4,22 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/numeric.h"
-#include "mruby/string.h"
-#include "mruby/array.h"
-
-#include <math.h>
-#include <stdio.h>
#include <assert.h>
-
-#if defined(__FreeBSD__) && __FreeBSD__ < 4
-#include <floatingpoint.h>
-#endif
-
-#ifdef HAVE_FLOAT_H
#include <float.h>
+#if defined(__FreeBSD__) && __FreeBSD__ < 4
+# include <floatingpoint.h>
#endif
-
#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
+# include <ieeefp.h>
#endif
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "mruby.h"
+#include "mruby/array.h"
+#include "mruby/numeric.h"
+#include "mruby/string.h"
#ifdef MRB_USE_FLOAT
#define floor(f) floorf(f)
@@ -166,6 +162,105 @@ num_abs(mrb_state *mrb, mrb_value num)
* representation.
*/
+mrb_value
+mrb_flo_to_str(mrb_state *mrb, mrb_value flo, int max_digit)
+{
+ mrb_value result;
+ mrb_float n;
+
+ if (max_digit > 40) {
+ mrb_raise(mrb, E_RANGE_ERROR, "Too large max_digit.");
+ }
+ else if (!mrb_float_p(flo)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "non float value");
+ }
+
+ n = mrb_float(flo);
+
+ if (isnan(n)) {
+ result = mrb_str_new(mrb, "NaN", 3);
+ }
+ else if (isinf(n)) {
+ if (n < 0) {
+ result = mrb_str_new(mrb, "-inf", 4);
+ }
+ else {
+ result = mrb_str_new(mrb, "inf", 3);
+ }
+ }
+ else {
+ int digit;
+ int m;
+ int exp;
+ int e = 0;
+ char s[48];
+ char *c = &s[0];
+
+ if (n < 0) {
+ n = -n;
+ *(c++) = '-';
+ }
+
+ exp = log10(n);
+
+ if ((exp < 0 ? -exp : exp) > max_digit) {
+ /* exponent representation */
+ e = 1;
+ m = exp;
+ if (m < 0) {
+ m -= 1;
+ }
+ n = n / pow(10.0, m);
+ m = 0;
+ }
+ else {
+ /* un-exponent (normal) representation */
+ m = exp;
+ if (m < 0) {
+ m = 0;
+ }
+ }
+
+ /* puts digits */
+ while (max_digit >= 0) {
+ mrb_float weight = pow(10.0, m);
+ digit = floor(n / weight + FLT_EPSILON);
+ *(c++) = '0' + digit;
+ n -= (digit * weight);
+ max_digit--;
+ if (m-- == 0) {
+ *(c++) = '.';
+ }
+ else if (m < -1 && n < FLT_EPSILON) {
+ break;
+ }
+ }
+
+ if (e) {
+ *(c++) = 'e';
+ if (exp > 0) {
+ *(c++) = '+';
+ } else {
+ *(c++) = '-';
+ exp = -exp;
+ }
+
+ if (exp >= 100) {
+ mrb_raise(mrb, E_RANGE_ERROR, "Too large expornent.");
+ }
+
+ *(c++) = '0' + exp / 10;
+ *(c++) = '0' + exp % 10;
+ }
+
+ *c = '\0';
+
+ result = mrb_str_new(mrb, &s[0], c - &s[0]);
+ }
+
+ return result;
+}
+
/* 15.2.9.3.16(x) */
/*
* call-seq:
@@ -180,27 +275,11 @@ num_abs(mrb_state *mrb, mrb_value num)
static mrb_value
flo_to_s(mrb_state *mrb, mrb_value flt)
{
- char buf[32];
- int n;
-
- mrb_float value = mrb_float(flt);
-
- if (isinf(value)) {
- static const char s[2][5] = { "-inf", "inf" };
- static const int n[] = { 4, 3 };
- int idx;
- idx = (value < 0) ? 0 : 1;
- return mrb_str_new(mrb, s[idx], n[idx]);
- } else if(isnan(value))
- return mrb_str_new(mrb, "NaN", 3);
-
#ifdef MRB_USE_FLOAT
- n = sprintf(buf, "%.7g", value);
+ return mrb_flo_to_str(mrb, flt, 7);
#else
- n = sprintf(buf, "%.14g", value);
+ return mrb_flo_to_str(mrb, flt, 14);
#endif
- assert(n >= 0);
- return mrb_str_new(mrb, buf, n);
}
/* 15.2.9.3.2 */
@@ -306,15 +385,17 @@ static mrb_value
num_eql(mrb_state *mrb, mrb_value x)
{
mrb_value y;
-
+ mrb_bool eql_p;
+
mrb_get_args(mrb, "o", &y);
- if (mrb_type(x) != mrb_type(y)) return mrb_false_value();
- if (mrb_equal(mrb, x, y)) {
- return mrb_true_value();
+ if (mrb_type(x) != mrb_type(y)) {
+ eql_p = 0;
}
else {
- return mrb_false_value();
+ eql_p = mrb_equal(mrb, x, y);
}
+
+ return mrb_bool_value(eql_p);
}
static mrb_value
@@ -356,7 +437,7 @@ flo_eq(mrb_state *mrb, mrb_value x)
return num_equal(mrb, x, y);
}
a = mrb_float(x);
- return (a == b)?mrb_true_value():mrb_false_value();
+ return mrb_bool_value(a == b);
}
/* 15.2.8.3.18 */
@@ -371,7 +452,8 @@ flo_hash(mrb_state *mrb, mrb_value num)
{
mrb_float d;
char *c;
- int i, hash;
+ size_t i;
+ int hash;
d = (mrb_float)mrb_fixnum(num);
/* normalize -0.0 to 0.0 */
@@ -437,10 +519,11 @@ static mrb_value
flo_finite_p(mrb_state *mrb, mrb_value num)
{
mrb_float value = mrb_float(num);
+ mrb_bool finite_p;
- if (isinf(value) || isnan(value))
- return mrb_false_value();
- return mrb_true_value();
+ finite_p = !(isinf(value) || isnan(value));
+
+ return mrb_bool_value(finite_p);
}
/* 15.2.9.3.10 */
@@ -568,7 +651,6 @@ flo_round(mrb_state *mrb, mrb_value num)
/*
* call-seq:
* flt.to_i -> integer
- * flt.to_int -> integer
* flt.truncate -> integer
*
* Returns <i>flt</i> truncated to an <code>Integer</code>.
@@ -639,7 +721,6 @@ num_round(mrb_state *mrb, mrb_value num)
/*
* call-seq:
* int.to_i -> integer
- * int.to_int -> integer
* int.floor -> integer
* int.ceil -> integer
* int.round -> integer
@@ -699,7 +780,7 @@ mrb_value
mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
{
mrb_int a;
-
+
a = mrb_fixnum(x);
if (a == 0) return x;
if (mrb_fixnum_p(y)) {
@@ -817,7 +898,7 @@ fix_divmod(mrb_state *mrb, mrb_value x)
if (mrb_fixnum(y) == 0) {
return mrb_assoc_new(mrb, mrb_float_value(str_to_mrb_float("inf")),
- mrb_float_value(str_to_mrb_float("nan")));
+ mrb_float_value(str_to_mrb_float("nan")));
}
fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod);
return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod));
@@ -849,19 +930,15 @@ static mrb_value
fix_equal(mrb_state *mrb, mrb_value x)
{
mrb_value y;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &y);
- if (mrb_obj_equal(mrb, x, y)) return mrb_true_value();
- switch (mrb_type(y)) {
- case MRB_TT_FLOAT:
- if ((mrb_float)mrb_fixnum(x) == mrb_float(y))
- return mrb_true_value();
- /* fall through */
- case MRB_TT_FIXNUM:
- default:
- return mrb_false_value();
- }
+ equal_p = mrb_obj_equal(mrb, x, y) ||
+ (mrb_type(y) == MRB_TT_FLOAT &&
+ (mrb_float)mrb_fixnum(x) == mrb_float(y));
+
+ return mrb_bool_value(equal_p);
}
/* 15.2.8.3.8 */
@@ -959,14 +1036,15 @@ fix_xor(mrb_state *mrb, mrb_value x)
return mrb_fixnum_value(val);
}
-#define NUMERIC_SHIFT_WIDTH_MAX (sizeof(mrb_int)*CHAR_BIT-1)
+#define NUMERIC_SHIFT_WIDTH_MAX (sizeof(mrb_int)*CHAR_BIT-1)
static mrb_value
lshift(mrb_state *mrb, mrb_int val, int width)
{
if (width > NUMERIC_SHIFT_WIDTH_MAX) {
- mrb_raisef(mrb, E_RANGE_ERROR, "width(%d) > (%d:sizeof(mrb_int)*CHAR_BIT-1)", width,
- NUMERIC_SHIFT_WIDTH_MAX);
+ mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:sizeof(mrb_int)*CHAR_BIT-1)",
+ mrb_fixnum_value(width),
+ mrb_fixnum_value(NUMERIC_SHIFT_WIDTH_MAX));
}
val = val << width;
return mrb_fixnum_value(val);
@@ -1101,32 +1179,34 @@ fix_to_f(mrb_state *mrb, mrb_value num)
* FloatDomainError: Infinity
*/
/* ------------------------------------------------------------------------*/
-static mrb_int
-flt2big(mrb_state *mrb, mrb_float d)
+mrb_value
+mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x)
{
mrb_int z;
- if (isinf(d)) {
- mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity");
- }
- if (isnan(d)) {
- mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
+ if (mrb_float_p(x)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "non float value");
+ z = 0; /* not reached. just supress warnings. */
}
- z = (mrb_int)d;
- return z;
-}
+ else {
+ mrb_float d = mrb_float(x);
-mrb_value
-mrb_flt2big(mrb_state *mrb, mrb_float d)
-{
- return mrb_fixnum_value(flt2big(mrb, d));
+ if (isinf(d)) {
+ mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity");
+ }
+ if (isnan(d)) {
+ mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
+ }
+ z = (mrb_int)d;
+ }
+ return mrb_fixnum_value(z);
}
mrb_value
mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
{
mrb_int a;
-
+
a = mrb_fixnum(x);
if (a == 0) return y;
if (mrb_fixnum_p(y)) {
@@ -1165,7 +1245,7 @@ mrb_value
mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
{
mrb_int a;
-
+
a = mrb_fixnum(x);
if (mrb_fixnum_p(y)) {
mrb_int b, c;
@@ -1202,14 +1282,14 @@ fix_minus(mrb_state *mrb, mrb_value self)
mrb_value
-mrb_fix2str(mrb_state *mrb, mrb_value x, int base)
+mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base)
{
char buf[sizeof(mrb_int)*CHAR_BIT+1];
char *b = buf + sizeof buf;
mrb_int val = mrb_fixnum(x);
if (base < 2 || 36 < base) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %d", base);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base));
}
if (val == 0) {
@@ -1250,7 +1330,7 @@ fix_to_s(mrb_state *mrb, mrb_value self)
mrb_int base = 10;
mrb_get_args(mrb, "|i", &base);
- return mrb_fix2str(mrb, self, base);
+ return mrb_fixnum_to_str(mrb, self, base);
}
/* 15.2.9.3.6 */
@@ -1330,6 +1410,8 @@ mrb_init_numeric(mrb_state *mrb)
/* Integer Class */
integer = mrb_define_class(mrb, "Integer", numeric);
+ mrb_undef_class_method(mrb, integer, "new");
+ mrb_define_method(mrb, integer, "to_i", int_to_i, ARGS_NONE()); /* 15.2.8.3.24 */
fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer);
mrb_undef_class_method(mrb, fixnum, "new");
@@ -1353,7 +1435,6 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, fixnum, "round", num_round, ARGS_ANY()); /* 15.2.8.3.20 */
mrb_define_method(mrb, fixnum, "succ", fix_succ, ARGS_NONE()); /* 15.2.8.3.21 */
mrb_define_method(mrb, fixnum, "to_f", fix_to_f, ARGS_NONE()); /* 15.2.8.3.23 */
- mrb_define_method(mrb, fixnum, "to_i", int_to_i, ARGS_NONE()); /* 15.2.8.3.24 */
mrb_define_method(mrb, fixnum, "to_s", fix_to_s, ARGS_NONE()); /* 15.2.8.3.25 */
mrb_define_method(mrb, fixnum, "inspect", fix_to_s, ARGS_NONE());
mrb_define_method(mrb, fixnum, "truncate", int_to_i, ARGS_NONE()); /* 15.2.8.3.26 */
diff --git a/src/object.c b/src/object.c
index 6707fc6e4..bc59b615e 100644
--- a/src/object.c
+++ b/src/object.c
@@ -5,11 +5,9 @@
*/
#include "mruby.h"
-#include <string.h>
-#include "mruby/string.h"
-#include <stdio.h>
#include "mruby/class.h"
#include "mruby/numeric.h"
+#include "mruby/string.h"
#include "error.h"
int
@@ -116,7 +114,8 @@ true_and(mrb_state *mrb, mrb_value obj)
int obj2;
mrb_get_args(mrb, "b", &obj2);
- return obj2 ? mrb_true_value() : mrb_false_value();
+
+ return mrb_bool_value(obj2);
}
/* 15.2.5.3.2 */
@@ -135,7 +134,7 @@ true_xor(mrb_state *mrb, mrb_value obj)
int obj2;
mrb_get_args(mrb, "b", &obj2);
- return obj2 ? mrb_false_value() : mrb_true_value();
+ return mrb_bool_value(!obj2);
}
/* 15.2.5.3.3 */
@@ -228,7 +227,7 @@ false_xor(mrb_state *mrb, mrb_value obj)
int obj2;
mrb_get_args(mrb, "b", &obj2);
- return obj2 ? mrb_true_value() : mrb_false_value();
+ return mrb_bool_value(obj2);
}
/* 15.2.4.3.3 */
@@ -248,7 +247,7 @@ false_or(mrb_state *mrb, mrb_value obj)
int obj2;
mrb_get_args(mrb, "b", &obj2);
- return obj2 ? mrb_true_value() : mrb_false_value();
+ return mrb_bool_value(obj2);
}
/* 15.2.6.3.3 */
@@ -306,12 +305,7 @@ convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *metho
m = mrb_intern(mrb, method);
if (!mrb_respond_to(mrb, val, m)) {
if (raise) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %s into %s",
- mrb_nil_p(val) ? "nil" :
- (mrb_type(val) == MRB_TT_TRUE) ? "true" :
- (mrb_type(val) == MRB_TT_FALSE) ? "false" :
- mrb_obj_classname(mrb, val),
- tname);
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", val, mrb_str_new_cstr(mrb, tname));
return mrb_nil_value();
}
else {
@@ -342,8 +336,8 @@ mrb_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char *tname,
if (mrb_type(val) == type) return val;
v = convert_type(mrb, val, tname, method, 1/*Qtrue*/);
if (mrb_type(v) != type) {
- mrb_raisef(mrb, E_TYPE_ERROR, "%s cannot be converted to %s by #%s",
- mrb_obj_classname(mrb, val), tname, method);
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to %S by #%S", val,
+ mrb_str_new_cstr(mrb, tname), mrb_str_new_cstr(mrb, method));
}
return v;
}
@@ -417,12 +411,13 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t)
else {
etype = mrb_obj_classname(mrb, x);
}
- mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s)",
- etype, type->name);
+ mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)",
+ mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->name));
}
type++;
}
- mrb_raisef(mrb, E_TYPE_ERROR, "unknown type 0x%x (0x%x given)", t, mrb_type(x));
+ mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %S (%S given)",
+ mrb_fixnum_value(t), mrb_fixnum_value(mrb_type(x)));
}
}
@@ -440,8 +435,15 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t)
mrb_value
mrb_any_to_s(mrb_state *mrb, mrb_value obj)
{
+ mrb_value str = mrb_str_buf_new(mrb, 20);
const char *cname = mrb_obj_classname(mrb, obj);
- return mrb_sprintf(mrb, "#<%s:%p>", cname, mrb_voidp(obj));
+
+ mrb_str_buf_cat(mrb, str, "#<", 2);
+ mrb_str_cat2(mrb, str, cname);
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_voidp(obj)));
+ mrb_str_buf_cat(mrb, str, ">", 1);
+
+ return str;
}
/*
@@ -501,9 +503,8 @@ mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method)
if (mrb_fixnum_p(val)) return val;
v = convert_type(mrb, val, "Integer", method, TRUE);
if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) {
- const char *cname = mrb_obj_classname(mrb, val);
- mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %s to Integer (%s#%s gives %s)",
- cname, cname, method, mrb_obj_classname(mrb, v));
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)",
+ val, val, mrb_str_new_cstr(mrb, method), v);
}
return v;
}
@@ -529,7 +530,7 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base)
if (FIXABLE(mrb_float(val))) {
break;
}
- return mrb_flt2big(mrb, mrb_float(val));
+ return mrb_flo_to_fixnum(mrb, val);
case MRB_TT_FIXNUM:
if (base != 0) goto arg_error;
diff --git a/src/opcode.h b/src/opcode.h
index d77e2451f..b4f843116 100644
--- a/src/opcode.h
+++ b/src/opcode.h
@@ -7,12 +7,15 @@
#ifndef OPCODE_H
#define OPCODE_H
-#define MAXARG_Bx ((1<<16)-1)
+#define MAXARG_Bx (0xffff)
#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
-/* instructions OP:A:B:C = 7:9:9:7 (32 bits) */
-/* OP:A:Bx = 7:9:16 */
-/* OP:Ax = 7:25 */
+/* instructions: packed 32 bit */
+/* ------------------------------- */
+/* A:B:C:OP = 9: 9: 7: 7 */
+/* A:Bx:OP = 9:16: 7 */
+/* Ax:OP = 25: 7 */
+/* A:Bz:Cz:OP = 9:14: 2: 7 */
#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f))
#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff))
@@ -20,19 +23,19 @@
#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f))
#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff))
#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx))
-#define GETARG_Ax(i) ((int)((((mrb_code)(i)) >> 7) & 0x1ffffff))
-#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+n2)) & (((1<<n1)-1))))
-#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<n2)-1))))
+#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff))
+#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1))))
+#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1))))
#define GETARG_b(i) GETARG_UNPACK_b(i,14,2)
#define GETARG_c(i) GETARG_UNPACK_c(i,14,2)
#define MKOPCODE(op) ((op) & 0x7f)
-#define MKARG_A(c) (((c) & 0x1ff) << 23)
-#define MKARG_B(c) (((c) & 0x1ff) << 14)
+#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23)
+#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14)
#define MKARG_C(c) (((c) & 0x7f) << 7)
-#define MKARG_Bx(v) (((v) & 0xffff) << 7)
+#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7)
#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx)
-#define MKARG_Ax(v) (((v) & 0x1ffffff) << 7)
+#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7)
#define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7))
#define MKARG_bc(b,c) MKARG_PACK(b,14,c,2)
diff --git a/src/parse.y b/src/parse.y
index 7bca4a4d6..1c0170ac9 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -17,20 +17,20 @@
#define YYFREE(o) mrb_free(p->mrb, (o))
#define YYSTACK_USE_ALLOCA 0
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
#include "mruby.h"
#include "mruby/compile.h"
#include "mruby/proc.h"
#include "node.h"
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-#include <string.h>
-
#define YYLEX_PARAM p
typedef mrb_ast_node node;
typedef struct mrb_parser_state parser_state;
+typedef struct mrb_parser_heredoc_info parser_heredoc_info;
static int yylex(void *lval, parser_state *p);
static void yyerror(parser_state *p, const char *s);
@@ -60,13 +60,27 @@ typedef unsigned int stack_type;
#define sym(x) ((mrb_sym)(intptr_t)(x))
#define nsym(x) ((node*)(intptr_t)(x))
-static mrb_sym
+static inline mrb_sym
intern_gen(parser_state *p, const char *s)
{
return mrb_intern(p->mrb, s);
}
#define intern(s) intern_gen(p,(s))
+static inline mrb_sym
+intern_gen2(parser_state *p, const char *s, size_t len)
+{
+ return mrb_intern2(p->mrb, s, len);
+}
+#define intern2(s,len) intern_gen2(p,(s),(len))
+
+static inline mrb_sym
+intern_gen_c(parser_state *p, const char c)
+{
+ return mrb_intern2(p->mrb, &c, 1);
+}
+#define intern_c(c) intern_gen_c(p,(c))
+
static void
cons_free_gen(parser_state *p, node *cons)
{
@@ -380,15 +394,6 @@ new_fcall(parser_state *p, mrb_sym b, node *c)
return list4((node*)NODE_FCALL, new_self(p), nsym(b), c);
}
-#if 0
-// (:vcall self mid)
-static node*
-new_vcall(parser_state *p, mrb_sym b)
-{
- return list3((node*)NODE_VCALL, new_self(p), (node*)b);
-}
-#endif
-
// (:super . c)
static node*
new_super(parser_state *p, node *c)
@@ -701,6 +706,20 @@ new_dstr(parser_state *p, node *a)
return cons((node*)NODE_DSTR, a);
}
+// (:str . (s . len))
+static node*
+new_xstr(parser_state *p, const char *s, int len)
+{
+ return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), (node*)(intptr_t)len));
+}
+
+// (:xstr . a)
+static node*
+new_dxstr(parser_state *p, node *a)
+{
+ return cons((node*)NODE_DXSTR, a);
+}
+
// (:dsym . a)
static node*
new_dsym(parser_state *p, node *a)
@@ -736,11 +755,39 @@ new_nth_ref(parser_state *p, int n)
return cons((node*)NODE_NTH_REF, (node*)(intptr_t)n);
}
+// (:heredoc . a)
+static node*
+new_heredoc(parser_state *p)
+{
+ parser_heredoc_info *inf = parser_palloc(p, sizeof(parser_heredoc_info));
+ return cons((node*)NODE_HEREDOC, (node*)inf);
+}
+
static void
new_bv(parser_state *p, mrb_sym id)
{
}
+static node*
+new_literal_delim(parser_state *p)
+{
+ return cons((node*)NODE_LITERAL_DELIM, 0);
+}
+
+// (:words . a)
+static node*
+new_words(parser_state *p, node *a)
+{
+ return cons((node*)NODE_WORDS, a);
+}
+
+// (:symbols . a)
+static node*
+new_symbols(parser_state *p, node *a)
+{
+ return cons((node*)NODE_SYMBOLS, a);
+}
+
// xxx -----------------------------
// (:call a op)
@@ -757,15 +804,6 @@ call_bin_op(parser_state *p, node *recv, char *m, node *arg1)
return new_call(p, recv, intern(m), list1(list1(arg1)));
}
-/*
-// (:match (a . b))
-static node*
-match_op(parser_state *p, node *a, node *b)
-{
- return cons((node*)NODE_MATCH, cons((node*)a, (node*)b));
-}
-*/
-
static void
args_with_block(parser_state *p, node *a, node *b)
{
@@ -844,6 +882,49 @@ var_reference(parser_state *p, node *lhs)
return lhs;
}
+typedef enum mrb_string_type string_type;
+
+static node*
+new_strterm(parser_state *p, string_type type, int term, int paren)
+{
+ return cons((node*)(intptr_t)type, cons((node*)0, cons((node*)(intptr_t)paren, (node*)(intptr_t)term)));
+}
+
+static void
+end_strterm(parser_state *p)
+{
+ cons_free(p->lex_strterm->cdr->cdr);
+ cons_free(p->lex_strterm->cdr);
+ cons_free(p->lex_strterm);
+ p->lex_strterm = NULL;
+}
+
+parser_heredoc_info *
+parsing_heredoc_inf(parser_state *p)
+{
+ node *nd = p->parsing_heredoc;
+ if (nd == NULL)
+ return NULL;
+ /* assert(nd->car->car == NODE_HEREDOC); */
+ return (parser_heredoc_info*)nd->car->cdr;
+}
+
+static void
+heredoc_end(parser_state *p)
+{
+ p->parsing_heredoc = p->parsing_heredoc->cdr;
+ if (p->parsing_heredoc == NULL) {
+ p->lstate = EXPR_BEG;
+ p->cmd_start = TRUE;
+ end_strterm(p);
+ p->heredoc_end_now = TRUE;
+ } else {
+ /* next heredoc */
+ p->lex_strterm->car = (node*)(intptr_t)parsing_heredoc_inf(p)->type;
+ }
+}
+#define is_strterm_type(p,str_func) ((int)(intptr_t)((p)->lex_strterm->car) & (str_func))
+
// xxx -----------------------------
%}
@@ -910,13 +991,13 @@ var_reference(parser_state *p, node *lhs)
keyword__FILE__
keyword__ENCODING__
-%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
-%token <nd> tINTEGER tFLOAT tCHAR tREGEXP
-%token <nd> tSTRING tSTRING_PART
-%token <nd> tNTH_REF tBACK_REF
-%token <num> tREGEXP_END
+%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
+%token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP
+%token <nd> tSTRING tSTRING_PART tSTRING_MID
+%token <nd> tNTH_REF tBACK_REF
+%token <num> tREGEXP_END
-%type <nd> singleton string string_interp regexp
+%type <nd> singleton string string_rep string_interp xstring regexp
%type <nd> literal numeric cpath symbol
%type <nd> top_compstmt top_stmts top_stmt
%type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
@@ -935,36 +1016,39 @@ var_reference(parser_state *p, node *lhs)
%type <nd> mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner
%type <id> fsym sym basic_symbol operation operation2 operation3
%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg
-
-%token tUPLUS /* unary+ */
-%token tUMINUS /* unary- */
-%token tPOW /* ** */
-%token tCMP /* <=> */
-%token tEQ /* == */
-%token tEQQ /* === */
-%token tNEQ /* != */
-%token tGEQ /* >= */
-%token tLEQ /* <= */
-%token tANDOP tOROP /* && and || */
-%token tMATCH tNMATCH /* =~ and !~ */
-%token tDOT2 tDOT3 /* .. and ... */
-%token tAREF tASET /* [] and []= */
-%token tLSHFT tRSHFT /* << and >> */
-%token tCOLON2 /* :: */
-%token tCOLON3 /* :: at EXPR_BEG */
-%token <id> tOP_ASGN /* +=, -= etc. */
-%token tASSOC /* => */
-%token tLPAREN /* ( */
-%token tLPAREN_ARG /* ( */
-%token tRPAREN /* ) */
-%token tLBRACK /* [ */
-%token tLBRACE /* { */
-%token tLBRACE_ARG /* { */
-%token tSTAR /* * */
-%token tAMPER /* & */
-%token tLAMBDA /* -> */
-%token tSYMBEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
-%token tSTRING_BEG tSTRING_DVAR tLAMBEG
+%type <nd> heredoc words symbols
+
+%token tUPLUS /* unary+ */
+%token tUMINUS /* unary- */
+%token tPOW /* ** */
+%token tCMP /* <=> */
+%token tEQ /* == */
+%token tEQQ /* === */
+%token tNEQ /* != */
+%token tGEQ /* >= */
+%token tLEQ /* <= */
+%token tANDOP tOROP /* && and || */
+%token tMATCH tNMATCH /* =~ and !~ */
+%token tDOT2 tDOT3 /* .. and ... */
+%token tAREF tASET /* [] and []= */
+%token tLSHFT tRSHFT /* << and >> */
+%token tCOLON2 /* :: */
+%token tCOLON3 /* :: at EXPR_BEG */
+%token <id> tOP_ASGN /* +=, -= etc. */
+%token tASSOC /* => */
+%token tLPAREN /* ( */
+%token tLPAREN_ARG /* ( */
+%token tRPAREN /* ) */
+%token tLBRACK /* [ */
+%token tLBRACE /* { */
+%token tLBRACE_ARG /* { */
+%token tSTAR /* * */
+%token tAMPER /* & */
+%token tLAMBDA /* -> */
+%token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG
+%token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG
+%token <nd> tHEREDOC_BEG /* <<, <<- */
+%token tHEREDOC_END tLITERAL_DELIM
/*
* precedence table
@@ -1024,7 +1108,7 @@ top_compstmt : top_stmts opt_terms
;
top_stmts : none
- {
+ {
$$ = new_begin(p, 0);
}
| top_stmt
@@ -1087,7 +1171,7 @@ compstmt : stmts opt_terms
;
stmts : none
- {
+ {
$$ = new_begin(p, 0);
}
| stmt
@@ -1148,7 +1232,7 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym
}
| primary_value '[' opt_call_args rbracket tOP_ASGN command_call
{
- $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6);
+ $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6);
}
| primary_value '.' tIDENTIFIER tOP_ASGN command_call
{
@@ -1387,7 +1471,7 @@ mlhs_node : variable
}
| primary_value '[' opt_call_args rbracket
{
- $$ = new_call(p, $1, intern("[]"), $3);
+ $$ = new_call(p, $1, intern2("[]",2), $3);
}
| primary_value '.' tIDENTIFIER
{
@@ -1426,7 +1510,7 @@ lhs : variable
}
| primary_value '[' opt_call_args rbracket
{
- $$ = new_call(p, $1, intern("[]"), $3);
+ $$ = new_call(p, $1, intern2("[]",2), $3);
}
| primary_value '.' tIDENTIFIER
{
@@ -1509,34 +1593,35 @@ undef_list : fsym
}
;
-op : '|' { $$ = intern("|"); }
- | '^' { $$ = intern("^"); }
- | '&' { $$ = intern("&"); }
- | tCMP { $$ = intern("<=>"); }
- | tEQ { $$ = intern("=="); }
- | tEQQ { $$ = intern("==="); }
- | tMATCH { $$ = intern("=~"); }
- | tNMATCH { $$ = intern("!~"); }
- | '>' { $$ = intern(">"); }
- | tGEQ { $$ = intern(">="); }
- | '<' { $$ = intern("<"); }
- | tLEQ { $$ = intern("<="); }
- | tNEQ { $$ = intern("!="); }
- | tLSHFT { $$ = intern("<<"); }
- | tRSHFT { $$ = intern(">>"); }
- | '+' { $$ = intern("+"); }
- | '-' { $$ = intern("-"); }
- | '*' { $$ = intern("*"); }
- | tSTAR { $$ = intern("*"); }
- | '/' { $$ = intern("/"); }
- | '%' { $$ = intern("%"); }
- | tPOW { $$ = intern("**"); }
- | '!' { $$ = intern("!"); }
- | '~' { $$ = intern("~"); }
- | tUPLUS { $$ = intern("+@"); }
- | tUMINUS { $$ = intern("-@"); }
- | tAREF { $$ = intern("[]"); }
- | tASET { $$ = intern("[]="); }
+op : '|' { $$ = intern_c('|'); }
+ | '^' { $$ = intern_c('^'); }
+ | '&' { $$ = intern_c('&'); }
+ | tCMP { $$ = intern2("<=>",3); }
+ | tEQ { $$ = intern2("==",2); }
+ | tEQQ { $$ = intern2("===",3); }
+ | tMATCH { $$ = intern2("=~",2); }
+ | tNMATCH { $$ = intern2("!~",2); }
+ | '>' { $$ = intern_c('>'); }
+ | tGEQ { $$ = intern2(">=",2); }
+ | '<' { $$ = intern_c('<'); }
+ | tLEQ { $$ = intern2("<=",2); }
+ | tNEQ { $$ = intern2("!=",2); }
+ | tLSHFT { $$ = intern2("<<",2); }
+ | tRSHFT { $$ = intern2(">>",2); }
+ | '+' { $$ = intern_c('+'); }
+ | '-' { $$ = intern_c('-'); }
+ | '*' { $$ = intern_c('*'); }
+ | tSTAR { $$ = intern_c('*'); }
+ | '/' { $$ = intern_c('/'); }
+ | '%' { $$ = intern_c('%'); }
+ | tPOW { $$ = intern2("**",2); }
+ | '!' { $$ = intern_c('!'); }
+ | '~' { $$ = intern_c('~'); }
+ | tUPLUS { $$ = intern2("+@",2); }
+ | tUMINUS { $$ = intern2("-@",2); }
+ | tAREF { $$ = intern2("[]",2); }
+ | tASET { $$ = intern2("[]=",3); }
+ | '`' { $$ = intern_c('`'); }
;
reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
@@ -1571,7 +1656,7 @@ arg : lhs '=' arg
}
| primary_value '[' opt_call_args rbracket tOP_ASGN arg
{
- $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6);
+ $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6);
}
| primary_value '.' tIDENTIFIER tOP_ASGN arg
{
@@ -1695,11 +1780,6 @@ arg : lhs '=' arg
| arg tMATCH arg
{
$$ = call_bin_op(p, $1, "=~", $3);
-#if 0
- if (nd_type($1) == NODE_LIT && TYPE($1->nd_lit) == T_REGEXP) {
- $$ = reg_named_capture_assign($1->nd_lit, $$);
- }
-#endif
}
| arg tNMATCH arg
{
@@ -1870,7 +1950,9 @@ mrhs : args ',' arg_value
primary : literal
| string
+ | xstring
| regexp
+ | heredoc
| var_ref
| backref
| tFID
@@ -2208,7 +2290,7 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
{
$$ = new_args(p, $1, $3, 0, $5, $6);
}
- | f_arg ',' f_rest_arg opt_f_block_arg
+ | f_arg ',' f_rest_arg opt_f_block_arg
{
$$ = new_args(p, $1, 0, $3, 0, $4);
}
@@ -2340,7 +2422,7 @@ block_call : command do_block
yyerror(p, "block given to yield");
}
else {
- call_with_block(p, $1, $2);
+ call_with_block(p, $1, $2);
}
$$ = $1;
}
@@ -2378,11 +2460,11 @@ method_call : operation paren_args
}
| primary_value '.' paren_args
{
- $$ = new_call(p, $1, intern("call"), $3);
+ $$ = new_call(p, $1, intern2("call",4), $3);
}
| primary_value tCOLON2 paren_args
{
- $$ = new_call(p, $1, intern("call"), $3);
+ $$ = new_call(p, $1, intern2("call",4), $3);
}
| keyword_super paren_args
{
@@ -2394,7 +2476,7 @@ method_call : operation paren_args
}
| primary_value '[' opt_call_args rbracket
{
- $$ = new_call(p, $1, intern("[]"), $3);
+ $$ = new_call(p, $1, intern2("[]",2), $3);
}
;
@@ -2474,6 +2556,8 @@ opt_ensure : keyword_ensure compstmt
literal : numeric
| symbol
+ | words
+ | symbols
;
string : tCHAR
@@ -2482,34 +2566,47 @@ string : tCHAR
{
$$ = $2;
}
- | tSTRING_BEG string_interp tSTRING
+ | tSTRING_BEG string_rep tSTRING
{
$$ = new_dstr(p, push($2, $3));
}
;
-string_interp : tSTRING_PART
+string_rep : string_interp
+ | string_rep string_interp
+ {
+ $$ = append($1, $2);
+ }
+ ;
+
+string_interp : tSTRING_MID
+ {
+ $$ = list1($1);
+ }
+ | tSTRING_PART
{
- $<num>$ = p->sterm;
- p->sterm = 0;
+ $<nd>$ = p->lex_strterm;
+ p->lex_strterm = NULL;
}
compstmt
'}'
{
- p->sterm = $<num>2;
+ p->lex_strterm = $<nd>2;
$$ = list2($1, $3);
}
- | string_interp
- tSTRING_PART
+ | tLITERAL_DELIM
{
- $<num>$ = p->sterm;
- p->sterm = 0;
+ $$ = list1(new_literal_delim(p));
}
- compstmt
- '}'
+ ;
+
+xstring : tXSTRING_BEG tXSTRING
{
- p->sterm = $<num>3;
- $$ = push(push($1, $2), $4);
+ $$ = $2;
+ }
+ | tXSTRING_BEG string_rep tXSTRING
+ {
+ $$ = new_dxstr(p, push($2, $3));
}
;
@@ -2517,12 +2614,46 @@ regexp : tREGEXP_BEG tREGEXP
{
$$ = $2;
}
- | tREGEXP_BEG string_interp tREGEXP
+ | tREGEXP_BEG string_rep tREGEXP
{
$$ = new_dregx(p, $2, $3);
}
;
+heredoc : tHEREDOC_BEG
+ ;
+
+opt_heredoc_bodies : none
+ | heredoc_bodies
+ ;
+
+heredoc_bodies : heredoc_body
+ | heredoc_bodies heredoc_body
+ ;
+
+heredoc_body : tHEREDOC_END
+ {
+ parsing_heredoc_inf(p)->doc = list1(new_str(p, "", 0));
+ heredoc_end(p);
+ }
+ | string_rep tHEREDOC_END
+ {
+ parsing_heredoc_inf(p)->doc = $1;
+ heredoc_end(p);
+ }
+ ;
+
+words : tWORDS_BEG tSTRING
+ {
+ $$ = new_words(p, list1($2));
+ }
+ | tWORDS_BEG string_rep tSTRING
+ {
+ $$ = new_words(p, push($2, $3));
+ }
+ ;
+
+
symbol : basic_symbol
{
$$ = new_sym(p, $1);
@@ -2555,6 +2686,16 @@ sym : fname
}
;
+symbols : tSYMBOLS_BEG tSTRING
+ {
+ $$ = new_symbols(p, list1($2));
+ }
+ | tSYMBOLS_BEG string_rep tSTRING
+ {
+ $$ = new_symbols(p, push($2, $3));
+ }
+ ;
+
numeric : tINTEGER
| tFLOAT
| tUMINUS_NUM tINTEGER %prec tLOWEST
@@ -2869,10 +3010,13 @@ singleton : var_ref
switch ((enum node_type)(int)(intptr_t)$3->car) {
case NODE_STR:
case NODE_DSTR:
+ case NODE_XSTR:
+ case NODE_DXSTR:
case NODE_DREGX:
case NODE_MATCH:
case NODE_FLOAT:
case NODE_ARRAY:
+ case NODE_HEREDOC:
yyerror(p, "can't define singleton method for literals");
default:
break;
@@ -2957,6 +3101,7 @@ nl : '\n'
p->lineno++;
p->column = 0;
}
+ opt_heredoc_bodies
terms : term
| terms ';' {yyerrok;}
@@ -3081,20 +3226,20 @@ nextc(parser_state *p)
cons_free(tmp);
}
else {
+#ifdef ENABLE_STDIO
if (p->f) {
if (feof(p->f)) return -1;
c = fgetc(p->f);
if (c == EOF) return -1;
}
- else if (!p->s || p->s >= p->send) {
+ else
+#endif
+ if (!p->s || p->s >= p->send) {
return -1;
}
else {
c = (unsigned char)*p->s++;
}
- if (c == '\n') {
- // must understand heredoc
- }
}
p->column++;
return c;
@@ -3147,6 +3292,7 @@ peeks(parser_state *p, const char *s)
{
int len = strlen(s);
+#ifdef ENABLE_STDIO
if (p->f) {
int n = 0;
while (*s) {
@@ -3154,7 +3300,9 @@ peeks(parser_state *p, const char *s)
}
return TRUE;
}
- else if (p->s && p->s + len >= p->send) {
+ else
+#endif
+ if (p->s && p->s + len >= p->send) {
if (memcmp(p->s, s, len) == 0) return TRUE;
}
return FALSE;
@@ -3177,7 +3325,7 @@ skips(parser_state *p, const char *s)
int len = strlen(s);
while (len--) {
- nextc(p);
+ nextc(p);
}
return TRUE;
}
@@ -3188,23 +3336,6 @@ skips(parser_state *p, const char *s)
return FALSE;
}
-#define STR_FUNC_ESCAPE 0x01
-#define STR_FUNC_EXPAND 0x02
-#define STR_FUNC_REGEXP 0x04
-#define STR_FUNC_QWORDS 0x08
-#define STR_FUNC_SYMBOL 0x10
-#define STR_FUNC_INDENT 0x20
-
-enum string_type {
- str_squote = (0),
- str_dquote = (STR_FUNC_EXPAND),
- str_xquote = (STR_FUNC_EXPAND),
- str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
- str_sword = (STR_FUNC_QWORDS),
- str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
- str_ssym = (STR_FUNC_SYMBOL),
- str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND)
-};
static int
newtok(parser_state *p)
@@ -3216,7 +3347,7 @@ newtok(parser_state *p)
static void
tokadd(parser_state *p, int c)
{
- if (p->bidx < 1024) {
+ if (p->bidx < MRB_PARSER_BUF_SIZE) {
p->buf[p->bidx++] = c;
}
}
@@ -3230,7 +3361,7 @@ toklast(parser_state *p)
static void
tokfix(parser_state *p)
{
- if (p->bidx >= 1024) {
+ if (p->bidx >= MRB_PARSER_BUF_SIZE) {
yyerror(p, "string too long (truncated)");
}
p->buf[p->bidx] = '\0';
@@ -3255,34 +3386,38 @@ toklen(parser_state *p)
#define IS_LABEL_POSSIBLE() ((p->lstate == EXPR_BEG && !cmd_state) || IS_ARG())
#define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1))
-static unsigned long
+static int
scan_oct(const int *start, int len, int *retlen)
{
const int *s = start;
- unsigned long retval = 0;
+ int retval = 0;
+ /* assert(len <= 3) */
while (len-- && *s >= '0' && *s <= '7') {
retval <<= 3;
retval |= *s++ - '0';
}
*retlen = s - start;
+
return retval;
}
-static unsigned long
+static int
scan_hex(const int *start, int len, int *retlen)
{
static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
register const int *s = start;
- register unsigned long retval = 0;
+ register int retval = 0;
char *tmp;
- while (len-- && *s && (tmp = (char *)strchr(hexdigit, *s))) {
+ /* assert(len <= 2) */
+ while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
retval <<= 4;
retval |= (tmp - hexdigit) & 15;
s++;
}
*retlen = s - start;
+
return retval;
}
@@ -3319,19 +3454,19 @@ read_escape(parser_state *p)
case '0': case '1': case '2': case '3': /* octal constant */
case '4': case '5': case '6': case '7':
{
- int buf[3];
- int i;
-
- buf[0] = c;
- for (i=1; i<3; i++) {
- buf[i] = nextc(p);
- if (buf[i] == -1) goto eof;
- if (buf[i] < '0' || '7' < buf[i]) {
- pushback(p, buf[i]);
- break;
- }
- }
- c = scan_oct(buf, i, &i);
+ int buf[3];
+ int i;
+
+ buf[0] = c;
+ for (i=1; i<3; i++) {
+ buf[i] = nextc(p);
+ if (buf[i] == -1) goto eof;
+ if (buf[i] < '0' || '7' < buf[i]) {
+ pushback(p, buf[i]);
+ break;
+ }
+ }
+ c = scan_oct(buf, i, &i);
}
return c;
@@ -3357,17 +3492,9 @@ read_escape(parser_state *p)
return c;
case 'b': /* backspace */
- if (p->regexp) {
- tokadd(p, '\\');
- return 'b';
- }
return '\010';
case 's': /* space */
- if (p->regexp) {
- tokadd(p, '\\');
- return 's';
- }
return ' ';
case 'M':
@@ -3405,57 +3532,154 @@ read_escape(parser_state *p)
return '\0';
default:
- if (p->regexp) {
- tokadd(p, '\\');
- }
return c;
}
}
+
static int
-parse_string(parser_state *p, int term)
+parse_string(parser_state *p)
{
int c;
+ string_type type = (string_type)(intptr_t)p->lex_strterm->car;
+ int nest_level = (intptr_t)p->lex_strterm->cdr->car;
+ int beg = (intptr_t)p->lex_strterm->cdr->cdr->car;
+ int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr;
+ parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
newtok(p);
- while ((c = nextc(p)) != term) {
- if (c == -1) {
+ while ((c = nextc(p)) != end || nest_level != 0) {
+ if (hinf && (c == '\n' || c == -1)) {
+ int line_head;
+ tokadd(p, '\n');
+ tokfix(p);
+ p->lineno++;
+ p->column = 0;
+ line_head = hinf->line_head;
+ hinf->line_head = TRUE;
+ if (line_head) {
+ /* check whether end of heredoc */
+ const char *s = tok(p);
+ int len = toklen(p);
+ if (hinf->allow_indent) {
+ while (ISSPACE(*s) && len > 0) {
+ ++s;
+ --len;
+ }
+ }
+ if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
+ return tHEREDOC_END;
+ }
+ }
+ if (c == -1) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "can't find string \"%s\" anywhere before EOF", hinf->term);
+ yyerror(p, buf);
+ return 0;
+ }
+ yylval.nd = new_str(p, tok(p), toklen(p));
+ return tSTRING_MID;
+ }
+ if (c == -1) {
yyerror(p, "unterminated string meets end of file");
return 0;
}
+ else if (c == beg) {
+ nest_level++;
+ p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
+ }
+ else if (c == end) {
+ nest_level--;
+ p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
+ }
else if (c == '\\') {
c = nextc(p);
- if (c == term) {
+ if (type & STR_FUNC_EXPAND) {
+ if (c == end || c == beg) {
+ tokadd(p, c);
+ }
+ else if ((c == '\n') && (type & STR_FUNC_ARRAY)) {
+ p->lineno++;
+ p->column = 0;
+ tokadd(p, '\n');
+ }
+ else {
+ pushback(p, c);
+
+ if(type & STR_FUNC_REGEXP)
+ tokadd(p, '\\');
+
+ tokadd(p, read_escape(p));
+ if (hinf)
+ hinf->line_head = FALSE;
+ }
+ } else {
+ if (c != beg && c != end) {
+ switch (c) {
+ case '\n':
+ p->lineno++;
+ p->column = 0;
+ break;
+
+ case '\\':
+ break;
+
+ default:
+ if (! ISSPACE(c))
+ tokadd(p, '\\');
+ }
+ }
tokadd(p, c);
}
- else {
- pushback(p, c);
- tokadd(p, read_escape(p));
- }
continue;
}
- if (c == '#') {
+ else if ((c == '#') && (type & STR_FUNC_EXPAND)) {
c = nextc(p);
if (c == '{') {
tokfix(p);
p->lstate = EXPR_BEG;
- p->sterm = term;
p->cmd_start = TRUE;
yylval.nd = new_str(p, tok(p), toklen(p));
+ if (hinf)
+ hinf->line_head = FALSE;
return tSTRING_PART;
}
tokadd(p, '#');
pushback(p, c);
continue;
}
+ if ((type & STR_FUNC_ARRAY) && ISSPACE(c)) {
+ if (toklen(p) == 0) {
+ do {
+ if (c == '\n') {
+ p->lineno++;
+ p->column = 0;
+ }
+ } while (ISSPACE(c = nextc(p)));
+ pushback(p, c);
+ return tLITERAL_DELIM;
+ } else {
+ pushback(p, c);
+ tokfix(p);
+ yylval.nd = new_str(p, tok(p), toklen(p));
+ return tSTRING_MID;
+ }
+ }
+
tokadd(p, c);
- }
+
+ }
tokfix(p);
p->lstate = EXPR_END;
- p->sterm = 0;
+ end_strterm(p);
- if (p->regexp) {
+ if (type & STR_FUNC_XQUOTE) {
+ yylval.nd = new_xstr(p, tok(p), toklen(p));
+ return tXSTRING;
+ }
+
+ if (type & STR_FUNC_REGEXP) {
int f = 0;
int c;
char *s = strndup(tok(p), toklen(p));
@@ -3475,14 +3699,13 @@ parse_string(parser_state *p, int term)
char msg[128];
tokfix(p);
snprintf(msg, sizeof(msg), "unknown regexp option%s - %s",
- toklen(p) > 1 ? "s" : "", tok(p));
+ toklen(p) > 1 ? "s" : "", tok(p));
yyerror(p, msg);
}
if (f & 1) strcat(flag, "i");
if (f & 2) strcat(flag, "x");
if (f & 4) strcat(flag, "m");
yylval.nd = new_regx(p, s, strdup(flag));
- p->regexp = 0;
return tREGEXP;
}
@@ -3490,61 +3713,78 @@ parse_string(parser_state *p, int term)
yylval.nd = new_str(p, tok(p), toklen(p));
return tSTRING;
}
+
-static node*
-qstring_node(parser_state *p, int beg, int end)
+static int
+heredoc_identifier(parser_state *p)
{
int c;
- int nest_level = 0;
-
- newtok(p);
- while ((c = nextc(p)) != end || nest_level != 0) {
- if (c == -1) {
- yyerror(p, "unterminated string meets end of file");
- return 0;
- }
- else if (c == beg) {
- nest_level++;
+ int type = str_heredoc;
+ int indent = FALSE;
+ int quote = FALSE;
+ node *newnode;
+ parser_heredoc_info *info;
+
+ c = nextc(p);
+ if (ISSPACE(c) || c == '=') {
+ pushback(p, c);
+ return 0;
+ }
+ if (c == '-') {
+ indent = TRUE;
+ c = nextc(p);
+ }
+ if (c == '\'' || c == '"') {
+ int term = c;
+ if (c == '\'')
+ quote = TRUE;
+ newtok(p);
+ while ((c = nextc(p)) != -1 && c != term) {
+ if (c == '\n') {
+ c = -1;
+ break;
+ }
+ tokadd(p, c);
}
- else if (c == end) {
- nest_level--;
+ if (c == -1) {
+ yyerror(p, "unterminated here document identifier");
+ return 0;
}
- else if (c == '\\') {
- c = nextc(p);
- if (c != beg && c != end) {
- switch (c) {
- case '\n':
- p->lineno++;
- p->column = 0;
- continue;
-
- case '\\':
- c = '\\';
- break;
-
- default:
- tokadd(p, '\\');
- }
- }
+ } else {
+ if (! identchar(c)) {
+ pushback(p, c);
+ if (indent) pushback(p, '-');
+ return 0;
}
- tokadd(p, c);
+ newtok(p);
+ do {
+ tokadd(p, c);
+ } while ((c = nextc(p)) != -1 && identchar(c));
+ pushback(p, c);
}
-
tokfix(p);
+ newnode = new_heredoc(p);
+ info = (parser_heredoc_info*)newnode->cdr;
+ info->term = strndup(tok(p), toklen(p));
+ info->term_len = toklen(p);
+ if (! quote)
+ type |= STR_FUNC_EXPAND;
+ info->type = type;
+ info->allow_indent = indent;
+ info->line_head = TRUE;
+ info->doc = NULL;
+ p->heredocs = push(p->heredocs, newnode);
+ if (p->parsing_heredoc == NULL) {
+ node *n = p->heredocs;
+ while (n->cdr)
+ n = n->cdr;
+ p->parsing_heredoc = n;
+ }
+ p->heredoc_starts_nextline = TRUE;
p->lstate = EXPR_END;
- return new_str(p, tok(p), toklen(p));
-}
-
-static int
-parse_qstring(parser_state *p, int beg, int end)
-{
- node *nd = qstring_node(p, beg, end);
- if (nd) {
- yylval.nd = nd;
- return tSTRING;
- }
- return 0;
+ yylval.nd = newnode;
+ return tHEREDOC_BEG;
}
static int
@@ -3565,30 +3805,40 @@ parser_yylex(parser_state *p)
enum mrb_lex_state_enum last_state;
int token_column;
- if (p->sterm) {
- return parse_string(p, p->sterm);
+ if (p->lex_strterm) {
+ if (is_strterm_type(p, STR_FUNC_HEREDOC)) {
+ if ((p->parsing_heredoc != NULL) && (! p->heredoc_starts_nextline))
+ return parse_string(p);
+ }
+ else
+ return parse_string(p);
}
cmd_state = p->cmd_start;
p->cmd_start = FALSE;
retry:
last_state = p->lstate;
switch (c = nextc(p)) {
- case '\0': /* NUL */
- case '\004': /* ^D */
- case '\032': /* ^Z */
- case -1: /* end of script. */
+ case '\0': /* NUL */
+ case '\004': /* ^D */
+ case '\032': /* ^Z */
+ case -1: /* end of script. */
return 0;
- /* white spaces */
+ /* white spaces */
case ' ': case '\t': case '\f': case '\r':
- case '\13': /* '\v' */
+ case '\13': /* '\v' */
space_seen = 1;
goto retry;
- case '#': /* it's a comment */
+ case '#': /* it's a comment */
skip(p, '\n');
- /* fall through */
+ /* fall through */
case '\n':
+ p->heredoc_starts_nextline = FALSE;
+ if (p->parsing_heredoc != NULL) {
+ p->lex_strterm = new_strterm(p, parsing_heredoc_inf(p)->type, 0, 0);
+ goto normal_newline;
+ }
switch (p->lstate) {
case EXPR_BEG:
case EXPR_FNAME:
@@ -3628,7 +3878,7 @@ parser_yylex(parser_state *p)
case '*':
if ((c = nextc(p)) == '*') {
if ((c = nextc(p)) == '=') {
- yylval.id = intern("**");
+ yylval.id = intern2("**",2);
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3637,7 +3887,7 @@ parser_yylex(parser_state *p)
}
else {
if (c == '=') {
- yylval.id = intern("*");
+ yylval.id = intern_c('*');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3684,7 +3934,7 @@ parser_yylex(parser_state *p)
if (p->column == 1) {
if (peeks(p, "begin\n")) {
skips(p, "\n=end\n");
- goto retry;
+ goto retry;
}
}
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
@@ -3711,23 +3961,21 @@ parser_yylex(parser_state *p)
case '<':
last_state = p->lstate;
c = nextc(p);
-#if 0
- // no heredoc supported yet
if (c == '<' &&
p->lstate != EXPR_DOT &&
p->lstate != EXPR_CLASS &&
!IS_END() &&
(!IS_ARG() || space_seen)) {
- int token = heredoc_identifier();
- if (token) return token;
+ int token = heredoc_identifier(p);
+ if (token)
+ return token;
}
-#endif
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
p->lstate = EXPR_ARG;
} else {
p->lstate = EXPR_BEG;
if (p->lstate == EXPR_CLASS) {
- p->cmd_start = TRUE;
+ p->cmd_start = TRUE;
}
}
if (c == '=') {
@@ -3739,7 +3987,7 @@ parser_yylex(parser_state *p)
}
if (c == '<') {
if ((c = nextc(p)) == '=') {
- yylval.id = intern("<<");
+ yylval.id = intern2("<<",2);
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3760,7 +4008,7 @@ parser_yylex(parser_state *p)
}
if (c == '>') {
if ((c = nextc(p)) == '=') {
- yylval.id = intern(">>");
+ yylval.id = intern2(">>",2);
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3771,11 +4019,27 @@ parser_yylex(parser_state *p)
return '>';
case '"':
- p->sterm = '"';
+ p->lex_strterm = new_strterm(p, str_dquote, '"', 0);
return tSTRING_BEG;
case '\'':
- return parse_qstring(p, '\'', '\'');
+ p->lex_strterm = new_strterm(p, str_squote, '\'', 0);
+ return parse_string(p);
+
+ case '`':
+ if (p->lstate == EXPR_FNAME) {
+ p->lstate = EXPR_ENDFN;
+ return '`';
+ }
+ if (p->lstate == EXPR_DOT) {
+ if (cmd_state)
+ p->lstate = EXPR_CMDARG;
+ else
+ p->lstate = EXPR_ARG;
+ return '`';
+ }
+ p->lex_strterm = new_strterm(p, str_xquote, '`', 0);
+ return tXSTRING_BEG;
case '?':
if (IS_END()) {
@@ -3858,7 +4122,7 @@ parser_yylex(parser_state *p)
if ((c = nextc(p)) == '&') {
p->lstate = EXPR_BEG;
if ((c = nextc(p)) == '=') {
- yylval.id = intern("&&");
+ yylval.id = intern2("&&",2);
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3866,7 +4130,7 @@ parser_yylex(parser_state *p)
return tANDOP;
}
else if (c == '=') {
- yylval.id = intern("&");
+ yylval.id = intern_c('&');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3892,7 +4156,7 @@ parser_yylex(parser_state *p)
if ((c = nextc(p)) == '|') {
p->lstate = EXPR_BEG;
if ((c = nextc(p)) == '=') {
- yylval.id = intern("||");
+ yylval.id = intern2("||",2);
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3900,7 +4164,7 @@ parser_yylex(parser_state *p)
return tOROP;
}
if (c == '=') {
- yylval.id = intern("|");
+ yylval.id = intern_c('|');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3924,7 +4188,7 @@ parser_yylex(parser_state *p)
return '+';
}
if (c == '=') {
- yylval.id = intern("+");
+ yylval.id = intern_c('+');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3952,7 +4216,7 @@ parser_yylex(parser_state *p)
return '-';
}
if (c == '=') {
- yylval.id = intern("-");
+ yylval.id = intern_c('-');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -3993,7 +4257,7 @@ parser_yylex(parser_state *p)
case '5': case '6': case '7': case '8': case '9':
{
int is_float, seen_point, seen_e, nondigit;
-
+
is_float = seen_point = seen_e = nondigit = 0;
p->lstate = EXPR_END;
token_column = newtok(p);
@@ -4181,7 +4445,7 @@ parser_yylex(parser_state *p)
if (nondigit) goto decode_num;
nondigit = c;
break;
-
+
default:
goto decode_num;
}
@@ -4248,26 +4512,17 @@ parser_yylex(parser_state *p)
case '/':
if (IS_BEG()) {
-#if 0
p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
-#endif
- p->regexp = 1;
- p->sterm = '/';
return tREGEXP_BEG;
}
if ((c = nextc(p)) == '=') {
- yylval.id = intern("/");
+ yylval.id = intern_c('/');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
pushback(p, c);
if (IS_SPCARG(c)) {
- arg_ambiguous(p);
-#if 0
p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
-#endif
- p->regexp = 1;
- p->sterm = '/';
return tREGEXP_BEG;
}
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
@@ -4279,7 +4534,7 @@ parser_yylex(parser_state *p)
case '^':
if ((c = nextc(p)) == '=') {
- yylval.id = intern("^");
+ yylval.id = intern_c('^');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -4294,7 +4549,7 @@ parser_yylex(parser_state *p)
case ';':
p->lstate = EXPR_BEG;
return ';';
-
+
case ',':
p->lstate = EXPR_BEG;
return ',';
@@ -4382,10 +4637,8 @@ parser_yylex(parser_state *p)
case '%':
if (IS_BEG()) {
- int beg = 0, term;
-#if 0
+ int term;
int paren;
-#endif
c = nextc(p);
quotation:
@@ -4394,7 +4647,7 @@ parser_yylex(parser_state *p)
c = 'Q';
}
else {
- beg = term = nextc(p);
+ term = nextc(p);
if (isalnum(term)) {
yyerror(p, "unknown type of %string");
return 0;
@@ -4404,70 +4657,57 @@ parser_yylex(parser_state *p)
yyerror(p, "unterminated quoted string meets end of file");
return 0;
}
-#if 0
paren = term;
-#endif
if (term == '(') term = ')';
else if (term == '[') term = ']';
else if (term == '{') term = '}';
else if (term == '<') term = '>';
- p->sterm = term;
-#if 0
else paren = 0;
-#endif
switch (c) {
case 'Q':
-#if 0
p->lex_strterm = new_strterm(p, str_dquote, term, paren);
-#endif
return tSTRING_BEG;
case 'q':
-#if 0
p->lex_strterm = new_strterm(p, str_squote, term, paren);
-#endif
- p->sterm = 0;
- return parse_qstring(p, beg, term);
+ return parse_string(p);
case 'W':
-#if 0
p->lex_strterm = new_strterm(p, str_dword, term, paren);
-#endif
- do {c = nextc(p);} while (isspace(c));
- pushback(p, c);
return tWORDS_BEG;
case 'w':
-#if 0
p->lex_strterm = new_strterm(p, str_sword, term, paren);
-#endif
- do {c = nextc(p);} while (isspace(c));
- pushback(p, c);
- return tQWORDS_BEG;
+ return tWORDS_BEG;
+
+ case 'x':
+ p->lex_strterm = new_strterm(p, str_xquote, term, paren);
+ return tXSTRING_BEG;
case 'r':
-#if 0
p->lex_strterm = new_strterm(p, str_regexp, term, paren);
-#endif
- p->regexp = 1;
- p->sterm = term;
return tREGEXP_BEG;
case 's':
-#if 0
p->lex_strterm = new_strterm(p, str_ssym, term, paren);
-#endif
- p->lstate = EXPR_FNAME;
return tSYMBEG;
+ case 'I':
+ p->lex_strterm = new_strterm(p, str_dsymbols, term, paren);
+ return tSYMBOLS_BEG;
+
+ case 'i':
+ p->lex_strterm = new_strterm(p, str_ssymbols, term, paren);
+ return tSYMBOLS_BEG;
+
default:
yyerror(p, "unknown type of %string");
return 0;
}
}
if ((c = nextc(p)) == '=') {
- yylval.id = intern("%");
+ yylval.id = intern_c('%');
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
@@ -4487,27 +4727,32 @@ parser_yylex(parser_state *p)
token_column = newtok(p);
c = nextc(p);
switch (c) {
- case '_': /* $_: last read line string */
+ case '_': /* $_: last read line string */
c = nextc(p);
+ if (c != -1 && identchar(c)) { /* if there is more after _ it is a variable */
+ tokadd(p, '$');
+ tokadd(p, c);
+ break;
+ }
pushback(p, c);
c = '_';
/* fall through */
- case '~': /* $~: match-data */
- case '*': /* $*: argv */
- case '$': /* $$: pid */
- case '?': /* $?: last status */
- case '!': /* $!: error string */
- case '@': /* $@: error position */
- case '/': /* $/: input record separator */
- case '\\': /* $\: output record separator */
- case ';': /* $;: field separator */
- case ',': /* $,: output field separator */
- case '.': /* $.: last read line number */
- case '=': /* $=: ignorecase */
- case ':': /* $:: load path */
- case '<': /* $<: reading filename */
- case '>': /* $>: default output handle */
- case '\"': /* $": already loaded files */
+ case '~': /* $~: match-data */
+ case '*': /* $*: argv */
+ case '$': /* $$: pid */
+ case '?': /* $?: last status */
+ case '!': /* $!: error string */
+ case '@': /* $@: error position */
+ case '/': /* $/: input record separator */
+ case '\\': /* $\: output record separator */
+ case ';': /* $;: field separator */
+ case ',': /* $,: output field separator */
+ case '.': /* $.: last read line number */
+ case '=': /* $=: ignorecase */
+ case ':': /* $:: load path */
+ case '<': /* $<: reading filename */
+ case '>': /* $>: default output handle */
+ case '\"': /* $": already loaded files */
tokadd(p, '$');
tokadd(p, c);
tokfix(p);
@@ -4524,10 +4769,10 @@ parser_yylex(parser_state *p)
yylval.id = intern(tok(p));
return tGVAR;
- case '&': /* $&: last match */
- case '`': /* $`: string before last match */
- case '\'': /* $': string after last match */
- case '+': /* $+: string matches last paren. */
+ case '&': /* $&: last match */
+ case '`': /* $`: string before last match */
+ case '\'': /* $': string after last match */
+ case '+': /* $+: string matches last pattern */
if (last_state == EXPR_FNAME) {
tokadd(p, '$');
tokadd(p, c);
@@ -4706,9 +4951,7 @@ parser_yylex(parser_state *p)
}
}
- if (IS_BEG() ||
- p->lstate == EXPR_DOT ||
- IS_ARG()) {
+ if (IS_BEG() || p->lstate == EXPR_DOT || IS_ARG()) {
if (cmd_state) {
p->lstate = EXPR_CMDARG;
}
@@ -4740,12 +4983,12 @@ parser_yylex(parser_state *p)
static int
yylex(void *lval, parser_state *p)
{
- int t;
+ int t;
- p->ylval = lval;
- t = parser_yylex(p);
+ p->ylval = lval;
+ t = parser_yylex(p);
- return t;
+ return t;
}
static void
@@ -4801,7 +5044,7 @@ mrb_parser_parse(parser_state *p, mrbc_context *c)
p->cmd_start = TRUE;
p->in_def = p->in_single = FALSE;
p->nerr = p->nwarn = 0;
- p->sterm = 0;
+ p->lex_strterm = NULL;
parser_init_cxt(p, c);
yyparse(p);
@@ -4832,7 +5075,9 @@ mrb_parser_new(mrb_state *mrb)
p->in_def = p->in_single = 0;
p->s = p->send = NULL;
+#ifdef ENABLE_STDIO
p->f = NULL;
+#endif
p->cmd_start = TRUE;
p->in_def = p->in_single = FALSE;
@@ -4844,6 +5089,9 @@ mrb_parser_new(mrb_state *mrb)
yydebug = 1;
#endif
+ p->lex_strterm = NULL;
+ p->heredocs = p->parsing_heredoc = NULL;
+
return p;
}
@@ -4882,6 +5130,7 @@ mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
return c->filename;
}
+#ifdef ENABLE_STDIO
parser_state*
mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
{
@@ -4895,6 +5144,7 @@ mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
mrb_parser_parse(p, c);
return p;
}
+#endif
parser_state*
mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c)
@@ -4930,14 +5180,14 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
char buf[256];
n = snprintf(buf, sizeof(buf), "line %d: %s\n",
- p->error_buffer[0].lineno, p->error_buffer[0].message);
- mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
+ p->error_buffer[0].lineno, p->error_buffer[0].message);
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
mrb_parser_free(p);
return mrb_undef_value();
}
else {
static const char msg[] = "syntax error";
- mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1));
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1));
mrb_parser_free(p);
return mrb_undef_value();
}
@@ -4946,7 +5196,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
mrb_parser_free(p);
if (n < 0) {
static const char msg[] = "codegen error";
- mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1));
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1));
return mrb_nil_value();
}
if (c) {
@@ -4958,6 +5208,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
return v;
}
+#ifdef ENABLE_STDIO
mrb_value
mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
{
@@ -4969,6 +5220,7 @@ mrb_load_file(mrb_state *mrb, FILE *f)
{
return mrb_load_file_cxt(mrb, f, NULL);
}
+#endif
mrb_value
mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c)
@@ -5269,8 +5521,8 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
parser_dump(mrb, tree->car, offset+1);
dump_prefix(offset+1);
printf("method='%s' (%d)\n",
- mrb_sym2name(mrb, sym(tree->cdr->car)),
- (int)(intptr_t)tree->cdr->car);
+ mrb_sym2name(mrb, sym(tree->cdr->car)),
+ (int)(intptr_t)tree->cdr->car);
tree = tree->cdr->cdr->car;
if (tree) {
dump_prefix(offset+1);
@@ -5359,11 +5611,11 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
if (n2->car) {
dump_prefix(offset+2);
printf("rest:\n");
- if (n2->car == (node*)-1) {
+ if (n2->car == (node*)-1) {
dump_prefix(offset+2);
printf("(empty)\n");
}
- else {
+ else {
parser_dump(mrb, n2->car, offset+3);
}
}
@@ -5509,6 +5761,15 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
dump_recur(mrb, tree, offset+1);
break;
+ case NODE_XSTR:
+ printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
+ break;
+
+ case NODE_DXSTR:
+ printf("NODE_DXSTR\n");
+ dump_recur(mrb, tree, offset+1);
+ break;
+
case NODE_REGX:
printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr);
break;
@@ -5544,8 +5805,8 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
case NODE_ALIAS:
printf("NODE_ALIAS %s %s:\n",
- mrb_sym2name(mrb, sym(tree->car)),
- mrb_sym2name(mrb, sym(tree->cdr)));
+ mrb_sym2name(mrb, sym(tree->car)),
+ mrb_sym2name(mrb, sym(tree->cdr)));
break;
case NODE_UNDEF:
@@ -5553,8 +5814,8 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
{
node *t = tree;
while (t) {
- printf(" %s", mrb_sym2name(mrb, sym(t->car)));
- t = t->cdr;
+ printf(" %s", mrb_sym2name(mrb, sym(t->car)));
+ t = t->cdr;
}
}
printf(":\n");
@@ -5735,6 +5996,11 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
parser_dump(mrb, tree, offset+1);
break;
+ case NODE_HEREDOC:
+ printf("NODE_HEREDOC:\n");
+ parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
+ break;
+
default:
printf("node type: %d (0x%x)\n", (int)n, (int)n);
break;
diff --git a/src/pool.c b/src/pool.c
index 71e4b477d..77ac8a69f 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -4,9 +4,9 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
#include <stddef.h>
#include <string.h>
+#include "mruby.h"
/* configuration section */
/* allocated memory address should be multiple of POOL_ALIGNMENT */
@@ -25,7 +25,7 @@ struct mrb_pool_page {
size_t offset;
size_t len;
void *last;
- char page[1];
+ char page[];
};
struct mrb_pool {
@@ -81,7 +81,7 @@ page_alloc(mrb_pool *pool, size_t len)
if (len < POOL_PAGE_SIZE)
len = POOL_PAGE_SIZE;
- page = (struct mrb_pool_page *)mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len-1);
+ page = (struct mrb_pool_page *)mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len);
if (page) {
page->offset = 0;
page->len = len;
diff --git a/src/print.c b/src/print.c
index 58297ea83..5367781f5 100644
--- a/src/print.c
+++ b/src/print.c
@@ -5,13 +5,12 @@
*/
#include "mruby.h"
-#ifdef ENABLE_STDIO
#include "mruby/string.h"
-#include <stdio.h>
static void
printstr(mrb_state *mrb, mrb_value obj)
{
+#ifdef ENABLE_STDIO
struct RString *str;
char *s;
int len;
@@ -22,64 +21,35 @@ printstr(mrb_state *mrb, mrb_value obj)
len = str->len;
fwrite(s, len, 1, stdout);
}
+#endif
}
void
mrb_p(mrb_state *mrb, mrb_value obj)
{
+#ifdef ENABLE_STDIO
obj = mrb_funcall(mrb, obj, "inspect", 0);
printstr(mrb, obj);
putc('\n', stdout);
+#endif
}
-/* 15.3.1.2.9 */
-/* 15.3.1.3.34 */
-mrb_value
-mrb_printstr(mrb_state *mrb, mrb_value self)
-{
- mrb_value argv;
-
- mrb_get_args(mrb, "o", &argv);
- printstr(mrb, argv);
-
- return argv;
-}
-
-void
-mrb_init_print(mrb_state *mrb)
-{
- struct RClass *krn;
-
- krn = mrb->kernel_module;
-
- mrb_define_method(mrb, krn, "__printstr__", mrb_printstr, ARGS_REQ(1));
-}
-
-
void
mrb_show_version(mrb_state *mrb)
{
- printf("mruby - Embeddable Ruby Copyright (c) 2010-2013 mruby developers\n");
-}
-
-void
-mrb_show_copyright(mrb_state *mrb)
-{
- printf("mruby - Copyright (c) 2010-2013 mruby developers\n");
-}
-#else
-void
-mrb_p(mrb_state *mrb, mrb_value obj)
-{
-}
+ static const char version_msg[] = "mruby - Embeddable Ruby Copyright (c) 2010-2013 mruby developers\n";
+ mrb_value msg;
-void
-mrb_show_version(mrb_state *mrb)
-{
+ msg = mrb_str_new(mrb, version_msg, sizeof(version_msg) - 1);
+ printstr(mrb, msg);
}
void
mrb_show_copyright(mrb_state *mrb)
{
+ static const char copyright_msg[] = "mruby - Copyright (c) 2010-2013 mruby developers\n";
+ mrb_value msg;
+
+ msg = mrb_str_new(mrb, copyright_msg, sizeof(copyright_msg) - 1);
+ printstr(mrb, msg);
}
-#endif
diff --git a/src/proc.c b/src/proc.c
index c4d7ec3ea..c32ce9c7a 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -5,8 +5,8 @@
*/
#include "mruby.h"
-#include "mruby/proc.h"
#include "mruby/class.h"
+#include "mruby/proc.h"
#include "opcode.h"
static mrb_code call_iseq[] = {
diff --git a/src/range.c b/src/range.c
index aac1d830a..fb4d975e7 100644
--- a/src/range.c
+++ b/src/range.c
@@ -8,7 +8,6 @@
#include "mruby/class.h"
#include "mruby/range.h"
#include "mruby/string.h"
-#include <string.h>
#define RANGE_CLASS (mrb_class_obj_get(mrb, "Range"))
@@ -16,8 +15,8 @@ static void
range_check(mrb_state *mrb, mrb_value a, mrb_value b)
{
mrb_value ans;
- int ta;
- int tb;
+ enum mrb_vtype ta;
+ enum mrb_vtype tb;
ta = mrb_type(a);
tb = mrb_type(b);
@@ -92,7 +91,7 @@ mrb_range_excl(mrb_state *mrb, mrb_value range)
{
struct RRange *r = mrb_range_ptr(range);
- return r->excl ? mrb_true_value() : mrb_false_value();
+ return mrb_bool_value(r->excl);
}
static void
@@ -153,25 +152,30 @@ mrb_range_eq(mrb_state *mrb, mrb_value range)
struct RRange *rr;
struct RRange *ro;
mrb_value obj;
+ mrb_bool eq_p;
mrb_get_args(mrb, "o", &obj);
- if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
-
- /* same class? */
- if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range)))
- return mrb_false_value();
-
- rr = mrb_range_ptr(range);
- ro = mrb_range_ptr(obj);
- if (!mrb_obj_equal(mrb, rr->edges->beg, ro->edges->beg))
- return mrb_false_value();
- if (!mrb_obj_equal(mrb, rr->edges->end, ro->edges->end))
- return mrb_false_value();
- if (rr->excl != ro->excl)
- return mrb_false_value();
+ if (mrb_obj_equal(mrb, range, obj)) {
+ eq_p = 1;
+ }
+ else if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */
+ eq_p = 0;
+ }
+ else {
+ rr = mrb_range_ptr(range);
+ ro = mrb_range_ptr(obj);
+ if (!mrb_obj_equal(mrb, rr->edges->beg, ro->edges->beg) ||
+ !mrb_obj_equal(mrb, rr->edges->end, ro->edges->end) ||
+ rr->excl != ro->excl) {
+ eq_p = 0;
+ }
+ else {
+ eq_p = 1;
+ }
+ }
- return mrb_true_value();
+ return mrb_bool_value(eq_p);
}
static int
@@ -181,7 +185,7 @@ r_le(mrb_state *mrb, mrb_value a, mrb_value b)
/* output :a < b => -1, a = b => 0, a > b => +1 */
if (mrb_type(r) == MRB_TT_FIXNUM) {
- int c = mrb_fixnum(r);
+ mrb_int c = mrb_fixnum(r);
if (c == 0 || c == -1) return TRUE;
}
@@ -208,7 +212,7 @@ r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
/* output :a < b => -1, a = b => 0, a > b => +1 */
if (mrb_type(r) == MRB_TT_FIXNUM) {
- int c = mrb_fixnum(r);
+ mrb_int c = mrb_fixnum(r);
if (c == 0 || c == 1) return TRUE;
}
@@ -228,21 +232,17 @@ mrb_range_include(mrb_state *mrb, mrb_value range)
mrb_value val;
struct RRange *r = mrb_range_ptr(range);
mrb_value beg, end;
+ mrb_bool include_p;
mrb_get_args(mrb, "o", &val);
beg = r->edges->beg;
end = r->edges->end;
- if (r_le(mrb, beg, val)) {
- /* beg <= val */
- if (r->excl) {
- if (r_gt(mrb, end, val)) return mrb_true_value(); /* end > val */
- }
- else {
- if (r_ge(mrb, end, val)) return mrb_true_value(); /* end >= val */
- }
- }
- return mrb_false_value();
+ include_p = r_le(mrb, beg, val) && /* beg <= val */
+ ((r->excl && r_gt(mrb, end, val)) || /* end > val */
+ (r_ge(mrb, end, val))); /* end >= val */
+
+ return mrb_bool_value(include_p);
}
/*
@@ -385,23 +385,34 @@ range_eql(mrb_state *mrb, mrb_value range)
{
mrb_value obj;
struct RRange *r, *o;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &obj);
- if (mrb_obj_equal(mrb, range, obj))
- return mrb_true_value();
- if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS))
- return mrb_false_value();
-
- r = mrb_range_ptr(range);
- if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value();
- o = mrb_range_ptr(obj);
- if (!mrb_eql(mrb, r->edges->beg, o->edges->beg))
- return mrb_false_value();
- if (!mrb_eql(mrb, r->edges->end, o->edges->end))
- return mrb_false_value();
- if (r->excl != o->excl)
- return mrb_false_value();
- return mrb_true_value();
+ if (mrb_obj_equal(mrb, range, obj)) {
+ eql_p = 1;
+ }
+ else if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) {
+ eql_p = 0;
+ }
+ else {
+ r = mrb_range_ptr(range);
+ if (mrb_type(obj) != MRB_TT_RANGE) {
+ eql_p = 0;
+ }
+ else {
+ o = mrb_range_ptr(obj);
+ if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) ||
+ !mrb_eql(mrb, r->edges->end, o->edges->end) ||
+ (r->excl != o->excl)) {
+ eql_p = 0;
+ }
+ else {
+ eql_p = 1;
+ }
+ }
+ }
+
+ return mrb_bool_value(eql_p);
}
/* 15.2.14.4.15(x) */
diff --git a/src/sprintf.c b/src/sprintf.c
deleted file mode 100644
index 905182147..000000000
--- a/src/sprintf.c
+++ /dev/null
@@ -1,1095 +0,0 @@
-/*
-** sprintf.c - Kernel.#sprintf
-**
-** See Copyright Notice in mruby.h
-*/
-
-#include "mruby.h"
-
-#ifdef ENABLE_SPRINTF
-
-#include <stdio.h>
-#include <string.h>
-#include "mruby/string.h"
-#include "mruby/hash.h"
-#include "mruby/numeric.h"
-#include <math.h>
-#include <ctype.h>
-
-#ifdef _MSC_VER
-#include <float.h>
-#endif
-
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-#define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
-#define BITSPERDIG (sizeof(mrb_int)*CHAR_BIT)
-#define EXTENDSIGN(n, l) (((~0 << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0 << (n)))
-
-static void fmt_setup(char*,size_t,int,int,int,int);
-
-static char*
-remove_sign_bits(char *str, int base)
-{
- char *t;
-
- t = str;
- if (base == 16) {
- while (*t == 'f') {
- t++;
- }
- }
- else if (base == 8) {
- *t |= EXTENDSIGN(3, strlen(t));
- while (*t == '7') {
- t++;
- }
- }
- else if (base == 2) {
- while (*t == '1') {
- t++;
- }
- }
-
- return t;
-}
-
-static char
-sign_bits(int base, const char *p)
-{
- char c;
-
- switch (base) {
- case 16:
- if (*p == 'X') c = 'F';
- else c = 'f';
- break;
- case 8:
- c = '7'; break;
- case 2:
- c = '1'; break;
- default:
- c = '.'; break;
- }
- return c;
-}
-
-static mrb_value
-mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
-{
- char buf[64], *b = buf + sizeof buf;
- unsigned long val = mrb_fixnum(x);
- char d;
-
- if (base != 2) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %d", base);
- }
-
- if (val >= (1 << 10))
- val &= 0x3ff;
-
- if (val == 0) {
- return mrb_str_new(mrb, "0", 1);
- }
- *--b = '\0';
- do {
- *--b = mrb_digitmap[(int)(val % base)];
- } while (val /= base);
-
- if (mrb_fixnum(x) < 0) {
- b = remove_sign_bits(b, base);
- switch (base) {
- case 16: d = 'f'; break;
- case 8: d = '7'; break;
- case 2: d = '1'; break;
- default: d = 0; break;
- }
-
- if (d && *b != d) {
- *--b = d;
- }
- }
-
- return mrb_str_new2(mrb, b);
-}
-
-#define FNONE 0
-#define FSHARP 1
-#define FMINUS 2
-#define FPLUS 4
-#define FZERO 8
-#define FSPACE 16
-#define FWIDTH 32
-#define FPREC 64
-#define FPREC0 128
-
-#define CHECK(l) do {\
-/* int cr = ENC_CODERANGE(result);*/\
- while (blen + (l) >= bsiz) {\
- bsiz*=2;\
- }\
- mrb_str_resize(mrb, result, bsiz);\
-/* ENC_CODERANGE_SET(result, cr);*/\
- buf = RSTRING_PTR(result);\
-} while (0)
-
-#define PUSH(s, l) do { \
- CHECK(l);\
- memcpy(&buf[blen], s, l);\
- blen += (l);\
-} while (0)
-
-#define FILL(c, l) do { \
- CHECK(l);\
- memset(&buf[blen], c, l);\
- blen += (l);\
-} while (0)
-
-#define GETARG() (!mrb_undef_p(nextvalue) ? nextvalue : \
- posarg == -1 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%d) mixed with numbered", nextarg), mrb_undef_value()) : \
- posarg == -2 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%d) mixed with named", nextarg), mrb_undef_value()) : \
- (posarg = nextarg++, GETNTHARG(posarg)))
-
-#define GETPOSARG(n) (posarg > 0 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%d) after unnumbered(%d)", n, posarg), mrb_undef_value()) : \
- posarg == -2 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%d) after named", n), mrb_undef_value()) : \
- ((n < 1) ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid index - %d$", n), mrb_undef_value()) : \
- (posarg = -1, GETNTHARG(n))))
-
-#define GETNTHARG(nth) \
- ((nth >= argc) ? (mrb_raise(mrb, E_ARGUMENT_ERROR, "too few arguments"), mrb_undef_value()) : argv[nth])
-
-#define GETNAMEARG(id, name, len) ( \
- posarg > 0 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%.*s after unnumbered(%d)", (len), (name), posarg), mrb_undef_value()) : \
- posarg == -1 ? \
- (mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%.*s after numbered", (len), (name)), mrb_undef_value()) : \
- (posarg = -2, mrb_hash_fetch(mrb, get_hash(mrb, &hash, argc, argv), id, mrb_undef_value())))
-
-#define GETNUM(n, val) \
- for (; p < end && ISDIGIT(*p); p++) {\
- int next_n = 10 * n + (*p - '0'); \
- if (next_n / 10 != n) {\
- mrb_raise(mrb, E_ARGUMENT_ERROR, #val " too big"); \
- } \
- n = next_n; \
- } \
- if (p >= end) { \
- mrb_raise(mrb, E_ARGUMENT_ERROR, "malformed format string - %*[0-9]"); \
- }
-
-#define GETASTER(num) do { \
- t = p++; \
- n = 0; \
- GETNUM(n, val); \
- if (*p == '$') { \
- tmp = GETPOSARG(n); \
- } \
- else { \
- tmp = GETARG(); \
- p = t; \
- } \
- num = mrb_fixnum(tmp); \
-} while (0)
-
-static mrb_value
-get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
-{
- mrb_value tmp;
-
- if (!mrb_undef_p(*hash)) return *hash;
- if (argc != 2) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required");
- }
- tmp = mrb_check_convert_type(mrb, argv[1], MRB_TT_HASH, "Hash", "to_hash");
- if (mrb_nil_p(tmp)) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required");
- }
- return (*hash = tmp);
-}
-
-/*
- * call-seq:
- * format(format_string [, arguments...] ) -> string
- * sprintf(format_string [, arguments...] ) -> string
- *
- * Returns the string resulting from applying <i>format_string</i> to
- * any additional arguments. Within the format string, any characters
- * other than format sequences are copied to the result.
- *
- * The syntax of a format sequence is follows.
- *
- * %[flags][width][.precision]type
- *
- * A format
- * sequence consists of a percent sign, followed by optional flags,
- * width, and precision indicators, then terminated with a field type
- * character. The field type controls how the corresponding
- * <code>sprintf</code> argument is to be interpreted, while the flags
- * modify that interpretation.
- *
- * The field type characters are:
- *
- * Field | Integer Format
- * ------+--------------------------------------------------------------
- * b | Convert argument as a binary number.
- * | Negative numbers will be displayed as a two's complement
- * | prefixed with `..1'.
- * B | Equivalent to `b', but uses an uppercase 0B for prefix
- * | in the alternative format by #.
- * d | Convert argument as a decimal number.
- * i | Identical to `d'.
- * o | Convert argument as an octal number.
- * | Negative numbers will be displayed as a two's complement
- * | prefixed with `..7'.
- * u | Identical to `d'.
- * x | Convert argument as a hexadecimal number.
- * | Negative numbers will be displayed as a two's complement
- * | prefixed with `..f' (representing an infinite string of
- * | leading 'ff's).
- * X | Equivalent to `x', but uses uppercase letters.
- *
- * Field | Float Format
- * ------+--------------------------------------------------------------
- * e | Convert floating point argument into exponential notation
- * | with one digit before the decimal point as [-]d.dddddde[+-]dd.
- * | The precision specifies the number of digits after the decimal
- * | point (defaulting to six).
- * E | Equivalent to `e', but uses an uppercase E to indicate
- * | the exponent.
- * f | Convert floating point argument as [-]ddd.dddddd,
- * | where the precision specifies the number of digits after
- * | the decimal point.
- * g | Convert a floating point number using exponential form
- * | if the exponent is less than -4 or greater than or
- * | equal to the precision, or in dd.dddd form otherwise.
- * | The precision specifies the number of significant digits.
- * G | Equivalent to `g', but use an uppercase `E' in exponent form.
- * a | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
- * | which is consisted from optional sign, "0x", fraction part
- * | as hexadecimal, "p", and exponential part as decimal.
- * A | Equivalent to `a', but use uppercase `X' and `P'.
- *
- * Field | Other Format
- * ------+--------------------------------------------------------------
- * c | Argument is the numeric code for a single character or
- * | a single character string itself.
- * p | The valuing of argument.inspect.
- * s | Argument is a string to be substituted. If the format
- * | sequence contains a precision, at most that many characters
- * | will be copied.
- * % | A percent sign itself will be displayed. No argument taken.
- *
- * The flags modifies the behavior of the formats.
- * The flag characters are:
- *
- * Flag | Applies to | Meaning
- * ---------+---------------+-----------------------------------------
- * space | bBdiouxX | Leave a space at the start of
- * | aAeEfgG | non-negative numbers.
- * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
- * | | a minus sign with absolute value for
- * | | negative values.
- * ---------+---------------+-----------------------------------------
- * (digit)$ | all | Specifies the absolute argument number
- * | | for this field. Absolute and relative
- * | | argument numbers cannot be mixed in a
- * | | sprintf string.
- * ---------+---------------+-----------------------------------------
- * # | bBoxX | Use an alternative format.
- * | aAeEfgG | For the conversions `o', increase the precision
- * | | until the first digit will be `0' if
- * | | it is not formatted as complements.
- * | | For the conversions `x', `X', `b' and `B'
- * | | on non-zero, prefix the result with ``0x'',
- * | | ``0X'', ``0b'' and ``0B'', respectively.
- * | | For `a', `A', `e', `E', `f', `g', and 'G',
- * | | force a decimal point to be added,
- * | | even if no digits follow.
- * | | For `g' and 'G', do not remove trailing zeros.
- * ---------+---------------+-----------------------------------------
- * + | bBdiouxX | Add a leading plus sign to non-negative
- * | aAeEfgG | numbers.
- * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
- * | | a minus sign with absolute value for
- * | | negative values.
- * ---------+---------------+-----------------------------------------
- * - | all | Left-justify the result of this conversion.
- * ---------+---------------+-----------------------------------------
- * 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
- * | aAeEfgG | For `o', `x', `X', `b' and `B', radix-1
- * | (numeric fmt) | is used for negative numbers formatted as
- * | | complements.
- * ---------+---------------+-----------------------------------------
- * * | all | Use the next argument as the field width.
- * | | If negative, left-justify the result. If the
- * | | asterisk is followed by a number and a dollar
- * | | sign, use the indicated argument as the width.
- *
- * Examples of flags:
- *
- * # `+' and space flag specifies the sign of non-negative numbers.
- * sprintf("%d", 123) #=> "123"
- * sprintf("%+d", 123) #=> "+123"
- * sprintf("% d", 123) #=> " 123"
- *
- * # `#' flag for `o' increases number of digits to show `0'.
- * # `+' and space flag changes format of negative numbers.
- * sprintf("%o", 123) #=> "173"
- * sprintf("%#o", 123) #=> "0173"
- * sprintf("%+o", -123) #=> "-173"
- * sprintf("%o", -123) #=> "..7605"
- * sprintf("%#o", -123) #=> "..7605"
- *
- * # `#' flag for `x' add a prefix `0x' for non-zero numbers.
- * # `+' and space flag disables complements for negative numbers.
- * sprintf("%x", 123) #=> "7b"
- * sprintf("%#x", 123) #=> "0x7b"
- * sprintf("%+x", -123) #=> "-7b"
- * sprintf("%x", -123) #=> "..f85"
- * sprintf("%#x", -123) #=> "0x..f85"
- * sprintf("%#x", 0) #=> "0"
- *
- * # `#' for `X' uses the prefix `0X'.
- * sprintf("%X", 123) #=> "7B"
- * sprintf("%#X", 123) #=> "0X7B"
- *
- * # `#' flag for `b' add a prefix `0b' for non-zero numbers.
- * # `+' and space flag disables complements for negative numbers.
- * sprintf("%b", 123) #=> "1111011"
- * sprintf("%#b", 123) #=> "0b1111011"
- * sprintf("%+b", -123) #=> "-1111011"
- * sprintf("%b", -123) #=> "..10000101"
- * sprintf("%#b", -123) #=> "0b..10000101"
- * sprintf("%#b", 0) #=> "0"
- *
- * # `#' for `B' uses the prefix `0B'.
- * sprintf("%B", 123) #=> "1111011"
- * sprintf("%#B", 123) #=> "0B1111011"
- *
- * # `#' for `e' forces to show the decimal point.
- * sprintf("%.0e", 1) #=> "1e+00"
- * sprintf("%#.0e", 1) #=> "1.e+00"
- *
- * # `#' for `f' forces to show the decimal point.
- * sprintf("%.0f", 1234) #=> "1234"
- * sprintf("%#.0f", 1234) #=> "1234."
- *
- * # `#' for `g' forces to show the decimal point.
- * # It also disables stripping lowest zeros.
- * sprintf("%g", 123.4) #=> "123.4"
- * sprintf("%#g", 123.4) #=> "123.400"
- * sprintf("%g", 123456) #=> "123456"
- * sprintf("%#g", 123456) #=> "123456."
- *
- * The field width is an optional integer, followed optionally by a
- * period and a precision. The width specifies the minimum number of
- * characters that will be written to the result for this field.
- *
- * Examples of width:
- *
- * # padding is done by spaces, width=20
- * # 0 or radix-1. <------------------>
- * sprintf("%20d", 123) #=> " 123"
- * sprintf("%+20d", 123) #=> " +123"
- * sprintf("%020d", 123) #=> "00000000000000000123"
- * sprintf("%+020d", 123) #=> "+0000000000000000123"
- * sprintf("% 020d", 123) #=> " 0000000000000000123"
- * sprintf("%-20d", 123) #=> "123 "
- * sprintf("%-+20d", 123) #=> "+123 "
- * sprintf("%- 20d", 123) #=> " 123 "
- * sprintf("%020x", -123) #=> "..ffffffffffffffff85"
- *
- * For
- * numeric fields, the precision controls the number of decimal places
- * displayed. For string fields, the precision determines the maximum
- * number of characters to be copied from the string. (Thus, the format
- * sequence <code>%10.10s</code> will always contribute exactly ten
- * characters to the result.)
- *
- * Examples of precisions:
- *
- * # precision for `d', 'o', 'x' and 'b' is
- * # minimum number of digits <------>
- * sprintf("%20.8d", 123) #=> " 00000123"
- * sprintf("%20.8o", 123) #=> " 00000173"
- * sprintf("%20.8x", 123) #=> " 0000007b"
- * sprintf("%20.8b", 123) #=> " 01111011"
- * sprintf("%20.8d", -123) #=> " -00000123"
- * sprintf("%20.8o", -123) #=> " ..777605"
- * sprintf("%20.8x", -123) #=> " ..ffff85"
- * sprintf("%20.8b", -11) #=> " ..110101"
- *
- * # "0x" and "0b" for `#x' and `#b' is not counted for
- * # precision but "0" for `#o' is counted. <------>
- * sprintf("%#20.8d", 123) #=> " 00000123"
- * sprintf("%#20.8o", 123) #=> " 00000173"
- * sprintf("%#20.8x", 123) #=> " 0x0000007b"
- * sprintf("%#20.8b", 123) #=> " 0b01111011"
- * sprintf("%#20.8d", -123) #=> " -00000123"
- * sprintf("%#20.8o", -123) #=> " ..777605"
- * sprintf("%#20.8x", -123) #=> " 0x..ffff85"
- * sprintf("%#20.8b", -11) #=> " 0b..110101"
- *
- * # precision for `e' is number of
- * # digits after the decimal point <------>
- * sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
- *
- * # precision for `f' is number of
- * # digits after the decimal point <------>
- * sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
- *
- * # precision for `g' is number of
- * # significant digits <------->
- * sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
- *
- * # <------->
- * sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
- *
- * # precision for `s' is
- * # maximum number of characters <------>
- * sprintf("%20.8s", "string test") #=> " string t"
- *
- * Examples:
- *
- * sprintf("%d %04x", 123, 123) #=> "123 007b"
- * sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
- * sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
- * sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
- * sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
- * sprintf("%u", -123) #=> "-123"
- *
- * For more complex formatting, Ruby supports a reference by name.
- * %<name>s style uses format style, but %{name} style doesn't.
- *
- * Exapmles:
- * sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 })
- * #=> 1 : 2.000000
- * sprintf("%{foo}f", { :foo => 1 })
- * # => "1f"
- */
-
-mrb_value
-mrb_f_sprintf(mrb_state *mrb, mrb_value obj)
-{
- int argc;
- mrb_value *argv;
-
- mrb_get_args(mrb, "*", &argv, &argc);
-
- if (argc <= 0) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "too few arguments");
- return mrb_nil_value();
- }
- else {
- return mrb_str_format(mrb, argc - 1, argv + 1, argv[0]);
- }
-}
-
-mrb_value
-mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
-{
- const char *p, *end;
- char *buf;
- long blen, bsiz;
- mrb_value result;
- int n;
- int width, prec, flags = FNONE;
- int nextarg = 1;
- int posarg = 0;
- mrb_value nextvalue;
- mrb_value tmp;
- mrb_value str;
- mrb_value hash = mrb_undef_value();
-
-#define CHECK_FOR_WIDTH(f) \
- if ((f) & FWIDTH) { \
- mrb_raise(mrb, E_ARGUMENT_ERROR, "width given twice"); \
- } \
- if ((f) & FPREC0) { \
- mrb_raise(mrb, E_ARGUMENT_ERROR, "width after precision"); \
- }
-#define CHECK_FOR_FLAGS(f) \
- if ((f) & FWIDTH) { \
- mrb_raise(mrb, E_ARGUMENT_ERROR, "flag after width"); \
- } \
- if ((f) & FPREC0) { \
- mrb_raise(mrb, E_ARGUMENT_ERROR, "flag after precision"); \
- }
-
- ++argc;
- --argv;
- mrb_string_value(mrb, &fmt);
- p = RSTRING_PTR(fmt);
- end = p + RSTRING_LEN(fmt);
- blen = 0;
- bsiz = 120;
- result = mrb_str_buf_new(mrb, bsiz);
- buf = RSTRING_PTR(result);
- memset(buf, 0, bsiz);
-
- for (; p < end; p++) {
- const char *t;
- mrb_sym id = 0;
-
- for (t = p; t < end && *t != '%'; t++) ;
- PUSH(p, t - p);
- if (t >= end)
- goto sprint_exit; /* end of fmt string */
-
- p = t + 1; /* skip `%' */
-
- width = prec = -1;
- nextvalue = mrb_undef_value();
-
-retry:
- switch (*p) {
- default:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - %%%c", *p);
- break;
-
- case ' ':
- CHECK_FOR_FLAGS(flags);
- flags |= FSPACE;
- p++;
- goto retry;
-
- case '#':
- CHECK_FOR_FLAGS(flags);
- flags |= FSHARP;
- p++;
- goto retry;
-
- case '+':
- CHECK_FOR_FLAGS(flags);
- flags |= FPLUS;
- p++;
- goto retry;
-
- case '-':
- CHECK_FOR_FLAGS(flags);
- flags |= FMINUS;
- p++;
- goto retry;
-
- case '0':
- CHECK_FOR_FLAGS(flags);
- flags |= FZERO;
- p++;
- goto retry;
-
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- GETNUM(n, width);
- if (*p == '$') {
- if (!mrb_undef_p(nextvalue)) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "value given twice - %d$", n);
- }
- nextvalue = GETPOSARG(n);
- p++;
- goto retry;
- }
- CHECK_FOR_WIDTH(flags);
- width = n;
- flags |= FWIDTH;
- goto retry;
-
- case '<':
- case '{': {
- const char *start = p;
- char term = (*p == '<') ? '>' : '}';
- mrb_value symname;
-
- for (; p < end && *p != term; )
- p++;
- if (id) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "name%.*s after <%s>",
- (int)(p - start + 1), start, mrb_sym2name(mrb, id));
- }
- symname = mrb_str_new(mrb, start + 1, p - start - 1);
- id = mrb_intern_str(mrb, symname);
- nextvalue = GETNAMEARG(mrb_symbol_value(id), start, (int)(p - start + 1));
- if (mrb_undef_p(nextvalue)) {
- mrb_raisef(mrb, E_KEY_ERROR, "key%.*s not found", (int)(p - start + 1), start);
- }
- if (term == '}') goto format_s;
- p++;
- goto retry;
- }
-
- case '*':
- CHECK_FOR_WIDTH(flags);
- flags |= FWIDTH;
- GETASTER(width);
- if (width < 0) {
- flags |= FMINUS;
- width = -width;
- }
- p++;
- goto retry;
-
- case '.':
- if (flags & FPREC0) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "precision given twice");
- }
- flags |= FPREC|FPREC0;
-
- prec = 0;
- p++;
- if (*p == '*') {
- GETASTER(prec);
- if (prec < 0) { /* ignore negative precision */
- flags &= ~FPREC;
- }
- p++;
- goto retry;
- }
-
- GETNUM(prec, precision);
- goto retry;
-
- case '\n':
- case '\0':
- p--;
-
- case '%':
- if (flags != FNONE) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format character - %");
- }
- PUSH("%", 1);
- break;
-
- case 'c': {
- mrb_value val = GETARG();
- mrb_value tmp;
- unsigned int c;
-
- tmp = mrb_check_string_type(mrb, val);
- if (!mrb_nil_p(tmp)) {
- if (RSTRING_LEN(tmp) != 1 ) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "%c requires a character");
- }
- c = RSTRING_PTR(tmp)[0];
- n = 1;
- }
- else {
- c = mrb_fixnum(val);
- n = 1;
- }
- if (n <= 0) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character");
- }
- if (!(flags & FWIDTH)) {
- CHECK(n);
- buf[blen] = c;
- blen += n;
- }
- else if ((flags & FMINUS)) {
- CHECK(n);
- buf[blen] = c;
- blen += n;
- FILL(' ', width-1);
- }
- else {
- FILL(' ', width-1);
- CHECK(n);
- buf[blen] = c;
- blen += n;
- }
- }
- break;
-
- case 's':
- case 'p':
- format_s:
- {
- mrb_value arg = GETARG();
- long len, slen;
-
- if (*p == 'p') arg = mrb_inspect(mrb, arg);
- str = mrb_obj_as_string(mrb, arg);
- len = RSTRING_LEN(str);
- RSTRING_LEN(result) = blen;
- if (flags&(FPREC|FWIDTH)) {
- slen = RSTRING_LEN(str);
- if (slen < 0) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid mbstring sequence");
- }
- if ((flags&FPREC) && (prec < slen)) {
- char *p = RSTRING_PTR(str) + prec;
- slen = prec;
- len = p - RSTRING_PTR(str);
- }
- /* need to adjust multi-byte string pos */
- if ((flags&FWIDTH) && (width > slen)) {
- width -= (int)slen;
- if (!(flags&FMINUS)) {
- CHECK(width);
- while (width--) {
- buf[blen++] = ' ';
- }
- }
- CHECK(len);
- memcpy(&buf[blen], RSTRING_PTR(str), len);
- blen += len;
- if (flags&FMINUS) {
- CHECK(width);
- while (width--) {
- buf[blen++] = ' ';
- }
- }
- break;
- }
- }
- PUSH(RSTRING_PTR(str), len);
- }
- break;
-
- case 'd':
- case 'i':
- case 'o':
- case 'x':
- case 'X':
- case 'b':
- case 'B':
- case 'u': {
- mrb_value val = GETARG();
- char fbuf[32], nbuf[64], *s;
- const char *prefix = 0;
- int sign = 0, dots = 0;
- char sc = 0;
- long v = 0, org_v = 0;
- int base;
- int len;
-
- switch (*p) {
- case 'd':
- case 'i':
- case 'u':
- sign = 1; break;
- case 'o':
- case 'x':
- case 'X':
- case 'b':
- case 'B':
- if (flags&(FPLUS|FSPACE)) sign = 1;
- break;
- default:
- break;
- }
- if (flags & FSHARP) {
- switch (*p) {
- case 'o': prefix = "0"; break;
- case 'x': prefix = "0x"; break;
- case 'X': prefix = "0X"; break;
- case 'b': prefix = "0b"; break;
- case 'B': prefix = "0B"; break;
- default: break;
- }
- }
-
- bin_retry:
- switch (mrb_type(val)) {
- case MRB_TT_FLOAT:
- if (FIXABLE(mrb_float(val))) {
- val = mrb_fixnum_value((mrb_int)mrb_float(val));
- goto bin_retry;
- }
- val = mrb_flt2big(mrb, mrb_float(val));
- if (mrb_fixnum_p(val)) goto bin_retry;
- break;
- case MRB_TT_STRING:
- val = mrb_str_to_inum(mrb, val, 0, TRUE);
- goto bin_retry;
- case MRB_TT_FIXNUM:
- v = (long)mrb_fixnum(val);
- break;
- default:
- val = mrb_Integer(mrb, val);
- goto bin_retry;
- }
-
- switch (*p) {
- case 'o':
- base = 8; break;
- case 'x':
- case 'X':
- base = 16; break;
- case 'b':
- case 'B':
- base = 2; break;
- case 'u':
- case 'd':
- case 'i':
- default:
- base = 10; break;
- }
-
- if (base == 2) {
- org_v = v;
- if ( v < 0 && !sign ) {
- val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
- dots = 1;
- }
- else {
- val = mrb_fix2str(mrb, mrb_fixnum_value(v), base);
- }
- v = mrb_fixnum(mrb_str_to_inum(mrb, val, 10, 0/*Qfalse*/));
- }
- if (sign) {
- char c = *p;
- if (c == 'i') c = 'd'; /* %d and %i are identical */
- if (base == 2) c = 'd';
- if (v < 0) {
- v = -v;
- sc = '-';
- width--;
- }
- else if (flags & FPLUS) {
- sc = '+';
- width--;
- }
- else if (flags & FSPACE) {
- sc = ' ';
- width--;
- }
- snprintf(fbuf, sizeof(fbuf), "%%l%c", c);
- snprintf(nbuf, sizeof(nbuf), fbuf, v);
- s = nbuf;
- }
- else {
- char c = *p;
- if (c == 'X') c = 'x';
- if (base == 2) c = 'd';
- s = nbuf;
- if (v < 0) {
- dots = 1;
- }
- snprintf(fbuf, sizeof(fbuf), "%%l%c", c);
- snprintf(++s, sizeof(nbuf) - 1, fbuf, v);
- if (v < 0) {
- char d;
-
- s = remove_sign_bits(s, base);
- switch (base) {
- case 16: d = 'f'; break;
- case 8: d = '7'; break;
- case 2: d = '1'; break;
- default: d = 0; break;
- }
-
- if (d && *s != d) {
- *--s = d;
- }
- }
- }
- len = (int)strlen(s);
-
- if (dots) {
- prec -= 2;
- width -= 2;
- }
-
- if (*p == 'X') {
- char *pp = s;
- int c;
- while ((c = (int)(unsigned char)*pp) != 0) {
- *pp = toupper(c);
- pp++;
- }
- }
-
- if (prefix && !prefix[1]) { /* octal */
- if (dots) {
- prefix = 0;
- }
- else if (len == 1 && *s == '0') {
- len = 0;
- if (flags & FPREC) prec--;
- }
- else if ((flags & FPREC) && (prec > len)) {
- prefix = 0;
- }
- }
- else if (len == 1 && *s == '0') {
- prefix = 0;
- }
-
- if (prefix) {
- width -= (int)strlen(prefix);
- }
-
- if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
- prec = width;
- width = 0;
- }
- else {
- if (prec < len) {
- if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
- prec = len;
- }
- width -= prec;
- }
-
- if (!(flags&FMINUS)) {
- CHECK(width);
- while (width-- > 0) {
- buf[blen++] = ' ';
- }
- }
-
- if (sc) PUSH(&sc, 1);
-
- if (prefix) {
- int plen = (int)strlen(prefix);
- PUSH(prefix, plen);
- }
- CHECK(prec - len);
- if (dots) PUSH("..", 2);
-
- if (v < 0 || (base == 2 && org_v < 0)) {
- char c = sign_bits(base, p);
- while (len < prec--) {
- buf[blen++] = c;
- }
- }
- else if ((flags & (FMINUS|FPREC)) != FMINUS) {
- char c = '0';
- while (len < prec--) {
- buf[blen++] = c;
- }
- }
-
- PUSH(s, len);
- CHECK(width);
- while (width-- > 0) {
- buf[blen++] = ' ';
- }
- }
- break;
-
- case 'f':
- case 'g':
- case 'G':
- case 'e':
- case 'E':
- case 'a':
- case 'A': {
- mrb_value val = GETARG();
- double fval;
- int i, need = 6;
- char fbuf[32];
-
- fval = mrb_float(mrb_Float(mrb, val));
- if (isnan(fval) || isinf(fval)) {
- const char *expr;
- const int elen = 3;
-
- if (isnan(fval)) {
- expr = "NaN";
- }
- else {
- expr = "Inf";
- }
- need = elen;
- if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS))
- need++;
- if ((flags & FWIDTH) && need < width)
- need = width;
-
- CHECK(need + 1);
- n = snprintf(&buf[blen], need + 1, "%*s", need, "");
- if (flags & FMINUS) {
- if (!isnan(fval) && fval < 0.0)
- buf[blen++] = '-';
- else if (flags & FPLUS)
- buf[blen++] = '+';
- else if (flags & FSPACE)
- blen++;
- memcpy(&buf[blen], expr, elen);
- }
- else {
- if (!isnan(fval) && fval < 0.0)
- buf[blen + need - elen - 1] = '-';
- else if (flags & FPLUS)
- buf[blen + need - elen - 1] = '+';
- else if ((flags & FSPACE) && need > width)
- blen++;
- memcpy(&buf[blen + need - elen], expr, elen);
- }
- blen += strlen(&buf[blen]);
- break;
- }
-
- fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
- need = 0;
- if (*p != 'e' && *p != 'E') {
- i = INT_MIN;
- frexp(fval, &i);
- if (i > 0)
- need = BIT_DIGITS(i);
- }
- need += (flags&FPREC) ? prec : 6;
- if ((flags&FWIDTH) && need < width)
- need = width;
- need += 20;
-
- CHECK(need);
- n = snprintf(&buf[blen], need, fbuf, fval);
- blen += n;
- }
- break;
- }
- flags = FNONE;
- }
-
- sprint_exit:
-#if 0
- /* XXX - We cannot validate the number of arguments if (digit)$ style used.
- */
- if (posarg >= 0 && nextarg < argc) {
- const char *mesg = "too many arguments for format string";
- if (mrb_test(ruby_debug)) mrb_raise(mrb, E_ARGUMENT_ERROR, mesg);
- if (mrb_test(ruby_verbose)) mrb_warn("%s", mesg);
- }
-#endif
- mrb_str_resize(mrb, result, blen);
-
- return result;
-}
-
-static void
-fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
-{
- char *end = buf + size;
- int n;
-
- *buf++ = '%';
- if (flags & FSHARP) *buf++ = '#';
- if (flags & FPLUS) *buf++ = '+';
- if (flags & FMINUS) *buf++ = '-';
- if (flags & FZERO) *buf++ = '0';
- if (flags & FSPACE) *buf++ = ' ';
-
- if (flags & FWIDTH) {
- n = snprintf(buf, end - buf, "%d", width);
- buf += n;
- }
-
- if (flags & FPREC) {
- n = snprintf(buf, end - buf, ".%d", prec);
- buf += n;
- }
-
- *buf++ = c;
- *buf = '\0';
-}
-
-#endif /* ENABLE_SPRINTF */
diff --git a/src/state.c b/src/state.c
index 53773ac89..adc7da06b 100644
--- a/src/state.c
+++ b/src/state.c
@@ -4,15 +4,23 @@
** See Copyright Notice in mruby.h
*/
+#include <stdlib.h>
+#include <string.h>
#include "mruby.h"
+#include "mruby/class.h"
#include "mruby/irep.h"
#include "mruby/variable.h"
-#include <string.h>
void mrb_init_heap(mrb_state*);
void mrb_init_core(mrb_state*);
void mrb_final_core(mrb_state*);
+static mrb_value
+inspect_main(mrb_state *mrb, mrb_value mod)
+{
+ return mrb_str_new(mrb, "main", 4);
+}
+
mrb_state*
mrb_open_allocf(mrb_allocf f, void *ud)
{
@@ -44,7 +52,7 @@ allocf(mrb_state *mrb, void *p, size_t size, void *ud)
struct alloca_header {
struct alloca_header *next;
- char buf[0];
+ char buf[];
};
void*
@@ -53,6 +61,7 @@ mrb_alloca(mrb_state *mrb, size_t size)
struct alloca_header *p;
p = (struct alloca_header*) mrb_malloc(mrb, sizeof(struct alloca_header)+size);
+ if (p == NULL) return NULL;
p->next = mrb->mems;
mrb->mems = p;
return (void*)p->buf;
@@ -61,9 +70,12 @@ mrb_alloca(mrb_state *mrb, size_t size)
static void
mrb_alloca_free(mrb_state *mrb)
{
- struct alloca_header *p = mrb->mems;
+ struct alloca_header *p;
struct alloca_header *tmp;
+ if (mrb == NULL) return;
+ p = mrb->mems;
+
while (p) {
tmp = p;
p = p->next;
@@ -72,7 +84,7 @@ mrb_alloca_free(mrb_state *mrb)
}
mrb_state*
-mrb_open()
+mrb_open(void)
{
mrb_state *mrb = mrb_open_allocf(allocf, NULL);
@@ -83,6 +95,17 @@ void mrb_free_symtbl(mrb_state *mrb);
void mrb_free_heap(mrb_state *mrb);
void
+mrb_irep_free(mrb_state *mrb, struct mrb_irep *irep)
+{
+ if (!(irep->flags & MRB_ISEQ_NO_FREE))
+ mrb_free(mrb, irep->iseq);
+ mrb_free(mrb, irep->pool);
+ mrb_free(mrb, irep->syms);
+ mrb_free(mrb, irep->lines);
+ mrb_free(mrb, irep);
+}
+
+void
mrb_close(mrb_state *mrb)
{
size_t i;
@@ -94,12 +117,7 @@ mrb_close(mrb_state *mrb)
mrb_free(mrb, mrb->stbase);
mrb_free(mrb, mrb->cibase);
for (i=0; i<mrb->irep_len; i++) {
- if (!(mrb->irep[i]->flags & MRB_ISEQ_NO_FREE))
- mrb_free(mrb, mrb->irep[i]->iseq);
- mrb_free(mrb, mrb->irep[i]->pool);
- mrb_free(mrb, mrb->irep[i]->syms);
- mrb_free(mrb, mrb->irep[i]->lines);
- mrb_free(mrb, mrb->irep[i]);
+ mrb_irep_free(mrb, mrb->irep[i]);
}
mrb_free(mrb, mrb->irep);
mrb_free(mrb, mrb->rescue);
@@ -110,6 +128,10 @@ mrb_close(mrb_state *mrb)
mrb_free(mrb, mrb);
}
+#ifndef MRB_IREP_ARRAY_INIT_SIZE
+# define MRB_IREP_ARRAY_INIT_SIZE (256u)
+#endif
+
mrb_irep*
mrb_add_irep(mrb_state *mrb)
{
@@ -117,14 +139,14 @@ mrb_add_irep(mrb_state *mrb)
mrb_irep *irep;
if (!mrb->irep) {
- int max = 256;
+ size_t max = MRB_IREP_ARRAY_INIT_SIZE;
if (mrb->irep_len > max) max = mrb->irep_len+1;
mrb->irep = (mrb_irep **)mrb_calloc(mrb, max, sizeof(mrb_irep*));
mrb->irep_capa = max;
}
else if (mrb->irep_capa <= mrb->irep_len) {
- int i;
+ size_t i;
size_t old_capa = mrb->irep_capa;
while (mrb->irep_capa <= mrb->irep_len) {
mrb->irep_capa *= 2;
@@ -145,8 +167,10 @@ mrb_add_irep(mrb_state *mrb)
mrb_value
mrb_top_self(mrb_state *mrb)
{
- mrb_value v;
-
- MRB_SET_VALUE(v, MRB_TT_MAIN, value.i, 0);
- return v;
+ if (!mrb->top_self) {
+ mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class);
+ mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, ARGS_NONE());
+ mrb_define_singleton_method(mrb, mrb->top_self, "to_s", inspect_main, ARGS_NONE());
+ }
+ return mrb_obj_value(mrb->top_self);
}
diff --git a/src/string.c b/src/string.c
index 28cf0ab9a..c4074a64f 100644
--- a/src/string.c
+++ b/src/string.c
@@ -4,36 +4,34 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-
-#include <string.h>
-#include "mruby/string.h"
-#include "mruby/class.h"
#include <ctype.h>
-#include <limits.h>
-#include "mruby/range.h"
+#ifndef SIZE_MAX
+ /* Some versions of VC++
+ * has SIZE_MAX in stdint.h
+ */
+# include <limits.h>
+#endif
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mruby.h"
#include "mruby/array.h"
#include "mruby/class.h"
#include "mruby/numeric.h"
-#include <stdio.h>
+#include "mruby/range.h"
+#include "mruby/string.h"
#include "re.h"
const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2);
-static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len);
+static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
#define RESIZE_CAPA(s,capacity) do {\
s->ptr = (char *)mrb_realloc(mrb, s->ptr, (capacity)+1);\
s->aux.capa = capacity;\
} while (0)
-static const char*
-_obj_classname(mrb_state *mrb, mrb_value obj)
-{
- return mrb_class_name(mrb, mrb_obj_class(mrb, obj));
-}
-
void
mrb_str_decref(mrb_state *mrb, mrb_shared_string *shared)
{
@@ -57,13 +55,13 @@ str_modify(mrb_state *mrb, struct RString *s)
}
else {
char *ptr, *p;
- long len;
+ mrb_int len;
p = s->ptr;
len = s->len;
- ptr = (char *)mrb_malloc(mrb, len+1);
+ ptr = (char *)mrb_malloc(mrb, (size_t)len + 1);
if (p) {
- memcpy(ptr, p, len);
+ memcpy(ptr, p, len);
}
ptr[len] = 0;
s->ptr = ptr;
@@ -88,7 +86,7 @@ mrb_str_resize(mrb_state *mrb, mrb_value str, int len)
}
s->aux.capa = len;
s->len = len;
- s->ptr[len] = '\0'; /* sentinel */
+ s->ptr[len] = '\0'; /* sentinel */
}
return str;
}
@@ -105,21 +103,6 @@ str_mod_check(mrb_state *mrb, mrb_value str, char *p, mrb_int len)
#define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class))
-static struct RString*
-str_alloc(mrb_state *mrb, struct RClass *c)
-{
- struct RString* s;
-
- s = mrb_obj_alloc_string(mrb);
-
- s->c = c;
- s->ptr = 0;
- s->len = 0;
- s->aux.capa = 0;
-
- return s;
-}
-
/* char offset to byte offset */
int
mrb_str_offset(mrb_state *mrb, mrb_value str, int pos)
@@ -130,8 +113,9 @@ mrb_str_offset(mrb_state *mrb, mrb_value str, int pos)
static struct RString*
str_new(mrb_state *mrb, const char *p, int len)
{
- struct RString *s = str_alloc(mrb, mrb->string_class);
+ struct RString *s;
+ s = mrb_obj_alloc_string(mrb);
s->len = len;
s->aux.capa = len;
s->ptr = (char *)mrb_malloc(mrb, len+1);
@@ -157,6 +141,10 @@ mrb_str_new_empty(mrb_state *mrb, mrb_value str)
return mrb_obj_value(s);
}
+#ifndef MRB_STR_BUF_MIN_SIZE
+# define MRB_STR_BUF_MIN_SIZE 128
+#endif
+
mrb_value
mrb_str_buf_new(mrb_state *mrb, int capa)
{
@@ -164,8 +152,8 @@ mrb_str_buf_new(mrb_state *mrb, int capa)
s = mrb_obj_alloc_string(mrb);
- if (capa < STR_BUF_MIN_SIZE) {
- capa = STR_BUF_MIN_SIZE;
+ if (capa < MRB_STR_BUF_MIN_SIZE) {
+ capa = MRB_STR_BUF_MIN_SIZE;
}
s->len = 0;
s->aux.capa = capa;
@@ -176,9 +164,11 @@ mrb_str_buf_new(mrb_state *mrb, int capa)
}
static void
-str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len)
+str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len)
{
- long capa, total, off = -1;
+ mrb_int capa;
+ mrb_int total;
+ ptrdiff_t off = -1;
str_modify(mrb, s);
if (ptr >= s->ptr && ptr <= s->ptr + s->len) {
@@ -186,13 +176,13 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len)
}
if (len == 0) return;
capa = s->aux.capa;
- if (s->len >= INT_MAX - len) {
+ if (s->len >= MRB_INT_MAX - len) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string sizes too big");
}
total = s->len+len;
if (capa <= total) {
while (total > capa) {
- if (capa + 1 >= INT_MAX / 2) {
+ if (capa + 1 >= MRB_INT_MAX / 2) {
capa = (total + 4095) / 4096;
break;
}
@@ -205,11 +195,11 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len)
}
memcpy(s->ptr + s->len, ptr, len);
s->len = total;
- s->ptr[total] = '\0'; /* sentinel */
+ s->ptr[total] = '\0'; /* sentinel */
}
mrb_value
-mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len)
+mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
{
if (len == 0) return str;
str_buf_cat(mrb, mrb_str_ptr(str), ptr, len);
@@ -217,7 +207,7 @@ mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len)
}
mrb_value
-mrb_str_new(mrb_state *mrb, const char *p, int len)
+mrb_str_new(mrb_state *mrb, const char *p, size_t len)
{
struct RString *s;
@@ -225,17 +215,6 @@ mrb_str_new(mrb_state *mrb, const char *p, int len)
return mrb_obj_value(s);
}
-mrb_value
-mrb_str_new2(mrb_state *mrb, const char *ptr)
-{
- struct RString *s;
- if (!ptr) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "NULL pointer given");
- }
- s = str_new(mrb, ptr, strlen(ptr));
- return mrb_obj_value(s);
-}
-
/*
* call-seq: (Caution! NULL string)
* String.new(str="") => new_str
@@ -247,11 +226,23 @@ mrb_value
mrb_str_new_cstr(mrb_state *mrb, const char *p)
{
struct RString *s;
- int len = strlen(p);
+ size_t len;
+
+ if (p) {
+ len = strlen(p);
+ if ((mrb_int)len < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big");
+ }
+ }
+ else {
+ len = 0;
+ }
s = mrb_obj_alloc_string(mrb);
s->ptr = (char *)mrb_malloc(mrb, len+1);
- memcpy(s->ptr, p, len);
+ if (p) {
+ memcpy(s->ptr, p, len);
+ }
s->ptr[len] = 0;
s->len = len;
s->aux.capa = len;
@@ -264,6 +255,10 @@ mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
{
mrb_value str;
+ if (!mrb_string_p(str0)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "expected String");
+ }
+
str = mrb_str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0));
if (strlen(RSTRING_PTR(str)) != RSTRING_LEN(str)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
@@ -303,7 +298,7 @@ mrb_str_literal(mrb_state *mrb, mrb_value str)
struct RString *s, *orig;
mrb_shared_string *shared;
- s = str_alloc(mrb, mrb->string_class);
+ s = mrb_obj_alloc_string(mrb);
orig = mrb_str_ptr(str);
if (!(orig->flags & MRB_STR_SHARED)) {
str_make_shared(mrb, mrb_str_ptr(str));
@@ -312,6 +307,7 @@ mrb_str_literal(mrb_state *mrb, mrb_value str)
shared->refcnt++;
s->ptr = shared->ptr;
s->len = shared->len;
+ s->aux.capa = 0;
s->aux.shared = shared;
s->flags |= MRB_STR_SHARED;
@@ -447,7 +443,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self)
if (times < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
}
- if (times && INT_MAX/times < RSTRING_LEN(self)) {
+ if (times && MRB_INT_MAX / times < RSTRING_LEN(self)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big");
}
@@ -533,10 +529,10 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1)
mrb_get_args(mrb, "o", &str2);
if (!mrb_string_p(str2)) {
- if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "to_s"))) {
+ if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_s", 4))) {
return mrb_nil_value();
}
- else if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "<=>"))) {
+ else if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "<=>", 3))) {
return mrb_nil_value();
}
else {
@@ -558,8 +554,9 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1)
static int
str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2)
{
- const long len = RSTRING_LEN(str1);
+ const size_t len = RSTRING_LEN(str1);
+ /* assert(SIZE_MAX >= MRB_INT_MAX) */
if (len != RSTRING_LEN(str2)) return FALSE;
if (memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len) == 0)
return TRUE;
@@ -572,7 +569,7 @@ mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2)
if (mrb_obj_equal(mrb, str1, str2)) return TRUE;
if (!mrb_string_p(str2)) {
if (mrb_nil_p(str2)) return FALSE;
- if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "to_str"))) {
+ if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_str", 6))) {
return FALSE;
}
str2 = mrb_funcall(mrb, str2, "to_str", 0);
@@ -596,11 +593,12 @@ static mrb_value
mrb_str_equal_m(mrb_state *mrb, mrb_value str1)
{
mrb_value str2;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &str2);
- if (mrb_str_equal(mrb, str1, str2))
- return mrb_true_value();
- return mrb_false_value();
+ equal_p = mrb_str_equal(mrb, str1, str2);
+
+ return mrb_bool_value(equal_p);
}
/* ---------------------------------- */
mrb_value
@@ -618,21 +616,10 @@ mrb_str_to_str(mrb_state *mrb, mrb_value str)
return str;
}
-mrb_value
-mrb_string_value(mrb_state *mrb, mrb_value *ptr)
-{
- mrb_value s = *ptr;
- if (!mrb_string_p(s)) {
- s = mrb_str_to_str(mrb, s);
- *ptr = s;
- }
- return s;
-}
-
char *
mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr)
{
- mrb_value str = mrb_string_value(mrb, &ptr);
+ mrb_value str = mrb_str_to_str(mrb, ptr);
return RSTRING_PTR(str);
}
/* 15.2.10.5.5 */
@@ -658,8 +645,8 @@ mrb_str_match(mrb_state *mrb, mrb_value self/* x */)
return mrb_nil_value();
}
-static inline long
-mrb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long n)
+static inline mrb_int
+mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
{
const unsigned char *x = xs, *xe = xs + m;
const unsigned char *y = ys;
@@ -678,8 +665,8 @@ mrb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long
return -1;
}
-static int
-mrb_memsearch(const void *x0, int m, const void *y0, int n)
+static mrb_int
+mrb_memsearch(const void *x0, mrb_int m, const void *y0, mrb_int n)
{
const unsigned char *x = (const unsigned char *)x0, *y = (const unsigned char *)y0;
@@ -706,7 +693,8 @@ mrb_str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset)
{
mrb_int pos;
char *s, *sptr;
- int len, slen;
+ mrb_int len, slen;
+
len = RSTRING_LEN(str);
slen = RSTRING_LEN(sub);
if (offset < 0) {
@@ -740,9 +728,9 @@ mrb_str_dup(mrb_state *mrb, mrb_value str)
static mrb_value
mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx)
{
- long idx;
+ mrb_int idx;
- if (!strcmp(_obj_classname(mrb, indx), REGEXP_CLASS)) {
+ if (!strcmp(mrb_obj_classname(mrb, indx), REGEXP_CLASS)) {
mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
}
switch (mrb_type(indx)) {
@@ -843,7 +831,7 @@ mrb_str_aref_m(mrb_state *mrb, mrb_value str)
return mrb_str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2));
}
if (argc != 1) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%d for 1)", argc);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(argc));
}
return mrb_str_aref(mrb, str, a1);
}
@@ -921,7 +909,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
mrb_value rs;
mrb_int newline;
char *p, *pp;
- long len, rslen;
+ mrb_int rslen;
+ mrb_int len;
struct RString *s = mrb_str_ptr(str);
str_modify(mrb, s);
@@ -932,8 +921,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
if (s->ptr[len-1] == '\n') {
s->len--;
if (s->len > 0 &&
- s->ptr[s->len-1] == '\r') {
- s->len--;
+ s->ptr[s->len-1] == '\r') {
+ s->len--;
}
}
else if (s->ptr[len-1] == '\r') {
@@ -1132,9 +1121,7 @@ mrb_str_empty_p(mrb_state *mrb, mrb_value self)
{
struct RString *s = mrb_str_ptr(self);
- if (s->len == 0)
- return mrb_true_value();
- return mrb_false_value();
+ return mrb_bool_value(s->len == 0);
}
/* 15.2.10.5.17 */
@@ -1148,17 +1135,16 @@ static mrb_value
mrb_str_eql(mrb_state *mrb, mrb_value self)
{
mrb_value str2;
+ mrb_bool eql_p;
mrb_get_args(mrb, "o", &str2);
- if (mrb_type(str2) != MRB_TT_STRING)
- return mrb_false_value();
- if (str_eql(mrb, self, str2))
- return mrb_true_value();
- return mrb_false_value();
+ eql_p = (mrb_type(str2) == MRB_TT_STRING) && str_eql(mrb, self, str2);
+
+ return mrb_bool_value(eql_p);
}
static mrb_value
-mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len)
+mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
struct RString *orig, *s;
mrb_shared_string *shared;
@@ -1177,7 +1163,7 @@ mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len)
}
mrb_value
-mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, int len)
+mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
mrb_value str2;
@@ -1268,7 +1254,7 @@ mrb_str_hash(mrb_state *mrb, mrb_value str)
{
/* 1-8-7 */
struct RString *s = mrb_str_ptr(str);
- long len = s->len;
+ mrb_int len = s->len;
char *p = s->ptr;
mrb_int key = 0;
@@ -1312,18 +1298,20 @@ mrb_str_include(mrb_state *mrb, mrb_value self)
{
mrb_int i;
mrb_value str2;
+ mrb_bool include_p;
mrb_get_args(mrb, "o", &str2);
if (mrb_type(str2) == MRB_TT_FIXNUM) {
- if (memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self)))
- return mrb_true_value();
- return mrb_false_value();
+ include_p = memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self));
}
- mrb_string_value(mrb, &str2);
- i = mrb_str_index(mrb, self, str2, 0);
+ else {
+ str2 = mrb_str_to_str(mrb, str2);
+ i = mrb_str_index(mrb, self, str2, 0);
- if (i == -1) return mrb_false_value();
- return mrb_true_value();
+ include_p = (i != -1);
+ }
+
+ return mrb_bool_value(include_p);
}
/* 15.2.10.5.22 */
@@ -1382,7 +1370,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
switch (mrb_type(sub)) {
case MRB_TT_FIXNUM: {
int c = mrb_fixnum(sub);
- long len = RSTRING_LEN(str);
+ mrb_int len = RSTRING_LEN(str);
unsigned char *p = (unsigned char*)RSTRING_PTR(str);
for (;pos<len;pos++) {
@@ -1396,8 +1384,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
tmp = mrb_check_string_type(mrb, sub);
if (mrb_nil_p(tmp)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %s given",
- _obj_classname(mrb, sub));
+ mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub);
}
sub = tmp;
}
@@ -1405,10 +1392,10 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
case MRB_TT_STRING:
pos = mrb_str_index(mrb, str, sub, pos);
break;
- }
+ }
- if (pos == -1) return mrb_nil_value();
- return mrb_fixnum_value(pos);
+ if (pos == -1) return mrb_nil_value();
+ return mrb_fixnum_value(pos);
}
#define STR_REPLACE_SHARED_MIN 10
@@ -1512,9 +1499,8 @@ mrb_value
mrb_str_intern(mrb_state *mrb, mrb_value self)
{
mrb_sym id;
- mrb_value str = RB_GC_GUARD(self);
- id = mrb_intern_str(mrb, str);
+ id = mrb_intern_str(mrb, self);
return mrb_symbol_value(id);
}
@@ -1534,6 +1520,36 @@ mrb_obj_as_string(mrb_state *mrb, mrb_value obj)
}
mrb_value
+mrb_ptr_to_str(mrb_state *mrb, void *p)
+{
+ struct RString *p_str;
+ char *p1;
+ char *p2;
+ intptr_t n = (intptr_t)p;
+
+ p_str = str_new(mrb, NULL, 2 + sizeof(uintptr_t) * CHAR_BIT / 4);
+ p1 = p_str->ptr;
+ *p1++ = '0';
+ *p1++ = 'x';
+ p2 = p1;
+
+ do {
+ *p2++ = mrb_digitmap[n % 16];
+ n /= 16;
+ } while (n > 0);
+ *p2 = '\0';
+ p_str->len = (mrb_int)(p2 - p_str->ptr);
+
+ while (p1 < p2) {
+ const char c = *p1;
+ *p1++ = *--p2;
+ *p2 = c;
+ }
+
+ return mrb_obj_value(p_str);
+}
+
+mrb_value
mrb_check_string_type(mrb_state *mrb, mrb_value str)
{
return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
@@ -1639,7 +1655,7 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
char *s, *sbeg, *t;
struct RString *ps = mrb_str_ptr(str);
struct RString *psub = mrb_str_ptr(sub);
- long len = psub->len;
+ mrb_int len = psub->len;
/* substring longer than string */
if (ps->len < len) return -1;
@@ -1663,15 +1679,6 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
}
}
-#ifdef INCLUDE_ENCODING
-/* byte offset to char offset */
-int
-mrb_str_sublen(mrb_state *mrb, mrb_value str, long pos)
-{
- return pos;
-}
-#endif //INCLUDE_ENCODING
-
/* 15.2.10.5.31 */
/*
* call-seq:
@@ -1730,7 +1737,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
switch (mrb_type(sub)) {
case MRB_TT_FIXNUM: {
int c = mrb_fixnum(sub);
- long len = RSTRING_LEN(str);
+ mrb_int len = RSTRING_LEN(str);
unsigned char *p = (unsigned char*)RSTRING_PTR(str);
for (pos=len;pos>=0;pos--) {
@@ -1744,8 +1751,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
tmp = mrb_check_string_type(mrb, sub);
if (mrb_nil_p(tmp)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %s given",
- mrb_obj_classname(mrb, sub));
+ mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub);
}
sub = tmp;
}
@@ -1867,7 +1873,9 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
int argc;
mrb_value spat = mrb_nil_value();
enum {awk, string, regexp} split_type = string;
- long beg, end, i = 0, lim_p;
+ long i = 0, lim_p;
+ mrb_int beg;
+ mrb_int end;
mrb_int lim = 0;
mrb_value result, tmp;
@@ -1911,24 +1919,24 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
int ai = mrb_gc_arena_save(mrb);
c = (unsigned char)*ptr++;
if (skip) {
- if (ascii_isspace(c)) {
- beg = ptr - bptr;
- }
- else {
- end = ptr - bptr;
- skip = 0;
- if (lim_p && lim <= i) break;
- }
+ if (ascii_isspace(c)) {
+ beg = ptr - bptr;
+ }
+ else {
+ end = ptr - bptr;
+ skip = 0;
+ if (lim_p && lim <= i) break;
+ }
}
else if (ascii_isspace(c)) {
- mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg));
+ mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg));
mrb_gc_arena_restore(mrb, ai);
- skip = 1;
- beg = ptr - bptr;
- if (lim_p) ++i;
+ skip = 1;
+ beg = ptr - bptr;
+ if (lim_p) ++i;
}
else {
- end = ptr - bptr;
+ end = ptr - bptr;
}
}
}
@@ -1936,15 +1944,15 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
char *ptr = RSTRING_PTR(str);
char *temp = ptr;
char *eptr = RSTRING_END(str);
- long slen = RSTRING_LEN(spat);
+ mrb_int slen = RSTRING_LEN(spat);
if (slen == 0) {
int ai = mrb_gc_arena_save(mrb);
while (ptr < eptr) {
- mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr-temp, 1));
+ mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr-temp, 1));
mrb_gc_arena_restore(mrb, ai);
- ptr++;
- if (lim_p && lim <= ++i) break;
+ ptr++;
+ if (lim_p && lim <= ++i) break;
}
}
else {
@@ -1952,11 +1960,11 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
int ai = mrb_gc_arena_save(mrb);
while (ptr < eptr &&
- (end = mrb_memsearch(sptr, slen, ptr, eptr - ptr)) >= 0) {
- mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr - temp, end));
+ (end = mrb_memsearch(sptr, slen, ptr, eptr - ptr)) >= 0) {
+ mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr - temp, end));
mrb_gc_arena_restore(mrb, ai);
- ptr += end + slen;
- if (lim_p && lim <= ++i) break;
+ ptr += end + slen;
+ if (lim_p && lim <= ++i) break;
}
}
beg = ptr - temp;
@@ -1974,7 +1982,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
mrb_ary_push(mrb, result, tmp);
}
if (!lim_p && lim == 0) {
- long len;
+ mrb_int len;
while ((len = RARRAY_LEN(result)) > 0 &&
(tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0))
mrb_ary_pop(mrb, result);
@@ -2050,14 +2058,11 @@ mrb_str_sub(mrb_state *mrb, mrb_value self)
mrb_value
mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
{
- #define BDIGIT unsigned int
- #define BDIGIT_DBL unsigned long
-
char *end;
char sign = 1;
int c;
- long len;
- unsigned long val;
+ unsigned long n;
+ mrb_int val;
#undef ISDIGIT
#define ISDIGIT(c) ('0' <= (c) && (c) <= '9')
@@ -2113,43 +2118,32 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
}
switch (base) {
case 2:
- len = 1;
if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
str += 2;
}
break;
case 3:
- len = 2;
break;
case 8:
if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
str += 2;
}
case 4: case 5: case 6: case 7:
- len = 3;
break;
case 10:
if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
str += 2;
}
case 9: case 11: case 12: case 13: case 14: case 15:
- len = 4;
break;
case 16:
- len = 4;
if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
str += 2;
}
break;
default:
if (base < 2 || 36 < base) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %d", base);
- }
- if (base <= 32) {
- len = 5;
- }
- else {
- len = 6;
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %S", mrb_fixnum_value(base));
}
break;
} /* end of switch (base) { */
@@ -2171,23 +2165,21 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
if (badcheck) goto bad;
return mrb_fixnum_value(0);
}
- len *= strlen(str);
-
- val = strtoul((char*)str, &end, base);
+ n = strtoul((char*)str, &end, base);
+ if (n > MRB_INT_MAX) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str));
+ }
+ val = n;
if (badcheck) {
if (end == str) goto bad; /* no number */
while (*end && ISSPACE(*end)) end++;
if (*end) goto bad; /* trailing garbage */
}
- if (sign) return mrb_fixnum_value(val);
- else {
- long result = -(long)val;
- return mrb_fixnum_value(result);
- }
+ return mrb_fixnum_value(sign ? val : -val);
bad:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%s)", str);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%S)", mrb_str_new_cstr(mrb, str));
/* not reached */
return mrb_fixnum_value(0);
}
@@ -2210,7 +2202,7 @@ mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, int badcheck)
char *s;
int len;
- mrb_string_value(mrb, &str);
+ str = mrb_str_to_str(mrb, str);
if (badcheck) {
s = mrb_string_value_cstr(mrb, &str);
}
@@ -2262,7 +2254,7 @@ mrb_str_to_i(mrb_state *mrb, mrb_value self)
base = mrb_fixnum(argv[0]);
if (base < 0) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %d", base);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %S", mrb_fixnum_value(base));
}
return mrb_str_to_inum(mrb, self, base, 0/*Qfalse*/);
}
@@ -2273,7 +2265,7 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, int badcheck)
char *end;
double d;
#if !defined(DBL_DIG)
- #define DBL_DIG 16
+# define DBL_DIG 16
#endif
enum {max_width = 20};
@@ -2291,7 +2283,7 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, int badcheck)
if (p == end) {
if (badcheck) {
bad:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%s)", p);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%S)", mrb_str_new_cstr(mrb, p));
/* not reached */
}
return d;
@@ -2342,7 +2334,7 @@ mrb_str_to_dbl(mrb_state *mrb, mrb_value str, int badcheck)
char *s;
int len;
- mrb_string_value(mrb, &str);
+ str = mrb_str_to_str(mrb, str);
s = RSTRING_PTR(str);
len = RSTRING_LEN(str);
if (s) {
@@ -2455,7 +2447,7 @@ mrb_str_upcase(mrb_state *mrb, mrb_value self)
mrb_value
mrb_str_dump(mrb_state *mrb, mrb_value str)
{
- long len;
+ mrb_int len;
const char *p, *pend;
char *q;
struct RString *result;
@@ -2545,7 +2537,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str)
const char *ptr;
int len;
chr = mrb_fixnum_value(c & 0xff);
- octstr = mrb_fix2str(mrb, chr, 8);
+ octstr = mrb_fixnum_to_str(mrb, chr, 8);
ptr = mrb_str_body(octstr, &len);
memcpy(q, "\\000", 4);
memcpy(q + 4 - len, ptr, len);
@@ -2557,7 +2549,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str)
}
mrb_value
-mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len)
+mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, mrb_int len)
{
if (len < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)");
@@ -2567,7 +2559,7 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len)
}
mrb_value
-mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr)
+mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr)
{
return mrb_str_cat(mrb, str, ptr, strlen(ptr));
}
@@ -2575,7 +2567,7 @@ mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr)
mrb_value
mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2)
{
- mrb_string_value(mrb, &str2);
+ str2 = mrb_str_to_str(mrb, str2);
return mrb_str_buf_append(mrb, str, str2);
}
@@ -2637,7 +2629,7 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str)
const char *ptr;
int len;
chr = mrb_fixnum_value(c & 0xff);
- octstr = mrb_fix2str(mrb, chr, 8);
+ octstr = mrb_fixnum_to_str(mrb, chr, 8);
ptr = mrb_str_body(octstr, &len);
memcpy(buf, "\\000", 4);
memcpy(buf + 4 - len, ptr, len);
diff --git a/src/symbol.c b/src/symbol.c
index 81c28d265..55bb4885a 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -4,16 +4,16 @@
** See Copyright Notice in mruby.h
*/
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
#include "mruby.h"
#include "mruby/khash.h"
-#include <string.h>
-
#include "mruby/string.h"
-#include <ctype.h>
/* ------------------------------------------------------ */
typedef struct symbol_name {
- int len;
+ size_t len;
const char *name;
} symbol_name;
@@ -35,7 +35,7 @@ KHASH_DECLARE(n2s, symbol_name, mrb_sym, 1)
KHASH_DEFINE (n2s, symbol_name, mrb_sym, 1, sym_hash_func, sym_hash_equal)
/* ------------------------------------------------------ */
mrb_sym
-mrb_intern2(mrb_state *mrb, const char *name, int len)
+mrb_intern2(mrb_state *mrb, const char *name, size_t len)
{
khash_t(n2s) *h = mrb->name2sym;
symbol_name sname;
@@ -61,7 +61,7 @@ mrb_intern2(mrb_state *mrb, const char *name, int len)
}
mrb_sym
-mrb_intern(mrb_state *mrb, const char *name)
+mrb_intern_cstr(mrb_state *mrb, const char *name)
{
return mrb_intern2(mrb, name, strlen(name));
}
@@ -72,8 +72,9 @@ mrb_intern_str(mrb_state *mrb, mrb_value str)
return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
}
+/* lenp must be a pointer to a size_t variable */
const char*
-mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, int *lenp)
+mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp)
{
khash_t(n2s) *h = mrb->name2sym;
khiter_t k;
@@ -81,16 +82,15 @@ mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, int *lenp)
for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)) {
- if (kh_value(h, k) == sym) break;
+ if (kh_value(h, k) == sym) {
+ sname = kh_key(h, k);
+ *lenp = sname.len;
+ return sname.name;
+ }
}
}
- if (k == kh_end(h)) {
- *lenp = 0;
- return NULL; /* missing */
- }
- sname = kh_key(h, k);
- *lenp = sname.len;
- return sname.name;
+ *lenp = 0;
+ return NULL; /* missing */
}
void
@@ -157,10 +157,12 @@ static mrb_value
sym_equal(mrb_state *mrb, mrb_value sym1)
{
mrb_value sym2;
+ mrb_bool equal_p;
mrb_get_args(mrb, "o", &sym2);
- if (mrb_obj_equal(mrb, sym1, sym2)) return mrb_true_value();
- return mrb_false_value();
+ equal_p = mrb_obj_equal(mrb, sym1, sym2);
+
+ return mrb_bool_value(equal_p);
}
/* 15.2.11.3.2 */
@@ -179,7 +181,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym)
{
mrb_sym id = mrb_symbol(sym);
const char *p;
- int len;
+ size_t len;
p = mrb_sym2name_len(mrb, id, &len);
return mrb_str_new(mrb, p, len);
@@ -199,7 +201,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym)
static mrb_value
sym_to_sym(mrb_state *mrb, mrb_value sym)
{
- return sym;
+ return sym;
}
/* 15.2.11.3.5(x) */
@@ -223,106 +225,107 @@ sym_to_sym(mrb_state *mrb, mrb_value sym)
static int
is_special_global_name(const char* m)
{
- switch (*m) {
- case '~': case '*': case '$': case '?': case '!': case '@':
- case '/': case '\\': case ';': case ',': case '.': case '=':
- case ':': case '<': case '>': case '\"':
- case '&': case '`': case '\'': case '+':
- case '0':
- ++m;
- break;
- case '-':
- ++m;
- if (is_identchar(*m)) m += 1;
- break;
- default:
- if (!ISDIGIT(*m)) return FALSE;
- do ++m; while (ISDIGIT(*m));
- }
- return !*m;
+ switch (*m) {
+ case '~': case '*': case '$': case '?': case '!': case '@':
+ case '/': case '\\': case ';': case ',': case '.': case '=':
+ case ':': case '<': case '>': case '\"':
+ case '&': case '`': case '\'': case '+':
+ case '0':
+ ++m;
+ break;
+ case '-':
+ ++m;
+ if (is_identchar(*m)) m += 1;
+ break;
+ default:
+ if (!ISDIGIT(*m)) return FALSE;
+ do ++m; while (ISDIGIT(*m));
+ break;
+ }
+ return !*m;
}
static int
symname_p(const char *name)
{
- const char *m = name;
- int localid = FALSE;
-
- if (!m) return FALSE;
- switch (*m) {
- case '\0':
- return FALSE;
-
- case '$':
- if (is_special_global_name(++m)) return TRUE;
- goto id;
-
- case '@':
- if (*++m == '@') ++m;
- goto id;
-
- case '<':
- switch (*++m) {
- case '<': ++m; break;
- case '=': if (*++m == '>') ++m; break;
- default: break;
- }
- break;
-
- case '>':
- switch (*++m) {
- case '>': case '=': ++m; break;
- default: break;
- }
- break;
-
- case '=':
- switch (*++m) {
- case '~': ++m; break;
- case '=': if (*++m == '=') ++m; break;
- default: return FALSE;
- }
- break;
-
- case '*':
- if (*++m == '*') ++m;
- break;
- case '!':
- if (*++m == '=') ++m;
- break;
- case '+': case '-':
- if (*++m == '@') ++m;
- break;
- case '|':
- if (*++m == '|') ++m;
- break;
- case '&':
- if (*++m == '&') ++m;
- break;
-
- case '^': case '/': case '%': case '~': case '`':
- ++m;
- break;
-
- case '[':
- if (*++m != ']') return FALSE;
- if (*++m == '=') ++m;
- break;
-
- default:
- localid = !ISUPPER(*m);
+ const char *m = name;
+ int localid = FALSE;
+
+ if (!m) return FALSE;
+ switch (*m) {
+ case '\0':
+ return FALSE;
+
+ case '$':
+ if (is_special_global_name(++m)) return TRUE;
+ goto id;
+
+ case '@':
+ if (*++m == '@') ++m;
+ goto id;
+
+ case '<':
+ switch (*++m) {
+ case '<': ++m; break;
+ case '=': if (*++m == '>') ++m; break;
+ default: break;
+ }
+ break;
+
+ case '>':
+ switch (*++m) {
+ case '>': case '=': ++m; break;
+ default: break;
+ }
+ break;
+
+ case '=':
+ switch (*++m) {
+ case '~': ++m; break;
+ case '=': if (*++m == '=') ++m; break;
+ default: return FALSE;
+ }
+ break;
+
+ case '*':
+ if (*++m == '*') ++m;
+ break;
+ case '!':
+ if (*++m == '=') ++m;
+ break;
+ case '+': case '-':
+ if (*++m == '@') ++m;
+ break;
+ case '|':
+ if (*++m == '|') ++m;
+ break;
+ case '&':
+ if (*++m == '&') ++m;
+ break;
+
+ case '^': case '/': case '%': case '~': case '`':
+ ++m;
+ break;
+
+ case '[':
+ if (*++m != ']') return FALSE;
+ if (*++m == '=') ++m;
+ break;
+
+ default:
+ localid = !ISUPPER(*m);
id:
- if (*m != '_' && !ISALPHA(*m)) return FALSE;
- while (is_identchar(*m)) m += 1;
- if (localid) {
- switch (*m) {
- case '!': case '?': case '=': ++m;
- default: break;
+ if (*m != '_' && !ISALPHA(*m)) return FALSE;
+ while (is_identchar(*m)) m += 1;
+ if (localid) {
+ switch (*m) {
+ case '!': case '?': case '=': ++m;
+ default: break;
}
}
- break;
- }
- return *m ? FALSE : TRUE;
+ break;
+ }
+ return *m ? FALSE : TRUE;
}
static mrb_value
@@ -330,7 +333,7 @@ sym_inspect(mrb_state *mrb, mrb_value sym)
{
mrb_value str;
const char *name;
- int len;
+ size_t len;
mrb_sym id = mrb_symbol(sym);
name = mrb_sym2name_len(mrb, id, &len);
@@ -344,10 +347,25 @@ sym_inspect(mrb_state *mrb, mrb_value sym)
return str;
}
+mrb_value
+mrb_sym2str(mrb_state *mrb, mrb_sym sym)
+{
+ size_t len;
+ const char *name = mrb_sym2name_len(mrb, sym, &len);
+
+ if (!name) return mrb_undef_value(); /* can't happen */
+ if (symname_p(name) && strlen(name) == len) {
+ return mrb_str_new(mrb, name, len);
+ }
+ else {
+ return mrb_str_dump(mrb, mrb_str_new(mrb, name, len));
+ }
+}
+
const char*
mrb_sym2name(mrb_state *mrb, mrb_sym sym)
{
- int len;
+ size_t len;
const char *name = mrb_sym2name_len(mrb, sym, &len);
if (!name) return NULL;
@@ -375,7 +393,8 @@ sym_cmp(mrb_state *mrb, mrb_value s1)
if (sym1 == sym2) return mrb_fixnum_value(0);
else {
const char *p1, *p2;
- int len, len1, len2, retval;
+ int retval;
+ size_t len, len1, len2;
p1 = mrb_sym2name_len(mrb, sym1, &len1);
p2 = mrb_sym2name_len(mrb, sym2, &len2);
diff --git a/src/value_array.h b/src/value_array.h
new file mode 100644
index 000000000..cabd2426d
--- /dev/null
+++ b/src/value_array.h
@@ -0,0 +1,27 @@
+#ifndef MRB_VALUE_ARRAY_H__
+#define MRB_VALUE_ARRAY_H__
+
+#include "mruby.h"
+
+static inline void
+value_move(mrb_value *s1, const mrb_value *s2, size_t n)
+{
+ if (s1 > s2 && s1 < s2 + n)
+ {
+ s1 += n;
+ s2 += n;
+ while (n-- > 0) {
+ *--s1 = *--s2;
+ }
+ }
+ else if (s1 != s2) {
+ while (n-- > 0) {
+ *s1++ = *s2++;
+ }
+ }
+ else {
+ /* nothing to do. */
+ }
+}
+
+#endif /* MRB_VALUE_ARRAY_H__ */
diff --git a/src/variable.c b/src/variable.c
index 5f657e3d7..941aaf83e 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -5,12 +5,12 @@
*/
#include "mruby.h"
+#include "mruby/array.h"
#include "mruby/class.h"
+#include "mruby/proc.h"
+#include "mruby/string.h"
#include "mruby/variable.h"
#include "error.h"
-#include "mruby/array.h"
-#include "mruby/string.h"
-#include "mruby/proc.h"
typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
@@ -28,8 +28,8 @@ typedef struct segment {
typedef struct iv_tbl {
segment *rootseg;
- int size;
- int last_len;
+ size_t size;
+ size_t last_len;
} iv_tbl;
static iv_tbl*
@@ -52,27 +52,27 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
segment *seg = t->rootseg;
segment *prev = NULL;
segment *matched_seg = NULL;
- int matched_idx = 0;
- int i;
+ size_t matched_idx = 0;
+ size_t i;
while (seg) {
for (i=0; i<MRB_SEGMENT_SIZE; i++) {
mrb_sym key = seg->key[i];
/* found room in last segment after last_len */
if (!seg->next && i >= t->last_len) {
- seg->key[i] = sym;
- seg->val[i] = val;
- t->last_len = i+1;
- t->size++;
- return;
+ seg->key[i] = sym;
+ seg->val[i] = val;
+ t->last_len = i+1;
+ t->size++;
+ return;
}
if (!matched_seg && key == 0) {
- matched_seg = seg;
- matched_idx = i;
+ matched_seg = seg;
+ matched_idx = i;
}
else if (key == sym) {
- seg->val[i] = val;
- return;
+ seg->val[i] = val;
+ return;
}
}
prev = seg;
@@ -102,11 +102,11 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
return;
}
-static int
+static mrb_bool
iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
segment *seg;
- int i;
+ size_t i;
seg = t->rootseg;
while (seg) {
@@ -114,11 +114,11 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
mrb_sym key = seg->key[i];
if (!seg->next && i >= t->last_len) {
- return FALSE;
+ return FALSE;
}
if (key == sym) {
- if (vp) *vp = seg->val[i];
- return TRUE;
+ if (vp) *vp = seg->val[i];
+ return TRUE;
}
}
seg = seg->next;
@@ -126,11 +126,11 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
return FALSE;
}
-static int
+static mrb_bool
iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
segment *seg;
- int i;
+ size_t i;
seg = t->rootseg;
while (seg) {
@@ -138,13 +138,13 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
mrb_sym key = seg->key[i];
if (!seg->next && i >= t->last_len) {
- return FALSE;
+ return FALSE;
}
if (key == sym) {
- t->size--;
- seg->key[i] = 0;
- if (vp) *vp = seg->val[i];
- return TRUE;
+ t->size--;
+ seg->key[i] = 0;
+ if (vp) *vp = seg->val[i];
+ return TRUE;
}
}
seg = seg->next;
@@ -152,11 +152,12 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
return FALSE;
}
-static int
+static mrb_bool
iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
{
segment *seg;
- int i, n;
+ size_t i;
+ int n;
seg = t->rootseg;
while (seg) {
@@ -165,15 +166,15 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
/* no value in last segment after last_len */
if (!seg->next && i >= t->last_len) {
- return FALSE;
+ return FALSE;
}
if (key != 0) {
- n =(*func)(mrb, key, seg->val[i], p);
- if (n > 0) return FALSE;
- if (n < 0) {
- t->size--;
- seg->key[i] = 0;
- }
+ n =(*func)(mrb, key, seg->val[i], p);
+ if (n > 0) return FALSE;
+ if (n < 0) {
+ t->size--;
+ seg->key[i] = 0;
+ }
}
}
seg = seg->next;
@@ -181,11 +182,11 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
return TRUE;
}
-static int
+static size_t
iv_size(mrb_state *mrb, iv_tbl *t)
{
segment *seg;
- int size = 0;
+ size_t size = 0;
if (!t) return 0;
if (t->size > 0) return t->size;
@@ -208,7 +209,7 @@ iv_copy(mrb_state *mrb, iv_tbl *t)
segment *seg;
iv_tbl *t2;
- int i;
+ size_t i;
seg = t->rootseg;
t2 = iv_new(mrb);
@@ -273,7 +274,7 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
kh_value(h, k) = val;
}
-static int
+static mrb_bool
iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
khash_t(iv) *h = &t->h;
@@ -287,7 +288,7 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
return FALSE;
}
-static int
+static mrb_bool
iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
khash_t(iv) *h = &t->h;
@@ -305,7 +306,7 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
return FALSE;
}
-static int
+static mrb_bool
iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
{
khash_t(iv) *h = &t->h;
@@ -315,18 +316,18 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
if (h) {
for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)){
- n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p);
- if (n > 0) return FALSE;
- if (n < 0) {
- kh_del(iv, h, k);
- }
+ n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p);
+ if (n > 0) return FALSE;
+ if (n < 0) {
+ kh_del(iv, h, k);
+ }
}
}
}
return TRUE;
}
-static int
+static size_t
iv_size(mrb_state *mrb, iv_tbl *t)
{
khash_t(iv) *h = &t->h;
@@ -408,7 +409,7 @@ mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v)
{
}
-static int
+static mrb_bool
obj_iv_p(mrb_value obj)
{
switch (mrb_type(obj)) {
@@ -481,7 +482,7 @@ mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v)
}
}
-int
+mrb_bool
mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
{
iv_tbl *t;
@@ -493,7 +494,7 @@ mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
return FALSE;
}
-int
+mrb_bool
mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym)
{
if (!obj_iv_p(obj)) return FALSE;
@@ -520,15 +521,15 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
mrb_value str = *(mrb_value*)p;
const char *s;
- int len;
+ size_t len;
/* need not to show internal data */
if (RSTRING_PTR(str)[0] == '-') { /* first element */
RSTRING_PTR(str)[0] = '#';
- mrb_str_cat2(mrb, str, " ");
+ mrb_str_cat(mrb, str, " ", 1);
}
else {
- mrb_str_cat2(mrb, str, ", ");
+ mrb_str_cat(mrb, str, ", ", 2);
}
s = mrb_sym2name_len(mrb, sym, &len);
mrb_str_cat(mrb, str, s, len);
@@ -541,13 +542,19 @@ mrb_value
mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj)
{
iv_tbl *t = obj->iv;
- int len = iv_size(mrb, t);
+ size_t len = iv_size(mrb, t);
if (len > 0) {
const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj));
- mrb_value str = mrb_sprintf(mrb, "-<%s:%p", cn, (void*)obj);
+ mrb_value str = mrb_str_buf_new(mrb, 30);
+
+ mrb_str_buf_cat(mrb, str, "-<", 2);
+ mrb_str_cat2(mrb, str, cn);
+ mrb_str_cat(mrb, str, ":", 1);
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj));
iv_foreach(mrb, t, inspect_i, &str);
+ mrb_str_cat(mrb, str, ">", 1);
return str;
}
return mrb_any_to_s(mrb, mrb_obj_value(obj));
@@ -586,7 +593,7 @@ iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
mrb_value ary;
const char* s;
- int len;
+ size_t len;
ary = *(mrb_value*)p;
s = mrb_sym2name_len(mrb, sym, &len);
@@ -630,7 +637,7 @@ cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
mrb_value ary;
const char* s;
- int len;
+ size_t len;
ary = *(mrb_value*)p;
s = mrb_sym2name_len(mrb, sym, &len);
@@ -683,8 +690,8 @@ mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym)
}
c = c->super;
}
- mrb_raisef(mrb, E_NAME_ERROR, "uninitialized class variable %s in %s",
- mrb_sym2name(mrb, sym), mrb_class_name(mrb, cls));
+ mrb_raisef(mrb, E_NAME_ERROR, "uninitialized class variable %S in %S",
+ mrb_sym2str(mrb, sym), cls);
/* not reached */
return mrb_nil_value();
}
@@ -727,7 +734,7 @@ mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v);
}
-int
+mrb_bool
mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym)
{
while (c) {
@@ -741,7 +748,7 @@ mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym)
return FALSE;
}
-int
+mrb_bool
mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
{
return mrb_mod_cv_defined(mrb, mrb_class_ptr(mod), sym);
@@ -753,7 +760,7 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
struct RClass *c = mrb->ci->proc->target_class;
if (!c) c = mrb->ci->target_class;
-
+
return mrb_mod_cv_get(mrb, c, sym);
}
@@ -769,7 +776,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
if (iv_get(mrb, t, sym, NULL)) {
mrb_write_barrier(mrb, (struct RBasic*)c);
- iv_put(mrb, t, sym, v);
+ iv_put(mrb, t, sym, v);
return;
}
}
@@ -783,7 +790,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
iv_put(mrb, c->iv, sym, v);
}
-int
+mrb_bool
mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
{
struct RClass *m = mrb_class_ptr(mod);
@@ -813,15 +820,15 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
struct RClass *c = base;
mrb_value v;
iv_tbl *t;
- int retry = 0;
+ mrb_bool retry = 0;
mrb_sym cm;
- L_RETRY:
+L_RETRY:
while (c) {
if (c->iv) {
t = c->iv;
if (iv_get(mrb, t, sym, &v))
- return v;
+ return v;
}
c = c->super;
}
@@ -831,7 +838,7 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
goto L_RETRY;
}
c = base;
- cm = mrb_intern(mrb, "const_missing");
+ cm = mrb_intern2(mrb, "const_missing", 13);
while (c) {
if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) {
mrb_value name = mrb_symbol_value(sym);
@@ -839,8 +846,8 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
}
c = c->super;
}
- mrb_raisef(mrb, E_NAME_ERROR, "uninitialized constant %s",
- mrb_sym2name(mrb, sym));
+ mrb_raisef(mrb, E_NAME_ERROR, "uninitialized constant %S",
+ mrb_sym2str(mrb, sym));
/* not reached */
return mrb_nil_value();
}
@@ -870,7 +877,7 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
c2 = mrb_class_outer_module(mrb, c2);
if (!c2) break;
if (c2->iv && iv_get(mrb, c2->iv, sym, &v)) {
- return v;
+ return v;
}
}
}
@@ -964,7 +971,7 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self)
{
iv_tbl *t = mrb->globals;
mrb_value ary = mrb_ary_new(mrb);
- int i;
+ size_t i;
char buf[3];
if (t) {
@@ -979,11 +986,11 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self)
return ary;
}
-static int
-mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, int exclude, int recurse)
+static mrb_bool
+mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, mrb_bool exclude, mrb_bool recurse)
{
struct RClass * tmp;
- int mod_retry = 0;
+ mrb_bool mod_retry = 0;
tmp = klass;
retry:
@@ -1036,7 +1043,7 @@ csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) {
a->sym = sym;
- return 1; /* stop iteration */
+ return 1; /* stop iteration */
}
return 0;
}
@@ -1046,7 +1053,7 @@ mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer)
{
mrb_value name;
- name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__"));
+ name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__classid__", 11));
if (mrb_nil_p(name)) {
if (!outer) return 0;
diff --git a/src/vm.c b/src/vm.c
index 6e15c48a0..596e34961 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -4,24 +4,24 @@
** See Copyright Notice in mruby.h
*/
+#include <string.h>
+#include <setjmp.h>
+#include <stddef.h>
+#include <stdarg.h>
#include "mruby.h"
-#include "opcode.h"
-#include "mruby/irep.h"
-#include "mruby/variable.h"
-#include "mruby/proc.h"
#include "mruby/array.h"
-#include "mruby/string.h"
-#include "mruby/hash.h"
-#include "mruby/range.h"
#include "mruby/class.h"
+#include "mruby/hash.h"
+#include "mruby/irep.h"
#include "mruby/numeric.h"
+#include "mruby/proc.h"
+#include "mruby/range.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
#include "error.h"
+#include "opcode.h"
+#include "value_array.h"
-#include <stdio.h>
-#include <string.h>
-#include <setjmp.h>
-#include <stddef.h>
-#include <stdarg.h>
#define SET_TRUE_VALUE(r) MRB_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
#define SET_FALSE_VALUE(r) MRB_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
@@ -46,7 +46,7 @@
/* Maximum stack depth. Should be set lower on memory constrained systems.
The value below allows about 60000 recursive calls in the simplest case. */
#ifndef MRB_STACK_MAX
-#define MRB_STACK_MAX ((1<<18) - MRB_STACK_GROWTH)
+#define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH)
#endif
#ifdef VM_DEBUG
@@ -56,12 +56,20 @@ The value below allows about 60000 recursive calls in the simplest case. */
#endif
static inline void
-stack_copy(mrb_value *dst, const mrb_value *src, size_t size)
+stack_clear(mrb_value *from, size_t count)
{
- size_t i;
+ const mrb_value mrb_value_zero = { { 0 } };
- for (i = 0; i < size; i++) {
- dst[i] = src[i];
+ while(count-- > 0) {
+ *from++ = mrb_value_zero;
+ }
+}
+
+static inline void
+stack_copy(mrb_value *dst, const mrb_value *src, size_t size)
+{
+ while (size-- > 0) {
+ *dst++ = *src++;
}
}
@@ -80,7 +88,7 @@ stack_init(mrb_state *mrb)
mrb->ci->target_class = mrb->object_class;
}
-static void
+static inline void
envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
{
mrb_callinfo *ci = mrb->cibase;
@@ -88,7 +96,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
while (ci <= mrb->ci) {
struct REnv *e = ci->env;
if (e && e->cioff >= 0) {
- int off = e->stack - oldbase;
+ ptrdiff_t off = e->stack - oldbase;
e->stack = newbase + off;
}
@@ -101,8 +109,9 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
static void
stack_extend(mrb_state *mrb, int room, int keep)
{
- int size, off;
if (mrb->stack + room >= mrb->stend) {
+ int size, off;
+
mrb_value *oldbase = mrb->stbase;
size = mrb->stend - mrb->stbase;
@@ -125,32 +134,24 @@ stack_extend(mrb_state *mrb, int room, int keep)
envadjust(mrb, oldbase, mrb->stbase);
/* Raise an exception if the new stack size will be too large,
to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raisef has stack space to work with. */
- if(size > MRB_STACK_MAX) {
- mrb_raisef(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=%d)", MRB_STACK_MAX);
+ if (size > MRB_STACK_MAX) {
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=%S)", mrb_fixnum_value(MRB_STACK_MAX));
}
}
if (room > keep) {
- int i;
- for (i=keep; i<room; i++) {
#ifndef MRB_NAN_BOXING
- static const mrb_value mrb_value_zero = { { 0 } };
- mrb->stack[i] = mrb_value_zero;
+ stack_clear(&(mrb->stack[keep]), room - keep);
#else
+ int i;
+ for (i=keep; i<room; i++) {
SET_NIL_VALUE(mrb->stack[i]);
-#endif
}
+#endif
}
}
-int
-mrb_checkstack(mrb_state *mrb, int size)
-{
- stack_extend(mrb, size+1, 1);
- return 0;
-}
-
-struct REnv*
+static inline struct REnv*
uvenv(mrb_state *mrb, int up)
{
struct REnv *e = mrb->ci->proc->env;
@@ -162,25 +163,6 @@ uvenv(mrb_state *mrb, int up)
return e;
}
-static mrb_value
-uvget(mrb_state *mrb, int up, int idx)
-{
- struct REnv *e = uvenv(mrb, up);
-
- if (!e) return mrb_nil_value();
- return e->stack[idx];
-}
-
-static void
-uvset(mrb_state *mrb, int up, int idx, mrb_value v)
-{
- struct REnv *e = uvenv(mrb, up);
-
- if (!e) return;
- e->stack[idx] = v;
- mrb_write_barrier(mrb, (struct RBasic*)e);
-}
-
static inline int
is_strict(mrb_state *mrb, struct REnv *e)
{
@@ -193,7 +175,7 @@ is_strict(mrb_state *mrb, struct REnv *e)
return 0;
}
-struct REnv*
+static inline struct REnv*
top_env(mrb_state *mrb, struct RProc *proc)
{
struct REnv *e = proc->env;
@@ -220,7 +202,7 @@ cipush(mrb_state *mrb)
mrb->ciend = mrb->cibase + size * 2;
}
mrb->ci++;
- mrb->ci->nregs = 2; /* protect method_missing arg and block */
+ mrb->ci->nregs = 2; /* protect method_missing arg and block */
mrb->ci->eidx = eidx;
mrb->ci->ridx = ridx;
mrb->ci->env = 0;
@@ -232,7 +214,7 @@ cipop(mrb_state *mrb)
{
if (mrb->ci->env) {
struct REnv *e = mrb->ci->env;
- int len = (int)e->flags;
+ size_t len = (size_t)e->flags;
mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
e->cioff = -1;
@@ -274,14 +256,13 @@ mrb_value
mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...)
{
mrb_sym mid = mrb_intern(mrb, name);
- va_list ap;
- int i;
if (argc == 0) {
return mrb_funcall_argv(mrb, self, mid, 0, 0);
}
else if (argc == 1) {
mrb_value v;
+ va_list ap;
va_start(ap, argc);
v = va_arg(ap, mrb_value);
@@ -290,9 +271,11 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...)
}
else {
mrb_value argv[MRB_FUNCALL_ARGC_MAX];
+ va_list ap;
+ int i;
if (argc > MRB_FUNCALL_ARGC_MAX) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%S)", mrb_fixnum_value(MRB_FUNCALL_ARGC_MAX));
}
va_start(ap, argc);
@@ -307,83 +290,86 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...)
mrb_value
mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv, mrb_value blk)
{
- struct RProc *p;
- struct RClass *c;
- mrb_sym undef = 0;
- mrb_callinfo *ci;
- int n;
mrb_value val;
if (!mrb->jmp) {
jmp_buf c_jmp;
mrb_callinfo *old_ci = mrb->ci;
- if (setjmp(c_jmp) != 0) { /* error */
+ if (setjmp(c_jmp) != 0) { /* error */
while (old_ci != mrb->ci) {
mrb->stack = mrb->stbase + mrb->ci->stackidx;
cipop(mrb);
}
mrb->jmp = 0;
- return mrb_nil_value();
+ val = mrb_nil_value();
+ }
+ else {
+ mrb->jmp = &c_jmp;
+ /* recursive call */
+ val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
+ mrb->jmp = 0;
}
- mrb->jmp = &c_jmp;
- /* recursive call */
- val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
- mrb->jmp = 0;
- return val;
- }
-
- if (!mrb->stack) {
- stack_init(mrb);
- }
- n = mrb->ci->nregs;
- if (argc < 0) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc);
- }
- c = mrb_class(mrb, self);
- p = mrb_method_search_vm(mrb, &c, mid);
- if (!p) {
- undef = mid;
- mid = mrb_intern(mrb, "method_missing");
- p = mrb_method_search_vm(mrb, &c, mid);
- n++; argc++;
- }
- ci = cipush(mrb);
- ci->mid = mid;
- ci->proc = p;
- ci->stackidx = mrb->stack - mrb->stbase;
- ci->argc = argc;
- ci->target_class = p->target_class;
- if (MRB_PROC_CFUNC_P(p)) {
- ci->nregs = argc + 2;
}
else {
- ci->nregs = p->body.irep->nregs + 2;
- }
- ci->acc = -1;
- mrb->stack = mrb->stack + n;
-
- stack_extend(mrb, ci->nregs, 0);
- mrb->stack[0] = self;
- if (undef) {
- mrb->stack[1] = mrb_symbol_value(undef);
- stack_copy(mrb->stack+2, argv, argc-1);
- }
- else if (argc > 0) {
- stack_copy(mrb->stack+1, argv, argc);
- }
- mrb->stack[argc+1] = blk;
+ struct RProc *p;
+ struct RClass *c;
+ mrb_sym undef = 0;
+ mrb_callinfo *ci;
+ int n;
- if (MRB_PROC_CFUNC_P(p)) {
- int ai = mrb_gc_arena_save(mrb);
- val = p->body.func(mrb, self);
- mrb_gc_arena_restore(mrb, ai);
- mrb_gc_protect(mrb, val);
- mrb->stack = mrb->stbase + mrb->ci->stackidx;
- cipop(mrb);
- }
- else {
- val = mrb_run(mrb, p, self);
+ if (!mrb->stack) {
+ stack_init(mrb);
+ }
+ n = mrb->ci->nregs;
+ if (argc < 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc));
+ }
+ c = mrb_class(mrb, self);
+ p = mrb_method_search_vm(mrb, &c, mid);
+ if (!p) {
+ undef = mid;
+ mid = mrb_intern2(mrb, "method_missing", 14);
+ p = mrb_method_search_vm(mrb, &c, mid);
+ n++; argc++;
+ }
+ ci = cipush(mrb);
+ ci->mid = mid;
+ ci->proc = p;
+ ci->stackidx = mrb->stack - mrb->stbase;
+ ci->argc = argc;
+ ci->target_class = p->target_class;
+ if (MRB_PROC_CFUNC_P(p)) {
+ ci->nregs = argc + 2;
+ }
+ else {
+ ci->nregs = p->body.irep->nregs + 2;
+ }
+ ci->acc = -1;
+ mrb->stack = mrb->stack + n;
+
+ stack_extend(mrb, ci->nregs, 0);
+ mrb->stack[0] = self;
+ if (undef) {
+ mrb->stack[1] = mrb_symbol_value(undef);
+ stack_copy(mrb->stack+2, argv, argc-1);
+ }
+ else if (argc > 0) {
+ stack_copy(mrb->stack+1, argv, argc);
+ }
+ mrb->stack[argc+1] = blk;
+
+ if (MRB_PROC_CFUNC_P(p)) {
+ int ai = mrb_gc_arena_save(mrb);
+ val = p->body.func(mrb, self);
+ mrb_gc_arena_restore(mrb, ai);
+ mrb_gc_protect(mrb, val);
+ mrb->stack = mrb->stbase + mrb->ci->stackidx;
+ cipop(mrb);
+ }
+ else {
+ val = mrb_run(mrb, p, self);
+ }
}
return val;
}
@@ -453,36 +439,45 @@ mrb_yield(mrb_state *mrb, mrb_value b, mrb_value v)
return mrb_yield_internal(mrb, b, 1, &v, mrb->stack[0], p->target_class);
}
+typedef enum {
+ LOCALJUMP_ERROR_RETURN = 0,
+ LOCALJUMP_ERROR_BREAK = 1,
+ LOCALJUMP_ERROR_YIELD = 2
+} localjump_error_kind;
+
static void
-localjump_error(mrb_state *mrb, const char *kind)
+localjump_error(mrb_state *mrb, localjump_error_kind kind)
{
- char buf[256];
- int len;
+ char kind_str[3][7] = { "return", "break", "yield" };
+ char kind_str_len[] = { 6, 5, 5 };
+ static const char lead[] = "unexpected ";
+ mrb_value msg;
mrb_value exc;
- len = snprintf(buf, sizeof(buf), "unexpected %s", kind);
- exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, buf, len);
- mrb->exc = (struct RObject*)mrb_object(exc);
+ msg = mrb_str_buf_new(mrb, sizeof(lead) + 7);
+ mrb_str_buf_cat(mrb, msg, lead, sizeof(lead) - 1);
+ mrb_str_buf_cat(mrb, msg, kind_str[kind], kind_str_len[kind]);
+ exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg);
+ mrb->exc = mrb_obj_ptr(exc);
}
static void
argnum_error(mrb_state *mrb, int num)
{
- char buf[256];
- int len;
mrb_value exc;
+ mrb_value str;
if (mrb->ci->mid) {
- len = snprintf(buf, sizeof(buf), "'%s': wrong number of arguments (%d for %d)",
- mrb_sym2name(mrb, mrb->ci->mid),
- mrb->ci->argc, num);
+ str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)",
+ mrb_sym2str(mrb, mrb->ci->mid),
+ mrb_fixnum_value(mrb->ci->argc), mrb_fixnum_value(num));
}
else {
- len = snprintf(buf, sizeof(buf), "wrong number of arguments (%d for %d)",
- mrb->ci->argc, num);
+ str = mrb_format(mrb, "wrong number of arguments (%S for %S)",
+ mrb_fixnum_value(mrb->ci->argc), mrb_fixnum_value(num));
}
- exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, len);
- mrb->exc = (struct RObject*)mrb_object(exc);
+ exc = mrb_exc_new3(mrb, E_ARGUMENT_ERROR, str);
+ mrb->exc = mrb_obj_ptr(exc);
}
#ifdef ENABLE_DEBUG
@@ -700,14 +695,34 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_GETUPVAR) {
/* A B C R(A) := uvget(B,C) */
+ mrb_value *regs_a = regs + GETARG_A(i);
+ int up = GETARG_C(i);
+
+ struct REnv *e = uvenv(mrb, up);
- regs[GETARG_A(i)] = uvget(mrb, GETARG_C(i), GETARG_B(i));
+ if (!e) {
+ *regs_a = mrb_nil_value();
+ }
+ else {
+ int idx = GETARG_B(i);
+ *regs_a = e->stack[idx];
+ }
NEXT;
}
CASE(OP_SETUPVAR) {
/* A B C uvset(B,C,R(A)) */
- uvset(mrb, GETARG_C(i), GETARG_B(i), regs[GETARG_A(i)]);
+ /* A B C R(A) := uvget(B,C) */
+ int up = GETARG_C(i);
+
+ struct REnv *e = uvenv(mrb, up);
+
+ if (e) {
+ mrb_value *regs_a = regs + GETARG_A(i);
+ int idx = GETARG_B(i);
+ e->stack[idx] = *regs_a;
+ mrb_write_barrier(mrb, (struct RBasic*)e);
+ }
NEXT;
}
@@ -764,7 +779,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_RAISE) {
/* A raise(R(A)) */
- mrb->exc = (struct RObject*)mrb_object(regs[GETARG_A(i)]);
+ mrb->exc = mrb_obj_ptr(regs[GETARG_A(i)]);
goto L_RAISE;
}
@@ -833,15 +848,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (!m) {
mrb_value sym = mrb_symbol_value(mid);
- mid = mrb_intern(mrb, "method_missing");
+ mid = mrb_intern2(mrb, "method_missing", 14);
m = mrb_method_search_vm(mrb, &c, mid);
if (n == CALL_MAXARGS) {
mrb_ary_unshift(mrb, regs[a+1], sym);
}
else {
- memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1));
+ value_move(regs+a+2, regs+a+1, ++n);
regs[a+1] = sym;
- n++;
}
}
@@ -850,8 +864,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->mid = mid;
ci->proc = m;
ci->stackidx = mrb->stack - mrb->stbase;
- ci->argc = n;
- if (ci->argc == CALL_MAXARGS) ci->argc = -1;
+ if (n == CALL_MAXARGS) {
+ ci->argc = -1;
+ }
+ else {
+ ci->argc = n;
+ }
ci->target_class = c;
ci->pc = pc + 1;
ci->acc = a;
@@ -972,15 +990,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
c = mrb->ci->target_class->super;
m = mrb_method_search_vm(mrb, &c, mid);
if (!m) {
- mid = mrb_intern(mrb, "method_missing");
+ mid = mrb_intern2(mrb, "method_missing", 14);
m = mrb_method_search_vm(mrb, &c, mid);
if (n == CALL_MAXARGS) {
mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid));
}
else {
- memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1));
+ value_move(regs+a+2, regs+a+1, ++n);
SET_SYM_VALUE(regs[a+1], ci->mid);
- n++;
}
}
@@ -989,8 +1006,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->mid = mid;
ci->proc = m;
ci->stackidx = mrb->stack - mrb->stbase;
- ci->argc = n;
- if (ci->argc == CALL_MAXARGS) ci->argc = -1;
+ if (n == CALL_MAXARGS) {
+ ci->argc = -1;
+ }
+ else {
+ ci->argc = n;
+ }
ci->target_class = m->target_class;
ci->pc = pc + 1;
@@ -1017,7 +1038,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
pool = irep->pool;
syms = irep->syms;
ci->nregs = irep->nregs;
- if (ci->argc < 0) {
+ if (n == CALL_MAXARGS) {
stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
}
else {
@@ -1046,13 +1067,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
mrb_value exc;
static const char m[] = "super called outside of method";
exc = mrb_exc_new(mrb, E_NOMETHOD_ERROR, m, sizeof(m) - 1);
- mrb->exc = (struct RObject*)mrb_object(exc);
+ mrb->exc = mrb_obj_ptr(exc);
goto L_RAISE;
}
stack = e->stack + 1;
}
if (r == 0) {
- regs[a] = mrb_ary_new_elts(mrb, m1+m2, stack);
+ regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack);
}
else {
mrb_value *pp = NULL;
@@ -1084,7 +1105,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_ENTER) {
/* Ax arg setup according to flags (24=5:5:1:5:5:1:1) */
/* number of optional arguments times OP_JMP should follow */
- int ax = GETARG_Ax(i);
+ int32_t ax = GETARG_Ax(i);
int m1 = (ax>>18)&0x1f;
int o = (ax>>13)&0x1f;
int r = (ax>>12)&0x1;
@@ -1122,10 +1143,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (argc < len) {
regs[len+1] = *blk; /* move block */
if (argv0 != argv) {
- memmove(&regs[1], argv, sizeof(mrb_value)*(argc-m2)); /* m1 + o */
+ value_move(&regs[1], argv, argc-m2); /* m1 + o */
}
if (m2) {
- memmove(&regs[len-m2+1], &argv[argc-m2], sizeof(mrb_value)*m2); /* m2 */
+ value_move(&regs[len-m2+1], &argv[argc-m2], m2); /* m2 */
}
if (r) { /* r */
regs[m1+o+1] = mrb_ary_new_capa(mrb, 0);
@@ -1137,13 +1158,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
if (argv0 != argv) {
regs[len+1] = *blk; /* move block */
- memmove(&regs[1], argv, sizeof(mrb_value)*(m1+o)); /* m1 + o */
+ value_move(&regs[1], argv, m1+o); /* m1 + o */
}
if (r) { /* r */
- regs[m1+o+1] = mrb_ary_new_elts(mrb, argc-m1-o-m2, argv+m1+o);
+ regs[m1+o+1] = mrb_ary_new_from_values(mrb, argc-m1-o-m2, argv+m1+o);
}
if (m2) {
- memmove(&regs[m1+o+r+1], &argv[argc-m2], sizeof(mrb_value)*m2);
+ value_move(&regs[m1+o+r+1], &argv[argc-m2], m2);
}
if (argv0 == argv) {
regs[len+1] = *blk; /* move block */
@@ -1174,8 +1195,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
L_RAISE:
ci = mrb->ci;
- mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern(mrb, "lastpc"), mrb_voidp_value(pc));
- mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->cibase));
+ mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(pc));
+ mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase));
eidx = ci->eidx;
if (ci == mrb->cibase) {
if (ci->ridx == 0) goto L_STOP;
@@ -1218,12 +1239,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
struct REnv *e = top_env(mrb, proc);
if (e->cioff < 0) {
- localjump_error(mrb, "return");
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
}
ci = mrb->cibase + e->cioff;
if (ci == mrb->cibase) {
- localjump_error(mrb, "return");
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
}
mrb->ci = ci;
@@ -1231,14 +1252,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
case OP_R_NORMAL:
if (ci == mrb->cibase) {
- localjump_error(mrb, "return");
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
}
ci = mrb->ci;
break;
case OP_R_BREAK:
if (proc->env->cioff < 0) {
- localjump_error(mrb, "break");
+ localjump_error(mrb, LOCALJUMP_ERROR_BREAK);
goto L_RAISE;
}
ci = mrb->ci = mrb->cibase + proc->env->cioff + 1;
@@ -1291,15 +1312,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (!m) {
mrb_value sym = mrb_symbol_value(mid);
- mid = mrb_intern(mrb, "method_missing");
+ mid = mrb_intern2(mrb, "method_missing", 14);
m = mrb_method_search_vm(mrb, &c, mid);
if (n == CALL_MAXARGS) {
mrb_ary_unshift(mrb, regs[a+1], sym);
}
else {
- memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1));
+ value_move(regs+a+2, regs+a+1, ++n);
regs[a+1] = sym;
- n++;
}
}
@@ -1308,11 +1328,15 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci = mrb->ci;
ci->mid = mid;
ci->target_class = m->target_class;
- ci->argc = n;
- if (ci->argc == CALL_MAXARGS) ci->argc = -1;
+ if (n == CALL_MAXARGS) {
+ ci->argc = -1;
+ }
+ else {
+ ci->argc = n;
+ }
/* move stack */
- memmove(mrb->stack, &regs[a], (ci->argc+1)*sizeof(mrb_value));
+ value_move(mrb->stack, &regs[a], ci->argc+1);
if (MRB_PROC_CFUNC_P(m)) {
mrb->stack[0] = m->body.func(mrb, recv);
@@ -1350,7 +1374,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
struct REnv *e = uvenv(mrb, lv-1);
if (!e) {
- localjump_error(mrb, "yield");
+ localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
goto L_RAISE;
}
stack = e->stack + 1;
@@ -1366,7 +1390,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
#define attr_f value.f
#endif
-#define TYPES2(a,b) (((((int)(a))<<8)|((int)(b)))&0xffff)
+#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
#define OP_MATH_BODY(op,v1,v2) do {\
regs[a].v1 = regs[a].v1 op regs[a+1].v2;\
} while(0)
@@ -1380,16 +1404,18 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
{
mrb_int x, y, z;
+ mrb_value *regs_a = regs + a;
- x = mrb_fixnum(regs[a]);
- y = mrb_fixnum(regs[a+1]);
+ x = mrb_fixnum(regs_a[0]);
+ y = mrb_fixnum(regs_a[1]);
z = x + y;
- if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) {
+ if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) == 0) {
/* integer overflow */
- SET_FLT_VALUE(regs[a], (mrb_float)x + (mrb_float)y);
- break;
+ SET_FLT_VALUE(regs_a[0], (mrb_float)x + (mrb_float)y);
+ }
+ else {
+ regs_a[0].attr_i = z;
}
- SET_INT_VALUE(regs[a], z);
}
break;
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
@@ -1561,28 +1587,30 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_SUBI) {
/* A B C R(A) := R(A)-C (Syms[B]=:+)*/
int a = GETARG_A(i);
+ mrb_value *regs_a = regs + a;
/* need to check if + is overridden */
- switch (mrb_type(regs[a])) {
+ switch (mrb_type(regs_a[0])) {
case MRB_TT_FIXNUM:
{
- mrb_int x = regs[a].attr_i;
+ mrb_int x = regs_a[0].attr_i;
mrb_int y = GETARG_C(i);
mrb_int z = x - y;
- if (((x < 0) ^ (y < 0)) != 0 && (x < 0) != (z < 0)) {
+ if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) != 0) {
/* integer overflow */
- SET_FLT_VALUE(regs[a], (mrb_float)x - (mrb_float)y);
- break;
+ SET_FLT_VALUE(regs_a[0], (mrb_float)x - (mrb_float)y);
+ }
+ else {
+ regs_a[0].attr_i = z;
}
- regs[a].attr_i = z;
}
break;
case MRB_TT_FLOAT:
- regs[a].attr_f -= GETARG_C(i);
+ regs_a[0].attr_f -= GETARG_C(i);
break;
default:
- SET_INT_VALUE(regs[a+1], GETARG_C(i));
+ SET_INT_VALUE(regs_a[1], GETARG_C(i));
i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
goto L_SEND;
}
@@ -1722,7 +1750,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int i;
if (len > pre + post) {
- regs[a++] = mrb_ary_new_elts(mrb, len - pre - post, ary->ptr+pre);
+ regs[a++] = mrb_ary_new_from_values(mrb, len - pre - post, ary->ptr+pre);
while (post--) {
regs[a++] = ary->ptr[len-post-1];
}
@@ -1895,7 +1923,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (!mrb->ci->target_class) {
static const char msg[] = "no target class or module";
mrb_value exc = mrb_exc_new(mrb, E_TYPE_ERROR, msg, sizeof(msg) - 1);
- mrb->exc = (struct RObject*)mrb_object(exc);
+ mrb->exc = mrb_obj_ptr(exc);
goto L_RAISE;
}
regs[GETARG_A(i)] = mrb_obj_value(mrb->ci->target_class);
@@ -1948,7 +1976,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg);
}
- mrb->exc = (struct RObject*)mrb_object(exc);
+ mrb->exc = mrb_obj_ptr(exc);
goto L_RAISE;
}
}