こんにちは、なかむら(う)です。

In message "[ruby-dev:22090] Re: Dir.glob と Shjift_JIS  について"
    on Nov.30,2003 20:15:50, <ocean / m2.ccsnet.ne.jp> wrote:
| mblen('\0', MB_CUR_MAX) == 1 と仮定して、整理してみました。
| ruby1.8.0(Release)に対するパッチです。

とりあえず、他の皆さんも追いやすいように、これを、
  (1) CVS HEADに対するパッチにした
  (2) タブが落ちているので整形しなおした
  (3) PERIOD_S()が間違ってると思われるので修正した
  (4) find_char()の戻り値からconstを落とした(strchr互換)
にしたパッチを添付します。

でも私もまだあまり検討してません ^^;;

Index: dir.c =================================================================== RCS file: /home/cvs/ruby/dir.c,v retrieving revision 1.88 diff -u -1 -p -w -r1.88 dir.c --- dir.c 22 Nov 2003 03:59:17 -0000 1.88 +++ dir.c 1 Dec 2003 02:11:29 -0000 @@ -77,11 +77,78 @@ char *strchr _((char*,char)); -#define downcase(c) (nocase && ISUPPER(c) ? tolower(c) : (c)) +#define downcase(c) (nocase && ISUPPER(c) ? tolower(c) : (c)) /* use for single byte */ -#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 +#if defined(_WIN32) +# define Next(p) (*(p) ? CharNext(p) : (p) + 1) +#elif defined(DJGPP) || defined(__EMX__) +# define Next(p) ((p) + mblen(p, MB_CUR_MAX)) +#endif + +#ifndef Next /* single byte environment */ +# define Next(p) ((p) + 1) +# define Inc(p) (++(p)) +# define IncLater(p) ((p)++) +# define CopyAndInc(dst, src) (*(dst)++ = *(src)++) +# define Compare(p1, p2) (((int)downcase(*(p1))) - ((int)downcase(*(p2)))) +# define find_char(s, c) strchr(s, c) +#else /* multi byte environment */ +# define Inc(p) (p = Next(p)) +# define IncLater(p) (IncLaterImpl(&(p))) +# define CopyAndInc(dst, src) (CopyAndIncImpl(&(dst), &(src))) +# define Compare(p1, p2) (CompareImpl(p1, p2, nocase)) +static char * +IncLaterImpl(pp) + char **pp; +{ + char *t = *pp; + Inc(*pp); + return t; +} + +static void +CopyAndIncImpl(pdst, psrc) + char **pdst; + const char **psrc; +{ + const int len = Next(*psrc) - *psrc; + memcpy(*pdst, *psrc, len); + (*pdst) += len; + (*psrc) += len; +} + +static int +CompareImpl(p1, p2, nocase) + const char *p1; + const char *p2; + int nocase; +{ + const int len1 = Next(p1) - p1; + const int len2 = Next(p2) - p2; + + if (len1 < len2) { + return -1; + } + else if (len1 > len2) { + return 1; + } + else if (len1 == 1) { + return ((int)downcase(*p1)) - ((int)downcase(*p2)); + } + else { + return strncmp(p1, p2, len1); + } +} + +static char * +find_char(s, c) + const char *s; + char c; +{ + while (*s) { + if (*s == c) + return (char *)s; + Inc(s); + } + return 0; +} +#endif /* environment */ @@ -96,3 +163,3 @@ find_dirsep(s) return s; - s = CharNext(s); + s = Next(s); } @@ -108,3 +175,3 @@ range(pat, test, flags) char *pat; - char test; + char *test; int flags; @@ -117,22 +184,20 @@ range(pat, test, flags) if (not) - pat++; - - test = downcase(test); + Inc(pat); while (*pat) { - int cstart, cend; - cstart = cend = *pat++; - if (cstart == ']') + char *pstart, *pend; + pstart = pend = IncLater(pat); + if (*pstart == ']') return ok == not ? 0 : pat; - else if (escape && cstart == '\\') - cstart = cend = *pat++; - if (*pat == '-' && pat[1] != ']') { - if (escape && pat[1] == '\\') - pat++; - cend = pat[1]; - if (!cend) + else if (escape && *pstart == '\\') + pstart = pend = IncLater(pat); + if (*pat == '-' && *Next(pat) != ']') { + if (escape && *Next(pat) == '\\') + Inc(pat); + pend = Next(pat); + if (!*pend) return 0; - pat += 2; + Inc(pat); Inc(pat); } - if (downcase(cstart) <= test && test <= downcase(cend)) + if (Compare(pstart, test) <= 0 && Compare(test, pend) <= 0) ok = 1; @@ -143,4 +208,5 @@ range(pat, test, flags) #define ISDIRSEP(c) (pathname && isdirsep(c)) -#define PERIOD(s) (period && *(s) == '.' && \ - ((s) == string || ISDIRSEP((s)[-1]))) +#define PERIOD_S() (period && *s == '.' && \ + (s == string || ISDIRSEP(*s_prev))) +#define INC_S() (s = Next(s_prev = s)) static int @@ -151,5 +217,5 @@ fnmatch(pat, string, flags) { - int c; - int test; - const char *s = string; + const char *p; + const char *test; + const char *s = string, *s_prev; int escape = !(flags & FNM_NOESCAPE); @@ -159,17 +225,17 @@ fnmatch(pat, string, flags) - while (c = *pat++) { - switch (c) { + while (*(p = IncLater(pat))) { + switch (*p) { case '?': - if (!*s || ISDIRSEP(*s) || PERIOD(s)) + if (!*s || ISDIRSEP(*s) || PERIOD_S()) return FNM_NOMATCH; - s++; + INC_S(); break; case '*': - while ((c = *pat++) == '*') + while (*(p = IncLater(pat)) == '*') ; - if (PERIOD(s)) + if (PERIOD_S()) return FNM_NOMATCH; - if (!c) { + if (!*p) { if (pathname && find_dirsep(s)) @@ -179,6 +245,6 @@ fnmatch(pat, string, flags) } - else if (ISDIRSEP(c)) { + else if (ISDIRSEP(*p)) { s = find_dirsep(s); if (s) { - s++; + INC_S(); break; @@ -188,7 +254,6 @@ fnmatch(pat, string, flags) - test = escape && c == '\\' ? *pat : c; - test = downcase(test); - pat--; + test = escape && *p == '\\' ? pat : p; + pat = p; while (*s) { - if ((c == '[' || downcase(*s) == test) && + if ((*p == '[' || Compare(s, test) == 0) && !fnmatch(pat, s, flags | FNM_DOTMATCH)) @@ -197,3 +262,3 @@ fnmatch(pat, string, flags) break; - s++; + INC_S(); } @@ -202,8 +267,8 @@ fnmatch(pat, string, flags) case '[': - if (!*s || ISDIRSEP(*s) || PERIOD(s)) + if (!*s || ISDIRSEP(*s) || PERIOD_S()) return FNM_NOMATCH; - pat = range(pat, *s, flags); + pat = range(pat, s, flags); if (!pat) return FNM_NOMATCH; - s++; + INC_S(); break; @@ -216,7 +281,7 @@ fnmatch(pat, string, flags) ) { - c = *pat; - if (!c) - c = '\\'; + p = pat; + if (!*p) + p = "\\"; /* point to embeded string */ else - pat++; + Inc(pat); } @@ -226,3 +291,3 @@ fnmatch(pat, string, flags) #if defined DOSISH - if (ISDIRSEP(c) && isdirsep(*s)) + if (ISDIRSEP(*p) && isdirsep(*s)) ; @@ -230,5 +295,5 @@ fnmatch(pat, string, flags) #endif - if(downcase(c) != downcase(*s)) + if(Compare(p, s) != 0) return FNM_NOMATCH; - s++; + INC_S(); break; @@ -576,4 +641,3 @@ has_magic(s, send, flags) { - register char *p = s; - register char c; + char *p; int open = 0; @@ -581,4 +645,4 @@ has_magic(s, send, flags) - while ((c = *p++) != '\0') { - switch (c) { + while (*(p = IncLater(s)) != '\0') { + switch (*p) { case '?': @@ -596,3 +660,3 @@ has_magic(s, send, flags) case '\\': - if (escape && *p++ == '\0') + if (escape && *IncLater(s) == '\0') return Qfalse; @@ -600,3 +664,3 @@ has_magic(s, send, flags) - if (send && p >= send) break; + if (send && s >= send) break; } @@ -612,2 +676,6 @@ extract_path(p, pend) + char *prev2 = 0; + char *prev1 = 0; + char *cur; + len = pend - p; @@ -615,11 +683,15 @@ extract_path(p, pend) memcpy(alloc, p, len); - if (len > 1 && pend[-1] == '/' + alloc[len] = 0; + + for (cur = alloc; cur != alloc + len; Inc(cur)) { + prev2 = prev1; + prev1 = cur; + } + + if (prev2 && *prev1 == '/' #if defined DOSISH_DRIVE_LETTER - && pend[-2] != ':' + && *prev2 != ':' #endif ) { - alloc[len-1] = 0; - } - else { - alloc[len] = 0; + *prev1 = 0; } @@ -635,3 +707,3 @@ extract_elem(path) - pend = strchr(path, '/'); + pend = find_char(path, '/'); if (!pend) pend = path + strlen(path); @@ -650,5 +722,5 @@ remove_backslashes(p) if (*p == '\\') { - if (++p == pend) break; + if (Inc(p) == pend) break; } - *t++ = *p++; + CopyAndInc(t, p); } @@ -657,2 +729,3 @@ remove_backslashes(p) + #ifndef S_ISDIR @@ -727,4 +800,4 @@ glob_helper(path, sub, flags, func, arg) while (p && !status) { - if (*p == '/') p++; - m = strchr(p, '/'); + if (*p == '/') Inc(p); + m = find_char(p, '/'); if (has_magic(p, m, flags)) { @@ -776,3 +849,3 @@ glob_helper(path, sub, flags, func, arg) #if defined DOSISH_DRIVE_LETTER -#define BASE (*base && !((isdirsep(*base) && !base[1]) || (base[1] == ':' && isdirsep(base[2]) && !base[3]))) +#define BASE (*base && !((isdirsep(*base) && !base[1]) || (ISALPHA(*base) && base[1] == ':' && isdirsep(base[2]) && !base[3]))) #else @@ -926,3 +999,3 @@ push_braces(ary, s, flags) } - p++; + Inc(p); } @@ -934,3 +1007,3 @@ push_braces(ary, s, flags) } - p++; + Inc(p); } @@ -944,9 +1017,9 @@ push_braces(ary, s, flags) while (*p != '}') { - t = p + 1; - for (p = t; *p!='}' && *p!=','; p++) { + t = Next(p); + for (p = t; *p!='}' && *p!=','; Inc(p)) { /* skip inner braces */ - if (*p == '{') while (*p!='}') p++; + if (*p == '{') while (*p!='}') Inc(p); } memcpy(b, t, p-t); - strcpy(b+(p-t), rbrace+1); + strcpy(b+(p-t), Next(rbrace)); push_braces(ary, buf, flags); @@ -988,3 +1061,3 @@ rb_push_glob(str, flags) nest = maxnest = 0; - while (p < pend && isdelim(*p)) p++; + while (p < pend && isdelim(*p)) Inc(p); while (p < pend && !isdelim(*p)) { @@ -993,6 +1066,6 @@ rb_push_glob(str, flags) if (!noescape && *p == '\\') { - *t++ = *p++; + CopyAndInc(t, p); if (p == pend) break; } - *t++ = *p++; + CopyAndInc(t, p); }
それでは。 -- U.Nakamura <usa / osb.att.ne.jp>