diff options
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | array.c | 40 | ||||
-rw-r--r-- | dir.c | 2 | ||||
-rw-r--r-- | eval.c | 55 | ||||
-rw-r--r-- | file.c | 47 | ||||
-rw-r--r-- | hash.c | 2 | ||||
-rw-r--r-- | intern.h | 2 | ||||
-rw-r--r-- | io.c | 65 | ||||
-rw-r--r-- | object.c | 8 | ||||
-rw-r--r-- | parse.y | 55 | ||||
-rw-r--r-- | ruby.c | 4 | ||||
-rw-r--r-- | sample/ruby-mode.el | 2 | ||||
-rw-r--r-- | signal.c | 17 | ||||
-rw-r--r-- | string.c | 35 |
14 files changed, 242 insertions, 122 deletions
@@ -1,3 +1,33 @@ +Thu Apr 16 01:38:02 1998 Yukihiro Matsumoto <matz@netlab.co.jp> + + * array.c (ary_flatten): new method. + + * eval.c (rb_longjmp): prints exception information with `-d'. + + * object.c (any_to_s): remove class name restriction. + + * file.c (thread_flock): do not block other threads. + + * eval.c (thread_trap_eval): signals are now delivered to the + current thread again. In case that the current thread is dead, + signals are forwarded to the main thread. + + * string.c (str_new4): need not to duplicate frozen strings. + +Wed Apr 15 01:22:56 1998 Yukihiro Matsumoto <matz@netlab.co.jp> + + * string.c (str_dup_frozen): do not duplicate frozen strings. + + * parse.y (yylex): allow nested parenthesises. + + * io.c (obj_displayln): prints newline after `display'ing the + receiver. + + * io.c (io_puts): avoid generating "\n" each time. use RS_default + instead. + + * io.c (f_p): ditto. + Tue Apr 14 11:34:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp> * experimental release 1.1b9_10. @@ -1234,6 +1234,44 @@ ary_nitems(ary) return INT2FIX(n); } +static VALUE +ary_flatten_bang(ary) + VALUE ary; +{ + int i; + int mod = 0; + + ary_modify(ary); + for (;;) { + int lmod = 0; + + for (i=0; i<RARRAY(ary)->len; i++) { + if (TYPE(RARRAY(ary)->ptr[i]) == T_ARRAY) { + VALUE ary2 = RARRAY(ary)->ptr[i]; + + ary_replace(ary, i, RARRAY(ary2)->len, ary2); + i += RARRAY(ary2)->len - 1; + lmod++; + } + } + if (lmod == 0) break; + mod = lmod; + } + + if (mod == 0) return Qnil; + return ary; +} + +static VALUE +ary_flatten(ary) + VALUE ary; +{ + VALUE v = ary_flatten_bang(ary_clone(ary)); + + if (NIL_P(v)) return ary; + return v; +} + extern VALUE mEnumerable; void @@ -1304,6 +1342,8 @@ Init_Array() rb_define_method(cArray, "uniq!", ary_uniq_bang, 0); rb_define_method(cArray, "compact", ary_compact, 0); rb_define_method(cArray, "compact!", ary_compact_bang, 0); + rb_define_method(cArray, "flatten", ary_flatten, 0); + rb_define_method(cArray, "flatten!", ary_flatten_bang, 0); rb_define_method(cArray, "nitems", ary_nitems, 0); cmp = rb_intern("<=>"); @@ -413,7 +413,7 @@ dir_foreach(io, dirname) { VALUE dir; - dir = dir_s_open(cDir, dirname); + dir = rb_funcall(cDir, rb_intern("open"), 1, dirname); return rb_ensure(dir_each, dir, dir_close, dir); } @@ -727,17 +727,8 @@ error_print() if (NIL_P(errinfo)) return; if (!NIL_P(errat)) { - VALUE mesg = Qnil; + VALUE mesg = RARRAY(errat)->ptr[0]; - switch (TYPE(errat)) { - case T_STRING: - mesg = errat; - errat = Qnil; - break; - case T_ARRAY: - mesg = RARRAY(errat)->ptr[0]; - break; - } if (NIL_P(mesg)) error_pos(); else { fwrite(RSTRING(mesg)->ptr, 1, RSTRING(mesg)->len, stderr); @@ -2681,7 +2672,13 @@ rb_longjmp(tag, mesg, at) if (NIL_P(errinfo) && NIL_P(mesg)) { errinfo = exc_new(eRuntimeError, 0, 0); } - +#if 1 + if (debug) { + fprintf(stderr, "Exception `%s' occurred at %s:%d\n", + rb_class2name(CLASS_OF(errinfo)), + sourcefile, sourceline); + } +#endif if (!NIL_P(at)) { errat = check_errat(at); } @@ -2698,6 +2695,11 @@ rb_longjmp(tag, mesg, at) } str_freeze(errinfo); } +#if 0 + if (debug) { + error_print(); + } +#endif trap_restore_mask(); JUMP_TAG(tag); @@ -5540,17 +5542,17 @@ thread_schedule() curr = curr->prev; } - FOREACH_THREAD_FROM(curr,th) { + FOREACH_THREAD_FROM(curr, th) { if (th->status != THREAD_STOPPED && th->status != THREAD_KILLED) { next = th; break; } } - END_FOREACH_FROM(curr,th); + END_FOREACH_FROM(curr, th); if (num_waiting_on_join) { - FOREACH_THREAD_FROM(curr,th) { - if ((th->wait_for & WAIT_JOIN) && thread_dead(th->join)) { + FOREACH_THREAD_FROM(curr, th) { + if ((th->wait_for&WAIT_JOIN) && thread_dead(th->join)) { th->join = 0; th->wait_for &= ~WAIT_JOIN; th->status = THREAD_RUNNABLE; @@ -5558,7 +5560,7 @@ thread_schedule() if (!next) next = th; } } - END_FOREACH_FROM(curr,th); + END_FOREACH_FROM(curr, th); } if (num_waiting_on_fd > 0 || num_waiting_on_timer > 0) { @@ -5572,19 +5574,19 @@ thread_schedule() max = 0; FD_ZERO(&readfds); if (num_waiting_on_fd > 0) { - FOREACH_THREAD_FROM(curr,th) { + FOREACH_THREAD_FROM(curr, th) { if (th->wait_for & WAIT_FD) { FD_SET(th->fd, &readfds); if (th->fd > max) max = th->fd; } } - END_FOREACH_FROM(curr,th); + END_FOREACH_FROM(curr, th); } delay = DELAY_INFTY; if (num_waiting_on_timer > 0) { now = timeofday(); - FOREACH_THREAD_FROM(curr,th) { + FOREACH_THREAD_FROM(curr, th) { if (th->wait_for & WAIT_TIME) { if (th->delay <= now) { th->delay = 0.0; @@ -5597,7 +5599,7 @@ thread_schedule() } } } - END_FOREACH_FROM(curr,th); + END_FOREACH_FROM(curr, th); } /* Do the select if needed */ if (num_waiting_on_fd > 0 || !next) { @@ -5626,7 +5628,7 @@ thread_schedule() if (n > 0) { /* Some descriptors are ready. Make the corresponding threads runnable. */ - FOREACH_THREAD_FROM(curr,th) { + FOREACH_THREAD_FROM(curr, th) { if ((th->wait_for&WAIT_FD) && FD_ISSET(th->fd, &readfds)) { /* Wake up only one thread per fd. */ @@ -5638,7 +5640,7 @@ thread_schedule() if (!next) next = th; /* Found one. */ } } - END_FOREACH_FROM(curr,th); + END_FOREACH_FROM(curr, th); } } /* The delays for some of the threads should have expired. @@ -5649,12 +5651,12 @@ thread_schedule() if (!next) { curr_thread->file = sourcefile; curr_thread->line = sourceline; - FOREACH_THREAD_FROM(curr,th) { + FOREACH_THREAD_FROM(curr, th) { fprintf(stderr, "%s:%d:deadlock 0x%x: %d:%d %s\n", th->file, th->line, th->thread, th->status, th->wait_for, th==main_thread?"(main)":""); } - END_FOREACH_FROM(curr,th); + END_FOREACH_FROM(curr, th); /* raise fatal error to main thread */ thread_deadlock(); } @@ -6272,11 +6274,12 @@ thread_trap_eval(cmd, sig) int sig; { thread_critical = 0; - thread_ready(main_thread); - if (curr_thread == main_thread) { + if (!thread_dead(curr_thread)) { + thread_ready(curr_thread); rb_trap_eval(cmd, sig); return; } + thread_ready(main_thread); thread_save_context(curr_thread); if (setjmp(curr_thread->context)) { return; @@ -189,7 +189,7 @@ file_tell(obj) GetOpenFile(obj, fptr); pos = ftell(fptr->f); - if (ferror(fptr->f) != 0) rb_sys_fail(0); + if (ferror(fptr->f) != 0) rb_sys_fail(fptr->path); return int2inum(pos); } @@ -203,10 +203,10 @@ file_seek(obj, offset, ptrname) GetOpenFile(obj, fptr); pos = fseek(fptr->f, NUM2INT(offset), NUM2INT(ptrname)); - if (pos != 0) rb_sys_fail(0); + if (pos != 0) rb_sys_fail(fptr->path); clearerr(fptr->f); - return obj; + return INT2FIX(0); } static VALUE @@ -218,10 +218,10 @@ file_set_pos(obj, offset) GetOpenFile(obj, fptr); pos = fseek(fptr->f, NUM2INT(offset), 0); - if (pos != 0) rb_sys_fail(0); + if (pos != 0) rb_sys_fail(fptr->path); clearerr(fptr->f); - return obj; + return INT2NUM(pos); } static VALUE @@ -231,10 +231,10 @@ file_rewind(obj) OpenFile *fptr; GetOpenFile(obj, fptr); - if (fseek(fptr->f, 0L, 0) != 0) rb_sys_fail(0); + if (fseek(fptr->f, 0L, 0) != 0) rb_sys_fail(fptr->path); clearerr(fptr->f); - return obj; + return INT2FIX(0); } static VALUE @@ -1100,7 +1100,7 @@ file_s_symlink(obj, from, to) if (symlink(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0) rb_sys_fail(RSTRING(from)->ptr); - return TRUE; + return INT2FIX(0); #else rb_notimplement(); #endif @@ -1384,7 +1384,7 @@ file_s_truncate(obj, path, len) rb_notimplement(); # endif #endif - return TRUE; + return INT2FIX(0); } static VALUE @@ -1409,8 +1409,32 @@ file_truncate(obj, len) rb_notimplement(); # endif #endif - return TRUE; + return INT2FIX(0); +} + +#if defined(THREAD) && defined(EWOULDBLOCK) +static int +thread_flock(fd, op) + int fd, op; +{ + if (thread_alone() || (op & LOCK_NB)) { + return flock(fd, op); + } + op |= LOCK_NB; + while (flock(fd, op) < 0) { + switch (errno) { + case EINTR: /* can be happen? */ + case EWOULDBLOCK: + thread_schedule(); /* busy wait */ + break; + default: + return -1; + } + } + return 0; } +#define flock thread_flock +#endif static VALUE file_flock(obj, operation) @@ -1430,8 +1454,9 @@ file_flock(obj, operation) #endif rb_sys_fail(fptr->path); } - return obj; + return INT2FIX(0); } +#undef flock static void test_check(n, argc, argv) @@ -450,7 +450,7 @@ hash_aset(hash, key, val) return Qnil; } if (TYPE(key) == T_STRING) { - key = str_dup_freezed(key); + key = str_dup_frozen(key); } st_insert(RHASH(hash)->tbl, key, val); return val; @@ -251,7 +251,7 @@ VALUE str_times _((VALUE, VALUE)); VALUE str_substr _((VALUE, int, int)); void str_modify _((VALUE)); VALUE str_freeze _((VALUE)); -VALUE str_dup_freezed _((VALUE)); +VALUE str_dup_frozen _((VALUE)); VALUE str_taint _((VALUE)); VALUE str_tainted _((VALUE)); VALUE str_resize _((VALUE, int)); @@ -455,7 +455,7 @@ io_gets_method(argc, argv, io) if (c != EOF && (!rslen || RSTRING(str)->len < rslen || - memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen, rsptr, rslen))) { + memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen,rsptr,rslen))) { append = 1; goto again; } @@ -820,7 +820,7 @@ io_binmode(io) fptr->mode |= FMODE_BINMODE; #endif - return io; + return INT2FIX(0); } int @@ -1419,7 +1419,7 @@ io_puts(argc, argv, out) /* if no argument given, print newline. */ if (argc == 0) { - io_write(out, str_new2("\n")); + io_write(out, RS_default); return Qnil; } for (i=0; i<argc; i++) { @@ -1439,7 +1439,7 @@ io_puts(argc, argv, out) line = obj_as_string(line); io_write(out, line); if (RSTRING(line)->ptr[RSTRING(line)->len-1] != '\n') { - io_write(out, str_new2("\n")); + io_write(out, RS_default); } } @@ -1456,20 +1456,11 @@ f_puts(argc, argv) } static VALUE -f_p(argc, argv, self) - int argc; - VALUE *argv; - VALUE self; +f_p(self, obj) + VALUE self, obj; { - VALUE str; - - if (argc > 0) { - rb_scan_args(argc, argv, "1", &self); - } - str = rb_inspect(self); - Check_Type(str, T_STRING); - io_write(rb_defout, str); - io_write(rb_defout, str_new2("\n")); + io_write(rb_defout, rb_inspect(obj)); + io_write(rb_defout, RS_default); return Qnil; } @@ -1478,7 +1469,7 @@ void rb_p(obj) /* for debug print within C code */ VALUE obj; { - f_p(0, 0, obj); + f_p(0, obj); } static VALUE @@ -1500,6 +1491,26 @@ obj_display(argc, argv, self) return Qnil; } +static VALUE +obj_displayln(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + VALUE out; + VALUE str; + + rb_scan_args(argc, argv, "01", &out); + if (NIL_P(out)) { + out = rb_defout; + } + + io_write(out, self); + io_write(rb_defout, RS_default); + + return Qnil; +} + static void io_defset(val, id) VALUE val; @@ -1546,15 +1557,15 @@ prep_stdio(f, mode, klass) VALUE klass; { OpenFile *fp; - NEWOBJ(obj, struct RFile); - OBJSETUP(obj, klass, T_FILE); + NEWOBJ(io, struct RFile); + OBJSETUP(io, klass, T_FILE); - MakeOpenFile(obj, fp); + MakeOpenFile(io, fp); fp->f = f; fp->mode = mode; - obj_call_init((VALUE)obj); + obj_call_init((VALUE)io); - return (VALUE)obj; + return (VALUE)io; } static VALUE @@ -1735,8 +1746,8 @@ f_getc() } static VALUE -f_ungetc(obj, c) - VALUE obj, c; +f_ungetc(self, c) + VALUE self, c; { if (!next_argv()) { ArgError("no stream to ungetc"); @@ -2423,8 +2434,9 @@ Init_IO() rb_define_global_function("`", f_backquote, 1); rb_define_global_function("pipe", io_s_pipe, 0); - rb_define_method(mKernel, "p", f_p, -1); + rb_define_global_function("p", f_p, 1); rb_define_method(mKernel, "display", obj_display, -1); + rb_define_method(mKernel, "displayln", obj_displayln, -1); cIO = rb_define_class("IO", cObject); rb_include_module(cIO, mEnumerable); @@ -2442,6 +2454,7 @@ Init_IO() RS = RS_default = str_new2("\n"); ORS = Qnil; rb_global_variable(&RS_default); + str_freeze(RS_default); /* avoid modifying RS_default */ rb_define_hooked_variable("$/", &RS, 0, rb_str_setter); rb_define_hooked_variable("$-0", &RS, 0, rb_str_setter); rb_define_hooked_variable("$\\", &ORS, 0, rb_str_setter); @@ -118,10 +118,12 @@ VALUE any_to_s(obj) VALUE obj; { - char buf[256]; + char *s; + char *cname = rb_class2name(CLASS_OF(obj)); - sprintf(buf, "#<%s:0x%x>", rb_class2name(CLASS_OF(obj)), obj); - return str_new2(buf); + s = ALLOCA_N(char, strlen(cname)+6+16+1); /* 6:tags 16:addr 1:eos */ + sprintf(s, "#<%s:0x%x>", cname, obj); + return str_new2(s); } VALUE @@ -1824,12 +1824,13 @@ read_escape() } static int -parse_regx(term) +parse_regx(term, paren) int term; { register int c; char kcode = 0; int once = 0; + int nest = 0; int casefold = 0; int in_brack = 0; int re_start = sourceline; @@ -1837,7 +1838,7 @@ parse_regx(term) newtok(); while ((c = nextc()) != -1) { - if (!in_brack && c == term) { + if ((!in_brack && c == term) || nest > 0) { goto regx_end; } @@ -1888,6 +1889,8 @@ parse_regx(term) } /* fall through */ default: + if (c == paren) nest++; + if (c == term) nest--; if (c == '\n') { sourceline++; } @@ -1961,23 +1964,24 @@ parse_regx(term) return 0; } -static int parse_qstring(); +static int parse_qstring _((int,int)); static int -parse_string(func,term) - int func, term; +parse_string(func, term, paren) + int func, term, paren; { int c; NODE *list = 0; int strstart; + int nest = 0; if (func == '\'') { - return parse_qstring(term); + return parse_qstring(term, paren); } strstart = sourceline; newtok(); - while ((c = nextc()) != term) { + while ((c = nextc()) != term || nest > 0) { if (c == -1) { unterm_str: sourceline = strstart; @@ -2011,6 +2015,8 @@ parse_string(func,term) } continue; } + if (c == paren) nest++; + if (c == term) nest--; tokadd(c); } @@ -2037,15 +2043,16 @@ parse_string(func,term) } static int -parse_qstring(term) +parse_qstring(term, paren) int term; { int strstart; int c; + int nest = 0; strstart = sourceline; newtok(); - while ((c = nextc()) != term) { + while ((c = nextc()) != term || nest > 0) { if (c == -1) { sourceline = strstart; Error("unterminated string meets end of file"); @@ -2079,6 +2086,8 @@ parse_qstring(term) tokadd('\\'); } } + if (c == paren) nest++; + if (c == term) nest--; tokadd(c); } @@ -2089,10 +2098,10 @@ parse_qstring(term) } static int -parse_quotedword(term) - int term; +parse_quotedword(term, paren) + int term, paren; { - if (parse_qstring(term) == 0) return 0; + if (parse_qstring(term, paren) == 0) return 0; yylval.node = NEW_CALL(NEW_STR(yylval.val), rb_intern("split"), 0); return tDSTRING; } @@ -2406,13 +2415,13 @@ retry: return '>'; case '"': - return parse_string(c,c); + return parse_string(c,c,c); case '`': if (lex_state == EXPR_FNAME) return c; - return parse_string(c,c); + return parse_string(c,c,c); case '\'': - return parse_qstring(c); + return parse_qstring(c,c); case '?': if (lex_state == EXPR_END) { @@ -2700,7 +2709,7 @@ retry: case '/': if (lex_state == EXPR_BEG || lex_state == EXPR_MID) { - return parse_regx('/'); + return parse_regx('/', '/'); } if ((c = nextc()) == '=') { lex_state = EXPR_BEG; @@ -2711,7 +2720,7 @@ retry: if (space_seen && !isspace(c)) { pushback(c); arg_ambiguous(); - return parse_regx('/'); + return parse_regx('/', '/'); } } lex_state = EXPR_BEG; @@ -2792,6 +2801,7 @@ retry: case '%': if (lex_state == EXPR_BEG || lex_state == EXPR_MID) { int term; + int paren; c = nextc(); quotation: @@ -2815,6 +2825,7 @@ retry: Error("unterminated quoted string meets end of file"); return 0; } + paren = term; if (term == '(') term = ')'; else if (term == '[') term = ']'; else if (term == '{') term = '}'; @@ -2822,19 +2833,19 @@ retry: switch (c) { case 'Q': - return parse_string('"', term); + return parse_string('"', term, paren); case 'q': - return parse_qstring(term); + return parse_qstring(term, paren); case 'w': - return parse_quotedword(term); + return parse_quotedword(term, paren); case 'x': - return parse_string('`', term); + return parse_string('`', term, paren); case 'r': - return parse_regx(term); + return parse_regx(term, paren); default: yyerror("unknown type of %string"); @@ -477,9 +477,7 @@ load_file(fname, script) line = io_gets(f); line_start++; - if (RSTRING(line)->len > 2 - && RSTRING(line)->ptr[0] == '!') { - + if (RSTRING(line)->len > 2 && RSTRING(line)->ptr[0] == '!') { if ((p = strstr(RSTRING(line)->ptr, "ruby")) == 0) { /* not ruby script, kick the program */ char **argv; diff --git a/sample/ruby-mode.el b/sample/ruby-mode.el index 33e9d2ce4d..f7e2fddbfa 100644 --- a/sample/ruby-mode.el +++ b/sample/ruby-mode.el @@ -646,7 +646,7 @@ An end of a defun is found by moving forward from the beginning of one." "\\)[ \n\t()]") 2) ;; variables - '("\\(^\\|[^_]\\)\\b\\(nil\\|self\\|true\\|false\\)\\b[^_]" + '("\\(^\\|[^_]\\)\\b\\(nil\\|self\\|true\\|false\\)\\b\\([^_]\\|$\\)" 2 font-lock-variable-name-face) ;; variables '("\\[$@].\\([a-zA-Z0-9_]\\)" @@ -271,6 +271,11 @@ posix_signal(signum, handler) } #endif +#ifdef THREAD +# define rb_interrupt thread_interrupt +# define rb_trap_eval thread_trap_eval +#endif + static RETSIGTYPE sighandle(sig) int sig; @@ -285,11 +290,7 @@ sighandle(sig) if (trap_immediate) { trap_immediate = 0; if (sig == SIGINT && !trap_list[SIGINT]) { -#ifdef THREAD - thread_interrupt(); -#else rb_interrupt(); -#endif } rb_trap_eval(trap_list[sig], sig); trap_immediate = 1; @@ -334,18 +335,10 @@ rb_trap_exec() if (trap_pending_list[i]) { trap_pending_list[i] = 0; if (i == SIGINT && trap_list[SIGINT] == 0) { -#ifdef THREAD - thread_interrupt(); -#else rb_interrupt(); -#endif return; } -#ifdef THREAD - thread_trap_eval(trap_list[i], i); -#else rb_trap_eval(trap_list[i], i); -#endif } } trap_pending = 0; @@ -84,23 +84,25 @@ VALUE str_new4(orig) VALUE orig; { - NEWOBJ(str, struct RString); - OBJSETUP(str, cString, T_STRING); - - str->len = RSTRING(orig)->len; - str->ptr = RSTRING(orig)->ptr; if (RSTRING(orig)->orig) { - str->orig = RSTRING(orig)->orig; + return str_freeze(RSTRING(orig)->orig); + } + else if (FL_TEST(orig, STR_FREEZE)) { + return orig; } else { + NEWOBJ(str, struct RString); + OBJSETUP(str, cString, T_STRING); + + str->len = RSTRING(orig)->len; + str->ptr = RSTRING(orig)->ptr; RSTRING(orig)->orig = (VALUE)str; str->orig = 0; + if (rb_safe_level() >= 3) { + FL_SET(str, STR_TAINT); + } + return (VALUE)str; } - if (rb_safe_level() >= 3) { - FL_SET(str, STR_TAINT); - } - - return (VALUE)str; } static void @@ -362,12 +364,15 @@ str_frozen_p(str) } VALUE -str_dup_freezed(str) +str_dup_frozen(str) VALUE str; { - str = str_dup(str); - str_freeze(str); - return str; + if (RSTRING(str)->orig) { + return str_freeze(RSTRING(str)->orig); + } + if (FL_TEST(str, STR_FREEZE)) + return str; + return str_freeze(str_dup(str)); } VALUE |