[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:219

From: ko1 atdot.net
Date: 9 Feb 2006 17:49:57 -0000
Subject: [yarv-diff:219] r377 - trunk

Author: matz
Date: 2006-02-10 02:49:56 +0900 (Fri, 10 Feb 2006)
New Revision: 377

Modified:
   trunk/defines.h
   trunk/dir.c
   trunk/error.c
   trunk/file.c
   trunk/gc.c
   trunk/io.c
   trunk/marshal.c
   trunk/process.c
   trunk/range.c
   trunk/ruby.h
   trunk/string.c
   trunk/struct.c
Log:
merge 1.9 modifies.


Modified: trunk/defines.h
===================================================================
--- trunk/defines.h	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/defines.h	2006-02-09 17:49:56 UTC (rev 377)
@@ -2,8 +2,8 @@
 
   defines.h -
 
-  $Author: nobu $
-  $Date: 2005/10/25 16:59:15 $
+  $Author: akr $
+  $Date: 2006/01/22 13:34:41 $
   created at: Wed May 18 00:21:44 JST 1994
 
 ************************************************/
@@ -48,11 +48,11 @@
 #define xrealloc2 ruby_xrealloc2
 #define xfree ruby_xfree
 
-void *xmalloc(long);
-void *xmalloc2(long,long);
-void *xcalloc(long,long);
-void *xrealloc(void*,long);
-void *xrealloc2(void*,long,long);
+void *xmalloc(size_t);
+void *xmalloc2(size_t,size_t);
+void *xcalloc(size_t,size_t);
+void *xrealloc(void*,size_t);
+void *xrealloc2(void*,size_t,size_t);
 void xfree(void*);
 
 #if SIZEOF_LONG_LONG > 0
@@ -230,9 +230,10 @@
 	;
 }
 #  define FLUSH_REGISTER_WINDOWS flush_register_windows()
-#elif defined(__ia64__)
-NOINLINE(void flush_register_windows(void));
-#  define FLUSH_REGISTER_WINDOWS flush_register_windows()
+#elif defined(__ia64)
+void *rb_ia64_bsp(void);
+void rb_ia64_flushrs(void);
+#  define FLUSH_REGISTER_WINDOWS rb_ia64_flushrs()
 #else
 #  define FLUSH_REGISTER_WINDOWS ((void)0)
 #endif

Modified: trunk/dir.c
===================================================================
--- trunk/dir.c	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/dir.c	2006-02-09 17:49:56 UTC (rev 377)
@@ -3,7 +3,7 @@
   dir.c -
 
   $Author: nobu $
-  $Date: 2005/09/16 13:46:03 $
+  $Date: 2005/12/14 14:40:14 $
   created at: Wed Jan  5 09:51:01 JST 1994
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -67,10 +67,23 @@
 #define lstat stat
 #endif
 
+#ifndef CASEFOLD_FILESYSTEM
+# if defined DOSISH || defined __VMS
+#   define CASEFOLD_FILESYSTEM 1
+# else
+#   define CASEFOLD_FILESYSTEM 0
+# endif
+#endif
+
 #define FNM_NOESCAPE	0x01
 #define FNM_PATHNAME	0x02
 #define FNM_DOTMATCH	0x04
 #define FNM_CASEFOLD	0x08
+#if CASEFOLD_FILESYSTEM
+#define FNM_SYSCASE	FNM_CASEFOLD
+#else
+#define FNM_SYSCASE	0
+#endif
 
 #define FNM_NOMATCH	1
 #define FNM_ERROR	2
@@ -121,7 +134,7 @@
     if (len2 == 0) return -len1;
 
 #ifdef _WIN32
-    if (nocase) {
+    if (nocase && rb_w32_iswinnt()) {
 	if (len1 > 1) {
 	    if (len1 >= sizeof(buf1)) {
 		rb_fatal("CompareImpl: too large len");
@@ -931,6 +944,7 @@
 has_magic(const char *s, int flags)
 {
     const int escape = !(flags & FNM_NOESCAPE);
+    const int nocase = flags & FNM_CASEFOLD;
 
     register const char *p = s;
     register char c;
@@ -946,6 +960,10 @@
 	    if (escape && !(c = *p++))
 		return 0;
 	    continue;
+
+	  default:
+	    if (!FNM_SYSCASE && ISALPHA(c) && nocase)
+		return 1;
 	}
 
 	p = Next(p-1);
@@ -1295,11 +1313,9 @@
     int status;
 
     start = root = path;
+    flags |= FNM_SYSCASE;
 #if defined DOSISH
-    flags |= FNM_CASEFOLD;
     root = rb_path_skip_prefix(root);
-#else
-    flags &= ~FNM_CASEFOLD;
 #endif
 
     if (root && *root == '/') root++;
@@ -1342,8 +1358,8 @@
     args.func = func;
     args.value = arg;
 
-    if (flags & FNM_CASEFOLD) {
-	rb_warn("Dir.glob() ignores File::FNM_CASEFOLD");
+    if (flags & FNM_SYSCASE) {
+	rb_warning("Dir.glob() ignores File::FNM_CASEFOLD");
     }
 
     return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
@@ -1822,4 +1838,5 @@
     rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
     rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
     rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
+    rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE));
 }

Modified: trunk/error.c
===================================================================
--- trunk/error.c	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/error.c	2006-02-09 17:49:56 UTC (rev 377)
@@ -967,7 +967,13 @@
     rb_eIndexError    = rb_define_class("IndexError", rb_eStandardError);
     rb_eKeyError      = rb_define_class("KeyError", rb_eIndexError);
     rb_eRangeError    = rb_define_class("RangeError", rb_eStandardError);
-    rb_eNameError     = rb_define_class("NameError", rb_eStandardError);
+
+    rb_eScriptError = rb_define_class("ScriptError", rb_eException);
+    rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
+    rb_eLoadError   = rb_define_class("LoadError", rb_eScriptError);
+    rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
+
+    rb_eNameError     = rb_define_class("NameError", rb_eScriptError);
     rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
     rb_define_method(rb_eNameError, "name", name_err_name, 0);
     rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
@@ -981,11 +987,6 @@
     rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
     rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
 
-    rb_eScriptError = rb_define_class("ScriptError", rb_eException);
-    rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
-    rb_eLoadError   = rb_define_class("LoadError", rb_eScriptError);
-    rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
-
     rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
     rb_eSecurityError = rb_define_class("SecurityError", rb_eStandardError);
     rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);

Modified: trunk/file.c
===================================================================
--- trunk/file.c	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/file.c	2006-02-09 17:49:56 UTC (rev 377)
@@ -2,8 +2,8 @@
 
   file.c -
 
-  $Author: eban $
-  $Date: 2005/10/12 02:26:14 $
+  $Author: ocean $
+  $Date: 2006/02/06 07:26:16 $
   created at: Mon Nov 15 12:24:34 JST 1993
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -53,10 +53,6 @@
 #include <pwd.h>
 #endif
 
-#ifndef HAVE_STRING_H
-char *strrchr(const char*,const char);
-#endif
-
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -68,6 +64,33 @@
 #define lstat stat
 #endif
 
+#ifdef __BEOS__ /* should not change ID if -1 */
+static int
+be_chown(const char *path, uid_t owner, gid_t group)
+{
+    if (owner == -1 || group == -1) {
+	struct stat st;
+	if (stat(path, &st) < 0) return -1;
+	if (owner == -1) owner = st.st_uid;
+	if (group == -1) group = st.st_gid;
+    }
+    return chown(path, owner, group);
+}
+#define chown be_chown
+static int
+be_fchown(int fd, uid_t owner, gid_t group)
+{
+    if (owner == -1 || group == -1) {
+	struct stat st;
+	if (fstat(fd, &st) < 0) return -1;
+	if (owner == -1) owner = st.st_uid;
+	if (group == -1) group = st.st_gid;
+    }
+    return fchown(fd, owner, group);
+}
+#define fchown be_fchown
+#endif /* __BEOS__ */
+
 VALUE rb_cFile;
 VALUE rb_mFileTest;
 static VALUE rb_cStat;
@@ -613,6 +636,38 @@
     return stat(StringValueCStr(file), st);
 }
 
+#ifdef _WIN32
+static HANDLE
+w32_io_info(VALUE *file, BY_HANDLE_FILE_INFORMATION *st)
+{
+    VALUE tmp;
+    HANDLE f, ret = 0;
+
+    tmp = rb_check_convert_type(*file, T_FILE, "IO", "to_io");
+    if (!NIL_P(tmp)) {
+	OpenFile *fptr;
+
+	GetOpenFile(tmp, fptr);
+	f = (HANDLE)rb_w32_get_osfhandle(fptr->fd);
+	if (f == (HANDLE)-1) return INVALID_HANDLE_VALUE;
+    }
+    else {
+	FilePathValue(*file);
+	f = CreateFile(StringValueCStr(*file), 0,
+	               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+	               rb_w32_iswin95() ? 0 : FILE_FLAG_BACKUP_SEMANTICS, NULL);
+	if (f == INVALID_HANDLE_VALUE) return f;
+	ret = f;
+    }
+    if (GetFileType(f) == FILE_TYPE_DISK) {
+	ZeroMemory(st, sizeof(*st));
+	if (GetFileInformationByHandle(f, st)) return ret;
+    }
+    if (ret) CloseHandle(ret);
+    return INVALID_HANDLE_VALUE;
+}
+#endif
+
 /*
  *  call-seq:
  *     File.stat(file_name)   =>  stat
@@ -763,6 +818,7 @@
 #  define S_IXUGO		(S_IXUSR | S_IXGRP | S_IXOTH)
 #endif
 
+#ifndef HAVE_EACCESS
 int
 eaccess(const char *path, int mode)
 {
@@ -802,6 +858,7 @@
     return access(path, mode);
 #endif
 }
+#endif
 
 
 /*
@@ -1292,7 +1349,7 @@
  * call-seq:
  *   File.setuid?(file_name)   =>  true or false
  *
- * Returns <code>true</code> if the named file is a has the setuid bit set.
+ * Returns <code>true</code> if the named file has the setuid bit set.
  */
 
 static VALUE
