diff --git a/ChangeLog b/ChangeLog index c95b406342..b1b2f8fa47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,57 @@ +Thu Jun 11 18:19:18 1998 Yukihiro Matsumoto + + * experimental release 1.1b9_25. + + * eval.c (dvar_add_compiling): register dyna_var at compile time. + + * regex.c (re_compile_pattern): RE_DUP_MAX iteration is too big. + +Wed Jun 10 15:12:04 1998 Yukihiro Matsumoto + + * io.c (io_eof): do not block other threads. + + * signal.c (trap): reserve SIGALRM for thread. + + * eval.c (thread_create): use ITIMER_REAL also to avoid system + call blocking. + + * io.c (f_syscall): add TRAP_BEG, TRAP_END around system calls. + + * io.c (io_ctl): add TRAP_BEG, TRAP_END around system calls. + + * enum.c (enum_collect): did not collect false values. + + * array.c (ary_new2): forgot to initialize capa field. + +Tue Jun 9 18:36:15 1998 WATANABE Hirofumi + + * string.c (str_split_method): split dumped core for "\xff". + +Tue Jun 9 16:22:12 1998 Yukihiro Matsumoto + + * experimental release 1.1b9_24. + +Tue Jun 9 16:04:07 1998 WATANABE Hirofumi + + * ext/kconv/kconv.c (kconv_guess): more precise decision for EUC, + using jless algorithm (3 sequential EUC hiragana characters). + +Tue Jun 9 15:12:44 1998 Yukihiro Matsumoto + + * ext/kconv/kconv.c (kconv_guess): wrong guess for EUC as SJIS in + some cases (0xe0 - 0xef). + + * gc.c (xmalloc): insert size check for big (negative in signed) + allocation size. + Tue Jun 9 02:54:51 1998 Yukihiro Matsumoto * lib/parsedate.rb: wday moved to the last in the return values. +Mon Jun 8 10:40:16 1998 Yukihiro Matsumoto + + * string.c (str_split_method): split dumped core for "\0". + Sat Jun 6 22:50:52 1998 Yukihiro Matsumoto * regex.c (calculate_must_string): wrong condition for diff --git a/README.EXT b/README.EXT index 7d2d6456c4..fb041bca9b 100644 --- a/README.EXT +++ b/README.EXT @@ -191,8 +191,8 @@ Ruby Creates an n-elements array from C array. - ary_push(VALUE ary) - ary_pop(VALUE ary, VALUE val) + ary_push(VALUE ary, VALUE val) + ary_pop(VALUE ary) ary_shift(VALUE ary) ary_unshift(VALUE ary, VALUE val) ary_entry(VALUE ary, int idx) diff --git a/README.EXT.jp b/README.EXT.jp index 2929f1b2d1..09983b5ee0 100644 --- a/README.EXT.jp +++ b/README.EXT.jp @@ -203,8 +203,8 @@ Ruby 配列で与えたn要素の配列を生成する. - ary_push(VALUE ary) - ary_pop(VALUE ary, VALUE val) + ary_push(VALUE ary, VALUE val) + ary_pop(VALUE ary) ary_shift(VALUE ary) ary_unshift(VALUE ary, VALUE val) ary_entry(VALUE ary, int idx) diff --git a/array.c b/array.c index a278e3395d..b48174793b 100644 --- a/array.c +++ b/array.c @@ -63,14 +63,17 @@ ary_new2(len) NEWOBJ(ary, struct RArray); OBJSETUP(ary, cArray, T_ARRAY); + if (len < 0) { + ArgError("negative array size (or size too big)"); + } + if (len > 0 && len*sizeof(VALUE) <= 0) { + ArgError("array size too big"); + } ary->len = 0; ary->capa = len; - if (len == 0) - ary->ptr = 0; - else { - ary->ptr = ALLOC_N(VALUE, len); - memclear(ary->ptr, len); - } + ary->ptr = 0; + ary->ptr = ALLOC_N(VALUE, len); + memclear(ary->ptr, len); return (VALUE)ary; } @@ -162,7 +165,19 @@ ary_s_new(argc, argv, klass) rb_scan_args(argc, argv, "01", &size); ary->len = 0; - ary->capa = NIL_P(size)?ARY_DEFAULT_SIZE:NUM2INT(size); + ary->ptr = 0; + if (NIL_P(size)) { + ary->capa = ARY_DEFAULT_SIZE; + } + else { + ary->capa = NUM2INT(size); + if (ary->capa < 0) { + ArgError("negative array size"); + } + if (ary->capa*sizeof(VALUE) < 0) { + ArgError("array size too big"); + } + } ary->ptr = ALLOC_N(VALUE, ary->capa); memclear(ary->ptr, ary->capa); obj_call_init((VALUE)ary); @@ -986,13 +1001,14 @@ ary_times(ary, times) return ary_join(ary, times); } - len = NUM2INT(times) * RARRAY(ary)->len; - ary2 = ary_new2(len); - RARRAY(ary2)->len = len; - + len = NUM2INT(times); if (len < 0) { ArgError("negative argument"); } + len *= RARRAY(ary)->len; + + ary2 = ary_new2(len); + RARRAY(ary2)->len = len; for (i=0; ilen) { MEMCPY(RARRAY(ary2)->ptr+i, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len); diff --git a/enum.c b/enum.c index 655cebeada..1e0ec9c30d 100644 --- a/enum.c +++ b/enum.c @@ -125,12 +125,7 @@ static VALUE collect_i(i, tmp) VALUE i, tmp; { - VALUE retval; - - retval = rb_yield(i); - if (RTEST(retval)) { - ary_push(tmp, retval); - } + ary_push(tmp, rb_yield(i)); return Qnil; } diff --git a/eval.c b/eval.c index 6f287b9b81..aa83d7533e 100644 --- a/eval.c +++ b/eval.c @@ -450,6 +450,17 @@ new_dvar(id, value) vars->id = id; vars->val = value; vars->next = the_dyna_vars; + + return vars; +} + +static struct RVarmap* +push_dvar(id, value) + ID id; + VALUE value; +{ + struct RVarmap* vars = new_dvar(id, value); + if (the_dyna_vars) { vars->next = the_dyna_vars->next; the_dyna_vars->next = vars; @@ -491,21 +502,42 @@ dyna_var_ref(id) return Qnil; } -VALUE -dyna_var_asgn(id, value) +static void +dvar_add_compiling(id) ID id; - VALUE value; { struct RVarmap *vars = the_dyna_vars; while (vars) { + if (vars->id == 0) break; if (vars->id == id) { - vars->val = value; - return value; + return; } vars = vars->next; } - new_dvar(id, value); + the_dyna_vars = new_dvar(id, 0); +} + +VALUE +dyna_var_asgn(id, value) + ID id; + VALUE value; +{ + if (id == 0) { + dvar_add_compiling((ID)value); + } + else { + struct RVarmap *vars = the_dyna_vars; + + while (vars) { + if (vars->id == id) { + vars->val = value; + return value; + } + vars = vars->next; + } + push_dvar(id, value); + } return value; } @@ -6159,8 +6191,10 @@ thread_create(fn, arg) #ifdef POSIX_SIGNAL posix_signal(SIGVTALRM, catch_timer); + posix_signal(SIGALRM, catch_timer); #else signal(SIGVTALRM, catch_timer); + posix_signal(SIGALRM, catch_timer); #endif tval.it_interval.tv_sec = 0; @@ -6168,6 +6202,11 @@ thread_create(fn, arg) tval.it_value = tval.it_interval; setitimer(ITIMER_VIRTUAL, &tval, NULL); + tval.it_interval.tv_sec = 2; /* unblock system calls */ + tval.it_interval.tv_usec = 0; + tval.it_value = tval.it_interval; + setitimer(ITIMER_REAL, &tval, NULL); + init = 1; } #endif diff --git a/ext/Setup b/ext/Setup index 9e3a2474c3..2eb11c7ade 100644 --- a/ext/Setup +++ b/ext/Setup @@ -9,5 +9,5 @@ #md5 #socket #tkutil -#tcltklib +tcltklib #gtk diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index 847e34f87e..e4823edb85 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -413,6 +413,7 @@ def extmake(target) end end if $static + $extlibs = "" unless $extlibs $extlibs += " " + $LDFLAGS if $LDFLAGS $extlibs += " " + $local_libs if $local_libs $extlibs += " " + $libs if $libs @@ -481,6 +482,7 @@ if $extlist.size > 0 \tInit_%s();\n\ \trb_provide(\"%s.o\");\n\ ", t, t) + $extobjs = "" unless $extobjs $extobjs += "ext/" $extobjs += f $extobjs += " " diff --git a/ext/kconv/kconv.c b/ext/kconv/kconv.c index 5762e3531f..fb229c6ef6 100644 --- a/ext/kconv/kconv.c +++ b/ext/kconv/kconv.c @@ -1893,8 +1893,22 @@ kconv_guess(obj, src) { unsigned char *p = RSTRING(src)->ptr; unsigned char *pend = p + RSTRING(src)->len; - -#define INCR {p++;if (p==pend) return INT2FIX(_UNKNOWN);} + int sequence_counter = 0; + +#define INCR do {\ + p++;\ + if (p==pend) return INT2FIX(_UNKNOWN);\ + sequence_counter++;\ + if (sequence_counter % 2 == 1 && *p != 0xa4)\ + sequence_counter = 0;\ + if (6 <= sequence_counter) {\ + sequence_counter = 0;\ + return INT2FIX(_EUC);\ + }\ +} while (0) + + if (*p == 0xa4) + sequence_counter = 1; while (p= 0x40) { + while (p < pend && *p >= 0x40) { if (*p >= 0x81) { - if (0x8d <= *p || (0x8f <= *p && *p <= 0x9f)) { + if (*p <= 0x8d || (0x8f <= *p && *p <= 0x9f)) { return INT2FIX(_SJIS); } else if (0xfd <= *p && *p <= 0xfe) { return INT2FIX(_EUC); } } + INCR; } } - if (*p <= 0x9f) { + else if (*p <= 0x9f) { return INT2FIX(_SJIS); } } - if (0xf0 <= *p && *p <= 0xfe) { + else if (0xf0 <= *p && *p <= 0xfe) { return INT2FIX(_EUC); } - if (0xe0 <= *p && *p <= 0xef) { + else if (0xe0 <= *p && *p <= 0xef) { INCR; if ((0x40 <= *p && *p <= 0x7e) || (0x80 <= *p && *p <= 0xa0)) { @@ -1948,7 +1966,7 @@ kconv_guess(obj, src) return INT2FIX(_EUC); } } - p++; + INCR; } return INT2FIX(_UNKNOWN); } diff --git a/gc.c b/gc.c index 5347585a00..36d08e99c1 100644 --- a/gc.c +++ b/gc.c @@ -47,10 +47,13 @@ static unsigned long malloc_memories = 0; void * xmalloc(size) - unsigned long size; + int size; { void *mem; + if (size < 0) { + ArgError("negative allocation size (or too big)"); + } if (size == 0) size = 1; #if 0 malloc_memories += size; @@ -71,7 +74,7 @@ xmalloc(size) void * xcalloc(n, size) - unsigned long n, size; + int n, size; { void *mem; @@ -84,10 +87,13 @@ xcalloc(n, size) void * xrealloc(ptr, size) void *ptr; - unsigned long size; + int size; { void *mem; + if (size < 0) { + ArgError("negative re-allocation size"); + } if (!ptr) return xmalloc(size); mem = realloc(ptr, size); if (!mem) { diff --git a/io.c b/io.c index 8f8a1e9442..44df7be792 100644 --- a/io.c +++ b/io.c @@ -289,8 +289,11 @@ io_eof(io) io_readable(fptr); if (READ_DATA_PENDING(fptr->f)) return FALSE; +#if 0 if (feof(fptr->f)) return TRUE; - + return FALSE; +#else + READ_CHECK(fptr->f); TRAP_BEG; ch = getc(fptr->f); TRAP_END; @@ -300,6 +303,7 @@ io_eof(io) return FALSE; } return TRUE; +#endif } static VALUE @@ -389,8 +393,10 @@ read_all(port) TRAP_BEG; n = fread(RSTRING(str)->ptr+bytes, 1, siz-bytes, fptr->f); TRAP_END; - if (n == 0) break; - if (n < 0) rb_sys_fail(fptr->path); + if (n <= 0) { + if (ferror(fptr->f)) rb_sys_fail(fptr->path); + return Qnil; + } bytes += n; if (bytes < siz) break; siz += BUFSIZ; @@ -425,11 +431,10 @@ io_read(argc, argv, io) TRAP_BEG; n = fread(RSTRING(str)->ptr, 1, len, fptr->f); TRAP_END; - if (n == 0) return Qnil; - if (n < 0) { - rb_sys_fail(fptr->path); + if (n <= 0) { + if (ferror(fptr->f)) rb_sys_fail(fptr->path); + return Qnil; } - RSTRING(str)->len = n; RSTRING(str)->ptr[n] = '\0'; @@ -521,7 +526,13 @@ io_gets_method(argc, argv, io) TRAP_BEG; cnt = fread(buf, 1, sizeof(buf), f); TRAP_END; - c = cnt ? 0 : EOF; + if (cnt == 0) { + if (ferror(f)) rb_sys_fail(fptr->path); + c = EOF; + } + else { + c = 0; + } } if (c == EOF && !append && cnt == 0) { @@ -2164,6 +2175,7 @@ io_ctl(io, req, arg, io_p) narg = (long)RSTRING(arg)->ptr; } fd = fileno(fptr->f); + TRAP_BEG; #ifdef HAVE_FCNTL # ifdef USE_CWGUSI retval = io_p?ioctl(fd, cmd, (void*) narg):fcntl(fd, cmd, narg); @@ -2171,6 +2183,7 @@ io_ctl(io, req, arg, io_p) retval = io_p?ioctl(fd, cmd, narg):fcntl(fd, cmd, narg); # endif #else + TRAP_END; if (!io_p) { rb_notimplement(); } @@ -2249,6 +2262,7 @@ f_syscall(argc, argv) } i++; } + TRAP_BEG; switch (argc) { case 1: retval = syscall(arg[0]); @@ -2302,6 +2316,7 @@ f_syscall(argc, argv) break; #endif /* atarist */ } + TRAP_END; if (retval == -1) rb_sys_fail(0); return INT2FIX(0); #else diff --git a/lib/tk.rb b/lib/tk.rb index 3891428ff7..62b275b432 100644 --- a/lib/tk.rb +++ b/lib/tk.rb @@ -26,6 +26,9 @@ def error_at private :error_at def tk_tcl2ruby(val) + if val =~ /^rb_out (c\d+)/ + return Tk_CMDTBL[$1] + end if val.include? ?\s return val.split.collect{|v| tk_tcl2ruby(v)} end @@ -34,8 +37,6 @@ def tk_tcl2ruby(val) val.to_i when /^\./ Tk_WINDOWS[val] - when /^rb_out (c\d+)/ - Tk_CMDTBL[$1] when / / val.split.collect{|elt| tk_tcl2ruby(elt) @@ -134,6 +135,7 @@ def _curr_cmd_id def _next_cmd_id id = _curr_cmd_id Tk_IDs[0] += 1 + id end def install_cmd(cmd) return '' if cmd == '' @@ -237,6 +239,10 @@ def pack(*args) TkPack.configure *args end + def grid(*args) + TkGrid.configure *args + end + def after(ms, cmd=Proc.new) myid = _curr_cmd_id tk_call 'after', ms, @@ -786,6 +792,70 @@ def propagate(master, bool=None) module_function :configure, :forget, :propagate end +module TkGrid + include Tk + extend Tk + + def bbox(*args) + list(tk_call('grid', 'bbox', *args)) + end + + def configure(widget, *args) + if args[-1].kind_of?(Hash) + keys = args.pop + end + wins = [widget.path] + for i in args + wins.push i.epath + end + tk_call "grid", 'configure', *(wins+hash_kv(keys)) + end + + def columnconfigure(master, index, *args) + tk_call "grid", 'columnconfigure', master, index, *hash_kv(keys) + end + + def rowconfigure(master, index, *args) + tk_call "grid", 'rowconfigure', master, index, *hash_kv(keys) + end + + def add(widget, *args) + configure(widget, *args) + end + + def forget(*args) + tk_call 'grid', 'forget', *args + end + + def info(slave) + list(tk_call('grid', 'info', slave)) + end + + def location(master, x, y) + list(tk_call('grid', 'location', master, x, y)) + end + + def propagate(master, bool=None) + bool(tk_call('grid', 'propagate', master.epath, bool)) + end + + def remove(*args) + tk_call 'grid', 'remove', *args + end + + def size(master) + tk_call 'grid', 'size', master + end + + def slaves(*args) + list(tk_call('grid', 'slaves', *hash_kv(args))) + end + + module_function :bbox, :forget, :propagate, :info + module_function :remove, :size, :slaves, :location + module_function :configure, :columnconfigure, :rowconfigure +end + module TkOption include Tk extend Tk @@ -833,10 +903,18 @@ def method_missing(id, *args) end end + def [](id) + cget id + end + def []=(id, val) configure id, val end + def cget(slot) + tk_tcl2ruby tk_call path, 'cget', "-#{slot}" + end + def configure(slot, value) if value == FALSE value = "0" @@ -891,6 +969,16 @@ def unpack(keys = nil) self end + def grid(keys = nil) + tk_call 'grid', epath, *hash_kv(keys) + self + end + + def ungrid(keys = nil) + tk_call 'grid', 'forget', epath + self + end + def place(keys = nil) tk_call 'place', epath, *hash_kv(keys) self @@ -1131,6 +1219,10 @@ def set(first, last) end class TkTextWin", id + def bind(seq, cmd=Proc.new, args=nil) + id = install_bind(cmd, args) + tk_call @t, 'tag', 'bind', @id, "<#{seq}>", id @t._addcmd cmd end diff --git a/parse.y b/parse.y index 1b4bbf2dc9..a070f4470a 100644 --- a/parse.y +++ b/parse.y @@ -1645,7 +1645,8 @@ nextc() sourceline = heredoc_end+1; heredoc_end = 0; } - while (RSTRING(v)->ptr[RSTRING(v)->len-1] == '\n' && + while (RSTRING(v)->len >= 2 && + RSTRING(v)->ptr[RSTRING(v)->len-1] == '\n' && RSTRING(v)->ptr[RSTRING(v)->len-2] == '\\') { VALUE v2 = io_gets(lex_input); @@ -3423,7 +3424,7 @@ assignable(id, val) } else{ if (!dyna_var_defined(id)) { - dyna_var_asgn(id, 0); + dyna_var_asgn(0, id); } lhs = NEW_DASGN(id, val); } diff --git a/regex.c b/regex.c index 16bdd0a671..a9ac531e24 100644 --- a/regex.c +++ b/regex.c @@ -1670,7 +1670,6 @@ re_compile_pattern(pattern, size, bufp) GET_UNSIGNED_NUMBER(lower_bound); if (c == ',') { GET_UNSIGNED_NUMBER(upper_bound); - if (upper_bound < 0) upper_bound = RE_DUP_MAX; } else /* Interval such as `{1}' => match exactly once. */ @@ -1679,8 +1678,9 @@ re_compile_pattern(pattern, size, bufp) if (lower_bound < 0 || c != '}') goto unfetch_interval; - if (lower_bound > RE_DUP_MAX || upper_bound > RE_DUP_MAX) + if (lower_bound >= RE_DUP_MAX || upper_bound >= RE_DUP_MAX) FREE_AND_RETURN(stackb, "too big quantifier in {,}"); + if (upper_bound < 0) upper_bound = RE_DUP_MAX; if (lower_bound > upper_bound) FREE_AND_RETURN(stackb, "can't do {n,m} with n > m"); diff --git a/ruby.h b/ruby.h index 55b56d9d9b..59c8528381 100644 --- a/ruby.h +++ b/ruby.h @@ -101,7 +101,7 @@ typedef unsigned int ID; # include # else /* assuming 32bit(2's compliment) long */ -# define LONG_MAX 2147483647 +# define LONG_MAX 2147483647 # endif # endif # ifndef LONG_MIN @@ -402,9 +402,9 @@ int rb_special_const_p _((VALUE)); int rb_test_false_or_nil _((VALUE)); #endif -void *xmalloc _((unsigned long)); -void *xcalloc _((unsigned long,unsigned long)); -void *xrealloc _((void*,unsigned long)); +void *xmalloc _((int)); +void *xcalloc _((int,int)); +void *xrealloc _((void*,int)); #define ALLOC_N(type,n) (type*)xmalloc(sizeof(type)*(n)) #define ALLOC(type) (type*)xmalloc(sizeof(type)) #define REALLOC_N(var,type,n) (var)=(type*)xrealloc((char*)(var),sizeof(type)*(n)) diff --git a/signal.c b/signal.c index 4755f590f0..f34e78d588 100644 --- a/signal.c +++ b/signal.c @@ -448,6 +448,9 @@ trap(arg) if (sig == SIGVTALRM) { ArgError("SIGVTALRM reserved for Thread; cannot set handler"); } + if (sig == SIGALRM) { + ArgError("SIGALRM reserved for Thread; cannot set handler"); + } #endif if (func == SIG_DFL) { switch (sig) { diff --git a/string.c b/string.c index 5229236f3b..90787cdb40 100644 --- a/string.c +++ b/string.c @@ -2002,7 +2002,7 @@ str_split_method(argc, argv, str) extern VALUE FS; VALUE spat; VALUE limit; - char char_sep = 0; + int char_sep = -1; int beg, end, lim, i; VALUE result, tmp; @@ -2026,7 +2026,7 @@ str_split_method(argc, argv, str) case T_STRING: fs_set: if (STRLEN(spat) == 1) { - char_sep = RSTRING(spat)->ptr[0]; + char_sep = (unsigned char)RSTRING(spat)->ptr[0]; } else { spat = reg_regcomp(spat); @@ -2041,7 +2041,7 @@ str_split_method(argc, argv, str) result = ary_new(); beg = 0; - if (char_sep != 0) { + if (char_sep >= 0) { char *ptr = RSTRING(str)->ptr; int len = RSTRING(str)->len; char *eptr = ptr + len; @@ -2074,7 +2074,7 @@ str_split_method(argc, argv, str) } else { for (end = beg = 0; ptr