なかだです。

At Mon, 10 Feb 2003 19:27:20 +0900 (JST),
akr / m17n.org wrote:
> % ruby -ve 'p File.expand_path(".", "/")'
> ruby 1.8.0 (2003-02-10) [i686-linux]
> ""
> 
> というように "" が返って来るのは変なのではないでしょうか。

At Tue, 11 Feb 2003 00:11:18 +0900 (JST),
akr / m17n.org wrote:
>   Trailing '/' characters in the path are not counted as part of the
>   path.
> 
> と最後の / を無視するように指定されてますし、dirname, basename(),
> basename の項にも同様な指定があります。また、Linux の dirname,
> basename もそれに従って
> 
> % dirname a/
> .
> % basename a/
> a
> 
> というように最後の / は無視して動作します。

まつもとさんのほうで直してるかも知れませんが、
File.dirname("a///b") => "a//"となるのも気になったので直してみ
ました。


Index: file.c =================================================================== RCS file: /cvs/ruby/src/ruby/file.c,v retrieving revision 1.131 diff -u -2 -p -r1.131 file.c --- file.c 31 Jan 2003 04:00:14 -0000 1.131 +++ file.c 11 Feb 2003 11:44:57 -0000 @@ -1407,12 +1407,32 @@ getcwdofdrv(drv, buf, len) #endif +static inline char * +skiproot(path) + const char *path; +{ +#if defined(DOSISH) || defined(__CYGWIN__) + if (isdirsep(*path)) + path++; +#ifdef DOSISH_DRIVE_LETTER + else if (has_drive_letter(path)) + path += 2; +#endif +#endif + if (isdirsep(*path)) path++; + return (char *)path; +} + static char * strrdirsep(path) - char *path; + const char *path; { char *last = NULL; + path = skiproot(path); while (*path) { if (isdirsep(*path)) { - last = path++; + const char *s = path; + do path++; while (isdirsep(*path)); + if (!*path) break; + last = (char *)s; } else { @@ -1423,4 +1443,21 @@ strrdirsep(path) } +static char * +chompdirsep(path) + const char *path; +{ + while (*path) { + if (isdirsep(*path)) { + const char *last = path++; + while (isdirsep(*path)) path++; + if (!*path) return (char *)last; + } + else { + path = CharNext(path); + } + } + return (char *)path; +} + #define BUFCHECK(cond) while (cond) {\ long bdiff = p - buf;\ @@ -1439,14 +1476,12 @@ static int is_absolute_path _((const cha VALUE -rb_file_s_expand_path(argc, argv) - int argc; - VALUE *argv; +rb_file_expand_path(fname, dname) + VALUE fname, dname; { - VALUE fname, dname, result; + VALUE result; char *s, *buf, *b, *p, *pend; long buflen = MAXPATHLEN; int tainted; - rb_scan_args(argc, argv, "11", &fname, &dname); result = rb_str_new(0, buflen + 2); @@ -1521,5 +1556,5 @@ rb_file_s_expand_path(argc, argv) int same = 0; if (!NIL_P(dname)) { - dname = rb_file_s_expand_path(1, &dname); + dname = rb_file_expand_path(dname, Qnil); if (has_drive_letter(RSTRING(dname)->ptr) && TOLOWER(*RSTRING(dname)->ptr) == TOLOWER(s[0])) { @@ -1539,6 +1574,5 @@ rb_file_s_expand_path(argc, argv) s += 2; tainted = 1; - p = &buf[strlen(buf)]; - if (strrdirsep(buf) == p - 1 && *s) p--; /* drop `/' */ + p = chompdirsep(skiproot(buf)); } } @@ -1563,9 +1597,8 @@ rb_file_s_expand_path(argc, argv) else if (!is_absolute_path(s)) { if (!NIL_P(dname)) { - dname = rb_file_s_expand_path(1, &dname); + dname = rb_file_expand_path(dname, Qnil); if (OBJ_TAINTED(dname)) tainted = 1; BUFCHECK(RSTRING(dname)->len > buflen); - memcpy(buf, RSTRING(dname)->ptr, RSTRING(dname)->len); - p += RSTRING(dname)->len; + memcpy(buf, RSTRING(dname)->ptr, RSTRING(dname)->len + 1); } else { @@ -1576,7 +1609,6 @@ rb_file_s_expand_path(argc, argv) strcpy(buf, dir); free(dir); - p = &buf[strlen(buf)]; } - while (p > buf && strrdirsep(buf) == p - 1) p--; + p = chompdirsep(skiproot(buf)); } else { @@ -1664,4 +1696,15 @@ rb_file_s_expand_path(argc, argv) } +VALUE +rb_file_s_expand_path(argc, argv) + int argc; + VALUE *argv; +{ + VALUE fname, dname, result; + rb_scan_args(argc, argv, "11", &fname, &dname); + + return rb_file_expand_path(fname, dname); +} + static int rmext(p, e) @@ -1672,5 +1715,5 @@ rmext(p, e) if (!e) return 0; - l1 = strlen(p); + l1 = chompdirsep(p) - p; l2 = strlen(e); if (l2 == 2 && e[1] == '*') { @@ -1681,5 +1724,5 @@ rmext(p, e) if (l1 < l2) return l1; - if (strcmp(p+l1-l2, e) == 0) { + if (strncmp(p+l1-l2, e, l2) == 0) { return l1-l2; } @@ -1706,5 +1749,5 @@ rb_file_s_basename(argc, argv) name += 2; if (NIL_P(fext)) { - f = strlen(name); + f = chompdirsep(name) - name; } else { @@ -1714,12 +1757,19 @@ rb_file_s_basename(argc, argv) else #endif - if (NIL_P(fext) || !(f = rmext(name, ext))) - return fname; + if (NIL_P(fext) || !(f = rmext(name, ext))) { + char *t = chompdirsep(name); + if (!*t) return fname; + f = t - name; + } basename = rb_str_new(name, f); } else { - p++; /* skip last / */ + while (isdirsep(*p)) p++; /* skip last / */ if (NIL_P(fext) || !(f = rmext(p, ext))) { - basename = rb_str_new2(p); + char *t = chompdirsep(name); + if (!*t) + basename = rb_str_new2(p); + else + basename = rb_str_new(p, t - p); } else { @@ -1854,5 +1904,5 @@ rb_file_join(ary, sep) } name = StringValuePtr(result); - if (i > 0 && !NIL_P(sep) && strrdirsep(name) != &name[strlen(name) - 1]) + if (i > 0 && !NIL_P(sep) && !*chompdirsep(skiproot(name))) rb_str_buf_append(result, sep); rb_str_buf_append(result, tmp);
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