@@ -1309,7 +1366,7 @@
  * call-seq:
  *   File.setgid?(file_name)   =>  true or false
  *
- * Returns <code>true</code> if the named file is a has the setgid bit set.
+ * Returns <code>true</code> if the named file has the setgid bit set.
  */
 
 static VALUE
@@ -1326,7 +1383,7 @@
  * call-seq:
  *   File.sticky?(file_name)   =>  true or false
  *
- * Returns <code>true</code> if the named file is a has the sticky bit set.
+ * Returns <code>true</code> if the named file has the sticky bit set.
  */
 
 static VALUE
@@ -1341,6 +1398,70 @@
 
 /*
  * call-seq:
+ *   File.identical?(file_1, file_2)   =>  true or false
+ *
+ * Returns <code>true</code> if the named files are identical.
+ *
+ *     open("a", "w") {}
+ *     p File.identical?("a", "a")      #=> true
+ *     p File.identical?("a", "./a")    #=> true
+ *     File.link("a", "b")
+ *     p File.identical?("a", "b")      #=> true
+ *     File.symlink("a", "c")
+ *     p File.identical?("a", "c")      #=> true
+ *     open("d", "w") {}
+ *     p File.identical?("a", "d")      #=> false
+ */
+
+static VALUE
+test_identical(VALUE obj, VALUE fname1, VALUE fname2)
+{
+#ifndef DOSISH
+    struct stat st1, st2;
+
+    if (rb_stat(fname1, &st1) < 0) return Qfalse;
+    if (rb_stat(fname2, &st2) < 0) return Qfalse;
+    if (st1.st_dev != st2.st_dev) return Qfalse;
+    if (st1.st_ino != st2.st_ino) return Qfalse;
+#else
+#ifdef _WIN32
+    BY_HANDLE_FILE_INFORMATION st1, st2;
+    HANDLE f1 = 0, f2 = 0;
+#endif
+
+    rb_secure(2);
+#ifdef _WIN32
+    f1 = w32_io_info(&fname1, &st1);
+    if (f1 == INVALID_HANDLE_VALUE) return Qfalse;
+    f2 = w32_io_info(&fname2, &st2);
+    if (f1) CloseHandle(f1);
+    if (f2 == INVALID_HANDLE_VALUE) return Qfalse;
+    if (f2) CloseHandle(f2);
+
+    if (st1.dwVolumeSerialNumber == st2.dwVolumeSerialNumber &&
+	st1.nFileIndexHigh == st2.nFileIndexHigh &&
+	st1.nFileIndexLow == st2.nFileIndexLow)
+	return Qtrue;
+    if (!f1 || !f2) return Qfalse;
+    if (rb_w32_iswin95()) return Qfalse;
+#else
+    FilePathValue(fname1);
+    fname1 = rb_str_new4(fname1);
+    FilePathValue(fname2);
+    if (access(RSTRING(fname1)->ptr, 0)) return Qfalse;
+    if (access(RSTRING(fname2)->ptr, 0)) return Qfalse;
+#endif
+    fname1 = rb_file_expand_path(fname1, Qnil);
+    fname2 = rb_file_expand_path(fname2, Qnil);
+    if (RSTRING(fname1)->len != RSTRING(fname2)->len) return Qfalse;
+    if (rb_memcicmp(RSTRING(fname1)->ptr, RSTRING(fname2)->ptr, RSTRING(fname1)->len))
+	return Qfalse;
+#endif
+    return Qtrue;
+}
+
+/*
+ * call-seq:
  *    File.size(file_name)   => integer
  *
  * Returns the size of <code>file_name</code>.
@@ -1562,7 +1683,7 @@
 static void
 chmod_internal(const char *path, void *mode)
 {
-    if (chmod(path, (int)mode) < 0)
+    if (chmod(path, *(int *)mode) < 0)
 	rb_sys_fail(path);
 }
 
@@ -1591,7 +1712,7 @@
     rb_scan_args(argc, argv, "1*", &vmode, &rest);
     mode = NUM2INT(vmode);
 
-    n = apply2files(chmod_internal, rest, (void *)(long)mode);
+    n = apply2files(chmod_internal, rest, &mode);
     return LONG2FIX(n);
 }
 
@@ -1986,7 +2107,11 @@
     rb_secure(2);
     FilePathValue(path);
     buf = xmalloc(size);
-    while ((rv = readlink(StringValueCStr(path), buf, size)) == size) {
+    while ((rv = readlink(RSTRING(path)->ptr, buf, size)) == size
+#ifdef _AIX
+	    || (rv < 0 && errno == ERANGE) /* quirky behavior of GPFS */
+#endif
+	) {
 	size *= 2;
 	buf = xrealloc(buf, size);
     }
