diff options
-rw-r--r-- | ChangeLog | 43 | ||||
-rw-r--r-- | class.c | 2 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | error.c | 2 | ||||
-rw-r--r-- | eval.c | 18 | ||||
-rw-r--r-- | ext/tcltklib/tcltklib.c | 484 | ||||
-rw-r--r-- | file.c | 15 | ||||
-rw-r--r-- | lib/uri/mailto.rb | 10 | ||||
-rw-r--r-- | object.c | 4 | ||||
-rw-r--r-- | parse.y | 46 | ||||
-rw-r--r-- | range.c | 4 | ||||
-rw-r--r-- | string.c | 2 | ||||
-rw-r--r-- | variable.c | 37 | ||||
-rw-r--r-- | version.h | 4 |
14 files changed, 545 insertions, 128 deletions
@@ -1,3 +1,19 @@ +Mon Sep 23 02:46:29 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * eval.c (ruby_run): should set toplevel visibility again here. + + * eval.c (rb_eval): should not rely on ruby_class == rb_cObject + check. Besides allow implicit publicity for attribute set + methods. + + * parse.y (primary): need not to check class_nest, just set + whether method is an attrset or not. + +Sun Sep 22 17:08:11 2002 Tanaka Akira <akr@m17n.org> + + * string.c (rb_str_each_line): p might be at the top of the + string. + Sun Sep 22 15:31:33 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net> * lib/mkmf.rb: some backports. @@ -97,6 +113,15 @@ Fri Sep 6 05:11:48 2002 Minero Aoki <aamine@loveruby.net> * intern.h (rb_gc_mark_parser): added. +Thu Sep 5 18:32:32 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * variable.c (rb_path2class): should not use rb_eval_string(). + +Thu Sep 5 15:33:16 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * parse.y (str_extend): expression substitution can contain string + terminator again. + Thu Sep 5 13:09:22 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net> * eval.c (rb_eval): overriding false constant with class/module @@ -108,6 +133,11 @@ Thu Sep 5 13:09:22 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net> * ruby.c (require_libraries): not clear source file. [ruby-dev:18074] +Wed Sep 4 05:10:16 2002 Koji Arai <jca02266@nifty.ne.jp> + + * parse.y (yylex): the warning message "invalid + character syntax" was never issued. + Tue Sep 3 00:22:43 2002 Minero Aoki <aamine@loveruby.net> * gc.c (gc_sweep): does reclaim nodes in also compile time, if we @@ -119,6 +149,19 @@ Tue Sep 3 00:22:43 2002 Minero Aoki <aamine@loveruby.net> * intern.h (ruby_parser_stack_on_heap): added. +Tue Aug 27 15:03:35 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * file.c (rb_find_file): $LOAD_PATH must not be empty. + + * file.c (rb_find_file_ext): ditto. + +Tue Aug 27 02:35:21 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * range.c (range_eq): class check should be based on range.class, + instead of Range to work with Range.dup. + + * range.c (range_eql): ditto. + Sun Aug 25 20:10:32 2002 Wakou Aoyama <wakou@ruby-lang.org> * lib/cgi.rb (CGI#form): fix ruby-bugs-ja:PR#280, add default action. @@ -643,7 +643,7 @@ rb_singleton_class(obj) klass = RBASIC(obj)->klass; } else { - klass = rb_make_metaclass(obj, RBASIC(obj)->klass); + klass = rb_make_metaclass(obj, CLASS_OF(obj)); } if (OBJ_TAINTED(obj)) { OBJ_TAINT(klass); diff --git a/configure.in b/configure.in index 9d064249e5..543965ba2a 100644 --- a/configure.in +++ b/configure.in @@ -913,7 +913,7 @@ case "$target_os" in CFLAGS="$CFLAGS -pipe -no-precomp" ;; darwin*) - CFLAGS="$CFLAGS -pipe -no-precomp" + CFLAGS="$CFLAGS -pipe" ;; os2_emx) CFLAGS="$CFLAGS -DOS2" @@ -469,7 +469,9 @@ static VALUE *syserr_list; #endif #if !defined(NT) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(sys_nerr) +# if !defined(__APPLE__) || (__APPLE_CC__ < 1151) extern int sys_nerr; +# endif #endif static VALUE @@ -1216,6 +1216,8 @@ ruby_run() Init_stack(&tmp); PUSH_TAG(PROT_NONE); PUSH_ITER(ITER_NOT); + /* default visibility is private at toplevel */ + SCOPE_SET(SCOPE_PRIVATE); if ((state = EXEC_TAG()) == 0) { eval_node(ruby_top_self, ruby_eval_tree); } @@ -2995,15 +2997,15 @@ rb_eval(self, n) } } - if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) { + if (node->nd_noex == NOEX_PUBLIC) { + noex = NOEX_PUBLIC; /* means is is an attrset */ + } + else if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) { noex = NOEX_PRIVATE; } else if (SCOPE_TEST(SCOPE_PROTECTED)) { noex = NOEX_PROTECTED; } - else if (ruby_class == rb_cObject) { - noex = node->nd_noex; - } else { noex = NOEX_PUBLIC; } @@ -3159,8 +3161,8 @@ rb_eval(self, n) } else { module = rb_define_module_id(node->nd_cname); - rb_const_set(ruby_class, node->nd_cname, module); rb_set_class_path(module,ruby_class,rb_id2name(node->nd_cname)); + rb_const_set(ruby_class, node->nd_cname, module); } if (ruby_wrapper) { rb_extend_object(module, ruby_wrapper); @@ -7946,7 +7948,7 @@ void rb_thread_wait_for(time) struct timeval time; { - double date; + double limit; if (rb_thread_critical || curr_thread == curr_thread->next || @@ -7986,9 +7988,9 @@ rb_thread_wait_for(time) } } - date = timeofday() + (double)time.tv_sec + (double)time.tv_usec*1e-6; + limit = timeofday() + (double)time.tv_sec + (double)time.tv_usec*1e-6; curr_thread->status = THREAD_STOPPED; - curr_thread->delay = date; + curr_thread->delay = limit; curr_thread->wait_for = WAIT_TIME; rb_thread_schedule(); } diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c index 7818f0e0bc..0972f9ec9d 100644 --- a/ext/tcltklib/tcltklib.c +++ b/ext/tcltklib/tcltklib.c @@ -48,20 +48,44 @@ int *tclDummyMathPtr = (int *) matherr; /*---- module TclTkLib ----*/ struct invoke_queue { + Tcl_Event ev; int argc; VALUE *argv; VALUE obj; int done; - VALUE result; + int safe_level; + VALUE *result; VALUE thread; - struct invoke_queue *next; }; -static struct invoke_queue *iqueue; static VALUE main_thread; +static VALUE eventloop_thread; +static VALUE watchdog_thread; +Tcl_Interp *current_interp; + +/* + * 'event_loop_max' is a maximum events which the eventloop processes in one + * term of thread scheduling. 'no_event_tick' is the count-up value when + * there are no event for processing. + * 'timer_tick' is a limit of one term of thread scheduling. + * If 'timer_tick' == 0, then not use the timer for thread scheduling. + */ +static int tick_counter; +#define DEFAULT_EVENT_LOOP_MAX 800 +#define DEFAULT_NO_EVENT_TICK 10 +#define DEFAULT_TIMER_TICK 0 +static int event_loop_max = DEFAULT_EVENT_LOOP_MAX; +static int no_event_tick = DEFAULT_NO_EVENT_TICK; +static int timer_tick = DEFAULT_TIMER_TICK; + +#if TCL_MAJOR_VERSION >= 8 +static int ip_ruby _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*)); +#else +static int ip_ruby _((ClientData, Tcl_Interp *, int, char **)); +#endif /* Tk_ThreadTimer */ -static Tcl_TimerToken timer_token; +static Tcl_TimerToken timer_token = (Tcl_TimerToken)NULL; /* timer callback */ static void _timer_for_tcl _((ClientData)); @@ -73,44 +97,265 @@ _timer_for_tcl(clientData) VALUE thread; Tk_DeleteTimerHandler(timer_token); - timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl, (ClientData)0); - - CHECK_INTS; - q = iqueue; - while (q) { - tmp = q; - q = q->next; - if (!tmp->done) { - tmp->done = 1; - tmp->result = ip_invoke_real(tmp->argc, tmp->argv, tmp->obj); - thread = tmp->thread; - tmp = tmp->next; - rb_thread_run(thread); + if (timer_tick > 0) { + timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl, + (ClientData)0); + } else { + timer_token = (Tcl_TimerToken)NULL; + } + + /* rb_thread_schedule(); */ + timer_tick += event_loop_max; +} + +static VALUE +set_eventloop_tick(self, tick) + VALUE self; + VALUE tick; +{ + int ttick = NUM2INT(tick); + + if (ttick < 0) { + rb_raise(rb_eArgError, "timer-tick parameter must be 0 or plus number"); + } + + /* delete old timer callback */ + Tk_DeleteTimerHandler(timer_token); + + timer_tick = ttick; + if (timer_tick > 0) { + /* start timer callback */ + timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl, + (ClientData)0); + } else { + timer_token = (Tcl_TimerToken)NULL; + } + + return tick; +} + +static VALUE +get_eventloop_tick(self) + VALUE self; +{ + return INT2NUM(timer_tick); +} + +static VALUE +set_eventloop_weight(self, loop_max, no_event) + VALUE self; + VALUE loop_max; + VALUE no_event; +{ + int lpmax = NUM2INT(loop_max); + int no_ev = NUM2INT(no_event); + + if (lpmax <= 0 || no_ev <= 0) { + rb_raise(rb_eArgError, "weight parameters must be plus number"); + } + + event_loop_max = lpmax; + no_event_tick = no_ev; + + return rb_ary_new3(2, loop_max, no_event); +} + +static VALUE +get_eventloop_weight(self) + VALUE self; +{ + return rb_ary_new3(2, INT2NUM(event_loop_max), INT2NUM(no_event_tick)); +} + +VALUE +lib_mainloop_core(check_root_widget) + VALUE check_root_widget; +{ + VALUE current = eventloop_thread; + int check = (check_root_widget == Qtrue); + + Tk_DeleteTimerHandler(timer_token); + if (timer_tick > 0) { + timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl, + (ClientData)0); + } else { + timer_token = (Tcl_TimerToken)NULL; + } + + for(;;) { + tick_counter = 0; + while(tick_counter < event_loop_max) { + if (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT)) { + tick_counter++; + } else { + tick_counter += no_event_tick; + } + if (watchdog_thread != 0 && eventloop_thread != current) { + return Qnil; } + } + if (check && Tk_GetNumMainWindows() == 0) { + break; + } + rb_thread_schedule(); + } + return Qnil; +} + +VALUE +lib_mainloop_ensure(parent_evloop) + VALUE parent_evloop; +{ + Tk_DeleteTimerHandler(timer_token); + timer_token = (Tcl_TimerToken)NULL; + DUMP2("mainloop-ensure: current-thread : %lx\n", rb_thread_current()); + DUMP2("mainloop-ensure: eventloop-thread : %lx\n", eventloop_thread); + if (eventloop_thread == rb_thread_current()) { + DUMP2("tcltklib: eventloop-thread -> %lx\n", parent_evloop); + eventloop_thread = parent_evloop; } - rb_thread_schedule(); + return Qnil; +} + +static VALUE +lib_mainloop_launcher(check_rootwidget) + VALUE check_rootwidget; +{ + VALUE parent_evloop = eventloop_thread; + + eventloop_thread = rb_thread_current(); + + if (ruby_debug) { + fprintf(stderr, "tcltklib: eventloop-thread : %lx -> %lx\n", + parent_evloop, eventloop_thread); + } + + return rb_ensure(lib_mainloop_core, check_rootwidget, + lib_mainloop_ensure, parent_evloop); } /* execute Tk_MainLoop */ static VALUE -lib_mainloop(self) +lib_mainloop(argc, argv, self) + int argc; + VALUE *argv; VALUE self; { - timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl, (ClientData)0); - DUMP1("start Tk_Mainloop"); - Tk_MainLoop(); - DUMP1("stop Tk_Mainloop"); - Tk_DeleteTimerHandler(timer_token); + VALUE check_rootwidget; + + if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) { + check_rootwidget = Qtrue; + } else if (RTEST(check_rootwidget)) { + check_rootwidget = Qtrue; + } else { + check_rootwidget = Qfalse; + } + + return lib_mainloop_launcher(check_rootwidget); +} + +VALUE +lib_watchdog_core(check_rootwidget) + VALUE check_rootwidget; +{ + VALUE current = eventloop_thread; + VALUE evloop; + int check = (check_rootwidget == Qtrue); + ID stop = rb_intern("stop?"); + + /* check other watchdog thread */ + if (watchdog_thread != 0) { + if (rb_funcall(watchdog_thread, stop, 0) == Qtrue) { + rb_funcall(watchdog_thread, rb_intern("kill"), 0); + } else { + return Qnil; + } + } + watchdog_thread = rb_thread_current(); + + /* watchdog start */ + do { + if (eventloop_thread == 0 + || rb_funcall(eventloop_thread, stop, 0) == Qtrue) { + /* start new eventloop thread */ + DUMP2("eventloop thread %lx is sleeping or dead", eventloop_thread); + evloop = rb_thread_create(lib_mainloop_launcher, + (void*)&check_rootwidget); + DUMP2("create new eventloop thread %lx", evloop); + rb_thread_run(evloop); + } else { + rb_thread_schedule(); + } + } while(!check || Tk_GetNumMainWindows() != 0); return Qnil; } +VALUE +lib_watchdog_ensure(arg) + VALUE arg; +{ + eventloop_thread = 0; /* stop eventloops */ + return Qnil; +} + +static VALUE +lib_mainloop_watchdog(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + VALUE check_rootwidget; + + if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) { + check_rootwidget = Qtrue; + } else if (RTEST(check_rootwidget)) { + check_rootwidget = Qtrue; + } else { + check_rootwidget = Qfalse; + } + + return rb_ensure(lib_watchdog_core, check_rootwidget, + lib_watchdog_ensure, Qnil); +} + +static VALUE +lib_do_one_event(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + VALUE obj, vflags; + int flags; + + if (rb_scan_args(argc, argv, "01", &vflags) == 0) { + flags = 0; + } else { + Check_Type(vflags, T_FIXNUM); + flags = FIX2INT(vflags); + } + return INT2NUM(Tcl_DoOneEvent(flags)); +} + /*---- class TclTkIp ----*/ struct tcltkip { Tcl_Interp *ip; /* the interpreter */ int return_value; /* return value */ }; +static struct tcltkip * +get_ip(self) + VALUE self; +{ + struct tcltkip *ptr; + + Data_Get_Struct(self, struct tcltkip, ptr); + if (ptr == 0) { + rb_raise(rb_eTypeError, "uninitialized TclTkIp"); + } + return ptr; +} + /* Tcl command `ruby' */ static VALUE ip_eval_rescue(failed, einfo) @@ -126,10 +371,7 @@ static VALUE lib_restart(self) VALUE self; { - struct tcltkip *ptr; /* tcltkip data struct */ - - /* get the data struct */ - Data_Get_Struct(self, struct tcltkip, ptr); + struct tcltkip *ptr = get_ip(self); /* destroy the root wdiget */ ptr->return_value = Tcl_Eval(ptr->ip, "destroy ."); @@ -185,7 +427,9 @@ ip_ruby(clientData, interp, argc, argv) DUMP2("rb_eval_string(%s)", arg); old_trapflg = rb_trap_immediate; rb_trap_immediate = 0; - res = rb_rescue(rb_eval_string, (VALUE)arg, ip_eval_rescue, (VALUE)&failed); + res = rb_rescue2(rb_eval_string, (VALUE)arg, + ip_eval_rescue, (VALUE)&failed, + rb_eStandardError, rb_eScriptError, 0); rb_trap_immediate = old_trapflg; Tcl_ResetResult(interp); @@ -221,8 +465,10 @@ ip_free(ptr) struct tcltkip *ptr; { DUMP1("Tcl_DeleteInterp"); - Tcl_DeleteInterp(ptr->ip); - free(ptr); + if (ptr) { + Tcl_DeleteInterp(ptr->ip); + free(ptr); + } } /* create and initialize interpreter */ @@ -276,10 +522,7 @@ ip_eval(self, str) { char *s; char *buf; /* Tcl_Eval requires re-writable string region */ - struct tcltkip *ptr; /* tcltkip data struct */ - - /* get the data struct */ - Data_Get_Struct(self, struct tcltkip, ptr); + struct tcltkip *ptr = get_ip(self); /* call Tcl_Eval() */ s = STR2CSTR(str); @@ -310,7 +553,7 @@ ip_toUTF8(self, str, encodename) struct tcltkip *ptr; char *buf; - Data_Get_Struct(self,struct tcltkip, ptr); + ptr = get_ip(self); interp = ptr->ip; encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename)); @@ -341,7 +584,7 @@ ip_fromUTF8(self, str, encodename) struct tcltkip *ptr; char *buf; - Data_Get_Struct(self,struct tcltkip, ptr); + ptr = get_ip(self); interp = ptr->ip; encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename)); @@ -367,10 +610,11 @@ ip_invoke_real(argc, argv, obj) VALUE *argv; VALUE obj; { + VALUE v; struct tcltkip *ptr; /* tcltkip data struct */ int i; Tcl_CmdInfo info; - char *cmd; + char *cmd, *s; char **av = (char **)NULL; #if TCL_MAJOR_VERSION >= 8 Tcl_Obj **ov = (Tcl_Obj **)NULL; @@ -378,10 +622,11 @@ ip_invoke_real(argc, argv, obj) #endif /* get the data struct */ - Data_Get_Struct(obj, struct tcltkip, ptr); + ptr = get_ip(obj); /* get the command name string */ - cmd = STR2CSTR(argv[0]); + v = argv[0]; + cmd = STR2CSTR(v); /* map from the command name to a C procedure */ if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) { @@ -394,8 +639,9 @@ ip_invoke_real(argc, argv, obj) /* object interface */ ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1); for (i = 0; i < argc; ++i) { - char *s = STR2CSTR(argv[i]); - ov[i] = Tcl_NewStringObj(s, strlen(s)); + v = argv[i]; + s = STR2CSTR(v); + ov[i] = Tcl_NewStringObj(s, RSTRING(v)->len); Tcl_IncrRefCount(ov[i]); } ov[argc] = (Tcl_Obj *)NULL; @@ -406,8 +652,8 @@ ip_invoke_real(argc, argv, obj) /* string interface */ av = (char **)ALLOCA_N(char *, argc+1); for (i = 0; i < argc; ++i) { - char *s = STR2CSTR(argv[i]); - + v = argv[i]; + s = STR2CSTR(v); av[i] = ALLOCA_N(char, strlen(s)+1); strcpy(av[i], s); } @@ -435,8 +681,9 @@ ip_invoke_real(argc, argv, obj) else #endif { - ptr->return_value = (*info.proc)(info.clientData, - ptr->ip, argc, av); + TRAP_BEG; + ptr->return_value = (*info.proc)(info.clientData, ptr->ip, argc, av); + TRAP_END; } if (ptr->return_value == TCL_ERROR) { @@ -447,48 +694,104 @@ ip_invoke_real(argc, argv, obj) return rb_str_new2(ptr->ip->result); } +VALUE +ivq_safelevel_handler(arg, ivq) + VALUE arg; + VALUE ivq; +{ + struct invoke_queue *q; + + Data_Get_Struct(ivq, struct invoke_queue, q); + DUMP2("(safe-level handler) $SAFE = %d", q->safe_level); + rb_set_safe_level(q->safe_level); + return ip_invoke_real(q->argc, q->argv, q->obj); +} + +int invoke_queue_handler _((Tcl_Event *, int)); +int +invoke_queue_handler(evPtr, flags) + Tcl_Event *evPtr; + int flags; +{ + struct invoke_queue *tmp, *q = (struct invoke_queue *)evPtr; + + DUMP1("do_invoke_queue_handler"); + DUMP2("invoke queue_thread : %lx", rb_thread_current()); + DUMP2("added by thread : %lx", q->thread); + + if (q->done) { + /* processed by another event-loop */ + return 0; + } + + /* process it */ + q->done = 1; + + /* check safe-level */ + if (rb_safe_level() != q->safe_level) { + *(q->result) = rb_funcall(rb_proc_new(ivq_safelevel_handler, + Data_Wrap_Struct(rb_cData,0,0,q)), + rb_intern("call"), 0); + } else { + *(q->result) = ip_invoke_real(q->argc, q->argv, q->obj); + } + + /* back to caller */ + rb_thread_run(q->thread); + + /* end of handler : remove it */ + return 1; +} + static VALUE ip_invoke(argc, argv, obj) int argc; VALUE *argv; VALUE obj; { - struct invoke_queue *tmp, *p; - VALUE result = rb_thread_current(); + struct invoke_queue *tmp; + VALUE current = rb_thread_current(); + VALUE result; + VALUE *alloc_argv, *alloc_result; + Tcl_QueuePosition position; - if (result == main_thread) { - return ip_invoke_real(argc, argv, obj); + if (eventloop_thread == 0 || current == eventloop_thread) { + DUMP2("invoke from current eventloop %lx", current); + return ip_invoke_real(argc, argv, obj); } - tmp = ALLOC(struct invoke_queue); + + DUMP2("invoke from thread %lx (NOT current eventloop)", current); + + /* allocate memory (protected from Tcl_ServiceEvent) */ + alloc_argv = ALLOC_N(VALUE,argc); + MEMCPY(alloc_argv, argv, VALUE, argc); + alloc_result = ALLOC(VALUE); + + /* allocate memory (freed by Tcl_ServiceEvent */ + tmp = (struct invoke_queue *)Tcl_Alloc(sizeof(struct invoke_queue)); + + /* construct event data */ + tmp->done = 0; tmp->obj = obj; tmp->argc = argc; - tmp->argv = ALLOC_N(VALUE, argc); - MEMCPY(tmp->argv, argv, VALUE, argc); - tmp->thread = result; - tmp->done = 0; + tmp->argv = alloc_argv; + tmp->result = alloc_result; + tmp->thread = current; + tmp->safe_level = rb_safe_level(); + tmp->ev.proc = invoke_queue_handler; + position = TCL_QUEUE_TAIL; - tmp->next = iqueue; - iqueue = tmp; + /* add the handler to Tcl event queue */ + Tcl_QueueEvent(&tmp->ev, position); + /* wait for the handler to be processed */ rb_thread_stop(); - result = tmp->result; - if (iqueue == tmp) { - iqueue = tmp->next; - free(tmp->argv); - free(tmp); - return result; - } - p = iqueue; - while (p->next) { - if (p->next == tmp) { - p->next = tmp->next; - free(tmp->argv); - free(tmp); - break; - } - p = p->next; - } + /* get result & free allocated memory */ + result = *alloc_result; + free(alloc_argv); + free(alloc_result); + return result; } @@ -500,7 +803,7 @@ ip_retval(self) struct tcltkip *ptr; /* tcltkip data struct */ /* get the data strcut */ - Data_Get_Struct(self, struct tcltkip, ptr); + ptr = get_ip(self); return (INT2FIX(ptr->return_value)); } @@ -521,6 +824,8 @@ Init_tcltklib() VALUE lib = rb_define_module("TclTkLib"); VALUE ip = rb_define_class("TclTkIp", rb_cObject); + VALUE ev_flag = rb_define_module_under(lib, "EventFlag"); + #if defined USE_TCL_STUBS && defined USE_TK_STUBS extern int ruby_tcltk_stubs(); int ret = ruby_tcltk_stubs(); @@ -528,10 +833,26 @@ Init_tcltklib() rb_raise(rb_eLoadError, "tcltklib: tcltk_stubs init error(%d)", ret); #endif + rb_define_const(ev_flag, "WINDOW", INT2FIX(TCL_WINDOW_EVENTS)); + rb_define_const(ev_flag, "FILE", INT2FIX(TCL_FILE_EVENTS)); + rb_define_const(ev_flag, "TIMER", INT2FIX(TCL_TIMER_EVENTS)); + rb_define_const(ev_flag, "IDLE", INT2FIX(TCL_IDLE_EVENTS)); + rb_define_const(ev_flag, "ALL", INT2FIX(TCL_ALL_EVENTS)); + rb_define_const(ev_flag, "DONT_WAIT", INT2FIX(TCL_DONT_WAIT)); + eTkCallbackBreak = rb_define_class("TkCallbackBreak", rb_eStandardError); eTkCallbackContinue = rb_define_class("TkCallbackContinue",rb_eStandardError); - rb_define_module_function(lib, "mainloop", lib_mainloop, 0); + rb_define_module_function(lib, "mainloop", lib_mainloop, -1); + rb_define_module_function(lib, "mainloop_watchdog", + lib_mainloop_watchdog, -1); + rb_define_module_function(lib, "do_one_event", lib_do_one_event, -1); + rb_define_module_function(lib, "set_eventloop_tick",set_eventloop_tick,1); + rb_define_module_function(lib, "get_eventloop_tick",get_eventloop_tick,0); + rb_define_module_function(lib, "set_eventloop_weight", + set_eventloop_weight, 2); + rb_define_module_function(lib, "get_eventloop_weight", + get_eventloop_weight, 0); rb_define_singleton_method(ip, "new", ip_new, 0); rb_define_method(ip, "_eval", ip_eval, 1); @@ -539,10 +860,19 @@ Init_tcltklib() rb_define_method(ip, "_fromUTF8",ip_fromUTF8,2); rb_define_method(ip, "_invoke", ip_invoke, -1); rb_define_method(ip, "_return_value", ip_retval, 0); - rb_define_method(ip, "mainloop", lib_mainloop, 0); + rb_define_method(ip, "mainloop", lib_mainloop, -1); + rb_define_method(ip, "mainloop_watchdog", lib_mainloop_watchdog, -1); + rb_define_method(ip, "do_one_event", lib_do_one_event, -1); + rb_define_method(ip, "set_eventloop_tick", set_eventloop_tick, 1); + rb_define_method(ip, "get_eventloop_tick", get_eventloop_tick, 0); + rb_define_method(ip, "set_eventloop_weight", set_eventloop_weight, 2); + rb_define_method(ip, "get_eventloop_weight", get_eventloop_weight, 0); rb_define_method(ip, "restart", lib_restart, 0); main_thread = rb_thread_current(); + eventloop_thread = 0; + watchdog_thread = 0; + #ifdef __MACOS__ _macinit(); #endif @@ -2198,6 +2198,7 @@ rb_find_file_ext(filep, ext) VALUE str = RARRAY(rb_load_path)->ptr[i]; Check_SafeStr(str); + if (RSTRING(str)->len == 0) return 0; path = RSTRING(str)->ptr; for (j=0; ext[j]; j++) { fname = rb_str_dup(*filep); @@ -2262,15 +2263,23 @@ rb_find_file(path) } } tmp = rb_ary_join(tmp, rb_str_new2(PATH_SEP)); - lpath = STR2CSTR(tmp); - if (rb_safe_level() >= 2 && !rb_path_check(lpath)) { - rb_raise(rb_eSecurityError, "loading from unsafe path %s", lpath); + if (RSTRING(tmp)->len == 0) { + lpath = 0; + } + else { + lpath = STR2CSTR(tmp); + if (rb_safe_level() >= 2 && !rb_path_check(lpath)) { + rb_raise(rb_eSecurityError, "loading from unsafe path %s", lpath); + } } } else { lpath = 0; } + if (!lpath) { + return 0; /* no path, no load */ + } f = dln_find_file(f, lpath); if (file_load_ok(f)) { return rb_str_new2(f); diff --git a/lib/uri/mailto.rb b/lib/uri/mailto.rb index bf6b954903..0a378b5c51 100644 --- a/lib/uri/mailto.rb +++ b/lib/uri/mailto.rb @@ -46,17 +46,19 @@ module URI # hname = *urlc # hvalue = *urlc # header = hname "=" hvalue - HEADER_REGEXP = "(?:[^?=&]*=[^?=&]*)".freeze + header_pattern = "(?:[^?=&]*=[^?=&]*)" + HEADER_REGEXP = /#{header_pattern}/ # headers = "?" header *( "&" header ) # to = #mailbox # mailtoURL = "mailto:" [ to ] [ headers ] - MAILBOX_REGEXP = "(?:[^(),%?=&]|#{PATTERN::ESCAPED})".freeze + mailbox_pattern = "(?:[^(),%?=&]|#{PATTERN::ESCAPED})" + MAILBOX_REGEXP = /#{mailbox_pattern}/ MAILTO_REGEXP = Regexp.new(" \\A - (#{MAILBOX_REGEXP}*?) (?# 1: to) + (#{mailbox_pattern}*?) (?# 1: to) (?: \\? - (#{HEADER_REGEXP}(?:\\&#{HEADER_REGEXP})*) (?# 2: headers) + (#{header_pattern}(?:\\&#{header_pattern})*) (?# 2: headers) )? \\z ", Regexp::EXTENDED, 'N').freeze @@ -114,8 +114,8 @@ rb_obj_dup(obj) VALUE dup; dup = rb_funcall(obj, clone, 0, 0); - if (TYPE(dup) != TYPE(obj)) { - rb_raise(rb_eTypeError, "dupulicated object must be same type"); + if (TYPE(dup) != TYPE(obj) || rb_obj_class(dup) != rb_obj_class(obj)) { + rb_raise(rb_eTypeError, "dupulicated object must be same class"); } if (!SPECIAL_CONST_P(dup)) { OBJSETUP(dup, rb_obj_class(obj), BUILTIN_TYPE(obj)); @@ -1362,8 +1362,7 @@ primary : literal } if ($8) $5 = NEW_ENSURE($5, $8); - /* NOEX_PRIVATE for toplevel */ - $$ = NEW_DEFN($2, $4, $5, class_nest?NOEX_PUBLIC:NOEX_PRIVATE); + $$ = NEW_DEFN($2, $4, $5, NOEX_PRIVATE); if (is_attrset_id($2)) $$->nd_noex = NOEX_PUBLIC; fixpos($$, $4); local_pop(); @@ -3154,22 +3153,22 @@ yylex() } if (ISSPACE(c)){ if (lex_state != EXPR_ARG){ - int c = 0; + int c2 = 0; switch (c) { case ' ': - c = 's'; + c2 = 's'; break; case '\n': - c = 'n'; + c2 = 'n'; break; case '\t': - c = 't'; + c2 = 't'; break; case '\v': - c = 'v'; + c2 = 'v'; break; } - if (c) { + if (c2) { rb_warn("invalid character syntax; use ?\\%c", c); } } @@ -4066,13 +4065,13 @@ str_extend(list, term, paren) case '{': if (c == '{') brace = '}'; - brace_nest = 0; + brace_nest = 1; do { loop_again: c = nextc(); switch (c) { case -1: - if (brace_nest > 0) { + if (brace_nest > 1) { yyerror("bad substitution in string"); newtok(); return list; @@ -4080,8 +4079,8 @@ str_extend(list, term, paren) return (NODE*)-1; case '}': if (c == brace) { - if (brace_nest == 0) break; brace_nest--; + if (brace_nest == 0) break; } tokadd(c); goto loop_again; @@ -4099,6 +4098,22 @@ str_extend(list, term, paren) case '{': if (brace != -1) brace_nest++; default: + /* within brace */ + if (brace_nest > 0) { + if (ismbchar(c)) { + int i, len = mbclen(c)-1; + + for (i = 0; i < len; i++) { + tokadd(c); + c = nextc(); + } + } + else { + tokadd(c); + } + break; + } + /* out of brace */ if (c == paren) paren_nest++; else if (c == term && (!paren || paren_nest-- == 0)) { pushback(c); @@ -4109,14 +4124,7 @@ str_extend(list, term, paren) newtok(); return list; } - else if (ismbchar(c)) { - int i, len = mbclen(c)-1; - - for (i = 0; i < len; i++) { - tokadd(c); - c = nextc(); - } - } + break; case '\n': tokadd(c); break; @@ -90,7 +90,7 @@ static VALUE range_eq(range, obj) VALUE range, obj; { - if (!rb_obj_is_kind_of(obj, rb_cRange)) return Qfalse; + if (!rb_obj_is_kind_of(obj, rb_obj_class(range))) return Qfalse; if (!rb_equal(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg))) return Qfalse; @@ -140,7 +140,7 @@ range_eql(range, obj) VALUE range, obj; { if (range == obj) return Qtrue; - if (!rb_obj_is_kind_of(obj, rb_cRange)) return Qfalse; + if (!rb_obj_is_kind_of(obj, rb_obj_class(range))) return Qfalse; if (!rb_eql(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg))) return Qfalse; @@ -2354,7 +2354,7 @@ rb_str_each_line(argc, argv, str) if (*++p != '\n') continue; while (*p == '\n') p++; } - if (p[-1] == newline && + if (RSTRING(str)->ptr < p && p[-1] == newline && (rslen <= 1 || rb_memcmp(RSTRING(rs)->ptr, p-rslen, rslen) == 0)) { line = rb_str_new(s, p - s); diff --git a/variable.c b/variable.c index 29dc1edb8a..95c03cd3fc 100644 --- a/variable.c +++ b/variable.c @@ -221,19 +221,40 @@ VALUE rb_path2class(path) const char *path; { - VALUE c; + const char *pbeg, *p; + ID id; + VALUE c = rb_cObject; if (path[0] == '#') { rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path); } - c = rb_eval_string(path); - switch (TYPE(c)) { - case T_MODULE: - case T_CLASS: - break; - default: - rb_raise(rb_eTypeError, "class path %s does not point class", path); + pbeg = p = path; + while (*p) { + VALUE str; + + while (*p && *p != ':') p++; + str = rb_str_new(pbeg, p-pbeg); + id = rb_intern(RSTRING(str)->ptr); + if (p[0] == ':') { + if (p[1] != ':') goto undefined_class; + p += 2; + pbeg = p; + } + if (!rb_const_defined(c, id)) { + undefined_class: + rb_raise(rb_eArgError, "undefined class/module %s", rb_id2name(id)); + rb_raise(rb_eArgError, "undefined class/module %s", path); + } + c = rb_const_get_at(c, id); + switch (TYPE(c)) { + case T_MODULE: + case T_CLASS: + break; + default: + rb_raise(rb_eTypeError, "%s does not refer class/module %d", path, TYPE(c)); + } } + return c; } @@ -1,4 +1,4 @@ #define RUBY_VERSION "1.6.7" -#define RUBY_RELEASE_DATE "2002-09-22" +#define RUBY_RELEASE_DATE "2002-09-25" #define RUBY_VERSION_CODE 167 -#define RUBY_RELEASE_CODE 20020922 +#define RUBY_RELEASE_CODE 20020925 |