なかだです。

現在glob_helper()は、バッファとしてVALUEを使い、また例外が起き
る可能性のあるコールバックはrb_protect()で保護しています。これ
はどちらか一方で充分なはずでないでしょうか。今ではrb_protect()
を跨いだcallccの呼び出しも禁止されていますし。

rb_glob()がStringを使わないようになれば、djgppやwin32などの
globbingを自前で行っている環境でもruby_init()の前に呼べるように
なり、以前ruby-talkかどこかで出ていた「違うargvを渡しても無視さ
れてしまう」という問題もなくなります。


Index: dir.c =================================================================== RCS file: /cvs/ruby/src/ruby/dir.c,v retrieving revision 1.138 diff -U2 -p -r1.138 dir.c --- dir.c 11 Apr 2005 13:30:10 -0000 1.138 +++ dir.c 17 May 2005 11:10:08 -0000 @@ -1117,19 +1117,19 @@ glob_free_pattern(list) } -static VALUE +static char * join_path(path, dirsep, name) - VALUE path; + const char *path; int dirsep; const char *name; { - long len = RSTRING(path)->len; - VALUE buf = rb_str_new(0, RSTRING(path)->len+strlen(name)+(dirsep?1:0)); + long len = strlen(path); + char *buf = ALLOC_N(char, len+strlen(name)+(dirsep?1:0)); - memcpy(RSTRING(buf)->ptr, RSTRING(path)->ptr, len); + memcpy(buf, path, len); if (dirsep) { - strcpy(RSTRING(buf)->ptr+len, "/"); + strcpy(buf+len, "/"); len++; } - strcpy(RSTRING(buf)->ptr+len, name); + strcpy(buf+len, name); return buf; } @@ -1150,6 +1150,6 @@ enum answer { YES, NO, UNKNOWN }; struct glob_args { - void (*func) _((VALUE, VALUE)); - VALUE c; + void (*func) _((const char *, VALUE)); + const char *c; VALUE v; }; @@ -1162,8 +1162,6 @@ glob_func_caller(val) { struct glob_args *args = (struct glob_args *)val; - VALUE path = args->c; - OBJ_TAINT(path); - (*args->func)(path, args->v); + (*args->func)(args->c, args->v); return Qnil; } @@ -1171,6 +1169,6 @@ glob_func_caller(val) static int glob_call_func(func, path, arg) - void (*func) _((VALUE, VALUE)); - VALUE path; + void (*func) _((const char *, VALUE)); + const char *path; VALUE arg; { @@ -1188,5 +1186,5 @@ glob_call_func(func, path, arg) static int glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg) - VALUE path; + 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? */ @@ -1195,5 +1193,5 @@ glob_helper(path, dirsep, exist, isdir, struct glob_pattern **end; int flags; - void (*func) _((VALUE, VALUE)); + void (*func) _((const char *, VALUE)); VALUE arg; { @@ -1226,7 +1224,7 @@ glob_helper(path, dirsep, exist, isdir, } - if (RSTRING(path)->len > 0) { + if (*path) { if (match_all && exist == UNKNOWN) { - if (do_lstat(RSTRING(path)->ptr, &st) == 0) { + if (do_lstat(path, &st) == 0) { exist = YES; isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO; @@ -1239,5 +1237,5 @@ glob_helper(path, dirsep, exist, isdir, if (match_dir && isdir == UNKNOWN) { - if (do_stat(RSTRING(path)->ptr, &st) == 0) { + if (do_stat(path, &st) == 0) { exist = YES; isdir = S_ISDIR(st.st_mode) ? YES : NO; @@ -1255,5 +1253,7 @@ glob_helper(path, dirsep, exist, isdir, if (match_dir && isdir == YES) { - status = glob_call_func(func, join_path(path, dirsep, ""), arg); + char *tmp = join_path(path, dirsep, ""); + status = glob_call_func(func, tmp, arg); + free(tmp); if (status) return status; } @@ -1264,9 +1264,9 @@ glob_helper(path, dirsep, exist, isdir, if (magical || recursive) { struct dirent *dp; - DIR *dirp = do_opendir(RSTRING(path)->len > 0 ? RSTRING(path)->ptr : "."); + DIR *dirp = do_opendir(path); if (dirp == NULL) return 0; for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { - VALUE buf = join_path(path, dirsep, dp->d_name); + char *buf = join_path(path, dirsep, dp->d_name); enum answer new_isdir = UNKNOWN; @@ -1274,5 +1274,5 @@ glob_helper(path, dirsep, exist, isdir, && fnmatch("*", dp->d_name, flags) == 0) { #ifndef _WIN32 - if (do_lstat(RSTRING(buf)->ptr, &st) == 0) + if (do_lstat(buf, &st) == 0) new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO; else @@ -1299,4 +1299,5 @@ glob_helper(path, dirsep, exist, isdir, status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end, flags, func, arg); + free(buf); free(new_beg); if (status) break; @@ -1314,5 +1315,5 @@ glob_helper(path, dirsep, exist, isdir, for (cur = copy_beg; cur < copy_end; ++cur) { if (*cur) { - VALUE buf; + char *buf; char *name; name = ALLOC_N(char, strlen((*cur)->str) + 1); @@ -1332,4 +1333,5 @@ glob_helper(path, dirsep, exist, isdir, free(name); status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg); + free(buf); free(new_beg); if (status) break; @@ -1345,13 +1347,13 @@ glob_helper(path, dirsep, exist, isdir, static int rb_glob2(path, offset, flags, func, arg) - VALUE path; + const char *path; long offset; int flags; - void (*func) _((VALUE, VALUE)); + void (*func) _((const char *, VALUE)); VALUE arg; { struct glob_pattern *list; const char *root, *start; - VALUE buf; + char *buf; int n; int status; @@ -1361,5 +1363,5 @@ rb_glob2(path, offset, flags, func, arg) } - start = root = StringValuePtr(path) + offset; + start = root = path + offset; #if defined DOSISH flags |= FNM_CASEFOLD; @@ -1372,9 +1374,12 @@ rb_glob2(path, offset, flags, func, arg) n = root - start; - buf = rb_str_new(start, n); + buf = ALLOC_N(char, n + 1); + MEMCPY(buf, start, char, n); + buf[n] = '\0'; list = glob_make_pattern(root, flags); status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg); glob_free_pattern(list); + free(buf); return status; @@ -1388,8 +1393,9 @@ struct rb_glob_args { static VALUE rb_glob_caller(path, a) - VALUE path, a; + const char *path; + VALUE a; { struct rb_glob_args *args = (struct rb_glob_args *)a; - (*args->func)(RSTRING(path)->ptr, args->arg); + (*args->func)(path, args->arg); return Qnil; } @@ -1406,5 +1412,5 @@ rb_glob(path, func, arg) args.func = func; args.arg = arg; - status = rb_glob2(rb_str_new2(path), 0, 0, rb_glob_caller, &args); + status = rb_glob2(path, 0, 0, rb_glob_caller, &args); if (status) rb_jump_tag(status); @@ -1413,7 +1419,8 @@ rb_glob(path, func, arg) static void push_pattern(path, ary) - VALUE path, ary; + const char *path; + VALUE ary; { - rb_ary_push(ary, path); + rb_ary_push(ary, rb_tainted_str_new2(path)); } Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.781 diff -U2 -p -r1.781 eval.c --- eval.c 13 May 2005 14:33:02 -0000 1.781 +++ eval.c 17 May 2005 17:46:07 -0000 @@ -1424,8 +1424,4 @@ ruby_options(argc, argv) int state; -#ifdef _WIN32 - argc = rb_w32_cmdvector(GetCommandLine(), &argv); -#endif - Init_stack((void*)&state); PUSH_THREAD_TAG(); @@ -1442,8 +1438,4 @@ ruby_options(argc, argv) } POP_THREAD_TAG(); - -#ifdef _WIN32_WCE - wce_FreeCommandLine(); -#endif } Index: win32/win32.c =================================================================== RCS file: /cvs/ruby/src/ruby/win32/win32.c,v retrieving revision 1.151 diff -U2 -p -r1.151 win32.c --- win32/win32.c 17 May 2005 02:50:42 -0000 1.151 +++ win32/win32.c 17 May 2005 17:48:50 -0000 @@ -423,4 +423,9 @@ void // + // subvert cmd.exe's feeble attempt at command line parsing + // + *argc = make_cmdvector(GetCommandLine(), argv); + + // // Now set up the correct time stuff // @@ -434,4 +439,9 @@ NtInitialize(int *argc, char ***argv) // Initialize Winsock StartSockets(); + +#ifdef _WIN32_WCE + // free commandline buffer + wce_FreeCommandLine(); +#endif }
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