1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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.

* string.c (rb_str_each_line): p might be at the top of the
  string.

* variable.c (rb_path2class): should not use rb_eval_string().

* parse.y (str_extend): expression substitution can contain string
  terminator again.

* parse.y (yylex): the warning message "invalid
  character syntax" was never issued.

* file.c (rb_find_file): $LOAD_PATH must not be empty.

* file.c (rb_find_file_ext): ditto.

* 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.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_6@2888 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2002-09-25 07:07:43 +00:00
parent d65fac5daa
commit f33958990a
14 changed files with 546 additions and 129 deletions

View file

@ -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.

View file

@ -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);

View file

@ -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"

View file

@ -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

18
eval.c
View file

@ -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();
}

View file

@ -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();
/* 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;
}
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

15
file.c
View file

@ -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);

View file

@ -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

View file

@ -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));

46
parse.y
View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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