@@ -2053,7 +2178,7 @@
     dst = StringValueCStr(to);
     if (rename(src, dst) < 0) {
 #if defined __CYGWIN__
-	extern unsigned long __attribute__((stdcall)) GetLastError();
+	extern unsigned long __attribute__((stdcall)) GetLastError(void);
 	errno = GetLastError(); /* This is a Cygwin bug */
 #elif defined DOSISH && !defined _WIN32
 	if (errno == EEXIST
@@ -2187,14 +2312,20 @@
     return (char *)s;
 }
 
+#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER) 
 #define skipprefix rb_path_skip_prefix
+#else
+#define skipprefix(path) (path)
+#endif
 char *
 rb_path_skip_prefix(const char *path)
 {
 #if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER) 
 #ifdef DOSISH_UNC
     if (isdirsep(path[0]) && isdirsep(path[1])) {
-	if (*(path = nextdirsep(path + 2)))
+	path += 2;
+	while (isdirsep(*path)) path++;
+	if (*(path = nextdirsep(path)) && path[1] && !isdirsep(path[1]))
 	    path = nextdirsep(path + 1);
 	return (char *)path;
     }
@@ -2542,6 +2673,9 @@
 {
     VALUE fname, fext, basename;
     char *name, *p;
+#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
+    char *root;
+#endif
     int f;
 
     if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
@@ -2550,15 +2684,31 @@
     StringValue(fname);
     if (RSTRING(fname)->len == 0 || !*(name = RSTRING(fname)->ptr))
 	return fname;
-    if (!*(name = skiproot(name))) {
+    name = skipprefix(name);
+#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
+    root = name;
+#endif
+    while (isdirsep(*name))
+	name++;
+    if (!*name) {
 	p = name - 1;
 	f = 1;
+#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
+	if (name != root) {
+	    /* has slashes */
+	}
 #ifdef DOSISH_DRIVE_LETTER
-	if (*p == ':') {
+	else if (*p == ':') {
 	    p++;
 	    f = 0;
 	}
 #endif
+#ifdef DOSISH_UNC
+	else {
+	    p = "/";
+	}
+#endif
+#endif
     }
     else if (!(p = strrdirsep(name))) {
 	if (NIL_P(fext) || !(f = rmext(name, StringValueCStr(fext)))) {
@@ -2599,8 +2749,8 @@
     name = StringValueCStr(fname);
     root = skiproot(name);
 #ifdef DOSISH_UNC
-    if (root > name + 2 && isdirsep(*name))
-	name = root - 2;
+    if (root > name + 1 && isdirsep(*name))
+	root = skipprefix(name = root - 2);
 #else
     if (root > name + 1)
 	name = root - 1;
@@ -2611,9 +2761,16 @@
     }
     if (p == name)
 	return rb_str_new2(".");
+#ifdef DOSISH_DRIVE_LETTER
+    if (has_drive_letter(name) && isdirsep(*(name + 2))) {
+	dirname = rb_str_new(name, 3);
+	rb_str_cat(dirname, skiproot(name + 2), p - skiproot(name + 2));
+    }
+    else
+#endif
     dirname = rb_str_new(name, p - name);
 #ifdef DOSISH_DRIVE_LETTER
-    if (root == name + 2 && name[1] == ':')
+    if (has_drive_letter(name) && root == name + 2 && p - name == 2)
 	rb_str_cat(dirname, ".", 1);
 #endif
     OBJ_INFECT(dirname, fname);
@@ -2745,7 +2902,7 @@
 	name = StringValueCStr(result);
 	if (i > 0 && !NIL_P(sep)) {
 	    tail = chompdirsep(name);
-	    if (isdirsep(RSTRING(tmp)->ptr[0])) {
+	    if (RSTRING(tmp)->ptr && isdirsep(RSTRING(tmp)->ptr[0])) {
 		RSTRING(result)->len = tail - name;
 	    }
 	    else if (!*tail) {
@@ -2882,8 +3039,23 @@
 #  define LOCK_UN 8
 # endif
 
-#if 1
+#ifdef __CYGWIN__
+#include <winerror.h>
 static int
+cygwin_flock(int fd, int op)
+{
+    int old_errno = errno;
+    int ret = flock(fd, op);
+    if (GetLastError() == ERROR_NOT_LOCKED) {
+	ret = 0;
+	errno = old_errno;
+    }
+    return ret;
+}
+# define flock(fd, op) cygwin_flock(fd, op)
+#endif
+
+static int
 rb_thread_flock(int fd, int op, OpenFile *fptr)
 {
     if (rb_thread_alone() || (op & LOCK_NB)) {
@@ -2910,8 +3082,10 @@
     }
     return 0;
 }
+#ifdef __CYGWIN__
+# undef flock
+#endif
 #define flock(fd, op) rb_thread_flock(fd, op, fptr)
-#endif
 
 /*
  *  call-seq:
@@ -3050,7 +3224,7 @@
  *
  * Tests that take two files:
  *
- *     ?-  | boolean | True if file1 is a hard link to file2
+ *     ?-  | boolean | True if file1 and file2 are identical
  *     ?=  | boolean | True if the modification times of file1
  *         |         | and file2 are equal
  *     ?<  | boolean | True if the modification time of file1
@@ -3162,7 +3336,12 @@
 	}
     }
 
-    if (strchr("-=<>", cmd)) {
+    if (cmd == '-') {
+	CHECK(2);
+	return test_identical(0, argv[1], argv[2]);
+    }
+
+    if (strchr("=<>", cmd)) {
 	struct stat st1, st2;
 
 	CHECK(2);
@@ -3170,11 +3349,6 @@
 	if (rb_stat(argv[2], &st2) < 0) return Qfalse;
 
 	switch (cmd) {
-	  case '-':
-	    if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
-		return Qtrue;
-            return Qfalse;
-
 	  case '=':
 	    if (st1.st_mtime == st2.st_mtime) return Qtrue;
 	    return Qfalse;
@@ -3881,8 +4055,7 @@
 #endif
 
 static int
-fpath_check(path)
-    char *path;
+fpath_check(const char *path)
 {
 #ifndef DOSISH
     return path_check_0(rb_str_new2(path), Qfalse);
@@ -3928,15 +4101,9 @@
 #endif
 
 static int
-file_load_ok(const char *file)
+file_load_ok(const char *path)
 {
-    FILE *f;
-
-    if (!file) return 0;
-    f = fopen(file, "r");
-    if (f == NULL) return 0;
-    fclose(f);
-    return 1;
+    return eaccess(path, R_OK) == 0;
 }
 
 extern VALUE rb_load_path;
@@ -4148,6 +4315,8 @@
     define_filetest_function("setgid?", test_sgid, 1);
     define_filetest_function("sticky?", test_sticky, 1);
 
+    define_filetest_function("identical?", test_identical, 2);
+
     rb_define_singleton_method(rb_cFile, "stat",  rb_file_s_stat, 1);
     rb_define_singleton_method(rb_cFile, "lstat", rb_file_s_lstat, 1);
     rb_define_singleton_method(rb_cFile, "ftype", rb_file_s_ftype, 1);

Modified: trunk/gc.c
===================================================================
--- trunk/gc.c	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/gc.c	2006-02-09 17:49:56 UTC (rev 377)
@@ -31,24 +31,6 @@
 #include <sys/resource.h>
 #endif
 
-#ifdef __ia64__
-#include <ucontext.h>
-#if defined(__FreeBSD__)
-/*
- * FreeBSD/ia64 currently does not have a way for a process to get the
- * base address for the RSE backing store, so hardcode it.
- */
-#define __libc_ia64_register_backing_store_base (4ULL<<61)
-#else
-#if defined(HAVE_UNWIND_H) && defined(HAVE__UNW_CREATECONTEXTFORSELF)
-#include <unwind.h>
-#else
-#pragma weak __libc_ia64_register_backing_store_base
-extern unsigned long __libc_ia64_register_backing_store_base;
-#endif
-#endif
-#endif
-
 #if defined _WIN32 || defined __CYGWIN__
 #include <windows.h>
 #endif
@@ -106,57 +88,80 @@
     rb_exc_raise(nomem_error);
 }
 
-static int gc_debug_flag = 0;
+int gc_stress = 0;
 
+/*
+ *  call-seq:
+ *    GC.stress                 => true or false
+ *
+ *  returns current status of GC stress mode.
+ */
+
 static VALUE
-get_gc_debug_flag(VALUE self){
-  return gc_debug_flag ? Qtrue : Qfalse;
+gc_stress_get(VALUE self)
+{
+    return gc_stress ? Qtrue : Qfalse;
 }
 
+/*
+ *  call-seq:
+ *    GC.stress = bool          => bool
+ *
+ *  updates GC stress mode.
+ *
+ *  When GC.stress = true, GC is invoked for all GC opportunity:
+ *  all memory and object allocation.
+ *
+ *  Since it makes Ruby very slow, it is only for debugging.
+ */
+
 static VALUE
-set_gc_debug_flag(VALUE self, VALUE v){
-  gc_debug_flag = (v == Qtrue);
-  return v;
+gc_stress_set(VALUE self, VALUE bool)
+{
+    rb_secure(2);
+    gc_stress = RTEST(bool);
+    return bool;
 }
 
 void *
-ruby_xmalloc(long size)
+ruby_xmalloc(size_t size)
 {
-  void *mem;
+    void *mem;
 
-  if (size < 0) {
-    rb_raise(rb_eNoMemError, "negative allocation size (or too big)");
-  }
-  if (size == 0) size = 1;
-  malloc_increase += size;
+    if (size < 0) {
+	rb_raise(rb_eNoMemError, "negative allocation size (or too big)");
+    }
+    if (size == 0) size = 1;
+    malloc_increase += size;
 
-  if (malloc_increase > malloc_limit || gc_debug_flag) {
-    garbage_collect();
-  }
-  RUBY_CRITICAL(mem = malloc(size));
-  if (!mem) {
-    if (garbage_collect()) {
-      RUBY_CRITICAL(mem = malloc(size));
+    if (gc_stress || malloc_increase > malloc_limit) {
+	garbage_collect();
     }
+    RUBY_CRITICAL(mem = malloc(size));
     if (!mem) {
-      rb_memerror();
+	if (garbage_collect()) {
+	    RUBY_CRITICAL(mem = malloc(size));
+	}
+	if (!mem) {
+	    rb_memerror();
+	}
     }
-  }
-  return mem;
+
+    return mem;
 }
 
 void *
-ruby_xmalloc2(long n, long size)
+ruby_xmalloc2(size_t n, size_t size)
 {
     long len = size * n;
-    if (len < n || (n > 0 && len < size)) {
+    if (n != 0 && size != len / n) {
 	rb_raise(rb_eArgError, "malloc: possible integer overflow");
     }
     return ruby_xmalloc(len);
 }
 
 void *
-ruby_xcalloc(long n, long size)
+ruby_xcalloc(size_t n, size_t size)
 {
     void *mem;
 
@@ -167,7 +172,7 @@
 }
 
 void *
-ruby_xrealloc(void *ptr, long size)
+ruby_xrealloc(void *ptr, size_t size)
 {
     void *mem;
 
@@ -177,10 +182,11 @@
     if (!ptr) return ruby_xmalloc(size);
     if (size == 0) size = 1;
     malloc_increase += size;
+    if (gc_stress) garbage_collect();
     RUBY_CRITICAL(mem = realloc(ptr, size));
     if (!mem) {
 	if (garbage_collect()) {
-	RUBY_CRITICAL(mem = realloc(ptr, size));
+	    RUBY_CRITICAL(mem = realloc(ptr, size));
 	}
 	if (!mem) {
 	    rb_memerror();
@@ -191,10 +197,10 @@
 }
 
 void *
-ruby_xrealloc2(void *ptr, long n, long size)
+ruby_xrealloc2(void *ptr, size_t n, size_t size)
 {
-    long len = size * n;
-    if (len < n || (n > 0 && len < size)) {
+    size_t len = size * n;
+    if (n != 0 && size != len / n) {
 	rb_raise(rb_eArgError, "realloc: possible integer overflow");
     }
     return ruby_xrealloc(ptr, len);
@@ -203,9 +209,8 @@
 void
 ruby_xfree(void *x)
 {
-  if (x){
-    RUBY_CRITICAL(free(x));
-  }
+    if (x)
+	RUBY_CRITICAL(free(x));
 }
 
 static int dont_gc;
@@ -405,20 +410,19 @@
 VALUE
 rb_newobj(void)
 {
-  VALUE obj;
+    VALUE obj;
 
-  if (!freelist && !garbage_collect()){
-    rb_memerror();
-  }
+    if ((gc_stress || !freelist) && !garbage_collect())
+	rb_memerror();
 
-  obj = (VALUE)freelist;
-  freelist = freelist->as.free.next;
-  MEMZERO((void*)obj, RVALUE, 1);
+    obj = (VALUE)freelist;
+    freelist = freelist->as.free.next;
+    MEMZERO((void*)obj, RVALUE, 1);
 #ifdef GC_DEBUG
-  RANY(obj)->file = ruby_sourcefile;
-  RANY(obj)->line = ruby_sourceline;
+    RANY(obj)->file = ruby_sourcefile;
+    RANY(obj)->line = ruby_sourceline;
 #endif
-  return obj;
+    return obj;
 }
 
 VALUE
@@ -436,7 +440,11 @@
 
 extern st_table *rb_class_tbl;
 VALUE *rb_gc_stack_start = 0;
+#ifdef __ia64
+VALUE *rb_gc_register_stack_start = 0;
+#endif
 
+
 #ifdef DJGPP
 /* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
 unsigned int _stklen = 0x180000; /* 1.5 kB */
@@ -652,7 +660,7 @@
     return ST_CONTINUE;
 }
 
-void
+static void
 mark_tbl(st_table *tbl, int lev)
 {
     if (!tbl) return;
@@ -673,7 +681,7 @@
     return ST_CONTINUE;
 }
 
-void
+static void
 mark_hash(st_table *tbl, int lev)
 {
     if (!tbl) return;
@@ -967,8 +975,8 @@
 
       case T_STRUCT:
 	{
-	    long len = obj->as.rstruct.len;
-	    VALUE *ptr = obj->as.rstruct.ptr;
+	    long len = RSTRUCT_LEN(obj);
+	    VALUE *ptr = RSTRUCT_PTR(obj);
 
 	    while (len--) {
 		gc_mark(*ptr++, lev);
@@ -1027,6 +1035,8 @@
     }
 }
 
+void rb_gc_abort_threads(void);
+
 static void
 gc_sweep(void)
 {
@@ -1036,7 +1046,9 @@
     unsigned long live = 0;
 
     mark_source_filename(ruby_sourcefile);
-    st_foreach(source_filenames, sweep_source_filename, 0);
+    if (source_filenames) {
+        st_foreach(source_filenames, sweep_source_filename, 0);
+    }
 
     freelist = 0;
     final_list = deferred_final_list;
@@ -1066,7 +1078,7 @@
 	    }
 	    else if (RBASIC(p)->flags == FL_MARK) {
 		/* objects to be finalized */
-		/* do notning remain marked */
+		/* do nothing remain marked */
 	    }
 	    else {
 		RBASIC(p)->flags &= ~FL_MARK;
@@ -1227,13 +1239,15 @@
 	break;
 
       case T_STRUCT:
-	if (RANY(obj)->as.rstruct.ptr) {
-	    RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr));
+	if (RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK == 0 &&
+	    RANY(obj)->as.rstruct.as.heap.ptr) {
+	    RUBY_CRITICAL(free(RANY(obj)->as.rstruct.as.heap.ptr));
 	}
+	break;
 
       default:
 	rb_bug("gc_sweep(): unknown data type 0x%lx(%p)", 
-	       RANY(obj)->as.basic.flags & T_MASK, (void*)obj);
+	       RANY(obj)->as.basic.flags & T_MASK, obj);
     }
 }
 
@@ -1432,6 +1446,28 @@
 void
 Init_stack(VALUE *addr)
 {
+#ifdef __ia64
+    if (rb_gc_register_stack_start == 0) {
+# if defined(__FreeBSD__)
+        /*
+         * FreeBSD/ia64 currently does not have a way for a process to get the
+         * base address for the RSE backing store, so hardcode it.
+         */
+        rb_gc_register_stack_start = (4ULL<<61);
+# elif defined(HAVE___LIBC_IA64_REGISTER_BACKING_STORE_BASE)
+#  pragma weak __libc_ia64_register_backing_store_base
+        extern unsigned long __libc_ia64_register_backing_store_base;
+        rb_gc_register_stack_start = (VALUE*)__libc_ia64_register_backing_store_base;
+# endif
+    }
+    {
+        VALUE *bsp = (VALUE*)rb_ia64_bsp();
+        if (rb_gc_register_stack_start == 0 ||
+            bsp < rb_gc_register_stack_start) {
+            rb_gc_register_stack_start = bsp;
+        }
+    }
+#endif
 #if defined(_WIN32) || defined(__CYGWIN__)
     MEMORY_BASIC_INFORMATION m;
     memset(&m, 0, sizeof(m));
@@ -1440,8 +1476,10 @@
 	STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress,
 		    (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1);
 #elif defined(STACK_END_ADDRESS)
-    extern void *STACK_END_ADDRESS;
-    rb_gc_stack_start = STACK_END_ADDRESS;
+    {
+        extern void *STACK_END_ADDRESS;
+        rb_gc_stack_start = STACK_END_ADDRESS;
+    }
 #else
     if (!addr) addr = (VALUE *)&addr;
     STACK_UPPER(&addr, addr, ++addr);
@@ -1468,7 +1506,38 @@
 #endif
 }
 
+void ruby_init_stack(VALUE *addr
+#ifdef __ia64
+    , void *bsp
+#endif
+    )
+{
+    if (!rb_gc_stack_start ||
+        STACK_UPPER(&addr,
+                    rb_gc_stack_start > addr,
+                    rb_gc_stack_start < addr)) {
+        rb_gc_stack_start = addr;
+    }
+#ifdef __ia64
+    if (!rb_gc_register_stack_start ||
+        (VALUE*)bsp < rb_gc_register_stack_start) {
+        rb_gc_register_stack_start = (VALUE*)bsp;
+    }
+#endif
+#ifdef HAVE_GETRLIMIT
+    {
+	struct rlimit rlim;
 
+	if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
+	    unsigned int space = rlim.rlim_cur/5;
+
+	    if (space > 1024*1024) space = 1024*1024;
+	    STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
+	}
+    }
+#endif
+}
+
 /*
  * Document-class: ObjectSpace
  *
@@ -1903,8 +1972,8 @@
     rb_define_singleton_method(rb_mGC, "start", rb_gc_start, 0);
     rb_define_singleton_method(rb_mGC, "enable", rb_gc_enable, 0);
     rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0);
-    rb_define_singleton_method(rb_mGC, "debug_flag", get_gc_debug_flag, 0);
-    rb_define_singleton_method(rb_mGC, "debug_flag=", set_gc_debug_flag, 1);
+    rb_define_singleton_method(rb_mGC, "stress", gc_stress_get, 0);
+    rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1);
     rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
 
     rb_mObSpace = rb_define_module("ObjectSpace");
@@ -1927,6 +1996,6 @@
 
     source_filenames = st_init_strtable();
 
+    rb_global_variable(&nomem_error);
     nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory");
-    rb_global_variable(&nomem_error);
 }

Modified: trunk/io.c
===================================================================
--- trunk/io.c	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/io.c	2006-02-09 17:49:56 UTC (rev 377)
@@ -2,8 +2,8 @@
 
   io.c -
 
-  $Author: ocean $
-  $Date: 2005/11/11 11:08:17 $
+  $Author: matz $
+  $Date: 2006/02/03 09:15:40 $
   created at: Fri Oct 15 18:08:59 JST 1993
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -3798,7 +3798,12 @@
 void
 rb_write_error2(const char *mesg, long len)
 {
-    rb_io_write(rb_stderr, rb_str_new(mesg, len));
+    if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
+	fwrite(mesg, sizeof(char), len, stderr);
+    }
+    else {
+	rb_io_write(rb_stderr, rb_str_new(mesg, len));
+    }
 }
 
 void
@@ -4373,7 +4378,8 @@
 static VALUE
 rb_f_backquote(VALUE obj, VALUE str)
 {
-    VALUE port, result;
+    volatile VALUE port;
+    VALUE result;
     OpenFile *fptr;
 
     SafeStringValue(str);
@@ -5482,9 +5488,9 @@
     rb_output_fs = Qnil;
     rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
 
+    rb_global_variable(&rb_default_rs);
     rb_rs = rb_default_rs = rb_str_new2("\n");
     rb_output_rs = Qnil;
-    rb_global_variable(&rb_default_rs);
     OBJ_FREEZE(rb_default_rs);	/* avoid modifying RS_default */
     rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
     rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
@@ -5557,12 +5563,12 @@
     rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
     rb_define_method(rb_cIO, "inspect",  rb_io_inspect, 0);
 
+    rb_define_variable("$stdin", &rb_stdin);
     rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
-    rb_define_variable("$stdin", &rb_stdin);
+    rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
     rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
-    rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
+    rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
     rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
-    rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
     rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
     orig_stdout = rb_stdout;
     rb_deferr = orig_stderr = rb_stderr;
@@ -5576,10 +5582,9 @@
     rb_define_global_const("STDOUT", rb_stdout);
     rb_define_global_const("STDERR", rb_stderr);
 
+    rb_define_readonly_variable("$<", &argf);
     argf = rb_obj_alloc(rb_cObject);
     rb_extend_object(argf, rb_mEnumerable);
-
-    rb_define_readonly_variable("$<", &argf);
     rb_define_global_const("ARGF", argf);
 
     rb_define_singleton_method(argf, "to_s", argf_to_s, 0);
@@ -5619,8 +5624,8 @@
     rb_define_singleton_method(argf, "lineno=",  argf_set_lineno, 1);
 
     rb_global_variable(&current_file);
+    rb_define_readonly_variable("$FILENAME", &filename);
     filename = rb_str_new2("-");
-    rb_define_readonly_variable("$FILENAME", &filename);
 
     rb_define_virtual_variable("$-i", opt_i_get, opt_i_set);
 

Modified: trunk/marshal.c
===================================================================
--- trunk/marshal.c	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/marshal.c	2006-02-09 17:49:56 UTC (rev 377)
@@ -2,8 +2,8 @@
 
   marshal.c -
 
-  $Author: ocean $
-  $Date: 2005/10/21 06:46:39 $
+  $Author: akr $
+  $Date: 2006/02/05 14:40:01 $
   created at: Thu Apr 27 16:30:01 JST 1995
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -585,7 +585,7 @@
 	  case T_STRUCT:
 	    w_class(TYPE_STRUCT, obj, arg, Qtrue);
 	    {
-		long len = RSTRUCT(obj)->len;
+		long len = RSTRUCT_LEN(obj);
 		VALUE mem;
 		long i;
 
@@ -593,7 +593,7 @@
 		mem = rb_struct_members(obj);
 		for (i=0; i<len; i++) {
 		    w_symbol(SYM2ID(RARRAY(mem)->ptr[i]), arg);
-		    w_object(RSTRUCT(obj)->ptr[i], arg, limit);
+		    w_object(RSTRUCT_PTR(obj)[i], arg, limit);
 		}
 	    }
 	    break;
@@ -765,7 +765,7 @@
 static void
 long_toobig(int size)
 {
-    rb_raise(rb_eTypeError, "long too big for this architecture (size %ld, given %d)",
+    rb_raise(rb_eTypeError, "long too big for this architecture (size %d, given %d)",
 	     sizeof(long), size);
 }
 
@@ -1038,7 +1038,7 @@
 	{
 	    long len;
 	    BDIGIT *digits;
-	    VALUE data;
+	    volatile VALUE data;
 
 	    NEWOBJ(big, struct RBignum);
 	    OBJSETUP(big, rb_cBignum, T_BIGNUM);

Modified: trunk/process.c
===================================================================
--- trunk/process.c	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/process.c	2006-02-09 17:49:56 UTC (rev 377)
@@ -2,8 +2,8 @@
 
   process.c -
 
-  $Author: matz $
-  $Date: 2005/10/05 16:15:15 $
+  $Author: aamine $
+  $Date: 2005/12/27 05:10:38 $
   created at: Tue Aug 10 14:30:50 JST 1993
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -1396,11 +1396,14 @@
  *  the parent, returning the process ID of the child, and once in
  *  the child, returning _nil_. The child process can exit using
  *  <code>Kernel.exit!</code> to avoid running any
- *  <code>at_exit</code> functions. The parent process should 
- *  use <code>Process.wait</code> to collect the termination statuses 
+ *  <code>at_exit</code> functions. The parent process should
+ *  use <code>Process.wait</code> to collect the termination statuses
  *  of its children or use <code>Process.detach</code> to register
  *  disinterest in their status; otherwise, the operating system
  *  may accumulate zombie processes.
+ *
+ *  The thread calling fork is the only thread in the created child process.
+ *  fork doesn't copy other threads.
  */
 
 static VALUE
@@ -2629,7 +2632,7 @@
 
     ngroups = RARRAY(ary)->len;
     if (ngroups > maxgroups)
-	rb_raise(rb_eArgError, "too many groups, %ld max", (long)maxgroups);
+	rb_raise(rb_eArgError, "too many groups, %lu max", (unsigned long)maxgroups);
 
     groups = ALLOCA_N(rb_gid_t, ngroups);
 
@@ -3580,6 +3583,7 @@
 #endif
 #endif
 
+    rb_define_singleton_method(rb_mProcess, "exec", rb_f_exec, -1);
     rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
     rb_define_singleton_method(rb_mProcess, "spawn", rb_f_spawn, -1);
     rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);

Modified: trunk/range.c
===================================================================
--- trunk/range.c	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/range.c	2006-02-09 17:49:56 UTC (rev 377)
@@ -3,7 +3,7 @@
   range.c -
 
   $Author: matz $
-  $Date: 2005/10/05 16:15:15 $
+  $Date: 2005/12/12 01:01:29 $
   created at: Thu Aug 19 17:46:47 JST 1993
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -366,47 +366,41 @@
  *     10 11 12 13 14 15
  */
 
-VALUE yarv_invoke_Range_each_special_block(VALUE, VALUE, VALUE, int);
-
 static VALUE
 range_each(VALUE range)
 {
-  VALUE beg, end, val;
-  
-  RETURN_ENUMERATOR(range, 0, 0);
+    VALUE beg, end;
 
-  beg = rb_ivar_get(range, id_beg);
-  end = rb_ivar_get(range, id_end);
+    RETURN_ENUMERATOR(range, 0, 0);
 
-  val = yarv_invoke_Range_each_special_block(range, beg, end, EXCL(range));
-  if(val != Qundef){
-    return val;
-  }
-  if (!rb_respond_to(beg, id_succ)) {
-    rb_raise(rb_eTypeError, "can't iterate from %s",
-             rb_obj_classname(beg));
-  }
-  if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
-    long lim = FIX2LONG(end);
-    long i;
+    beg = rb_ivar_get(range, id_beg);
+    end = rb_ivar_get(range, id_end);
 
-    if (!EXCL(range)) lim += 1;
-    for (i=FIX2LONG(beg); i<lim; i++) {
-      rb_yield(LONG2NUM(i));
+    if (!rb_respond_to(beg, id_succ)) {
+	rb_raise(rb_eTypeError, "can't iterate from %s",
+		 rb_obj_classname(beg));
     }
-  }
-  else if (TYPE(beg) == T_STRING) {
-    VALUE args[5];
-    long iter[2];
+    if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
+	long lim = FIX2LONG(end);
+	long i;
 
-    args[0] = beg; args[1] = end; args[2] = range;
-    iter[0] = 1; iter[1] = 1;
-    rb_iterate(str_step, (VALUE)args, step_i, (VALUE)iter);
-  }
-  else {
-    range_each_func(range, each_i, beg, end, NULL);
-  }
-  return range;
+	if (!EXCL(range)) lim += 1;
+	for (i=FIX2LONG(beg); i<lim; i++) {
+	    rb_yield(LONG2NUM(i));
+	}
+    }
+    else if (TYPE(beg) == T_STRING) {
+	VALUE args[5];
+	long iter[2];
+
+	args[0] = beg; args[1] = end; args[2] = range;
+	iter[0] = 1; iter[1] = 1;
+	rb_iterate(str_step, (VALUE)args, step_i, (VALUE)iter);
+    }
+    else {
+	range_each_func(range, each_i, beg, end, NULL);
+    }
+    return range;
 }
 
 /*
@@ -442,6 +436,70 @@
     return rb_ivar_get(range, id_end);
 }
 
+/*
+ *  call-seq:
+ *     rng.min                    => obj
+ *     rng.min {| a,b | block }   => obj
+ *  
+ *  Returns the minimum value in <i>rng</i>. The second uses
+ *  the block to compare values.  Returns nil if the first
+ *  value in range is larger than the last value.
+ *     
+ */
+
+
+static VALUE
+range_min(VALUE range)
+{
+    if (rb_block_given_p()) {
+	return rb_call_super(0, 0);
+    }
+    else {
+	VALUE b = rb_ivar_get(range, id_beg);
+	VALUE e = rb_ivar_get(range, id_end);
+	int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
+
+	if (c > 0) return Qnil;
+	return b;
+    }
+}
+
+/*
+ *  call-seq:
+ *     rng.max                    => obj
+ *     rng.max {| a,b | block }   => obj
+ *  
+ *  Returns the maximum value in <i>rng</i>. The second uses
+ *  the block to compare values.  Returns nil if the first
+ *  value in range is larger than the last value.
+ *     
+ */
+
+
+static VALUE
+range_max(VALUE range)
+{
+    VALUE e = rb_ivar_get(range, id_end);
+    int ip = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cInteger);
+
+    if (rb_block_given_p() || (EXCL(range) && !ip)) {
+	return rb_call_super(0, 0);
+    }
+    else {
+	VALUE b = rb_ivar_get(range, id_beg);
+	int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
+
+	if (c > 0) return Qnil;
+	if (EXCL(range)) {
+	    if (FIXNUM_P(e)) {
+		return INT2NUM(FIX2INT(e)-1);
+	    }
+	    return rb_funcall(e, '-', 1, INT2FIX(1));
+	}
+	return e;
+    }
+}
+
 VALUE
 rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
 {
@@ -560,6 +618,45 @@
 static VALUE
 range_include(VALUE range, VALUE val)
 {
+    VALUE beg = rb_ivar_get(range, id_beg);
+    VALUE end = rb_ivar_get(range, id_end);
+    int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
+	     rb_obj_is_kind_of(beg, rb_cNumeric) ||
+	     rb_obj_is_kind_of(end, rb_cNumeric);
+
+    if (nv ||
+	!NIL_P(rb_check_to_integer(beg, "to_int")) ||
+	!NIL_P(rb_check_to_integer(end, "to_int"))) {
+	if (r_le(beg, val)) {
+	    if (EXCL(range)) {
+		if (r_lt(val, end)) return Qtrue;
+	    }
+	    else {
+		if (r_le(val, end)) return Qtrue;
+	    }
+	}
+	return Qfalse;
+    }
+    return rb_call_super(1, &val);
+}
+
+
+/*
+ *  call-seq:
+ *     rng.cover?(val)  =>  true or false
+ *  
+ *  Returns <code>true</code> if <i>obj</i> is between beg and end,
+ *  i.e <code>beg <= obj <= end</code> (or <i>end</i> exclusive when
+ *  <code>exclude_end?</code> is true).
+ *     
+ *     ("a".."z").cover?("c")    #=> true
+ *     ("a".."z").cover?("5")    #=> false
+ */
+
+static VALUE
+range_cover(range, val)
+    VALUE range, val;
+{
     VALUE beg, end;
 
     beg = rb_ivar_get(range, id_beg);
@@ -644,6 +741,8 @@
     rb_define_method(rb_cRange, "last", range_last, 0);
     rb_define_method(rb_cRange, "begin", range_first, 0);
     rb_define_method(rb_cRange, "end", range_last, 0);
+    rb_define_method(rb_cRange, "min", range_min, 0);
+    rb_define_method(rb_cRange, "max", range_max, 0);
     rb_define_method(rb_cRange, "to_s", range_to_s, 0);
     rb_define_method(rb_cRange, "inspect", range_inspect, 0);
 
@@ -651,6 +750,7 @@
 
     rb_define_method(rb_cRange, "member?", range_include, 1);
     rb_define_method(rb_cRange, "include?", range_include, 1);
+    rb_define_method(rb_cRange, "cover?", range_cover, 1);
 
     id_cmp = rb_intern("<=>");
     id_succ = rb_intern("succ");

Modified: trunk/ruby.h
===================================================================
--- trunk/ruby.h	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/ruby.h	2006-02-09 17:49:56 UTC (rev 377)
@@ -2,7 +2,7 @@
 
   ruby.h -
 
-  $Author: ocean $
+  $Author: akr $
   created at: Thu Jun 10 14:26:32 JST 1993
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -41,8 +41,6 @@
 #define PRINTF_ARGS(decl, string_index, first_to_check) decl
 #endif
 
-#include "defines.h"
-
 #ifdef HAVE_STDLIB_H
 # include <stdlib.h>
 #endif
@@ -60,6 +58,8 @@
 #include <stddef.h>
 #include <stdio.h>
 
+#include "defines.h"
+
 /* need to include <ctype.h> to use these macros */
 #ifndef ISPRINT
 #define ISASCII(c) isascii((int)(unsigned char)(c))
@@ -425,11 +425,28 @@
     sval = (type*)DATA_PTR(obj);\
 } while (0)
 
+#define RSTRUCT_EMBED_LEN_MAX 3
 struct RStruct {
     struct RBasic basic;
-    long len;
-    VALUE *ptr;
+    union {
+	struct {
+	    long len;
+	    VALUE *ptr;
+	} heap;
+	VALUE ary[RSTRUCT_EMBED_LEN_MAX];
+    } as;
 };
+#define RSTRUCT_EMBED_LEN_MASK (FL_USER2|FL_USER1)
+#define RSTRUCT_EMBED_LEN_SHIFT FL_USHIFT+1
+#define RSTRUCT_LEN(st) \
+    ((RBASIC(st)->flags & RSTRUCT_EMBED_LEN_MASK) ? \
+     (RBASIC(st)->flags >> RSTRUCT_EMBED_LEN_SHIFT) & \
+     (RSTRUCT_EMBED_LEN_MASK >> RSTRUCT_EMBED_LEN_SHIFT) : \
+     RSTRUCT(st)->as.heap.len)
+#define RSTRUCT_PTR(st) \
+    ((RBASIC(st)->flags & RSTRUCT_EMBED_LEN_MASK) ? \
+     RSTRUCT(st)->as.ary : \
+     RSTRUCT(st)->as.heap.ptr)
 
 struct RBignum {
     struct RBasic basic;
@@ -592,6 +609,17 @@
 
 VALUE rb_require(const char*);
 
+#ifdef __ia64
+void ruby_init_stack(VALUE*, void*);
+#define RUBY_INIT_STACK \
+    VALUE variable_in_this_stack_frame; \
+    ruby_init_stack(&variable_in_this_stack_frame, rb_ia64_bsp());
+#else
+void ruby_init_stack(VALUE*);
+#define RUBY_INIT_STACK \
+    VALUE variable_in_this_stack_frame; \
+    ruby_init_stack(&variable_in_this_stack_frame);
+#endif
 void ruby_init(void);
 void ruby_options(int, char**);
 NORETURN(void ruby_run(void));

Modified: trunk/string.c
===================================================================
--- trunk/string.c	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/string.c	2006-02-09 17:49:56 UTC (rev 377)
@@ -2,8 +2,8 @@
 
   string.c -
 
-  $Author: matz $
-  $Date: 2005/10/27 08:18:38 $
+  $Author: akr $
+  $Date: 2005/12/29 17:03:27 $
   created at: Mon Aug  9 17:12:58 JST 1993
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -2155,99 +2155,8 @@
     return str;
 }
 
-static VALUE
-uscore_get(void)
-{
-    VALUE line;
-
-    line = rb_lastline_get();
-    if (TYPE(line) != T_STRING) {
-	rb_raise(rb_eTypeError, "$_ value need to be String (%s given)",
-		 NIL_P(line) ? "nil" : rb_obj_classname(line));
-    }
-    return line;
-}
-
 /*
  *  call-seq:
- *     sub!(pattern, replacement)    => $_ or nil
- *     sub!(pattern) {|...| block }  => $_ or nil
- *  
- *  Equivalent to <code>$_.sub!(<i>args</i>)</code>.
- */
-
-static VALUE
-rb_f_sub_bang(int argc, VALUE *argv)
-{
-    return rb_str_sub_bang(argc, argv, uscore_get());
-}
-
-/*
- *  call-seq:
- *     sub(pattern, replacement)   => $_
- *     sub(pattern) { block }      => $_
- *  
- *  Equivalent to <code>$_.sub(<i>args</i>)</code>, except that
- *  <code>$_</code> will be updated if substitution occurs.
- */
-
-static VALUE
-rb_f_sub(int argc, VALUE *argv)
-{
-    VALUE str = rb_str_dup(uscore_get());
-
-    if (NIL_P(rb_str_sub_bang(argc, argv, str)))
-	return str;
-    rb_lastline_set(str);
-    return str;
-}
-
-/*
- *  call-seq:
- *     gsub!(pattern, replacement)    => string or nil
- *     gsub!(pattern) {|...| block }  => string or nil
- *  
- *  Equivalent to <code>Kernel::gsub</code>, except <code>nil</code> is
- *  returned if <code>$_</code> is not modified.
- *     
- *     $_ = "quick brown fox"
- *     gsub! /cat/, '*'   #=> nil
- *     $_                 #=> "quick brown fox"
- */
-
-static VALUE
-rb_f_gsub_bang(int argc, VALUE *argv)
-{
-    return rb_str_gsub_bang(argc, argv, uscore_get());
-}
-
-/*
- *  call-seq:
- *     gsub(pattern, replacement)    => string
- *     gsub(pattern) {|...| block }  => string
- *  
- *  Equivalent to <code>$_.gsub...</code>, except that <code>$_</code>
- *  receives the modified result.
- *     
- *     $_ = "quick brown fox"
- *     gsub /[aeiou]/, '*'   #=> "q**ck br*wn f*x"
- *     $_                    #=> "q**ck br*wn f*x"
- */
-
-static VALUE
-rb_f_gsub(int argc, VALUE *argv)
-{
-    VALUE str = rb_str_dup(uscore_get());
-
-    if (NIL_P(rb_str_gsub_bang(argc, argv, str)))
-	return str;
-    rb_lastline_set(str);
-    return str;
-}
-
-
-/*
- *  call-seq:
  *     str.reverse!   => str
  *  
  *  Reverses <i>str</i> in place.
@@ -3439,20 +3348,6 @@
 
 /*
  *  call-seq:
- *     split([pattern [, limit]])    => array
- *  
- *  Equivalent to <code>$_.split(<i>pattern</i>, <i>limit</i>)</code>.
- *  See <code>String#split</code>.
- */
-
-static VALUE
-rb_f_split(int argc, VALUE *argv)
-{
-    return rb_str_split_m(argc, argv, uscore_get());
-}
-
-/*
- *  call-seq:
  *     str.each(separator=$/) {|substr| block }        => str
  *     str.each_line(separator=$/) {|substr| block }   => str
  *  
@@ -3622,61 +3517,6 @@
 
 /*
  *  call-seq:
- *     chop!    => $_ or nil
- *  
- *  Equivalent to <code>$_.chop!</code>.
- *     
- *     a  = "now\r\n"
- *     $_ = a
- *     chop!   #=> "now"
- *     chop!   #=> "no"
- *     chop!   #=> "n"
- *     chop!   #=> ""
- *     chop!   #=> nil
- *     $_      #=> ""
- *     a       #=> ""
- */
-
-static VALUE
-rb_f_chop_bang(VALUE str)
-{
-    return rb_str_chop_bang(uscore_get());
-}
-
-/*
- *  call-seq:
- *     chop   => string
- *  
- *  Equivalent to <code>($_.dup).chop!</code>, except <code>nil</code>
- *  is never returned. See <code>String#chop!</code>.
- *     
- *     a  =  "now\r\n"
- *     $_ = a
- *     chop   #=> "now"
- *     $_     #=> "now"
- *     chop   #=> "no"
- *     chop   #=> "n"
- *     chop   #=> ""
- *     chop   #=> ""
- *     a      #=> "now\r\n"
- */
-
-static VALUE
-rb_f_chop(void)
-{
-    VALUE str = uscore_get();
-
-    if (RSTRING(str)->len > 0) {
-	str = rb_str_dup(str);
-	rb_str_chop_bang(str);
-	rb_lastline_set(str);
-    }
-    return str;
-}
-
-
-/*
- *  call-seq:
  *     str.chomp!(separator=$/)   => str or nil
  *  
  *  Modifies <i>str</i> in place as described for <code>String#chomp</code>,
@@ -3782,57 +3622,6 @@
 
 /*
  *  call-seq:
- *     chomp!             => $_ or nil
- *     chomp!(string)     => $_ or nil
- *  
- *  Equivalent to <code>$_.chomp!(<em>string</em>)</code>. See
- *  <code>String#chomp!</code>
- *     
- *     $_ = "now\n"
- *     chomp!       #=> "now"
- *     $_           #=> "now"
- *     chomp! "x"   #=> nil
- *     $_           #=> "now"
- */
-
-static VALUE
-rb_f_chomp_bang(int argc, VALUE *argv)
-{
-    return rb_str_chomp_bang(argc, argv, uscore_get());
-}
-
-/*
- *  call-seq:
- *     chomp            => $_
- *     chomp(string)    => $_
- *  
- *  Equivalent to <code>$_ = $_.chomp(<em>string</em>)</code>. See
- *  <code>String#chomp</code>.
- *     
- *     $_ = "now\n"
- *     chomp         #=> "now"
- *     $_            #=> "now"
- *     chomp "ow"    #=> "n"
- *     $_            #=> "n"
- *     chomp "xxx"   #=> "n"
- *     $_            #=> "n"
- */
-
-static VALUE
-rb_f_chomp(int argc, VALUE *argv)
-{
-    VALUE str = uscore_get();
-    VALUE dup = rb_str_dup(str);
-
-    if (NIL_P(rb_str_chomp_bang(argc, argv, dup)))
-	return str;
-    rb_lastline_set(dup);
-    return dup;
-}
-
-
-/*
- *  call-seq:
  *     str.lstrip!   => self or nil
  *  
  *  Removes leading whitespace from <i>str</i>, returning <code>nil</code> if no
@@ -4075,22 +3864,7 @@
     return str;
 }
 
-/*
- *  call-seq:
- *     scan(pattern)                   => array
- *     scan(pattern) {|///| block }    => $_
- *  
- *  Equivalent to calling <code>$_.scan</code>. See
- *  <code>String#scan</code>.
- */
 
-static VALUE
-rb_f_scan(VALUE self, VALUE pat)
-{
-    return rb_str_scan(uscore_get(), pat);
-}
-
-
 /*
  *  call-seq:
  *     str.hex   => integer
@@ -4510,21 +4284,6 @@
 
     rb_define_method(rb_cString, "sum", rb_str_sum, -1);
 
-    rb_define_global_function("sub", rb_f_sub, -1);
-    rb_define_global_function("gsub", rb_f_gsub, -1);
-
-    rb_define_global_function("sub!", rb_f_sub_bang, -1);
-    rb_define_global_function("gsub!", rb_f_gsub_bang, -1);
-
-    rb_define_global_function("chop", rb_f_chop, 0);
-    rb_define_global_function("chop!", rb_f_chop_bang, 0);
-
-    rb_define_global_function("chomp", rb_f_chomp, -1);
-    rb_define_global_function("chomp!", rb_f_chomp_bang, -1);
-
-    rb_define_global_function("split", rb_f_split, -1);
-    rb_define_global_function("scan", rb_f_scan, 1);
-
     rb_define_method(rb_cString, "slice", rb_str_aref_m, -1);
     rb_define_method(rb_cString, "slice!", rb_str_slice_bang, -1);
 

Modified: trunk/struct.c
===================================================================
--- trunk/struct.c	2006-02-09 17:19:49 UTC (rev 376)
+++ trunk/struct.c	2006-02-09 17:49:56 UTC (rev 377)
@@ -2,8 +2,8 @@
 
   struct.c -
 
-  $Author: ocean $
-  $Date: 2005/10/21 06:46:39 $
+  $Author: akr $
+  $Date: 2006/02/05 14:40:01 $
   created at: Tue Mar 22 18:44:30 JST 1995
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -47,9 +47,9 @@
 {
     VALUE members = rb_struct_s_members(rb_obj_class(s));
 
-    if (RSTRUCT(s)->len != RARRAY(members)->len) {
+    if (RSTRUCT_LEN(s) != RARRAY(members)->len) {
 	rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
-		 RARRAY(members)->len, RSTRUCT(s)->len);
+		 RARRAY(members)->len, RSTRUCT_LEN(s));
     }
     return members;
 }
@@ -99,7 +99,7 @@
     slot = ID2SYM(id);
     for (i=0; i<RARRAY(members)->len; i++) {
 	if (RARRAY(members)->ptr[i] == slot) {
-	    return RSTRUCT(obj)->ptr[i];
+	    return RSTRUCT_PTR(obj)[i];
 	}
     }
     rb_name_error(id, "%s is not struct member", rb_id2name(id));
@@ -112,16 +112,16 @@
     return rb_struct_getmember(obj, rb_frame_this_func());
 }
 
-static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT(obj)->ptr[0];}
-static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT(obj)->ptr[1];}
-static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT(obj)->ptr[2];}
-static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT(obj)->ptr[3];}
-static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT(obj)->ptr[4];}
-static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT(obj)->ptr[5];}
-static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT(obj)->ptr[6];}
-static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT(obj)->ptr[7];}
-static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT(obj)->ptr[8];}
-static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT(obj)->ptr[9];}
+static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_PTR(obj)[0];}
+static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_PTR(obj)[1];}
+static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_PTR(obj)[2];}
+static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_PTR(obj)[3];}
+static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_PTR(obj)[4];}
+static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_PTR(obj)[5];}
+static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_PTR(obj)[6];}
+static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_PTR(obj)[7];}
+static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_PTR(obj)[8];}
+static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_PTR(obj)[9];}
 
 #define N_REF_FUNC (sizeof(ref_func) / sizeof(ref_func[0]))
 
@@ -157,7 +157,7 @@
     for (i=0; i<RARRAY(members)->len; i++) {
 	slot = RARRAY(members)->ptr[i];
 	if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) {
-	    return RSTRUCT(obj)->ptr[i] = val;
+	    return RSTRUCT_PTR(obj)[i] = val;
 	}
     }
     rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
@@ -315,9 +315,9 @@
     if (n < RARRAY(values)->len) {
 	rb_raise(rb_eArgError, "struct size differs");
     }
-    MEMCPY(RSTRUCT(self)->ptr, RARRAY(values)->ptr, VALUE, RARRAY(values)->len);
+    MEMCPY(RSTRUCT_PTR(self), RARRAY(values)->ptr, VALUE, RARRAY(values)->len);
     if (n > RARRAY(values)->len) {
-	rb_mem_clear(RSTRUCT(self)->ptr+RARRAY(values)->len,
+	rb_mem_clear(RSTRUCT_PTR(self)+RARRAY(values)->len,
 		     n-RARRAY(values)->len);
     }
     return Qnil;
@@ -334,9 +334,16 @@
     size = rb_struct_iv_get(klass, "__size__");
     n = FIX2LONG(size);
 
-    st->ptr = ALLOC_N(VALUE, n);
-    rb_mem_clear(st->ptr, n);
-    st->len = n;
+    if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
+        RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
+        RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
+	rb_mem_clear(st->as.ary, n);
+    }
+    else {
+	st->as.heap.ptr = ALLOC_N(VALUE, n);
+	rb_mem_clear(st->as.heap.ptr, n);
+	st->as.heap.len = n;
+    }
 
     return (VALUE)st;
 }
@@ -390,8 +397,8 @@
     long i;
 
     RETURN_ENUMERATOR(s, 0, 0);
-    for (i=0; i<RSTRUCT(s)->len; i++) {
-	rb_yield(RSTRUCT(s)->ptr[i]);
+    for (i=0; i<RSTRUCT_LEN(s); i++) {
+	rb_yield(RSTRUCT_PTR(s)[i]);
     }
     return s;
 }
@@ -422,8 +429,8 @@
 
     RETURN_ENUMERATOR(s, 0, 0);
     members = rb_struct_members(s);
-    for (i=0; i<RSTRUCT(s)->len; i++) {
-	rb_yield_values(2, rb_ary_entry(members, i), RSTRUCT(s)->ptr[i]);
+    for (i=0; i<RSTRUCT_LEN(s); i++) {
+	rb_yield_values(2, rb_ary_entry(members, i), RSTRUCT_PTR(s)[i]);
     }
     return s;
 }
@@ -441,7 +448,7 @@
 
     members = rb_struct_members(s);
     str = rb_sprintf("#<struct %s ", cname);
-    for (i=0; i<RSTRUCT(s)->len; i++) {
+    for (i=0; i<RSTRUCT_LEN(s); i++) {
 	VALUE slot;
 	ID id;
 	char *p;
@@ -459,7 +466,7 @@
 	    rb_str_append(str, rb_inspect(slot));
 	}
 	rb_str_cat2(str, "=");
-	rb_str_append(str, rb_inspect(RSTRUCT(s)->ptr[i]));
+	rb_str_append(str, rb_inspect(RSTRUCT_PTR(s)[i]));
     }
     rb_str_cat2(str, ">");
     OBJ_INFECT(str, s);
@@ -496,7 +503,7 @@
 static VALUE
 rb_struct_to_a(VALUE s)
 {
-    return rb_ary_new4(RSTRUCT(s)->len, RSTRUCT(s)->ptr);
+    return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_PTR(s));
 }
 
 /* :nodoc: */
@@ -508,9 +515,15 @@
     if (!rb_obj_is_instance_of(s, rb_obj_class(copy))) {
 	rb_raise(rb_eTypeError, "wrong argument class");
     }
-    RSTRUCT(copy)->ptr = ALLOC_N(VALUE, RSTRUCT(s)->len);
-    RSTRUCT(copy)->len = RSTRUCT(s)->len;
-    MEMCPY(RSTRUCT(copy)->ptr, RSTRUCT(s)->ptr, VALUE, RSTRUCT(copy)->len);
+    if (0 < RSTRUCT_LEN(s) && RSTRUCT_LEN(s) <= RSTRUCT_EMBED_LEN_MAX) {
+        RBASIC(copy)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
+        RBASIC(copy)->flags |= RSTRUCT_LEN(s) << RSTRUCT_EMBED_LEN_SHIFT;
+    }
+    else {
+	RSTRUCT(copy)->as.heap.ptr = ALLOC_N(VALUE, RSTRUCT_LEN(s));
+	RSTRUCT(copy)->as.heap.len = RSTRUCT_LEN(s);
+    }
+    MEMCPY(RSTRUCT_PTR(copy), RSTRUCT_PTR(s), VALUE, RSTRUCT_LEN(copy));
 
     return copy;
 }
@@ -525,7 +538,7 @@
     len = RARRAY(members)->len;
     for (i=0; i<len; i++) {
 	if (SYM2ID(RARRAY(members)->ptr[i]) == id) {
-	    return RSTRUCT(s)->ptr[i];
+	    return RSTRUCT_PTR(s)[i];
 	}
     }
     rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
@@ -561,14 +574,14 @@
     }
 
     i = NUM2LONG(idx);
-    if (i < 0) i = RSTRUCT(s)->len + i;
+    if (i < 0) i = RSTRUCT_LEN(s) + i;
     if (i < 0)
         rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
-		 i, RSTRUCT(s)->len);
-    if (RSTRUCT(s)->len <= i)
+		 i, RSTRUCT_LEN(s));
+    if (RSTRUCT_LEN(s) <= i)
         rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
-		 i, RSTRUCT(s)->len);
-    return RSTRUCT(s)->ptr[i];
+		 i, RSTRUCT_LEN(s));
+    return RSTRUCT_PTR(s)[i];
 }
 
 static VALUE
@@ -580,13 +593,13 @@
     members = rb_struct_members(s);
     rb_struct_modify(s);
     len = RARRAY(members)->len;
-    if (RSTRUCT(s)->len != RARRAY(members)->len) {
+    if (RSTRUCT_LEN(s) != RARRAY(members)->len) {
 	rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
-		 RARRAY(members)->len, RSTRUCT(s)->len);
+		 RARRAY(members)->len, RSTRUCT_LEN(s));
     }
     for (i=0; i<len; i++) {
 	if (SYM2ID(RARRAY(members)->ptr[i]) == id) {
-	    RSTRUCT(s)->ptr[i] = val;
+	    RSTRUCT_PTR(s)[i] = val;
 	    return val;
 	}
     }
@@ -624,17 +637,17 @@
     }
 
     i = NUM2LONG(idx);
-    if (i < 0) i = RSTRUCT(s)->len + i;
+    if (i < 0) i = RSTRUCT_LEN(s) + i;
     if (i < 0) {
         rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
-		 i, RSTRUCT(s)->len);
+		 i, RSTRUCT_LEN(s));
     }
-    if (RSTRUCT(s)->len <= i) {
+    if (RSTRUCT_LEN(s) <= i) {
         rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
-		 i, RSTRUCT(s)->len);
+		 i, RSTRUCT_LEN(s));
     }
     rb_struct_modify(s);
