[前][次][番号順一覧][スレッド一覧]

ruby-changes:6437

From: usa <ko1@a...>
Date: Tue, 8 Jul 2008 11:44:31 +0900 (JST)
Subject: [ruby-changes:6437] Ruby:r17953 (trunk): * dir.c: shoudn't use ruby object in globbing, because glob service

usa	2008-07-08 11:44:12 +0900 (Tue, 08 Jul 2008)

  New Revision: 17953

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17953

  Log:
    * dir.c: shoudn't use ruby object in globbing, because glob service
      routines are called before initializing ruby on some platforms (ex.
      windows).
    

  Modified files:
    trunk/ChangeLog
    trunk/dir.c
    trunk/include/ruby/ruby.h

Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h	(revision 17952)
+++ include/ruby/ruby.h	(revision 17953)
@@ -725,8 +725,8 @@
 
 void rb_obj_infect(VALUE,VALUE);
 
-typedef int ruby_glob_func(VALUE,VALUE);
-void rb_glob(const char*,void(*)(VALUE,VALUE),VALUE);
+typedef int ruby_glob_func(const char*,VALUE, void*);
+void rb_glob(const char*,void(*)(const char*,VALUE,void*),VALUE);
 int ruby_glob(const char*,int,ruby_glob_func*,VALUE);
 int ruby_brace_glob(const char*,int,ruby_glob_func*,VALUE);
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 17952)
+++ ChangeLog	(revision 17953)
@@ -1,3 +1,9 @@
+Tue Jul  8 11:41:17 2008  NAKAMURA Usaku  <usa@r...>
+
+	* dir.c: shoudn't use ruby object in globbing, because glob service
+	  routines are called before initializing ruby on some platforms (ex.
+	  windows).
+
 Tue Jul  8 10:08:40 2008  NARUSE, Yui  <naruse@r...>
 
 	* dir.c (Next): use rb_enc_mbclen. [ruby-dev:35390]
Index: dir.c
===================================================================
--- dir.c	(revision 17952)
+++ dir.c	(revision 17953)
@@ -87,13 +87,14 @@
 char_casecmp(const char *p1, const char *p2, rb_encoding *enc, const int nocase)
 {
     const char *p1end, *p2end;
+    int c1, c2;
 
     if (!*p1) return *p1;
     if (!*p2) return -*p2;
     p1end = p1 + strlen(p1);
     p2end = p2 + strlen(p2);
-    int c1 = rb_enc_codepoint(p1, p1end, enc);
-    int c2 = rb_enc_codepoint(p2, p2end, enc);
+    c1 = rb_enc_codepoint(p1, p1end, enc);
+    c2 = rb_enc_codepoint(p2, p2end, enc);
 
     if (c1 == c2) return 0;
     if (nocase) {
@@ -237,16 +238,16 @@
 
 static int
 fnmatch(
-    VALUE pattern,
-    VALUE string,
+    const char *pattern,
+    rb_encoding *enc,
+    const char *string,
     int flags)
 {
-    const char *p = RSTRING_PTR(pattern); /* pattern */
-    const char *s = RSTRING_PTR(string); /* string */
-    const char *send = RSTRING_END(string);
+    const char *p = pattern;
+    const char *s = string;
+    const char *send = s + strlen(string);
     const int period = !(flags & FNM_DOTMATCH);
     const int pathname = flags & FNM_PATHNAME;
-    rb_encoding *enc = rb_enc_get(pattern);
 
     const char *ptmp = 0;
     const char *stmp = 0;
@@ -1180,9 +1181,10 @@
 #endif
 
 struct glob_args {
-    void (*func)(VALUE, VALUE);
-    VALUE path;
+    void (*func)(const char *, VALUE, rb_encoding *);
+    const char *path;
     VALUE value;
+    rb_encoding *enc;
 };
 
 static VALUE
@@ -1190,15 +1192,15 @@
 {
     struct glob_args *args = (struct glob_args *)val;
 
-    (*args->func)(args->path, args->value);
+    (*args->func)(args->path, args->value, args->enc);
     return Qnil;
 }
 
-#define glob_call_func(func, path, arg) (*func)(path, arg)
+#define glob_call_func(func, path, arg, enc) (*func)(path, arg, enc)
 
 static int
 glob_helper(
-    VALUE vpath,
+    const char *path,
     int dirsep, /* '/' should be placed before appending child entry's name to 'path'. */
     enum answer exist, /* Does 'path' indicate an existing entry? */
     enum answer isdir, /* Does 'path' indicate a directory or a symlink to a directory? */
@@ -1206,9 +1208,9 @@
     struct glob_pattern **end,
     int flags,
     ruby_glob_func *func,
-    VALUE arg)
+    VALUE arg,
+    rb_encoding *enc)
 {
-    const char *path = RSTRING_PTR(vpath);
     struct stat st;
     int status = 0;
     struct glob_pattern **cur, **new_beg, **new_end;
@@ -1261,13 +1263,13 @@
 	    }
 	}
 	if (match_all && exist == YES) {
-	    status = glob_call_func(func, rb_tainted_str_new2(path), arg);
+	    status = glob_call_func(func, path, arg, enc);
 	    if (status) return status;
 	}
 	if (match_dir && isdir == YES) {
 	    char *tmp = join_path(path, dirsep, "");
 	    if (!tmp) return -1;
-	    status = glob_call_func(func, rb_tainted_str_new2(tmp), arg);
+	    status = glob_call_func(func, tmp, arg, enc);
 	    GLOB_FREE(tmp);
 	    if (status) return status;
 	}
@@ -1289,7 +1291,7 @@
 		break;
 	    }
 	    if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0
