なかだです。

At Wed, 7 Jan 2004 17:52:53 +0900,
H.Yamamoto wrote:
> > findと比べてみると、今の1.9はfind -depth相当ですが、1.8はちょっ
> > と独自の順序です。どちらかというと、1.8の順序に戻すよりもfindの
> > デフォルトができたほうがいいように思うんですが。
> 
> デフォルト == find のデフォルト(-depth == find の -depth)
> にすべきということですか?

です。こんな感じ。

あと、Dir.openも継承されたときサブクラスのinitializeを呼ぶよう
になってます。


Index: dir.c =================================================================== RCS file: /cvs/ruby/src/ruby/dir.c,v retrieving revision 1.94 diff -u -2 -p -d -r1.94 dir.c --- dir.c 5 Jan 2004 10:01:51 -0000 1.94 +++ dir.c 7 Jan 2004 10:31:14 -0000 @@ -72,4 +72,5 @@ char *strchr _((char*,char)); #define FNM_DOTMATCH 0x04 #define FNM_CASEFOLD 0x08 +#define GLOB_DEPTH 0x0100 #define FNM_NOMATCH 1 @@ -347,11 +348,11 @@ dir_initialize(dir, dirname) */ static VALUE -dir_s_open(klass, dirname) - VALUE klass, dirname; +dir_s_open(argc, argv, klass) + int argc; + VALUE *argv; + VALUE klass; { - struct dir_data *dp; - VALUE dir = Data_Make_Struct(klass, struct dir_data, 0, free_dir, dp); + VALUE dir = rb_class_new_instance(argc, argv, klass); - dir_initialize(dir, dirname); if (rb_block_given_p()) { return rb_ensure(rb_yield, dir, dir_close, dir); @@ -996,9 +997,21 @@ glob_helper(path, sub, separator, flags, struct stat st; int status = 0; - char *p = sub, *m, *buf; + char *p = sub, *m, *buf = 0; DIR *dirp; struct dirent *dp; int recursive = 0; int magical = 1; + int maxlen = 0, buflen; + int n1; +#define ALLOC_BUF(size) do { \ + int buflen = size; \ + if (!maxlen) { \ + memcpy(buf = ALLOC_N(char, buflen), path, n1); \ + } \ + else if (buflen > maxlen) { \ + REALLOC_N(buf, char, buflen); \ + } \ + maxlen = buflen; \ + } while (0) struct d_link { @@ -1062,48 +1075,49 @@ glob_helper(path, sub, separator, flags, } + n1 = p - path; + + if (!magical && !(flags & GLOB_DEPTH)) { + status = glob_helper(path, p, separator, flags, func, arg); + } for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { - const int n1 = p - path; const int n2 = n1 + NAMLEN(dp); - const int ok = 0; - const int ln = 1; - const int no = 2; - int is_dir = -1; /* not checked yet */ -#ifdef _WIN32 - is_dir = dp->d_isdir ? (dp->d_isrep ? ln : ok) : no; -#endif + enum {dir, symlnk, nodir} dirtype = -1; /* not checked yet */ + if (recursive && strcmp(".", dp->d_name) != 0 && strcmp("..", dp->d_name) != 0) { - buf = ALLOC_N(char, n2+4+strlen(p)+1); - memcpy(buf, path, n1); - strcpy(buf+n1, dp->d_name); + dirtype = nodir; + ALLOC_BUF(n2+4+strlen(p)+1); #ifndef _WIN32 - is_dir = no; + strcpy(buf+n1, dp->d_name); if (do_lstat(buf, &st) == 0) { if (S_ISDIR(st.st_mode)) - is_dir = ok; + dirtype = dir; else if (S_ISLNK(st.st_mode) && do_stat(buf, &st) == 0 && S_ISDIR(st.st_mode)) - is_dir = ln; + dirtype = symlnk; } +#else + if (dp->d_isdir) dirtype = (dp->d_isrep ? symlnk : dir); #endif - if (is_dir == ok) { + if (dirtype == dir && (flags & GLOB_DEPTH)) { strcpy(buf+n2, "/**/"); strcpy(buf+n2+4, p); status = glob_helper(buf, buf+n2+1, 1, flags, func, arg); } - free(buf); - if (status) break; } - if (is_dir == no && *m == '/') { + if (dirtype == nodir && *m == '/') { continue; } if (magical && do_fnmatch(p, m, dp->d_name, flags) == 0) { - buf = ALLOC_N(char, n2+1+1); - memcpy(buf, path, n1); - strcpy(buf+n1, dp->d_name); if (*m == '\0') { + ALLOC_BUF(n2+1); + strcpy(buf+n1, dp->d_name); status = glob_call_func(func, buf, arg); + if (status) break; } - else if (m[1] == '\0' && (is_dir == ok || is_dir == ln)) { /* *m == '/' */ + else if (m[1] == '\0' && (dirtype == dir || dirtype == symlnk)) { /* *m == '/' */ + ALLOC_BUF(n2+1+1); + strcpy(buf+n1, dp->d_name); strcpy(buf+n2, "/"); status = glob_call_func(func, buf, arg); + if (status) break; } else { @@ -1114,6 +1128,9 @@ glob_helper(path, sub, separator, flags, tail = &tmp->next; } - free(buf); - if (status) break; + } + if (dirtype == dir && !(flags & GLOB_DEPTH)) { + strcpy(buf+n2, "/**/"); + strcpy(buf+n2+4, p); + status = glob_helper(buf, buf+n2+1, 1, flags, func, arg); } } @@ -1123,5 +1140,4 @@ glob_helper(path, sub, separator, flags, while (link) { if (status == 0) { - const int n1 = p - path; const int n2 = n1 + strlen(link->name); buf = ALLOC_N(char, n2+strlen(m)+1); @@ -1137,8 +1153,9 @@ glob_helper(path, sub, separator, flags, } - if (!magical) { + if (!magical && (flags & GLOB_DEPTH)) { status = glob_helper(path, p, separator, flags, func, arg); } + free(buf); return status; } @@ -1495,5 +1512,5 @@ Init_Dir() rb_define_alloc_func(rb_cDir, dir_s_alloc); - rb_define_singleton_method(rb_cDir, "open", dir_s_open, 1); + rb_define_singleton_method(rb_cDir, "open", dir_s_open, -1); rb_define_singleton_method(rb_cDir, "foreach", dir_foreach, 1); rb_define_singleton_method(rb_cDir, "entries", dir_entries, 1); @@ -1529,3 +1546,5 @@ Init_Dir() rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH)); rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD)); + + rb_define_const(rb_cDir, "GLOB_DEPTH", INT2FIX(GLOB_DEPTH)); }
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