summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--eval.c239
-rw-r--r--ext/curses/curses.c22
-rw-r--r--io.c33
-rw-r--r--node.h2
-rw-r--r--regex.h22
-rw-r--r--ruby.h15
-rw-r--r--string.c2
8 files changed, 271 insertions, 78 deletions
diff --git a/ChangeLog b/ChangeLog
index cffc1c7b12..ba907f86ad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
+Tue Mar 3 14:20:15 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (obj_method): returns bound method object.
+
+ * eval.c (rb_call): argument check for empty methods.
+
+ * ruby.h (NUM2CHR): new macro, originally from curses module.
+
+Tue Mar 3 13:03:35 1998 MAEDA shugo <shugo@po.aianet.ne.jp>
+
+ * io.c (io_putc): new method.
+
Tue Mar 3 11:21:28 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+ * string.c (str_inspect): more strict charcode detection.
+
* eval.c (thread_stop): stopping only thread raises ThreadError
exception.
diff --git a/eval.c b/eval.c
index bc928bb715..5eca27a224 100644
--- a/eval.c
+++ b/eval.c
@@ -3051,39 +3051,19 @@ stack_length()
}
static VALUE
-rb_call(klass, recv, mid, argc, argv, scope)
+rb_call0(klass, recv, mid, id, argc, argv, scope, body, type)
VALUE klass, recv;
- ID mid;
+ ID mid, id;
int argc; /* OK */
VALUE *argv; /* OK */
int scope;
+ NODE *body;
+ enum node_type type;
{
- NODE *body, *b2; /* OK */
- int noex;
- ID id = mid;
- struct cache_entry *ent;
+ NODE *b2; /* OK */
volatile VALUE result = Qnil;
int itr;
- enum node_type type;
static int tick;
- TMP_PROTECT;
-
- again:
- /* is it in the method cache? */
- ent = cache + EXPR1(klass, mid);
- if (ent->mid == mid && ent->klass == klass) {
- klass = ent->origin;
- id = ent->mid0;
- noex = ent->noex;
- body = ent->method;
- }
- else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
- return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
- }
-
- /* receiver specified form for private method */
- if (noex == NOEX_PRIVATE && scope == 0)
- return rb_undefined(recv, mid, argc, argv, CSTAT_NOEX);
switch (the_iter->iter) {
case ITER_PRE:
@@ -3095,28 +3075,6 @@ rb_call(klass, recv, mid, argc, argv, scope)
break;
}
- type = nd_type(body);
- if (type == NODE_ZSUPER) {
- /* for re-scoped/renamed method */
- mid = id;
- if (scope == 0) scope = 1;
- if (RCLASS(klass)->super == 0) {
- /* origin is the Module, so need to scan superclass hierarchy. */
- struct RClass *cl = RCLASS(klass);
-
- klass = RBASIC(recv)->klass;
- while (klass) {
- if (RCLASS(klass)->m_tbl == cl->m_tbl)
- break;
- klass = RCLASS(klass)->super;
- }
- }
- else {
- klass = RCLASS(klass)->super;
- }
- goto again;
- }
-
if ((++tick & 0xfff) == 0 && stack_length() > STACK_LEVEL_MAX)
Fatal("stack level too deep");
@@ -3271,15 +3229,22 @@ rb_call(klass, recv, mid, argc, argv, scope)
PUSH_VARS();
if ((state = EXEC_TAG()) == 0) {
- if (nd_type(body) == NODE_BLOCK) {
- NODE *node = body->nd_head;
- int i;
+ NODE *node = 0;
+ int i;
+ if (nd_type(body) == NODE_ARGS) {
+ node = body;
+ body = 0;
+ }
+ else if (nd_type(body) == NODE_BLOCK) {
+ node = body->nd_head;
+ body = body->nd_next;
+ }
+ if (node) {
if (nd_type(node) != NODE_ARGS) {
Bug("no argument-node");
}
- body = body->nd_next;
i = node->nd_cnt;
if (i > argc) {
ArgError("Wrong # of arguments(%d for %d)", argc, i);
@@ -3321,9 +3286,7 @@ rb_call(klass, recv, mid, argc, argv, scope)
}
}
}
- else if (nd_type(body) == NODE_ARGS) {
- body = 0;
- }
+
if (trace_func) {
call_trace_func("call", b2->nd_file, nd_line(b2),
recv, the_frame->last_func);
@@ -3373,6 +3336,61 @@ rb_call(klass, recv, mid, argc, argv, scope)
return result;
}
+static VALUE
+rb_call(klass, recv, mid, argc, argv, scope)
+ VALUE klass, recv;
+ ID mid;
+ int argc; /* OK */
+ VALUE *argv; /* OK */
+ int scope;
+{
+ NODE *body; /* OK */
+ int noex;
+ ID id = mid;
+ struct cache_entry *ent;
+ enum node_type type;
+ TMP_PROTECT;
+
+ again:
+ /* is it in the method cache? */
+ ent = cache + EXPR1(klass, mid);
+ if (ent->mid == mid && ent->klass == klass) {
+ klass = ent->origin;
+ id = ent->mid0;
+ noex = ent->noex;
+ body = ent->method;
+ }
+ else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
+ return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
+ }
+
+ /* receiver specified form for private method */
+ if (noex == NOEX_PRIVATE && scope == 0)
+ return rb_undefined(recv, mid, argc, argv, CSTAT_NOEX);
+
+ type = nd_type(body);
+ if (type == NODE_ZSUPER) {
+ /* for re-scoped/renamed method */
+ mid = id;
+ if (scope == 0) scope = 1;
+ if (BUILTIN_TYPE(klass) == T_MODULE) {
+ /* origin is the Module, so need to scan superclass hierarchy. */
+ struct RClass *cl = RCLASS(klass);
+
+ klass = RBASIC(recv)->klass;
+ while (klass) {
+ if (RCLASS(klass)->m_tbl == cl->m_tbl)
+ break;
+ klass = RCLASS(klass)->super;
+ }
+ }
+ klass = RCLASS(klass)->super;
+ goto again;
+ }
+
+ return rb_call0(klass, recv, mid, id, argc, argv, scope, body, type);
+}
+
VALUE
rb_apply(recv, mid, args)
VALUE recv;
@@ -4682,6 +4700,113 @@ proc_iterate(proc)
return result;
}
+static VALUE cMethod;
+struct METHOD {
+ VALUE klass;
+ VALUE recv;
+ ID id;
+ NODE *body;
+};
+
+static void
+bm_mark(struct METHOD *data)
+{
+ gc_mark(data->klass);
+ gc_mark(data->recv);
+ gc_mark(data->body);
+}
+
+static VALUE
+obj_method(obj, vid)
+ VALUE obj;
+ VALUE vid;
+{
+ VALUE method;
+ VALUE klass = CLASS_OF(obj);
+ ID mid, id;
+ NODE *body;
+ int noex;
+ enum node_type type;
+ struct METHOD *data;
+
+ mid = id = rb_to_id(vid);
+
+ again:
+ if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
+ return rb_undefined(obj, mid, 0, 0, 0);
+ }
+
+ type = nd_type(body);
+ if (type == NODE_ZSUPER) {
+ /* for re-scoped/renamed method */
+ mid = id;
+ if (BUILTIN_TYPE(klass) == T_MODULE) {
+ /* origin is the Module, so need to scan superclass hierarchy. */
+ struct RClass *cl = RCLASS(klass);
+
+ klass = RBASIC(obj)->klass;
+ while (klass) {
+ if (RCLASS(klass)->m_tbl == cl->m_tbl)
+ break;
+ klass = RCLASS(klass)->super;
+ }
+ }
+ klass = RCLASS(klass)->super;
+ goto again;
+ }
+ if (BUILTIN_TYPE(klass) == T_ICLASS) {
+ klass = RBASIC(klass)->klass;
+ }
+
+ method = Data_Make_Struct(cMethod, struct METHOD, bm_mark, free, data);
+ data->klass = klass;
+ data->recv = obj;
+ data->id = id;
+ data->body = body;
+
+ return method;
+}
+
+static VALUE
+method_call(argc, argv, method)
+ int argc;
+ VALUE *argv;
+ VALUE method;
+{
+ VALUE result;
+ struct METHOD *data;
+
+ Data_Get_Struct(method, struct METHOD, data);
+ PUSH_ITER(iterator_p()?ITER_PRE:ITER_NOT);
+ result = rb_call0(data->klass, data->recv, data->id, data->id,
+ argc, argv, 1, data->body, nd_type(data->body));
+ POP_ITER();
+ return result;
+}
+
+static VALUE
+method_inspect(method)
+ VALUE method;
+{
+ struct METHOD *data;
+ VALUE str;
+ char *s;
+
+ Data_Get_Struct(method, struct METHOD, data);
+ str = str_new2("#<");
+ s = rb_class2name(CLASS_OF(method));
+ str_cat(str, s, strlen(s));
+ str_cat(str, ": ", 2);
+ s = rb_class2name(data->klass);
+ str_cat(str, s, strlen(s));
+ str_cat(str, "#", 1);
+ s = rb_id2name(data->id);
+ str_cat(str, s, strlen(s));
+ str_cat(str, ">", 1);
+
+ return str;
+}
+
void
Init_Proc()
{
@@ -4695,6 +4820,12 @@ Init_Proc()
rb_define_global_function("proc", f_lambda, 0);
rb_define_global_function("lambda", f_lambda, 0);
rb_define_global_function("binding", f_binding, 0);
+
+ cMethod = rb_define_class("Method", cObject);
+ rb_undef_method(CLASS_OF(cMethod), "new");
+ rb_define_method(cMethod, "call", method_call, -1);
+ rb_define_method(cMethod, "inspect", method_inspect, 0);
+ rb_define_method(mKernel, "method", obj_method, 1);
}
#ifdef THREAD
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index 9984b50380..0230636c50 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -32,10 +32,6 @@ struct windata {
WINDOW *window;
};
-#define NUM2CHAR(x) ((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\
- RSTRING(x)->ptr[0]:(char)NUM2INT(x)
-#define CHAR2FIX(x) INT2FIX((int)x)
-
static void
no_window()
{
@@ -288,7 +284,7 @@ static VALUE
curses_inch(obj)
VALUE obj;
{
- return CHAR2FIX(inch());
+ return CHR2FIX(inch());
}
/* def addch(ch) */
@@ -297,7 +293,7 @@ curses_addch(obj, ch)
VALUE obj;
VALUE ch;
{
- addch(NUM2CHAR(ch));
+ addch(NUM2CHR(ch));
return Qnil;
}
@@ -307,7 +303,7 @@ curses_insch(obj, ch)
VALUE obj;
VALUE ch;
{
- insch(NUM2CHAR(ch));
+ insch(NUM2CHR(ch));
return Qnil;
}
@@ -326,7 +322,7 @@ static VALUE
curses_getch(obj)
VALUE obj;
{
- return CHAR2FIX(getch());
+ return CHR2FIX(getch());
}
/* def getstr */
@@ -454,7 +450,7 @@ window_box(obj, vert, hor)
struct windata *winp;
GetWINDOW(obj, winp);
- box(winp->window, NUM2CHAR(vert), NUM2CHAR(hor));
+ box(winp->window, NUM2CHR(vert), NUM2CHR(hor));
return Qnil;
}
@@ -623,7 +619,7 @@ window_inch(obj)
struct windata *winp;
GetWINDOW(obj, winp);
- return CHAR2FIX(winch(winp->window));
+ return CHR2FIX(winch(winp->window));
}
/* def addch(ch) */
@@ -635,7 +631,7 @@ window_addch(obj, ch)
struct windata *winp;
GetWINDOW(obj, winp);
- waddch(winp->window, NUM2CHAR(ch));
+ waddch(winp->window, NUM2CHR(ch));
return Qnil;
}
@@ -649,7 +645,7 @@ window_insch(obj, ch)
struct windata *winp;
GetWINDOW(obj, winp);
- winsch(winp->window, NUM2CHAR(ch));
+ winsch(winp->window, NUM2CHR(ch));
return Qnil;
}
@@ -686,7 +682,7 @@ window_getch(obj)
struct windata *winp;
GetWINDOW(obj, winp);
- return CHAR2FIX(wgetch(winp->window));
+ return CHR2FIX(wgetch(winp->window));
}
/* def getstr */
diff --git a/io.c b/io.c
index d5b10ee141..d3cbcfc56e 100644
--- a/io.c
+++ b/io.c
@@ -1314,6 +1314,35 @@ f_print(argc, argv)
}
static VALUE
+io_putc(io, ch)
+ VALUE io, ch;
+{
+ OpenFile *fptr;
+ FILE *f;
+ int c = NUM2CHR(ch);
+
+ rb_secure(4);
+ GetOpenFile(io, fptr);
+ io_writable(fptr);
+
+ f = GetWriteFile(fptr);
+
+ if (fputc(c, f) == EOF || ferror(f))
+ rb_sys_fail(fptr->path);
+ if (fptr->mode & FMODE_SYNC)
+ fflush(f);
+
+ return ch;
+}
+
+static VALUE
+f_putc(recv, ch)
+ VALUE recv, ch;
+{
+ return io_putc(rb_defout, ch);
+}
+
+static VALUE
io_puts(argc, argv, out)
int argc;
VALUE *argv;
@@ -2275,6 +2304,7 @@ opt_i_set(val)
void
Init_IO()
{
+ extern VALUE mKernel;
extern VALUE mEnumerable;
extern VALUE eException;
@@ -2287,6 +2317,8 @@ Init_IO()
rb_define_global_function("open", f_open, -1);
rb_define_global_function("printf", f_printf, -1);
rb_define_global_function("print", f_print, -1);
+ rb_define_global_function("putc", f_putc, 1);
+ rb_define_global_function("putchar", f_putc, 1);
rb_define_global_function("puts", f_puts, -1);
rb_define_global_function("gets", f_gets_method, -1);
rb_define_global_function("readline", f_readline, -1);
@@ -2331,6 +2363,7 @@ Init_IO()
rb_define_method(cIO, "reopen", io_reopen, 1);
rb_define_method(cIO, "print", io_print, -1);
+ rb_define_method(cIO, "putc", io_putc, 1);
rb_define_method(cIO, "puts", io_puts, -1);
rb_define_method(cIO, "printf", io_printf, -1);
diff --git a/node.h b/node.h
index eb94ceb39d..f55ea0f557 100644
--- a/node.h
+++ b/node.h
@@ -135,7 +135,7 @@ typedef struct RNode {
#define RNODE(obj) (R_CAST(RNode)(obj))
-#define nd_type(n) (((RNODE(n))->flags>>FL_USHIFT)&0x7f)
+#define nd_type(n) (((RNODE(n))->flags>>FL_USHIFT)&0xff)
#define nd_set_type(n,t) \
RNODE(n)->flags=((RNODE(n)->flags&~FL_UMASK)|(((t)<<FL_USHIFT)&FL_UMASK))
diff --git a/regex.h b/regex.h
index 91442a8b2b..bf35589085 100644
--- a/regex.h
+++ b/regex.h
@@ -182,11 +182,25 @@ extern long re_syntax_options;
#undef ismbchar
#define ismbchar(c) \
(re_syntax_options & RE_MBCTYPE_EUC \
- ? ((unsigned char) (c) >= 0x80) \
- : (re_syntax_options & RE_MBCTYPE_SJIS \
- ? (( 0x80 <= (unsigned char) (c) \
+ ? ( 0xa1 <= (unsigned char) (c) \
+ && (unsigned char) (c) <= 0xfe) \
+ : (re_syntax_options & RE_MBCTYPE_SJIS \
+ ? (( 0x81 <= (unsigned char) (c) \
&& (unsigned char) (c) <= 0x9f) \
- || (0xe0 <= (unsigned char) (c))) \
+ || ((0xe0 <= (unsigned char) (c)) \
+ && (unsigned char) (c) <= 0xef)) \
+ : 0))
+
+#undef ismbchar2
+#define ismbchar2(c) \
+ (re_syntax_options & RE_MBCTYPE_EUC \
+ ? ( 0xa1 <= (unsigned char) (c) \
+ && (unsigned char) (c) <= 0xfe) \
+ : (re_syntax_options & RE_MBCTYPE_SJIS \
+ ? (( 0x40 <= (unsigned char) (c) \
+ && (unsigned char) (c) <= 0x7e) \
+ || ((0x80 <= (unsigned char) (c)) \
+ && (unsigned char) (c) <= 0xfc)) \
: 0))
/* This data structure is used to represent a compiled pattern. */
diff --git a/ruby.h b/ruby.h
index 97c751086a..9f8ede3e13 100644
--- a/ruby.h
+++ b/ruby.h
@@ -172,6 +172,10 @@ double num2dbl _((VALUE));
char *str2cstr _((VALUE));
#define STR2CSTR(x) str2cstr((VALUE)(x))
+#define NUM2CHR(x) (((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\
+ RSTRING(x)->ptr[0]:(char)NUM2INT(x))
+#define CHR2FIX(x) INT2FIX((int)x)
+
VALUE rb_newobj _((void));
#define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()
#define OBJSETUP(obj,c,t) {\
@@ -290,11 +294,11 @@ struct RBignum {
#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
#define RFILE(obj) (R_CAST(RFile)(obj))
-#define FL_SINGLETON (1<<8)
-#define FL_MARK (1<<9)
-#define FL_FINALIZE (1<<10)
+#define FL_SINGLETON FL_USER0
+#define FL_MARK (1<<8)
+#define FL_FINALIZE (1<<9)
-#define FL_USHIFT 11
+#define FL_USHIFT 10
#define FL_USER0 (1<<(FL_USHIFT+0))
#define FL_USER1 (1<<(FL_USHIFT+1))
@@ -303,8 +307,9 @@ struct RBignum {
#define FL_USER4 (1<<(FL_USHIFT+4))
#define FL_USER5 (1<<(FL_USHIFT+5))
#define FL_USER6 (1<<(FL_USHIFT+6))
+#define FL_USER7 (1<<(FL_USHIFT+7))
-#define FL_UMASK (0x7f<<FL_USHIFT)
+#define FL_UMASK (0xff<<FL_USHIFT)
#define FL_ABLE(x) (!(FIXNUM_P(x)||rb_special_const_p((VALUE)(x))))
#define FL_TEST(x,f) (FL_ABLE(x)?(RBASIC(x)->flags&(f)):0)
diff --git a/string.c b/string.c
index 5552e4f9d0..42666eefab 100644
--- a/string.c
+++ b/string.c
@@ -1375,7 +1375,7 @@ str_inspect(str)
while (p < pend) {
UCHAR c = *p++;
- if (ismbchar(c) && p < pend) {
+ if (ismbchar(c) && p < pend && ismbchar2(*p)) {
CHECK(2);
*b++ = c;
*b++ = *p++;