-		&& fnmatch(rb_usascii_str_new2("*"), rb_str_new2(dp->d_name), flags) == 0) {
+		&& fnmatch("*", rb_usascii_encoding(), dp->d_name, flags) == 0) {
 #ifndef _WIN32
 		if (do_lstat(buf, &st, flags) == 0)
 		    new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
@@ -1315,13 +1317,13 @@
 		    p = p->next; /* 0 times recursion */
 		}
 		if (p->type == PLAIN || p->type == MAGICAL) {
-		    if (fnmatch(rb_str_new2(p->str), rb_str_new2(dp->d_name), flags) == 0)
+		    if (fnmatch(p->str, enc, dp->d_name, flags) == 0)
 			*new_end++ = p->next;
 		}
 	    }
 
-	    status = glob_helper(rb_enc_str_new(buf, strlen(buf), rb_enc_get(vpath)), 1,
-	    			 YES, new_isdir, new_beg, new_end, flags, func, arg);
+	    status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end,
+				 flags, func, arg, enc);
 	    GLOB_FREE(buf);
 	    GLOB_FREE(new_beg);
 	    if (status) break;
@@ -1347,7 +1349,7 @@
 		    break;
 		}
 		strcpy(name, (*cur)->str);
-		if (escape) remove_backslashes(name, rb_enc_get(vpath));
+		if (escape) remove_backslashes(name, enc);
 
 		new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
 		if (!new_beg) {
@@ -1357,7 +1359,7 @@
 		}
 		*new_end++ = (*cur)->next;
 		for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
-		    if (*cur2 && fnmatch(rb_str_new2((*cur2)->str), rb_str_new2(name), flags) == 0) {
+		    if (*cur2 && fnmatch((*cur2)->str, enc, name, flags) == 0) {
 			*new_end++ = (*cur2)->next;
 			*cur2 = 0;
 		    }
@@ -1370,8 +1372,8 @@
 		    status = -1;
 		    break;
 		}
-		status = glob_helper(rb_enc_str_new(buf, strlen(buf), rb_enc_get(vpath)), 1,
-				     UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg);
+		status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg,
+				     new_end, flags, func, arg, enc);
 		GLOB_FREE(buf);
 		GLOB_FREE(new_beg);
 		if (status) break;
@@ -1385,14 +1387,15 @@
 }
 
 static int
-ruby_glob0(VALUE path, int flags, ruby_glob_func *func, VALUE arg)
+ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
 {
     struct glob_pattern *list;
     const char *root, *start;
+    char *buf;
+    int n;
     int status;
-    VALUE buf;
 
-    start = root = RSTRING_PTR(path);
+    start = root = path;
     flags |= FNM_SYSCASE;
 #if defined DOSISH
     root = rb_path_skip_prefix(root);
@@ -1400,14 +1403,20 @@
 
     if (root && *root == '/') root++;
 
-    buf = rb_enc_str_new(start, root - start, rb_enc_get(path));
+    n = root - start;
+    buf = GLOB_ALLOC_N(char, n + 1);
+    if (!buf) return -1;
+    MEMCPY(buf, start, char, n);
+    buf[n] = '\0';
 
-    list = glob_make_pattern(root, flags, rb_enc_get(path));
+    list = glob_make_pattern(root, flags, enc);
     if (!list) {
+	GLOB_FREE(buf);
 	return -1;
     }
-    status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg);
+    status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg, enc);
     glob_free_pattern(list);
+    GLOB_FREE(buf);
 
     return status;
 }
@@ -1415,51 +1424,59 @@
 int
 ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
 {
-    return ruby_glob0(rb_str_new2(path), flags & ~GLOB_VERBOSE, func, arg);
+    return ruby_glob0(path, flags & ~GLOB_VERBOSE, func, arg,
+		      rb_ascii8bit_encoding());
 }
 
 static int