-    return RSTRUCT(s)->ptr[i] = val;
+    return RSTRUCT_PTR(s)[i] = val;
 }
 
 static VALUE
@@ -662,26 +675,20 @@
 static VALUE
 rb_struct_values_at(int argc, VALUE *argv, VALUE s)
 {
-    return rb_get_values_at(s, RSTRUCT(s)->len, argc, argv, struct_entry);
+    return rb_get_values_at(s, RSTRUCT_LEN(s), argc, argv, struct_entry);
 }
 
 /*
  *  call-seq:
- *     struct.select(fixnum, ... )   => array
  *     struct.select {|i| block }    => array
  *  
- *  The first form returns an array containing the elements in
- *  <i>struct</i> corresponding to the given indices. The second
- *  form invokes the block passing in successive elements from
+ *  Invokes the block passing in successive elements from
  *  <i>struct</i>, returning an array containing those elements
  *  for which the block returns a true value (equivalent to
  *  <code>Enumerable#select</code>).
  *     
  *     Lots = Struct.new(:a, :b, :c, :d, :e, :f)
  *     l = Lots.new(11, 22, 33, 44, 55, 66)
- *     l.select(1, 3, 5)               #=> [22, 44, 66]
- *     l.select(0, 2, 4)               #=> [11, 33, 55]
- *     l.select(-1, -3, -5)            #=> [66, 44, 22]
  *     l.select {|v| (v % 2).zero? }   #=> [22, 44, 66]
  */
 
