From: nobu.nakada@... Date: 2001-07-21T23:56:05+09:00 Subject: [ruby-dev:13978] Re: library search path なかだです。 At Tue, 17 Jul 2001 03:04:51 +0900, Nobuyoshi-Nakada wrote: > > * 検索時に$arch-$osを付加して検索[ruby-ext:01796] provideのことを忘れてたので、[ruby-dev:13945]を追加して作り直 してみました。 こんなのはやりすぎかも知れませんが。 until test $cpu = i386; do cpu=i`expr $cpu : 'i\(.\)86' | tr 4-9 3-8`86 RUBY_LOAD_ARCH="${RUBY_LOAD_ARCH}\"${cpu}-${target_os}\", " done Index: configure.in =================================================================== RCS file: /cvs/ruby/src/ruby/configure.in,v retrieving revision 1.92 diff -u -2 -p -r1.92 configure.in --- configure.in 2001/06/11 05:31:17 1.92 +++ configure.in 2001/07/19 09:27:48 @@ -1052,7 +1052,9 @@ configure_args=$ac_configure_args AC_SUBST(configure_args)dnl +RUBY_LOAD_ARCH="" if test "$fat_binary" = yes ; then arch="fat-${target_os}" + RUBY_LOAD_ARCH="${RUBY_LOAD_ARCH}__ARCHITECTURE__\"-${target_os}\", " AC_DEFINE_UNQUOTED(RUBY_THIN_ARCHLIB, "${RUBY_LIB_PATH}/" __ARCHITECTURE__ "-${target_os}") @@ -1066,6 +1068,28 @@ else fi +RUBY_LOAD_ARCH="${RUBY_LOAD_ARCH}\"${arch}\", " +case ${target_cpu} in +[i[4-9]86]) + cpu=$target_cpu + until test $cpu = i386; do + cpu=i`expr $cpu : 'i\(.\)86' | tr 4-9 3-8`86 + RUBY_LOAD_ARCH="${RUBY_LOAD_ARCH}\"${cpu}-${target_os}\", " + done + ;; +esac + AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${RUBY_LIB_PATH}/${arch}") AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${RUBY_SITE_LIB_PATH2}/${arch}") +case ${target_os} in + mingw*|mswin*) + cpu=${target_cpu} + case ${cpu} in + i*86) cpu=i386;; + esac + RUBY_LOAD_ARCH="${RUBY_LOAD_ARCH}\"${cpu}-msvcrt\", " + ;; +esac +RUBY_LOAD_ARCH=`expr "${RUBY_LOAD_ARCH}" : '\(.*\), '` +AC_DEFINE_UNQUOTED(RUBY_LOAD_ARCH, ${RUBY_LOAD_ARCH}) AC_ARG_WITH(search-path, Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.194 diff -u -2 -p -r1.194 eval.c --- eval.c 2001/07/18 05:55:20 1.194 +++ eval.c 2001/07/20 15:13:24 @@ -5393,16 +5393,4 @@ rb_provide_feature(feature) VALUE feature; { - char *ext; - char *f = RSTRING(feature)->ptr; - - ext = strrchr(f, '.'); - if (ext && (strcmp(DLEXT, ext) == 0 -#ifdef DLEXT2 - || strcmp(DLEXT2, ext) == 0 -#endif - )) { - feature = rb_str_new(RSTRING(feature)->ptr, ext-RSTRING(feature)->ptr); - rb_str_cat2(feature, ".so"); - } if (rb_feature_p(RSTRING(feature)->ptr, Qtrue)) return; rb_ary_push(rb_features, feature); @@ -5426,4 +5414,12 @@ rb_f_require(obj, fname) volatile int safe = ruby_safe_level; + static const char *const dlext[] = { + ".rb", DLEXT, +#ifdef DLEXT2 + DLEXT2, +#endif + 0 + }; + SafeStringValue(fname); if (rb_feature_p(RSTRING(fname)->ptr, Qtrue)) @@ -5432,7 +5428,7 @@ rb_f_require(obj, fname) if (ext) { if (strcmp(".rb", ext) == 0) { - feature = rb_str_dup(fname); - tmp = rb_find_file(fname); - if (tmp) { + tmp = fname; + if (rb_find_file_ext(&tmp, NULL)) { + feature = fname; fname = tmp; goto load_rb; @@ -5440,52 +5436,38 @@ rb_f_require(obj, fname) } else if (strcmp(".so", ext) == 0 || strcmp(".o", ext) == 0) { - fname = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr); - tmp = rb_str_dup(fname); - rb_str_cat2(tmp, DLEXT); - tmp = rb_find_file(tmp); - if (tmp) { - feature = fname = tmp; - goto load_dyna; - } -#ifdef DLEXT2 - tmp = rb_str_dup(fname); - rb_str_cat2(tmp, DLEXT); - tmp = rb_find_file(tmp); - if (tmp) { - feature = fname = tmp; - goto load_dyna; - } -#endif - } - else if (strcmp(DLEXT, ext) == 0) { - tmp = rb_find_file(fname); - if (tmp) { - feature = fname = tmp; + feature = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr); + tmp = feature; + if (rb_find_file_ext(&tmp, dlext + 1)) { /* exclude .rb */ + rb_str_cat2(feature, ".so"); + fname = tmp; goto load_dyna; } } + else if (strcmp(DLEXT, ext) == 0 #ifdef DLEXT2 - else if (strcmp(DLEXT2, ext) == 0) { - tmp = rb_find_file(fname); - if (tmp) { - feature = fname = tmp; + || strcmp(DLEXT2, ext) == 0 +#endif + ) { + tmp = fname; + if (rb_find_file_ext(&tmp, NULL)) { + feature = fname; + fname = tmp; goto load_dyna; } } -#endif } tmp = fname; - switch (rb_find_file_noext(&tmp)) { + switch (rb_find_file_ext(&tmp, dlext)) { case 0: break; case 1: - feature = fname; + feature = rb_str_cat2(fname, ".rb"); fname = tmp; goto load_rb; default: - feature = fname; - fname = rb_find_file(tmp); + feature = rb_str_cat2(fname, ".so"); + fname = tmp; goto load_dyna; } Index: file.c =================================================================== RCS file: /cvs/ruby/src/ruby/file.c,v retrieving revision 1.61 diff -u -2 -p -r1.61 file.c --- file.c 2001/07/18 05:55:20 1.61 +++ file.c 2001/07/20 04:14:37 @@ -1291,4 +1291,8 @@ rb_file_s_umask(argc, argv) } +#ifndef HAVE_GETCWD +#define getcwd(buf, len) ((void)(len), getwd(buf)) +#endif + #if defined DOSISH #define isdirsep(x) ((x) == '/' || (x) == '\\') @@ -1296,5 +1300,103 @@ rb_file_s_umask(argc, argv) #define isdirsep(x) ((x) == '/') #endif +#ifndef CharNext /* defined as CharNext[AW] on Windows. */ +# if defined(DJGPP) +# define CharNext(p) ((p) + mblen(p, MB_CUR_MAX)) +# else +# define CharNext(p) ((p) + 1) +# endif +#endif + +static void +check_pathname(str) + VALUE str; +{ + if (RSTRING(str)->len != strlen(RSTRING(str)->ptr)) { + str = rb_inspect(str); + rb_raise(rb_eArgError, "path can't contain \\0: %s", StringValuePtr(str)); + } +} +static char * +strrdirsep(path) + char *path; +{ + char *last = NULL; + while (*path) { + if (isdirsep(*path)) { + last = path++; + } + else { + path = CharNext(path); + } + } + return last; +} + +static char * +chompdirsep(path) + char *path; +{ +#ifdef DOSISH + if (ISALPHA(*path) && path[1] == ':') path += 2; +#endif + if (isdirsep(*path)) { + do { +#ifdef DOSISH + *path = '/'; +#endif + } while (++path, isdirsep(*path)); + if (!*path) return path - 1; + path = CharNext(path); + } + while (*path) { + if (isdirsep(*path)) { + char *last = path; + do { +#ifdef DOSISH + *path = '/'; +#endif + } while (++path, isdirsep(*path)); + if (!*path) return last; + } + else { + path = CharNext(path); + } + } + return path; +} + +static int +rb_str_buf_append_path(str, str2, ofs) + VALUE str, str2; + int ofs; +{ + char *ptr = RSTRING(str)->ptr; + long len = RSTRING(str2)->len; + + if (*(ptr += ofs) && + ((ofs = (ptr = chompdirsep(ptr)) - RSTRING(str)->ptr), (*ptr == '/'))) { + RSTRING(str)->len = ofs + 1; + } + else { + RSTRING(str)->len = ofs; + rb_str_buf_cat(str, "/", 1); + } + + if (len) { + ptr = RSTRING(str2)->ptr; + if (RSTRING(str)->len) { + while (isdirsep(*ptr) && --len) ptr++; + } + if (len) { + rb_str_buf_cat(str, ptr, len); + ptr = RSTRING(str)->ptr; + ofs = chompdirsep(ptr + ofs + 1) - ptr; + } + } + + return ofs; +} + VALUE rb_file_s_expand_path(argc, argv) @@ -1367,9 +1469,5 @@ rb_file_s_expand_path(argc, argv) else { tainted = 1; -#ifdef HAVE_GETCWD getcwd(buf, MAXPATHLEN); -#else - getwd(buf); -#endif } p = &buf[strlen(buf)]; @@ -1477,5 +1575,5 @@ rb_file_s_basename(argc, argv) } name = StringValuePtr(fname); - p = strrchr(name, '/'); + p = strrdirsep(name); if (!p) { if (NIL_P(fext) || !(f = rmext(name, ext))) @@ -1504,5 +1602,5 @@ rb_file_s_dirname(klass, fname) name = StringValuePtr(fname); - p = strrchr(name, '/'); + p = strrdirsep(name); if (!p) { return rb_str_new2("."); @@ -2137,9 +2235,14 @@ is_absolute_path(path) const char *path; { +#ifdef DOSISH + if (ISALPHA(path[0]) && path[1] == ':' && isdirsep(path[2])) return 1; + if (isdirsep(path[0]) && isdirsep(path[1])) return 1; +#else if (path[0] == '/') return 1; -# if defined DOSISH - if (path[0] == '\\') return 1; - if (strlen(path) > 2 && path[1] == ':') return 1; +# ifdef __MACOS__ + if (path[0] == ':') return 0; + if (strchr(path, ':')) return 1; # endif +#endif return 0; } @@ -2156,9 +2259,5 @@ path_check_1(path) char buf[MAXPATHLEN+1]; -#ifdef HAVE_GETCWD if (getcwd(buf, MAXPATHLEN) == 0) return 0; -#else - if (getwd(buf) == 0) return 0; -#endif strncat(buf, "/", MAXPATHLEN); strncat(buf, path, MAXPATHLEN); @@ -2168,8 +2267,8 @@ path_check_1(path) for (;;) { if (stat(path, &st) == 0 && (st.st_mode & 002)) { - if (p) *p = '/'; + if (p) *p = '/'; return 0; } - s = strrchr(path, '/'); + s = strrdirsep(path); if (p) *p = '/'; if (!s || s == path) return 1; @@ -2218,4 +2317,20 @@ is_macos_native_path(path) #endif +static inline int +is_explicit_relative(path) + const char *path; +{ +#ifdef __MACOS__ + if (*path == ':') return 1; +#endif +#ifdef DOSISH + if (ISALPHA(path[0]) && path[1] == ':') return 1; +#endif + if (*path++ != '.') return 0; + if (*path == '.') path++; + if (!*path || isdirsep(*path)) return 1; + return 0; +} + static int file_load_ok(file) @@ -2232,36 +2347,40 @@ file_load_ok(file) extern VALUE rb_load_path; +VALUE rb_load_arch; int -rb_find_file_noext(filep) +rb_find_file_ext(filep, ext) VALUE *filep; + const char* const* ext; { - char *path, *e, *found; - char *f = RSTRING(*filep)->ptr; - VALUE fname; - int i, j; - - static char *ext[] = { - ".rb", DLEXT, -#ifdef DLEXT2 - DLEXT2, -#endif - 0 - }; + VALUE path, fname = *filep; + char *f = RSTRING(fname)->ptr; + long plen; + int i, j, k; + + static const char *const noext[] = {"", 0}; + check_pathname(fname); + + if (!ext) ext = noext; + if (f[0] == '~') { - fname = *filep; fname = rb_file_s_expand_path(1, &fname); + f = RSTRING(fname)->ptr; + } + + path = rb_str_buf_new(MAXPATHLEN); + + if (is_absolute_path(f) || is_explicit_relative(f)) { if (rb_safe_level() >= 2 && OBJ_TAINTED(fname)) { rb_raise(rb_eSecurityError, "loading from unsafe file %s", f); } - } - - if (is_absolute_path(f)) { + rb_str_buf_append(path, fname); + plen = RSTRING(path)->len; for (i=0; ext[i]; i++) { - fname = rb_str_dup(*filep); - rb_str_cat2(fname, ext[i]); - if (file_load_ok(RSTRING(fname)->ptr)) { - *filep = fname; + RSTRING(path)->len = plen; + rb_str_buf_cat2(path, ext[i]); + if (file_load_ok(RSTRING(path)->ptr)) { + *filep = path; return i+1; } @@ -2273,18 +2392,34 @@ rb_find_file_noext(filep) Check_Type(rb_load_path, T_ARRAY); + Check_Type(rb_load_arch, T_ARRAY); for (i=0;ilen;i++) { VALUE str = RARRAY(rb_load_path)->ptr[i]; SafeStringValue(str); - path = RSTRING(str)->ptr; + check_pathname(str); + rb_str_buf_append(path, str); + plen = chompdirsep(RSTRING(path)->ptr) - RSTRING(path)->ptr; for (j=0; ext[j]; j++) { - fname = rb_str_dup(*filep); - rb_str_cat2(fname, ext[j]); - found = dln_find_file(RSTRING(fname)->ptr, path); - if (found && file_load_ok(found)) { - *filep = fname; - return j+1; + for (k=0; k<=RARRAY(rb_load_arch)->len; k++) { + if (k < RARRAY(rb_load_arch)->len) { + VALUE arch = RARRAY(rb_load_arch)->ptr[k]; + if (!NIL_P(arch)) { + SafeStringValue(arch); + if (*RSTRING(arch)->ptr) { + check_pathname(str); + rb_str_buf_append_path(path, arch, plen); + } + } + } + rb_str_buf_append_path(path, fname, plen); + if (*ext[j]) rb_str_buf_cat2(path, ext[j]); + if (file_load_ok(RSTRING(path)->ptr)) { + *filep = path; + return j+1; + } + RSTRING(path)->ptr[RSTRING(path)->len = plen] = '\0'; } } + RSTRING(path)->ptr[RSTRING(path)->len = 0] = '\0'; } return 0; @@ -2349,4 +2484,5 @@ rb_find_file(path) return rb_str_new2(f); } + return 0; } @@ -2507,3 +2643,13 @@ Init_File() rb_define_method(rb_cStat, "setgid?", rb_stat_sgid, 0); rb_define_method(rb_cStat, "sticky?", rb_stat_sticky, 0); + + rb_define_readonly_variable("$LOAD_ARCH", &rb_load_arch); + rb_load_arch = rb_ary_new(); + { + static const char *const arch[] = {RUBY_LOAD_ARCH, 0}; + const char *const *p = arch; + while (*p) { + rb_ary_push(rb_load_arch, rb_obj_freeze(rb_str_new2(*p++))); + } + } } Index: intern.h =================================================================== RCS file: /cvs/ruby/src/ruby/intern.h,v retrieving revision 1.55 diff -u -2 -p -r1.55 intern.h --- intern.h 2001/07/18 05:55:20 1.55 +++ intern.h 2001/07/20 02:39:55 @@ -184,5 +184,5 @@ int eaccess _((const char*, int)); VALUE rb_file_s_expand_path _((int, VALUE *)); void rb_file_const _((const char*, VALUE)); -int rb_find_file_noext _((VALUE*)); +int rb_find_file_ext _((VALUE*, const char* const*)); VALUE rb_find_file _((VALUE)); /* gc.c */ Index: mkconfig.rb =================================================================== RCS file: /cvs/ruby/src/ruby/mkconfig.rb,v retrieving revision 1.15 diff -u -2 -p -r1.15 mkconfig.rb --- mkconfig.rb 2001/05/31 04:40:37 1.15 +++ mkconfig.rb 2001/07/16 14:25:08 @@ -40,5 +40,5 @@ File.foreach "config.status" do |line| next if $install_name and /^RUBY_INSTALL_NAME$/ =~ name next if $so_name and /^RUBY_SO_NAME$/ =~ name v = " CONFIG[\"" + name + "\"] = " + - val.sub(/^\s*(.*)\s*$/, '"\1"').gsub(/\$\{?(\w+)\}?/) { + val.sub(/^\s*(\"?)(.*)\1\s*$/, '"\2"').gsub(/\$\{?(\w+)\}?/) { "$(#{$1})" } + "\n" -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