-rb_glob_caller(VALUE path, VALUE a)
+rb_glob_caller(const char *path, VALUE a, rb_encoding *enc)
 {
     int status;
     struct glob_args *args = (struct glob_args *)a;
 
     args->path = path;
+    args->enc = enc;
     rb_protect(glob_func_caller, a, &status);
     return status;
 }
 
 static int
-rb_glob2(VALUE path, int flags, void (*func)(VALUE, VALUE), VALUE arg)
+rb_glob2(const char *path, int flags,
+	 void (*func)(const char *, VALUE, rb_encoding *), VALUE arg,
+	 rb_encoding* enc)
 {
     struct glob_args args;
 
     args.func = func;
     args.value = arg;
+    args.enc = enc;
 
     if (flags & FNM_SYSCASE) {
 	rb_warning("Dir.glob() ignores File::FNM_CASEFOLD");
     }
 
-    return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
+    return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args,
+		      enc);
 }
 
 void
-rb_glob(const char *path, void (*func)(VALUE, VALUE), VALUE arg)
+rb_glob(const char *path, void (*func)(const char *, VALUE, void *), VALUE arg)
 {
-    int status = rb_glob2(rb_str_new2(path), 0, func, arg);
+    int status = rb_glob2(path, 0, func, arg, rb_ascii8bit_encoding());
     if (status) GLOB_JUMP_TAG(status);
 }
 
 static void
-push_pattern(VALUE path, VALUE ary)
+push_pattern(const char *path, VALUE ary, rb_encoding *enc)
 {
-    OBJ_TAINT(path);
-    rb_ary_push(ary, path);
+    VALUE vpath = rb_tainted_str_new2(path);
+    rb_enc_associate(vpath, enc);
+    rb_ary_push(ary, vpath);
 }
 
 static int
-ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
+ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg,
+		  rb_encoding *enc)
 {
     const int escape = !(flags & FNM_NOESCAPE);
     const char *p = str;
@@ -1509,7 +1526,7 @@
 	GLOB_FREE(buf);
     }
     else if (!lbrace && !rbrace) {
-	status = (*func)(rb_enc_str_new(s, strlen(s), enc), arg);
+	status = (*func)(s, arg, enc);
     }
 
     return status;
@@ -1522,28 +1539,30 @@
 };
 
 static int
-glob_brace(VALUE path, VALUE val)
+glob_brace(const char *path, VALUE val, rb_encoding *enc)
 {
     struct brace_args *arg = (struct brace_args *)val;
 
-    return ruby_glob0(path, arg->flags, arg->func, arg->value);
+    return ruby_glob0(path, arg->flags, arg->func, arg->value, enc);
 }
 
 static int
-ruby_brace_glob0(VALUE str, int flags, ruby_glob_func *func, VALUE arg)
+ruby_brace_glob0(const char *str, int flags, ruby_glob_func *func, VALUE arg,
+		 rb_encoding* enc)
 {
     struct brace_args args;
 
     args.func = func;
     args.value = arg;
     args.flags = flags;
-    return ruby_brace_expand(RSTRING_PTR(str), flags, glob_brace, (VALUE)&args, rb_enc_get(str));
+    return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args, enc);
 }
 
 int
 ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
 {
-    return ruby_brace_glob0(rb_str_new2(str), flags & ~GLOB_VERBOSE, func, arg);
+    return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg,
+			    rb_ascii8bit_encoding());
 }
 
 static int
@@ -1553,7 +1572,8 @@
 
     args.func = push_pattern;
     args.value = ary;
-    return ruby_brace_glob0(str, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
+    return ruby_brace_glob0(RSTRING_PTR(str), flags | GLOB_VERBOSE,
+			    rb_glob_caller, (VALUE)&args, rb_enc_get(str));
 }
 
 static VALUE
@@ -1567,9 +1587,10 @@
 
     while (offset < RSTRING_LEN(str)) {
 	char *p, *pend;
+	int status;
 	p = RSTRING_PTR(str) + offset;
-	int status = push_glob(ary,
-		rb_enc_str_new(p, strlen(p), rb_enc_get(str)), flags);
+	status = push_glob(ary, rb_enc_str_new(p, strlen(p), rb_enc_get(str)),
+			   flags);
 	if (status) GLOB_JUMP_TAG(status);
 	if (offset >= RSTRING_LEN(str)) break;
 	p += strlen(p) + 1;
@@ -1863,7 +1884,8 @@
     StringValue(pattern);
     FilePathStringValue(path);
 
-    if (fnmatch(pattern, path, flags) == 0)
+    if (fnmatch(RSTRING_PTR(pattern), rb_enc_get(pattern), RSTRING_PTR(path),
+		flags) == 0)
 	return Qtrue;
 
     return Qfalse;

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]