@@ -695,9 +702,9 @@
 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
     }
     result = rb_ary_new();
-    for (i = 0; i < RSTRUCT(s)->len; i++) {
-	if (RTEST(rb_yield(RSTRUCT(s)->ptr[i]))) {
-	    rb_ary_push(result, RSTRUCT(s)->ptr[i]);
+    for (i = 0; i < RSTRUCT_LEN(s); i++) {
+	if (RTEST(rb_yield(RSTRUCT_PTR(s)[i]))) {
+	    rb_ary_push(result, RSTRUCT_PTR(s)[i]);
 	}
     }
 
@@ -729,12 +736,12 @@
     if (s == s2) return Qtrue;
     if (TYPE(s2) != T_STRUCT) return Qfalse;
     if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
-    if (RSTRUCT(s)->len != RSTRUCT(s2)->len) {
+    if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
 	rb_bug("inconsistent struct"); /* should never happen */
     }
 
-    for (i=0; i<RSTRUCT(s)->len; i++) {
-	if (!rb_equal(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return Qfalse;
+    for (i=0; i<RSTRUCT_LEN(s); i++) {
+	if (!rb_equal(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse;
     }
     return Qtrue;
 }
@@ -753,9 +760,9 @@
     VALUE n;
 
     h = rb_hash(rb_obj_class(s));
-    for (i = 0; i < RSTRUCT(s)->len; i++) {
+    for (i = 0; i < RSTRUCT_LEN(s); i++) {
 	h = (h << 1) | (h<0 ? 1 : 0);
-	n = rb_hash(RSTRUCT(s)->ptr[i]);
+	n = rb_hash(RSTRUCT_PTR(s)[i]);
 	h ^= NUM2LONG(n);
     }
     return LONG2FIX(h);
@@ -777,12 +784,12 @@
     if (s == s2) return Qtrue;
     if (TYPE(s2) != T_STRUCT) return Qfalse;
     if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
-    if (RSTRUCT(s)->len != RSTRUCT(s2)->len) {
+    if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
 	rb_bug("inconsistent struct"); /* should never happen */
     }
 
-    for (i=0; i<RSTRUCT(s)->len; i++) {
-	if (!rb_eql(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return Qfalse;
+    for (i=0; i<RSTRUCT_LEN(s); i++) {
+	if (!rb_eql(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse;
     }
     return Qtrue;
 }
@@ -802,7 +809,7 @@
 static VALUE
 rb_struct_size(VALUE s)
 {
-    return LONG2FIX(RSTRUCT(s)->len);
+    return LONG2FIX(RSTRUCT_LEN(s));
 }
 
 /*


-- 
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]