山本です。

修正できたと思います。Sienaさんのテストスクリプトの結果は、

?       : ー − 表
??      : 表裏
???     : ソフト てすと
ー      : ー
ー*     : ー
−      : −
−*     : −
?\      :
ソフト  : ソフト

でした。[ruby-dev:22270]に対するパッチです。

find_magicにエスケープ削除を組み込もうかと思いましたが、
find_magicが複雑になりすぎる気がして、とりあえず今の形にしました。

リファクタリング前後で速度比較しましたが、あまり違いがなかったです。うーむ・・・
5992個のファイルがあるドライブに Dir.glob("f:/**/*"){} で、
リファクタリング前で11sec、後で10secでした。
(一度目はハードディスクにアクセスするので、二度目以降)


--- dir.c-22270	Sun Dec 14 10:57:46 2003
+++ dir.c	Sun Dec 14 11:02:14 2003
@@ -167,7 +167,7 @@ range(pat, test, flags)
 	char *pstart, *pend;
+	if (*pat == ']')
+	    return ok == not ? 0 : pat+1;
+	if (escape && pat[1] == '\\')
+	    pat++;
 	pstart = pend = pat;
-	if (*pstart == ']')
-	    return ok == not ? 0 : ++pat;
-	else if (escape && *pstart == '\\')
-	    pstart = pend = ++pat;
 		Inc(pat);
@@ -680,5 +680,6 @@ do_fnmatch(beg, end, string, flags)
 
-static void
-remove_backslashes(p)
+static int
+remove_backslashes(p, pend)
     char *p;
+    char *pend;
 {
@@ -686,4 +687,5 @@ remove_backslashes(p)
     char *s = p;
+    int n = 0;
 
-    while (*p) {
+    while (*p && p < pend) {
 	if (*p == '\\') {
@@ -691,2 +693,3 @@ remove_backslashes(p)
 		memmove(t, s, p - s);
+		n++;
 	    }
@@ -699,5 +702,10 @@ remove_backslashes(p)
 
+    while (*p++);
+
     if (t != s) {
-	memmove(t, s, p - s + 1); /* move '\0' too */
+	memmove(t, s, p - s); /* move '\0' too */
+	n++;
     }
+
+    return n;
 }
@@ -764,2 +772,8 @@ glob_helper(path, sub, flags, func, arg)
 
+    if (!(flags & FNM_NOESCAPE)) {
+	int n = remove_backslashes(sub, beg);
+	beg -= n;
+	end -= n;
+    }
+
     if (*beg == '\0') { /* magic not found */
@@ -907,6 +921,4 @@ rb_glob2(path, flags, func, arg)
 #if defined DOSISH
-    remove_backslashes(path);
     status = glob_helper(path, (ISALPHA(path[0]) && path[1] == ':' ? path + 2 : path), flags, func, arg);
 #else
-    if (!(flags & FNM_NOESCAPE)) remove_backslashes(path);
     status = glob_helper(path, path, flags, func, arg);