summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c90
-rw-r--r--src/class.c12
-rw-r--r--src/codegen.c55
-rw-r--r--src/error.c26
-rw-r--r--src/gc.c4
-rw-r--r--src/hash.c8
-rw-r--r--src/kernel.c13
-rw-r--r--src/load.c2
-rw-r--r--src/node.h1
-rw-r--r--src/numeric.c8
-rw-r--r--src/parse.y1549
-rw-r--r--src/range.c8
-rw-r--r--src/sprintf.c1095
-rw-r--r--src/state.c8
-rw-r--r--src/string.c13
-rw-r--r--src/variable.c2
16 files changed, 1019 insertions, 1875 deletions
diff --git a/src/array.c b/src/array.c
index c767283aa..b55a47f66 100644
--- a/src/array.c
+++ b/src/array.c
@@ -10,14 +10,18 @@
#include "mruby/string.h"
#include "mruby/class.h"
+/* SIZE_MAX is not supported by VC++. */
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t)-1)
+#endif
+
#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 +31,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 +53,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);
@@ -89,7 +91,7 @@ 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_ary_new_from_values(mrb_state *mrb, mrb_int size, mrb_value *vals)
{
mrb_value ary;
struct RArray *a;
@@ -112,7 +114,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 +136,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 +172,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,9 +189,7 @@ 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) {
a->aux.capa = capa;
@@ -202,7 +200,7 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, int len)
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 +226,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 +253,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 +267,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,7 +303,7 @@ 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();
@@ -329,7 +327,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,7 +427,7 @@ 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_new4(mrb_state *mrb, mrb_int n, const mrb_value *elts)
{
mrb_value ary;
@@ -443,7 +441,7 @@ mrb_ary_new4(mrb_state *mrb, int n, const mrb_value *elts)
}
mrb_value
-mrb_ary_new_elts(mrb_state *mrb, int n, const mrb_value *elts)
+mrb_ary_new_elts(mrb_state *mrb, mrb_int n, const mrb_value *elts)
{
return mrb_ary_new4(mrb, n, elts);
}
@@ -505,7 +503,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)) {
@@ -612,9 +610,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 */
@@ -660,7 +658,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 +675,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,7 +712,7 @@ 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:
@@ -757,7 +755,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 +801,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 +828,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 +843,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--) {
@@ -904,7 +902,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 +913,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[] = { ',', ' ' };
@@ -934,7 +932,7 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
mrb_str_buf_cat(mrb, arystr, head, sizeof(head));
for(i=0; i<RARRAY_LEN(ary); i++) {
- int ai = mrb_gc_arena_save(mrb);
+ mrb_int ai = mrb_gc_arena_save(mrb);
if (i > 0) {
mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep));
@@ -977,7 +975,7 @@ mrb_ary_inspect(mrb_state *mrb, mrb_value ary)
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 */
@@ -1092,7 +1090,7 @@ mrb_ary_equal(mrb_state *mrb, mrb_value ary1)
}
if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value();
else {
- int i;
+ mrb_int i;
for (i=0; i<RARRAY_LEN(ary1); i++) {
if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i)))
@@ -1121,11 +1119,11 @@ mrb_ary_eql(mrb_state *mrb, mrb_value ary1)
if (!mrb_array_p(ary2)) return mrb_false_value();
if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value();
else {
- int i;
+ mrb_int i;
for (i=0; i<RARRAY_LEN(ary1); i++) {
if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i)))
- return mrb_false_value();
+ return mrb_false_value();
}
return mrb_true_value();
}
diff --git a/src/class.c b/src/class.c
index c0e71dad7..8ea323945 100644
--- a/src/class.c
+++ b/src/class.c
@@ -29,7 +29,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);
}
}
}
@@ -356,7 +356,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 +367,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]
@@ -489,10 +489,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);
@@ -774,7 +774,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)
{
diff --git a/src/codegen.c b/src/codegen.c
index ff7e87c28..6f564586c 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -330,7 +330,7 @@ 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);
@@ -410,9 +410,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);
@@ -1161,7 +1179,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);
@@ -1902,6 +1920,11 @@ codegen(codegen_scope *s, node *tree, int val)
}
break;
+ case NODE_HEREDOC:
+ /*if(tree == NULL){printf("heredoc error 1\n");exit(11);}*/
+ tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
+ /*if(tree == NULL){printf("heredoc error 2\n");exit(12);}*/
+ /* fall through */
case NODE_DSTR:
if (val) {
node *n = tree;
@@ -1951,7 +1974,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
sym = new_sym(s, mrb_intern(s->mrb, "compile"));
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;
@@ -1979,16 +2002,16 @@ codegen(codegen_scope *s, node *tree, int val)
}
n = tree->cdr->cdr;
if (n->car) {
- p = (char*)n->car;
- off = new_lit(s, mrb_str_new(s->mrb, p, strlen(p)));
- 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(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1));
}
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)));
@@ -1999,7 +2022,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
sym = new_sym(s, mrb_intern(s->mrb, "compile"));
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 {
@@ -2370,13 +2393,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);
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 +2701,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/error.c b/src/error.c
index 70a84455f..7599bd0a9 100644
--- a/src/error.c
+++ b/src/error.c
@@ -125,7 +125,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc)
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"));
-
+
if (!mrb_nil_p(file) && !mrb_nil_p(line)) {
str = file;
mrb_str_cat2(mrb, str, ":");
@@ -190,12 +190,12 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
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_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;
}
}
pc = ci->pc;
@@ -366,14 +366,14 @@ 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_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");
+ }
}
break;
diff --git a/src/gc.c b/src/gc.c
index ae47de025..da6844fa5 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -301,7 +301,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);
}
@@ -586,7 +586,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]);
}
}
}
diff --git a/src/hash.c b/src/hash.c
index 2439a235d..728fc0f2f 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -559,7 +559,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);
}
}
}
@@ -1119,9 +1119,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/kernel.c b/src/kernel.c
index e45953fd3..7187a125d 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -191,7 +191,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);
}
@@ -305,7 +305,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:
@@ -483,7 +483,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>
@@ -913,7 +913,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) {
@@ -1108,11 +1108,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/load.c b/src/load.c
index 850fa6e8d..84c21c186 100644
--- a/src/load.c
+++ b/src/load.c
@@ -536,7 +536,7 @@ mrb_read_irep(mrb_state *mrb, const char *bin)
nirep = read_rite_header(mrb, src, &bin_header);
if (nirep < 0)
return nirep;
-
+
src += sizeof(bin_header) + MRB_DUMP_SIZE_OF_SHORT; //header + crc
//Read Binary Data Section
diff --git a/src/node.h b/src/node.h
index 284105023..86933c224 100644
--- a/src/node.h
+++ b/src/node.h
@@ -102,5 +102,6 @@ enum node_type {
NODE_IFUNC,
NODE_DSYM,
NODE_ATTRASGN,
+ NODE_HEREDOC,
NODE_LAST
};
diff --git a/src/numeric.c b/src/numeric.c
index b5bff652d..5aa577828 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -306,7 +306,7 @@ static mrb_value
num_eql(mrb_state *mrb, mrb_value x)
{
mrb_value y;
-
+
mrb_get_args(mrb, "o", &y);
if (mrb_type(x) != mrb_type(y)) return mrb_false_value();
if (mrb_equal(mrb, x, y)) {
@@ -699,7 +699,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)) {
@@ -1126,7 +1126,7 @@ 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 +1165,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;
diff --git a/src/parse.y b/src/parse.y
index 7bca4a4d6..2b09c3e56 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -31,6 +31,7 @@
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);
@@ -736,6 +737,14 @@ 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)
{
@@ -757,15 +766,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,10 +844,80 @@ var_reference(parser_state *p, node *lhs)
return lhs;
}
+
+static node*
+heredoc_start_sb(parser_state *p, const char* term, size_t term_len, enum heredoc_type type, int allow_indent)
+{
+ node *newnode = new_heredoc(p);
+ parser_heredoc_info *inf = (parser_heredoc_info*)newnode->cdr;
+ inf->term = term;
+ inf->term_len = term_len;
+ inf->type = type;
+ inf->allow_indent = allow_indent;
+ inf->line_head = TRUE;
+ inf->doc = NULL;
+ p->heredocs = push(p->heredocs, newnode);
+ if (p->parsing_heredoc == NULL) {
+ node *c = p->heredocs;
+ while (c->cdr)
+ c = c->cdr;
+ p->parsing_heredoc = c;
+ }
+ p->heredoc_starts_nextline = TRUE;
+ p->lstate = EXPR_END;
+ return newnode;
+}
+
+static node*
+heredoc_start(parser_state *p, node *beg, node *str, enum heredoc_type type)
+{
+ char *bs = (char*)beg->cdr->car;
+ int allow_indent = (bs[2] == '-');
+ const char *s = (char*)str->cdr->car;
+ size_t len = (intptr_t)str->cdr->cdr;
+ return heredoc_start_sb(p, s, len, type, allow_indent);
+}
+
+static node*
+heredoc_start_sym(parser_state *p, node *beg, mrb_sym sym, enum heredoc_type type)
+{
+ char *bs = (char*)beg->cdr->car;
+ int allow_indent = (bs[2] == '-');
+ int len;
+ const char *s = mrb_sym2name_len(p->mrb, sym, &len);
+ return heredoc_start_sb(p, s, len, type, allow_indent);
+}
+
+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;
+ p->sterm = 0;
+ p->heredoc_end_now = TRUE;
+ } else {
+ p->sterm = ' '; /* next heredoc */
+ }
+}
+
+
// xxx -----------------------------
%}
+%expect 2
%pure_parser
%parse-param {parser_state *p}
%lex-param {parser_state *p}
@@ -910,11 +980,11 @@ 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 tREGEXP
+%token <nd> tSTRING tSTRING_PART
+%token <nd> tNTH_REF tBACK_REF
+%token <num> tREGEXP_END
%type <nd> singleton string string_interp regexp
%type <nd> literal numeric cpath symbol
@@ -935,36 +1005,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 /* -> */
+%type <nd> heredoc heredoc_rep heredoc_interp
+
+%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
+%token <nd> tHEREDOC_BEG /* <<, <<- */
+%token tHEREDOC_END
/*
* precedence table
@@ -1871,6 +1944,7 @@ mrhs : args ',' arg_value
primary : literal
| string
| regexp
+ | heredoc
| var_ref
| backref
| tFID
@@ -2523,6 +2597,71 @@ regexp : tREGEXP_BEG tREGEXP
}
;
+heredoc : tHEREDOC_BEG tSTRING_BEG tSTRING
+ {
+ $$ = heredoc_start(p, $1, $3, heredoc_type_norm);
+ }
+ | tHEREDOC_BEG tSTRING
+ {
+ $$ = heredoc_start(p, $1, $2, heredoc_type_quote);
+ }
+ | tHEREDOC_BEG tIDENTIFIER
+ {
+ $$ = heredoc_start_sym(p, $1, $2, heredoc_type_norm);
+ }
+ | tHEREDOC_BEG tCONSTANT
+ {
+ $$ = heredoc_start_sym(p, $1, $2, heredoc_type_norm);
+ }
+ ;
+
+
+opt_heredoc_bodies : none
+ | heredoc_bodies
+ ;
+
+heredoc_bodies : heredoc_body
+ | heredoc_bodies heredoc_body
+ ;
+
+heredoc_body : tHEREDOC_END
+ {
+ /* assert(parsing_heredoc_inf(p) != NULL); */
+ parsing_heredoc_inf(p)->doc = list1(new_str(p, "", 0));
+ heredoc_end(p);
+ }
+ | heredoc_rep tHEREDOC_END
+ {
+ /* assert(parsing_heredoc_inf(p) != NULL); */
+ parsing_heredoc_inf(p)->doc = $1;
+ heredoc_end(p);
+ }
+ ;
+
+heredoc_rep : heredoc_interp
+ | heredoc_rep heredoc_interp
+ {
+ $$ = append($1, $2);
+ }
+ ;
+
+heredoc_interp : tSTRING
+ {
+ $$ = list1($1);
+ }
+ | tSTRING_PART
+ {
+ $<num>$ = p->sterm;
+ p->sterm = 0;
+ }
+ compstmt
+ '}'
+ {
+ p->sterm = $<num>2;
+ $$ = list2($1, $3);
+ }
+ ;
+
symbol : basic_symbol
{
$$ = new_sym(p, $1);
@@ -2873,6 +3012,7 @@ singleton : var_ref
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 +3097,7 @@ nl : '\n'
p->lineno++;
p->column = 0;
}
+ opt_heredoc_bodies
terms : term
| terms ';' {yyerrok;}
@@ -3092,9 +3233,7 @@ nextc(parser_state *p)
else {
c = (unsigned char)*p->s++;
}
- if (c == '\n') {
- // must understand heredoc
- }
+ /* if (c == '\n') { } */ /* heredoc treated in parser_yylex() */
}
p->column++;
return c;
@@ -3324,12 +3463,12 @@ read_escape(parser_state *p)
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;
- }
+ 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);
}
@@ -3341,17 +3480,17 @@ read_escape(parser_state *p)
int i;
for (i=0; i<2; i++) {
- buf[i] = nextc(p);
- if (buf[i] == -1) goto eof;
- if (!isxdigit(buf[i])) {
- pushback(p, buf[i]);
- break;
- }
+ buf[i] = nextc(p);
+ if (buf[i] == -1) goto eof;
+ if (!isxdigit(buf[i])) {
+ pushback(p, buf[i]);
+ break;
+ }
}
c = scan_hex(buf, i, &i);
if (i == 0) {
- yyerror(p, "Invalid escape character syntax");
- return 0;
+ yyerror(p, "Invalid escape character syntax");
+ return 0;
}
}
return c;
@@ -3426,23 +3565,23 @@ parse_string(parser_state *p, int term)
else if (c == '\\') {
c = nextc(p);
if (c == term) {
- tokadd(p, c);
+ tokadd(p, c);
}
else {
- pushback(p, c);
- tokadd(p, read_escape(p));
+ pushback(p, c);
+ tokadd(p, read_escape(p));
}
continue;
}
if (c == '#') {
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));
- return tSTRING_PART;
+ tokfix(p);
+ p->lstate = EXPR_BEG;
+ p->sterm = term;
+ p->cmd_start = TRUE;
+ yylval.nd = new_str(p, tok(p), toklen(p));
+ return tSTRING_PART;
}
tokadd(p, '#');
pushback(p, c);
@@ -3548,6 +3687,73 @@ parse_qstring(parser_state *p, int beg, int end)
}
static int
+parse_heredoc_line(parser_state *p)
+{
+ parser_heredoc_info *inf = parsing_heredoc_inf(p);
+ /* assert(inf != NULL); */
+ int c;
+ int line_head;
+
+ newtok(p);
+ while ((c = nextc(p)) != '\n') {
+ if (c == -1)
+ break;
+ if (inf->type != heredoc_type_quote) {
+ if (c == '\\') {
+ tokadd(p, read_escape(p));
+ inf->line_head = FALSE;
+ continue;
+ }
+ if (c == '#') {
+ c = nextc(p);
+ if (c == '{') {
+ tokfix(p);
+ p->lstate = EXPR_BEG;
+ p->sterm = ' ';
+ p->cmd_start = TRUE;
+ yylval.nd = new_str(p, tok(p), toklen(p));
+ inf->line_head = FALSE;
+ return tSTRING_PART;
+ }
+ tokadd(p, '#');
+ pushback(p, c);
+ continue;
+ }
+ }
+ tokadd(p, c);
+ }
+ tokadd(p, '\n');
+ tokfix(p);
+ p->lineno++;
+ p->column = 0;
+ line_head = inf->line_head;
+ inf->line_head = TRUE;
+ if (line_head) {
+ /* check whether end of heredoc */
+ const char *s = tok(p);
+ int len = toklen(p);
+ if (inf->allow_indent) {
+ while (ISSPACE(*s) && len > 0) {
+ ++s;
+ --len;
+ }
+ }
+ if ((len-1 == inf->term_len) && (strncmp(s, inf->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", inf->term);
+ yyerror(p, buf);
+ return 0;
+ }
+
+ yylval.nd = new_str(p, tok(p), toklen(p));
+ return tSTRING;
+}
+
+static int
arg_ambiguous(parser_state *p)
{
yywarning(p, "ambiguous first argument; put parentheses or even spaces");
@@ -3560,11 +3766,15 @@ static int
parser_yylex(parser_state *p)
{
register int c;
+ int c2;
int space_seen = 0;
int cmd_state;
enum mrb_lex_state_enum last_state;
int token_column;
+ if ((p->sterm == ' ') && (p->parsing_heredoc != NULL) && (! p->heredoc_starts_nextline)) {
+ return parse_heredoc_line(p);
+ }
if (p->sterm) {
return parse_string(p, p->sterm);
}
@@ -3573,22 +3783,27 @@ parser_yylex(parser_state *p)
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->sterm = ' ';
+ goto normal_newline;
+ }
switch (p->lstate) {
case EXPR_BEG:
case EXPR_FNAME:
@@ -3605,19 +3820,19 @@ parser_yylex(parser_state *p)
switch (c) {
case ' ': case '\t': case '\f': case '\r':
case '\13': /* '\v' */
- space_seen = 1;
- break;
+ space_seen = 1;
+ break;
case '.':
- if ((c = nextc(p)) != '.') {
- pushback(p, c);
- pushback(p, '.');
- goto retry;
- }
+ if ((c = nextc(p)) != '.') {
+ pushback(p, c);
+ pushback(p, '.');
+ goto retry;
+ }
case -1: /* EOF */
- goto normal_newline;
+ goto normal_newline;
default:
- pushback(p, c);
- goto normal_newline;
+ pushback(p, c);
+ goto normal_newline;
}
}
normal_newline:
@@ -3628,29 +3843,29 @@ parser_yylex(parser_state *p)
case '*':
if ((c = nextc(p)) == '*') {
if ((c = nextc(p)) == '=') {
- yylval.id = intern("**");
- p->lstate = EXPR_BEG;
- return tOP_ASGN;
+ yylval.id = intern("**");
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
}
pushback(p, c);
c = tPOW;
}
else {
if (c == '=') {
- yylval.id = intern("*");
- p->lstate = EXPR_BEG;
- return tOP_ASGN;
+ yylval.id = intern("*");
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
}
pushback(p, c);
if (IS_SPCARG(c)) {
- yywarning(p, "`*' interpreted as argument prefix");
- c = tSTAR;
+ yywarning(p, "`*' interpreted as argument prefix");
+ c = tSTAR;
}
else if (IS_BEG()) {
- c = tSTAR;
+ c = tSTAR;
}
else {
- c = '*';
+ c = '*';
}
}
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
@@ -3665,7 +3880,7 @@ parser_yylex(parser_state *p)
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
p->lstate = EXPR_ARG;
if (c == '@') {
- return '!';
+ return '!';
}
}
else {
@@ -3683,8 +3898,8 @@ parser_yylex(parser_state *p)
case '=':
if (p->column == 1) {
if (peeks(p, "begin\n")) {
- skips(p, "\n=end\n");
- goto retry;
+ skips(p, "\n=end\n");
+ goto retry;
}
}
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
@@ -3694,7 +3909,7 @@ parser_yylex(parser_state *p)
}
if ((c = nextc(p)) == '=') {
if ((c = nextc(p)) == '=') {
- return tEQQ;
+ return tEQQ;
}
pushback(p, c);
return tEQ;
@@ -3711,17 +3926,26 @@ 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;
+ p->lstate != EXPR_DOT &&
+ p->lstate != EXPR_CLASS &&
+ !IS_END() &&
+ (!IS_ARG() || space_seen)) {
+ /* heredocument check */
+ newtok(p); tokadd(p, '<'); tokadd(p, '<');
+ c2 = nextc(p);
+ if (c2 == '-') {
+ tokadd(p, c2);
+ c2 = nextc(p);
+ }
+ pushback(p, c2);
+ if (!ISSPACE(c2)) {
+ tokfix(p);
+ yylval.nd = new_str(p, tok(p), toklen(p));
+ p->lstate = EXPR_DOT;
+ return tHEREDOC_BEG;
+ }
}
-#endif
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
p->lstate = EXPR_ARG;
} else {
@@ -3732,16 +3956,16 @@ parser_yylex(parser_state *p)
}
if (c == '=') {
if ((c = nextc(p)) == '>') {
- return tCMP;
+ return tCMP;
}
pushback(p, c);
return tLEQ;
}
if (c == '<') {
if ((c = nextc(p)) == '=') {
- yylval.id = intern("<<");
- p->lstate = EXPR_BEG;
- return tOP_ASGN;
+ yylval.id = intern("<<");
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
}
pushback(p, c);
return tLSHFT;
@@ -3760,9 +3984,9 @@ parser_yylex(parser_state *p)
}
if (c == '>') {
if ((c = nextc(p)) == '=') {
- yylval.id = intern(">>");
- p->lstate = EXPR_BEG;
- return tOP_ASGN;
+ yylval.id = intern(">>");
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
}
pushback(p, c);
return tRSHFT;
@@ -3789,35 +4013,35 @@ parser_yylex(parser_state *p)
}
if (isspace(c)) {
if (!IS_ARG()) {
- int c2;
- switch (c) {
- case ' ':
- c2 = 's';
- break;
- case '\n':
- c2 = 'n';
- break;
- case '\t':
- c2 = 't';
- break;
- case '\v':
- c2 = 'v';
- break;
- case '\r':
- c2 = 'r';
- break;
- case '\f':
- c2 = 'f';
- break;
- default:
- c2 = 0;
- break;
- }
- if (c2) {
- char buf[256];
- snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2);
- yyerror(p, buf);
- }
+ int c2;
+ switch (c) {
+ case ' ':
+ c2 = 's';
+ break;
+ case '\n':
+ c2 = 'n';
+ break;
+ case '\t':
+ c2 = 't';
+ break;
+ case '\v':
+ c2 = 'v';
+ break;
+ case '\r':
+ c2 = 'r';
+ break;
+ case '\f':
+ c2 = 'f';
+ break;
+ default:
+ c2 = 0;
+ break;
+ }
+ if (c2) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2);
+ yyerror(p, buf);
+ }
}
ternary:
pushback(p, c);
@@ -3830,20 +4054,20 @@ parser_yylex(parser_state *p)
int c2 = nextc(p);
pushback(p, c2);
if ((isalnum(c2) || c2 == '_')) {
- goto ternary;
+ goto ternary;
}
}
if (c == '\\') {
c = nextc(p);
if (c == 'u') {
#if 0
- tokadd_utf8(p);
+ tokadd_utf8(p);
#endif
}
else {
- pushback(p, c);
- c = read_escape(p);
- tokadd(p, c);
+ pushback(p, c);
+ c = read_escape(p);
+ tokadd(p, c);
}
}
else {
@@ -3858,9 +4082,9 @@ parser_yylex(parser_state *p)
if ((c = nextc(p)) == '&') {
p->lstate = EXPR_BEG;
if ((c = nextc(p)) == '=') {
- yylval.id = intern("&&");
- p->lstate = EXPR_BEG;
- return tOP_ASGN;
+ yylval.id = intern("&&");
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
}
pushback(p, c);
return tANDOP;
@@ -3892,9 +4116,9 @@ parser_yylex(parser_state *p)
if ((c = nextc(p)) == '|') {
p->lstate = EXPR_BEG;
if ((c = nextc(p)) == '=') {
- yylval.id = intern("||");
- p->lstate = EXPR_BEG;
- return tOP_ASGN;
+ yylval.id = intern("||");
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
}
pushback(p, c);
return tOROP;
@@ -3918,7 +4142,7 @@ parser_yylex(parser_state *p)
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
p->lstate = EXPR_ARG;
if (c == '@') {
- return tUPLUS;
+ return tUPLUS;
}
pushback(p, c);
return '+';
@@ -3932,8 +4156,8 @@ parser_yylex(parser_state *p)
p->lstate = EXPR_BEG;
pushback(p, c);
if (c != -1 && ISDIGIT(c)) {
- c = '+';
- goto start_num;
+ c = '+';
+ goto start_num;
}
return tUPLUS;
}
@@ -3946,7 +4170,7 @@ parser_yylex(parser_state *p)
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
p->lstate = EXPR_ARG;
if (c == '@') {
- return tUMINUS;
+ return tUMINUS;
}
pushback(p, c);
return '-';
@@ -3964,7 +4188,7 @@ parser_yylex(parser_state *p)
p->lstate = EXPR_BEG;
pushback(p, c);
if (c != -1 && ISDIGIT(c)) {
- return tUMINUS_NUM;
+ return tUMINUS_NUM;
}
return tUMINUS;
}
@@ -3976,7 +4200,7 @@ parser_yylex(parser_state *p)
p->lstate = EXPR_BEG;
if ((c = nextc(p)) == '.') {
if ((c = nextc(p)) == '.') {
- return tDOT3;
+ return tDOT3;
}
pushback(p, c);
return tDOT2;
@@ -3993,223 +4217,223 @@ 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);
if (c == '-' || c == '+') {
- tokadd(p, c);
- c = nextc(p);
+ tokadd(p, c);
+ c = nextc(p);
}
if (c == '0') {
#define no_digits() do {yyerror(p,"numeric literal without digits"); return 0;} while (0)
- int start = toklen(p);
- c = nextc(p);
- if (c == 'x' || c == 'X') {
- /* hexadecimal */
- c = nextc(p);
- if (c != -1 && ISXDIGIT(c)) {
- do {
- if (c == '_') {
- if (nondigit) break;
- nondigit = c;
- continue;
- }
- if (!ISXDIGIT(c)) break;
- nondigit = 0;
- tokadd(p, tolower(c));
- } while ((c = nextc(p)) != -1);
- }
- pushback(p, c);
- tokfix(p);
- if (toklen(p) == start) {
- no_digits();
- }
- else if (nondigit) goto trailing_uc;
- yylval.nd = new_int(p, tok(p), 16);
- return tINTEGER;
- }
- if (c == 'b' || c == 'B') {
- /* binary */
- c = nextc(p);
- if (c == '0' || c == '1') {
- do {
- if (c == '_') {
- if (nondigit) break;
- nondigit = c;
- continue;
- }
- if (c != '0' && c != '1') break;
- nondigit = 0;
- tokadd(p, c);
- } while ((c = nextc(p)) != -1);
- }
- pushback(p, c);
- tokfix(p);
- if (toklen(p) == start) {
- no_digits();
- }
- else if (nondigit) goto trailing_uc;
- yylval.nd = new_int(p, tok(p), 2);
- return tINTEGER;
- }
- if (c == 'd' || c == 'D') {
- /* decimal */
- c = nextc(p);
- if (c != -1 && ISDIGIT(c)) {
- do {
- if (c == '_') {
- if (nondigit) break;
- nondigit = c;
- continue;
- }
- if (!ISDIGIT(c)) break;
- nondigit = 0;
- tokadd(p, c);
- } while ((c = nextc(p)) != -1);
- }
- pushback(p, c);
- tokfix(p);
- if (toklen(p) == start) {
- no_digits();
- }
- else if (nondigit) goto trailing_uc;
- yylval.nd = new_int(p, tok(p), 10);
- return tINTEGER;
- }
- if (c == '_') {
- /* 0_0 */
- goto octal_number;
- }
- if (c == 'o' || c == 'O') {
- /* prefixed octal */
- c = nextc(p);
- if (c == -1 || c == '_' || !ISDIGIT(c)) {
- no_digits();
- }
- }
- if (c >= '0' && c <= '7') {
- /* octal */
- octal_number:
- do {
- if (c == '_') {
- if (nondigit) break;
- nondigit = c;
- continue;
- }
- if (c < '0' || c > '9') break;
- if (c > '7') goto invalid_octal;
- nondigit = 0;
- tokadd(p, c);
- } while ((c = nextc(p)) != -1);
-
- if (toklen(p) > start) {
- pushback(p, c);
- tokfix(p);
- if (nondigit) goto trailing_uc;
- yylval.nd = new_int(p, tok(p), 8);
- return tINTEGER;
- }
- if (nondigit) {
- pushback(p, c);
- goto trailing_uc;
- }
- }
- if (c > '7' && c <= '9') {
- invalid_octal:
- yyerror(p, "Invalid octal digit");
- }
- else if (c == '.' || c == 'e' || c == 'E') {
- tokadd(p, '0');
- }
- else {
- pushback(p, c);
- yylval.nd = new_int(p, "0", 10);
- return tINTEGER;
- }
+ int start = toklen(p);
+ c = nextc(p);
+ if (c == 'x' || c == 'X') {
+ /* hexadecimal */
+ c = nextc(p);
+ if (c != -1 && ISXDIGIT(c)) {
+ do {
+ if (c == '_') {
+ if (nondigit) break;
+ nondigit = c;
+ continue;
+ }
+ if (!ISXDIGIT(c)) break;
+ nondigit = 0;
+ tokadd(p, tolower(c));
+ } while ((c = nextc(p)) != -1);
+ }
+ pushback(p, c);
+ tokfix(p);
+ if (toklen(p) == start) {
+ no_digits();
+ }
+ else if (nondigit) goto trailing_uc;
+ yylval.nd = new_int(p, tok(p), 16);
+ return tINTEGER;
+ }
+ if (c == 'b' || c == 'B') {
+ /* binary */
+ c = nextc(p);
+ if (c == '0' || c == '1') {
+ do {
+ if (c == '_') {
+ if (nondigit) break;
+ nondigit = c;
+ continue;
+ }
+ if (c != '0' && c != '1') break;
+ nondigit = 0;
+ tokadd(p, c);
+ } while ((c = nextc(p)) != -1);
+ }
+ pushback(p, c);
+ tokfix(p);
+ if (toklen(p) == start) {
+ no_digits();
+ }
+ else if (nondigit) goto trailing_uc;
+ yylval.nd = new_int(p, tok(p), 2);
+ return tINTEGER;
+ }
+ if (c == 'd' || c == 'D') {
+ /* decimal */
+ c = nextc(p);
+ if (c != -1 && ISDIGIT(c)) {
+ do {
+ if (c == '_') {
+ if (nondigit) break;
+ nondigit = c;
+ continue;
+ }
+ if (!ISDIGIT(c)) break;
+ nondigit = 0;
+ tokadd(p, c);
+ } while ((c = nextc(p)) != -1);
+ }
+ pushback(p, c);
+ tokfix(p);
+ if (toklen(p) == start) {
+ no_digits();
+ }
+ else if (nondigit) goto trailing_uc;
+ yylval.nd = new_int(p, tok(p), 10);
+ return tINTEGER;
+ }
+ if (c == '_') {
+ /* 0_0 */
+ goto octal_number;
+ }
+ if (c == 'o' || c == 'O') {
+ /* prefixed octal */
+ c = nextc(p);
+ if (c == -1 || c == '_' || !ISDIGIT(c)) {
+ no_digits();
+ }
+ }
+ if (c >= '0' && c <= '7') {
+ /* octal */
+ octal_number:
+ do {
+ if (c == '_') {
+ if (nondigit) break;
+ nondigit = c;
+ continue;
+ }
+ if (c < '0' || c > '9') break;
+ if (c > '7') goto invalid_octal;
+ nondigit = 0;
+ tokadd(p, c);
+ } while ((c = nextc(p)) != -1);
+
+ if (toklen(p) > start) {
+ pushback(p, c);
+ tokfix(p);
+ if (nondigit) goto trailing_uc;
+ yylval.nd = new_int(p, tok(p), 8);
+ return tINTEGER;
+ }
+ if (nondigit) {
+ pushback(p, c);
+ goto trailing_uc;
+ }
+ }
+ if (c > '7' && c <= '9') {
+ invalid_octal:
+ yyerror(p, "Invalid octal digit");
+ }
+ else if (c == '.' || c == 'e' || c == 'E') {
+ tokadd(p, '0');
+ }
+ else {
+ pushback(p, c);
+ yylval.nd = new_int(p, "0", 10);
+ return tINTEGER;
+ }
}
for (;;) {
- switch (c) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- nondigit = 0;
- tokadd(p, c);
- break;
-
- case '.':
- if (nondigit) goto trailing_uc;
- if (seen_point || seen_e) {
- goto decode_num;
- }
- else {
- int c0 = nextc(p);
- if (c0 == -1 || !ISDIGIT(c0)) {
- pushback(p, c0);
- goto decode_num;
- }
- c = c0;
- }
- tokadd(p, '.');
- tokadd(p, c);
- is_float++;
- seen_point++;
- nondigit = 0;
- break;
-
- case 'e':
- case 'E':
- if (nondigit) {
- pushback(p, c);
- c = nondigit;
- goto decode_num;
- }
- if (seen_e) {
- goto decode_num;
- }
- tokadd(p, c);
- seen_e++;
- is_float++;
- nondigit = c;
- c = nextc(p);
- if (c != '-' && c != '+') continue;
- tokadd(p, c);
- nondigit = c;
- break;
-
- case '_': /* `_' in number just ignored */
- if (nondigit) goto decode_num;
- nondigit = c;
- break;
-
- default:
- goto decode_num;
- }
- c = nextc(p);
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ nondigit = 0;
+ tokadd(p, c);
+ break;
+
+ case '.':
+ if (nondigit) goto trailing_uc;
+ if (seen_point || seen_e) {
+ goto decode_num;
+ }
+ else {
+ int c0 = nextc(p);
+ if (c0 == -1 || !ISDIGIT(c0)) {
+ pushback(p, c0);
+ goto decode_num;
+ }
+ c = c0;
+ }
+ tokadd(p, '.');
+ tokadd(p, c);
+ is_float++;
+ seen_point++;
+ nondigit = 0;
+ break;
+
+ case 'e':
+ case 'E':
+ if (nondigit) {
+ pushback(p, c);
+ c = nondigit;
+ goto decode_num;
+ }
+ if (seen_e) {
+ goto decode_num;
+ }
+ tokadd(p, c);
+ seen_e++;
+ is_float++;
+ nondigit = c;
+ c = nextc(p);
+ if (c != '-' && c != '+') continue;
+ tokadd(p, c);
+ nondigit = c;
+ break;
+
+ case '_': /* `_' in number just ignored */
+ if (nondigit) goto decode_num;
+ nondigit = c;
+ break;
+
+ default:
+ goto decode_num;
+ }
+ c = nextc(p);
}
decode_num:
pushback(p, c);
if (nondigit) {
trailing_uc:
- yyerror_i(p, "trailing `%c' in number", nondigit);
+ yyerror_i(p, "trailing `%c' in number", nondigit);
}
tokfix(p);
if (is_float) {
- double d;
- char *endp;
-
- errno = 0;
- d = strtod(tok(p), &endp);
- if (d == 0 && endp == tok(p)) {
- yywarning_s(p, "corrupted float value %s", tok(p));
- }
- else if (errno == ERANGE) {
- yywarning_s(p, "float %s out of range", tok(p));
- errno = 0;
- }
- yylval.nd = new_float(p, tok(p));
- return tFLOAT;
+ double d;
+ char *endp;
+
+ errno = 0;
+ d = strtod(tok(p), &endp);
+ if (d == 0 && endp == tok(p)) {
+ yywarning_s(p, "corrupted float value %s", tok(p));
+ }
+ else if (errno == ERANGE) {
+ yywarning_s(p, "float %s out of range", tok(p));
+ errno = 0;
+ }
+ yylval.nd = new_float(p, tok(p));
+ return tFLOAT;
}
yylval.nd = new_int(p, tok(p), 10);
return tINTEGER;
@@ -4231,8 +4455,8 @@ parser_yylex(parser_state *p)
c = nextc(p);
if (c == ':') {
if (IS_BEG() || p->lstate == EXPR_CLASS || IS_SPCARG(-1)) {
- p->lstate = EXPR_BEG;
- return tCOLON3;
+ p->lstate = EXPR_BEG;
+ return tCOLON3;
}
p->lstate = EXPR_DOT;
return tCOLON2;
@@ -4294,7 +4518,7 @@ parser_yylex(parser_state *p)
case ';':
p->lstate = EXPR_BEG;
return ';';
-
+
case ',':
p->lstate = EXPR_BEG;
return ',';
@@ -4302,7 +4526,7 @@ parser_yylex(parser_state *p)
case '~':
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
if ((c = nextc(p)) != '@') {
- pushback(p, c);
+ pushback(p, c);
}
p->lstate = EXPR_ARG;
}
@@ -4329,11 +4553,11 @@ parser_yylex(parser_state *p)
if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
p->lstate = EXPR_ARG;
if ((c = nextc(p)) == ']') {
- if ((c = nextc(p)) == '=') {
- return tASET;
- }
- pushback(p, c);
- return tAREF;
+ if ((c = nextc(p)) == '=') {
+ return tASET;
+ }
+ pushback(p, c);
+ return tAREF;
}
pushback(p, c);
return '[';
@@ -4390,19 +4614,19 @@ parser_yylex(parser_state *p)
c = nextc(p);
quotation:
if (c == -1 || !ISALNUM(c)) {
- term = c;
- c = 'Q';
+ term = c;
+ c = 'Q';
}
else {
- beg = term = nextc(p);
- if (isalnum(term)) {
- yyerror(p, "unknown type of %string");
- return 0;
- }
+ beg = term = nextc(p);
+ if (isalnum(term)) {
+ yyerror(p, "unknown type of %string");
+ return 0;
+ }
}
if (c == -1 || term == -1) {
- yyerror(p, "unterminated quoted string meets end of file");
- return 0;
+ yyerror(p, "unterminated quoted string meets end of file");
+ return 0;
}
#if 0
paren = term;
@@ -4419,51 +4643,51 @@ parser_yylex(parser_state *p)
switch (c) {
case 'Q':
#if 0
- p->lex_strterm = new_strterm(p, str_dquote, term, paren);
+ p->lex_strterm = new_strterm(p, str_dquote, term, paren);
#endif
- return tSTRING_BEG;
+ return tSTRING_BEG;
case 'q':
#if 0
- p->lex_strterm = new_strterm(p, str_squote, term, paren);
+ p->lex_strterm = new_strterm(p, str_squote, term, paren);
#endif
- p->sterm = 0;
- return parse_qstring(p, beg, term);
+ p->sterm = 0;
+ return parse_qstring(p, beg, term);
case 'W':
#if 0
- p->lex_strterm = new_strterm(p, str_dword, term, paren);
+ p->lex_strterm = new_strterm(p, str_dword, term, paren);
#endif
- do {c = nextc(p);} while (isspace(c));
- pushback(p, c);
- return tWORDS_BEG;
+ 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);
+ p->lex_strterm = new_strterm(p, str_sword, term, paren);
#endif
- do {c = nextc(p);} while (isspace(c));
- pushback(p, c);
- return tQWORDS_BEG;
+ do {c = nextc(p);} while (isspace(c));
+ pushback(p, c);
+ return tQWORDS_BEG;
case 'r':
#if 0
- p->lex_strterm = new_strterm(p, str_regexp, term, paren);
+ p->lex_strterm = new_strterm(p, str_regexp, term, paren);
#endif
- p->regexp = 1;
- p->sterm = term;
- return tREGEXP_BEG;
+ p->regexp = 1;
+ p->sterm = term;
+ return tREGEXP_BEG;
case 's':
#if 0
- p->lex_strterm = new_strterm(p, str_ssym, term, paren);
+ p->lex_strterm = new_strterm(p, str_ssym, term, paren);
#endif
- p->lstate = EXPR_FNAME;
- return tSYMBEG;
+ p->lstate = EXPR_FNAME;
+ return tSYMBEG;
default:
- yyerror(p, "unknown type of %string");
- return 0;
+ yyerror(p, "unknown type of %string");
+ return 0;
}
}
if ((c = nextc(p)) == '=') {
@@ -4487,27 +4711,27 @@ 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);
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,14 +4748,14 @@ 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);
- goto gvar;
+ tokadd(p, '$');
+ tokadd(p, c);
+ goto gvar;
}
yylval.nd = new_back_ref(p, c);
return tBACK_REF;
@@ -4540,8 +4764,8 @@ parser_yylex(parser_state *p)
case '4': case '5': case '6':
case '7': case '8': case '9':
do {
- tokadd(p, c);
- c = nextc(p);
+ tokadd(p, c);
+ c = nextc(p);
} while (c != -1 && isdigit(c));
pushback(p, c);
if (last_state == EXPR_FNAME) goto gvar;
@@ -4551,8 +4775,8 @@ parser_yylex(parser_state *p)
default:
if (!identchar(c)) {
- pushback(p, c);
- return '$';
+ pushback(p, c);
+ return '$';
}
case '0':
tokadd(p, '$');
@@ -4569,10 +4793,10 @@ parser_yylex(parser_state *p)
}
if (c != -1 && isdigit(c)) {
if (p->bidx == 1) {
- yyerror_i(p, "`@%c' is not allowed as an instance variable name", c);
+ yyerror_i(p, "`@%c' is not allowed as an instance variable name", c);
}
else {
- yyerror_i(p, "`@@%c' is not allowed as a class variable name", c);
+ yyerror_i(p, "`@@%c' is not allowed as a class variable name", c);
}
return 0;
}
@@ -4630,97 +4854,95 @@ parser_yylex(parser_state *p)
case '@':
p->lstate = EXPR_END;
if (tok(p)[1] == '@')
- result = tCVAR;
+ result = tCVAR;
else
- result = tIVAR;
+ result = tIVAR;
break;
default:
if (toklast(p) == '!' || toklast(p) == '?') {
- result = tFID;
+ result = tFID;
}
else {
- if (p->lstate == EXPR_FNAME) {
- if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') &&
- (!peek(p, '=') || (peek_n(p, '>', 1)))) {
- result = tIDENTIFIER;
- tokadd(p, c);
- tokfix(p);
- }
- else {
- pushback(p, c);
- }
- }
- if (result == 0 && isupper((int)tok(p)[0])) {
- result = tCONSTANT;
- }
- else {
- result = tIDENTIFIER;
- }
+ if (p->lstate == EXPR_FNAME) {
+ if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') &&
+ (!peek(p, '=') || (peek_n(p, '>', 1)))) {
+ result = tIDENTIFIER;
+ tokadd(p, c);
+ tokfix(p);
+ }
+ else {
+ pushback(p, c);
+ }
+ }
+ if (result == 0 && isupper((int)tok(p)[0])) {
+ result = tCONSTANT;
+ }
+ else {
+ result = tIDENTIFIER;
+ }
}
if (IS_LABEL_POSSIBLE()) {
- if (IS_LABEL_SUFFIX(0)) {
- p->lstate = EXPR_BEG;
- nextc(p);
- tokfix(p);
- yylval.id = intern(tok(p));
- return tLABEL;
- }
+ if (IS_LABEL_SUFFIX(0)) {
+ p->lstate = EXPR_BEG;
+ nextc(p);
+ tokfix(p);
+ yylval.id = intern(tok(p));
+ return tLABEL;
+ }
}
if (p->lstate != EXPR_DOT) {
- const struct kwtable *kw;
-
- /* See if it is a reserved word. */
- kw = mrb_reserved_word(tok(p), toklen(p));
- if (kw) {
- enum mrb_lex_state_enum state = p->lstate;
- p->lstate = kw->state;
- if (state == EXPR_FNAME) {
- yylval.id = intern(kw->name);
- return kw->id[0];
- }
- if (p->lstate == EXPR_BEG) {
- p->cmd_start = TRUE;
- }
- if (kw->id[0] == keyword_do) {
- if (p->lpar_beg && p->lpar_beg == p->paren_nest) {
- p->lpar_beg = 0;
- p->paren_nest--;
- return keyword_do_LAMBDA;
- }
- if (COND_P()) return keyword_do_cond;
- if (CMDARG_P() && state != EXPR_CMDARG)
- return keyword_do_block;
- if (state == EXPR_ENDARG || state == EXPR_BEG)
- return keyword_do_block;
- return keyword_do;
- }
- if (state == EXPR_BEG || state == EXPR_VALUE)
- return kw->id[0];
- else {
- if (kw->id[0] != kw->id[1])
- p->lstate = EXPR_BEG;
- return kw->id[1];
- }
- }
+ const struct kwtable *kw;
+
+ /* See if it is a reserved word. */
+ kw = mrb_reserved_word(tok(p), toklen(p));
+ if (kw) {
+ enum mrb_lex_state_enum state = p->lstate;
+ p->lstate = kw->state;
+ if (state == EXPR_FNAME) {
+ yylval.id = intern(kw->name);
+ return kw->id[0];
+ }
+ if (p->lstate == EXPR_BEG) {
+ p->cmd_start = TRUE;
+ }
+ if (kw->id[0] == keyword_do) {
+ if (p->lpar_beg && p->lpar_beg == p->paren_nest) {
+ p->lpar_beg = 0;
+ p->paren_nest--;
+ return keyword_do_LAMBDA;
+ }
+ if (COND_P()) return keyword_do_cond;
+ if (CMDARG_P() && state != EXPR_CMDARG)
+ return keyword_do_block;
+ if (state == EXPR_ENDARG || state == EXPR_BEG)
+ return keyword_do_block;
+ return keyword_do;
+ }
+ if (state == EXPR_BEG || state == EXPR_VALUE)
+ return kw->id[0];
+ else {
+ if (kw->id[0] != kw->id[1])
+ p->lstate = EXPR_BEG;
+ return kw->id[1];
+ }
+ }
}
- if (IS_BEG() ||
- p->lstate == EXPR_DOT ||
- IS_ARG()) {
- if (cmd_state) {
- p->lstate = EXPR_CMDARG;
- }
- else {
- p->lstate = EXPR_ARG;
- }
+ if (IS_BEG() || p->lstate == EXPR_DOT || IS_ARG()) {
+ if (cmd_state) {
+ p->lstate = EXPR_CMDARG;
+ }
+ else {
+ p->lstate = EXPR_ARG;
+ }
}
else if (p->lstate == EXPR_FNAME) {
- p->lstate = EXPR_ENDFN;
+ p->lstate = EXPR_ENDFN;
}
else {
- p->lstate = EXPR_END;
+ p->lstate = EXPR_END;
}
}
{
@@ -4729,7 +4951,7 @@ parser_yylex(parser_state *p)
yylval.id = ident;
#if 0
if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) {
- p->lstate = EXPR_END;
+ p->lstate = EXPR_END;
}
#endif
}
@@ -4740,12 +4962,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
@@ -4844,6 +5066,8 @@ mrb_parser_new(mrb_state *mrb)
yydebug = 1;
#endif
+ p->heredocs = p->parsing_heredoc = NULL;
+
return p;
}
@@ -4930,7 +5154,7 @@ 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);
+ 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));
mrb_parser_free(p);
return mrb_undef_value();
@@ -5047,23 +5271,23 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
dump_prefix(offset+1);
printf("rescue:\n");
while (n2) {
- node *n3 = n2->car;
- if (n3->car) {
- dump_prefix(offset+2);
- printf("handle classes:\n");
- dump_recur(mrb, n3->car, offset+3);
- }
- if (n3->cdr->car) {
- dump_prefix(offset+2);
- printf("exc_var:\n");
- parser_dump(mrb, n3->cdr->car, offset+3);
- }
- if (n3->cdr->cdr->car) {
- dump_prefix(offset+2);
- printf("rescue body:\n");
- parser_dump(mrb, n3->cdr->cdr->car, offset+3);
- }
- n2 = n2->cdr;
+ node *n3 = n2->car;
+ if (n3->car) {
+ dump_prefix(offset+2);
+ printf("handle classes:\n");
+ dump_recur(mrb, n3->car, offset+3);
+ }
+ if (n3->cdr->car) {
+ dump_prefix(offset+2);
+ printf("exc_var:\n");
+ parser_dump(mrb, n3->cdr->car, offset+3);
+ }
+ if (n3->cdr->cdr->car) {
+ dump_prefix(offset+2);
+ printf("rescue body:\n");
+ parser_dump(mrb, n3->cdr->cdr->car, offset+3);
+ }
+ n2 = n2->cdr;
}
}
tree = tree->cdr;
@@ -5096,40 +5320,40 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
node *n = tree->car;
if (n->car) {
- dump_prefix(offset+1);
- printf("mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
+ dump_prefix(offset+1);
+ printf("mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
- dump_prefix(offset+1);
- printf("optional args:\n");
- {
- node *n2 = n->car;
-
- while (n2) {
- dump_prefix(offset+2);
- printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
- parser_dump(mrb, n2->car->cdr, 0);
- n2 = n2->cdr;
- }
- }
+ dump_prefix(offset+1);
+ printf("optional args:\n");
+ {
+ node *n2 = n->car;
+
+ while (n2) {
+ dump_prefix(offset+2);
+ printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
+ parser_dump(mrb, n2->car->cdr, 0);
+ n2 = n2->cdr;
+ }
+ }
}
n = n->cdr;
if (n->car) {
- dump_prefix(offset+1);
- printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
+ dump_prefix(offset+1);
+ printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
- dump_prefix(offset+1);
- printf("post mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
+ dump_prefix(offset+1);
+ printf("post mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n) {
- dump_prefix(offset+1);
- printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
+ dump_prefix(offset+1);
+ printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
}
}
dump_prefix(offset+1);
@@ -5209,25 +5433,25 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
node *n2 = tree->car;
if (n2->car) {
- dump_prefix(offset+2);
- printf("pre:\n");
- dump_recur(mrb, n2->car, offset+3);
+ dump_prefix(offset+2);
+ printf("pre:\n");
+ dump_recur(mrb, n2->car, offset+3);
}
n2 = n2->cdr;
if (n2) {
- if (n2->car) {
- dump_prefix(offset+2);
- printf("rest:\n");
- parser_dump(mrb, n2->car, offset+3);
- }
- n2 = n2->cdr;
- if (n2) {
- if (n2->car) {
- dump_prefix(offset+2);
- printf("post:\n");
- dump_recur(mrb, n2->car, offset+3);
- }
- }
+ if (n2->car) {
+ dump_prefix(offset+2);
+ printf("rest:\n");
+ parser_dump(mrb, n2->car, offset+3);
+ }
+ n2 = n2->cdr;
+ if (n2) {
+ if (n2->car) {
+ dump_prefix(offset+2);
+ printf("post:\n");
+ dump_recur(mrb, n2->car, offset+3);
+ }
+ }
}
}
tree = tree->cdr;
@@ -5246,17 +5470,17 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
node *n2 = tree->car;
if (n2 && (n2->car || n2->cdr)) {
- dump_prefix(offset+1);
- printf("local variables:\n");
- dump_prefix(offset+2);
- while (n2) {
- if (n2->car) {
- if (n2 != tree->car) printf(", ");
- printf("%s", mrb_sym2name(mrb, sym(n2->car)));
- }
- n2 = n2->cdr;
- }
- printf("\n");
+ dump_prefix(offset+1);
+ printf("local variables:\n");
+ dump_prefix(offset+2);
+ while (n2) {
+ if (n2->car) {
+ if (n2 != tree->car) printf(", ");
+ printf("%s", mrb_sym2name(mrb, sym(n2->car)));
+ }
+ n2 = n2->cdr;
+ }
+ printf("\n");
}
}
tree = tree->cdr;
@@ -5269,17 +5493,17 @@ 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);
printf("args:\n");
dump_recur(mrb, tree->car, offset+2);
if (tree->cdr) {
- dump_prefix(offset+1);
- printf("block:\n");
- parser_dump(mrb, tree->cdr, offset+2);
+ dump_prefix(offset+1);
+ printf("block:\n");
+ parser_dump(mrb, tree->cdr, offset+2);
}
}
break;
@@ -5350,31 +5574,31 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
node *n2 = tree->car;
if (n2->car) {
- dump_prefix(offset+2);
- printf("pre:\n");
- dump_recur(mrb, n2->car, offset+3);
+ dump_prefix(offset+2);
+ printf("pre:\n");
+ dump_recur(mrb, n2->car, offset+3);
}
n2 = n2->cdr;
if (n2) {
- if (n2->car) {
- dump_prefix(offset+2);
- printf("rest:\n");
+ if (n2->car) {
+ dump_prefix(offset+2);
+ printf("rest:\n");
if (n2->car == (node*)-1) {
- dump_prefix(offset+2);
- printf("(empty)\n");
- }
+ dump_prefix(offset+2);
+ printf("(empty)\n");
+ }
else {
- parser_dump(mrb, n2->car, offset+3);
- }
- }
- n2 = n2->cdr;
- if (n2) {
- if (n2->car) {
- dump_prefix(offset+2);
- printf("post:\n");
- dump_recur(mrb, n2->car, offset+3);
- }
- }
+ parser_dump(mrb, n2->car, offset+3);
+ }
+ }
+ n2 = n2->cdr;
+ if (n2) {
+ if (n2->car) {
+ dump_prefix(offset+2);
+ printf("post:\n");
+ dump_recur(mrb, n2->car, offset+3);
+ }
+ }
}
}
dump_prefix(offset+1);
@@ -5401,9 +5625,9 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
printf("args:\n");
dump_recur(mrb, tree->car, offset+2);
if (tree->cdr) {
- dump_prefix(offset+1);
- printf("block:\n");
- parser_dump(mrb, tree->cdr, offset+2);
+ dump_prefix(offset+1);
+ printf("block:\n");
+ parser_dump(mrb, tree->cdr, offset+2);
}
}
break;
@@ -5544,8 +5768,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:
@@ -5622,17 +5846,17 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
node *n2 = tree->car;
if (n2 && (n2->car || n2->cdr)) {
- dump_prefix(offset+1);
- printf("local variables:\n");
- dump_prefix(offset+2);
- while (n2) {
- if (n2->car) {
- if (n2 != tree->car) printf(", ");
- printf("%s", mrb_sym2name(mrb, sym(n2->car)));
- }
- n2 = n2->cdr;
- }
- printf("\n");
+ dump_prefix(offset+1);
+ printf("local variables:\n");
+ dump_prefix(offset+2);
+ while (n2) {
+ if (n2->car) {
+ if (n2 != tree->car) printf(", ");
+ printf("%s", mrb_sym2name(mrb, sym(n2->car)));
+ }
+ n2 = n2->cdr;
+ }
+ printf("\n");
}
}
tree = tree->cdr;
@@ -5640,40 +5864,40 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
node *n = tree->car;
if (n->car) {
- dump_prefix(offset+1);
- printf("mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
+ dump_prefix(offset+1);
+ printf("mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
- dump_prefix(offset+1);
- printf("optional args:\n");
- {
- node *n2 = n->car;
-
- while (n2) {
- dump_prefix(offset+2);
- printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
- parser_dump(mrb, n2->car->cdr, 0);
- n2 = n2->cdr;
- }
- }
+ dump_prefix(offset+1);
+ printf("optional args:\n");
+ {
+ node *n2 = n->car;
+
+ while (n2) {
+ dump_prefix(offset+2);
+ printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
+ parser_dump(mrb, n2->car->cdr, 0);
+ n2 = n2->cdr;
+ }
+ }
}
n = n->cdr;
if (n->car) {
- dump_prefix(offset+1);
- printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
+ dump_prefix(offset+1);
+ printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
- dump_prefix(offset+1);
- printf("post mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
+ dump_prefix(offset+1);
+ printf("post mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n) {
- dump_prefix(offset+1);
- printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
+ dump_prefix(offset+1);
+ printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
}
}
parser_dump(mrb, tree->cdr->car, offset+1);
@@ -5690,40 +5914,40 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
node *n = tree->car;
if (n->car) {
- dump_prefix(offset+1);
- printf("mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
+ dump_prefix(offset+1);
+ printf("mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
- dump_prefix(offset+1);
- printf("optional args:\n");
- {
- node *n2 = n->car;
-
- while (n2) {
- dump_prefix(offset+2);
- printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
- parser_dump(mrb, n2->car->cdr, 0);
- n2 = n2->cdr;
- }
- }
+ dump_prefix(offset+1);
+ printf("optional args:\n");
+ {
+ node *n2 = n->car;
+
+ while (n2) {
+ dump_prefix(offset+2);
+ printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
+ parser_dump(mrb, n2->car->cdr, 0);
+ n2 = n2->cdr;
+ }
+ }
}
n = n->cdr;
if (n->car) {
- dump_prefix(offset+1);
- printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
+ dump_prefix(offset+1);
+ printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
- dump_prefix(offset+1);
- printf("post mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
+ dump_prefix(offset+1);
+ printf("post mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n) {
- dump_prefix(offset+1);
- printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
+ dump_prefix(offset+1);
+ printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
}
}
tree = tree->cdr;
@@ -5735,6 +5959,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/range.c b/src/range.c
index aac1d830a..59bf445aa 100644
--- a/src/range.c
+++ b/src/range.c
@@ -16,8 +16,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);
@@ -181,7 +181,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 +208,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;
}
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..1936b8aab 100644
--- a/src/state.c
+++ b/src/state.c
@@ -72,7 +72,7 @@ mrb_alloca_free(mrb_state *mrb)
}
mrb_state*
-mrb_open()
+mrb_open(void)
{
mrb_state *mrb = mrb_open_allocf(allocf, NULL);
@@ -110,6 +110,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,7 +121,7 @@ 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*));
diff --git a/src/string.c b/src/string.c
index 28cf0ab9a..23da3baa6 100644
--- a/src/string.c
+++ b/src/string.c
@@ -2056,7 +2056,6 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
char *end;
char sign = 1;
int c;
- long len;
unsigned long val;
#undef ISDIGIT
@@ -2113,30 +2112,25 @@ 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;
}
@@ -2145,12 +2139,6 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
if (base < 2 || 36 < base) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %d", base);
}
- if (base <= 32) {
- len = 5;
- }
- else {
- len = 6;
- }
break;
} /* end of switch (base) { */
if (*str == '0') { /* squeeze preceeding 0s */
@@ -2171,7 +2159,6 @@ 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);
diff --git a/src/variable.c b/src/variable.c
index 5f657e3d7..d5331f844 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -753,7 +753,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);
}