* dir.c: FNM_PERIOD is obsoleted and FNM_DOTMATCH is introduced

instead, which has the opposite meaning of FNM_PERIOD.

* dir.c: Dir::glob now accepts optional FNM_* flags via the second
  argument, whereas Dir::[] doesn't.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2191 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
knu 2002-03-13 10:11:09 +00:00
parent 14461ddae6
commit b9522c1687
3 changed files with 87 additions and 44 deletions

View File

@ -1,3 +1,11 @@
Wed Mar 13 19:05:15 2002 Akinori MUSHA <knu@iDaemons.org>
* dir.c: FNM_PERIOD is obsoleted and FNM_DOTMATCH is introduced
instead, which has the opposite meaning of FNM_PERIOD.
* dir.c: Dir::glob now accepts optional FNM_* flags via the second
argument, whereas Dir::[] doesn't.
Wed Mar 13 18:36:55 2002 Akinori MUSHA <knu@iDaemons.org> Wed Mar 13 18:36:55 2002 Akinori MUSHA <knu@iDaemons.org>
* lib/getopts.rb: single_options can be nil[*], and is not not * lib/getopts.rb: single_options can be nil[*], and is not not

102
dir.c
View File

@ -69,7 +69,7 @@ char *strchr _((char*,char));
#define FNM_NOESCAPE 0x01 #define FNM_NOESCAPE 0x01
#define FNM_PATHNAME 0x02 #define FNM_PATHNAME 0x02
#define FNM_PERIOD 0x04 #define FNM_DOTMATCH 0x04
#define FNM_CASEFOLD 0x08 #define FNM_CASEFOLD 0x08
#define FNM_NOMATCH 1 #define FNM_NOMATCH 1
@ -153,7 +153,7 @@ fnmatch(pat, string, flags)
const char *s = string; const char *s = string;
int escape = !(flags & FNM_NOESCAPE); int escape = !(flags & FNM_NOESCAPE);
int pathname = flags & FNM_PATHNAME; int pathname = flags & FNM_PATHNAME;
int period = flags & FNM_PERIOD; int period = !(flags & FNM_DOTMATCH);
int nocase = flags & FNM_CASEFOLD; int nocase = flags & FNM_CASEFOLD;
while (c = *pat++) { while (c = *pat++) {
@ -188,7 +188,7 @@ fnmatch(pat, string, flags)
pat--; pat--;
while (*s) { while (*s) {
if ((c == '[' || downcase(*s) == test) && if ((c == '[' || downcase(*s) == test) &&
!fnmatch(pat, s, flags & ~FNM_PERIOD)) !fnmatch(pat, s, flags | FNM_DOTMATCH))
return 0; return 0;
else if (ISDIRSEP(*s)) else if (ISDIRSEP(*s))
break; break;
@ -793,13 +793,23 @@ glob_helper(path, sub, flags, func, arg)
} }
} }
static void
rb_glob2(path, flags, func, arg)
char *path;
int flags;
void (*func) _((const char*, VALUE));
VALUE arg;
{
glob_helper(path, 0, flags, func, arg);
}
void void
rb_glob(path, func, arg) rb_glob(path, func, arg)
char *path; char *path;
void (*func) _((const char*, VALUE)); void (*func) _((const char*, VALUE));
VALUE arg; VALUE arg;
{ {
glob_helper(path, 0, FNM_PERIOD, func, arg); rb_glob2(path, 0, func, arg);
} }
void void
@ -808,11 +818,9 @@ rb_globi(path, func, arg)
void (*func) _((const char*, VALUE)); void (*func) _((const char*, VALUE));
VALUE arg; VALUE arg;
{ {
glob_helper(path, 0, FNM_PERIOD|FNM_CASEFOLD, func, arg); rb_glob2(path, FNM_CASEFOLD, func, arg);
} }
static void push_pattern _((const char *path, VALUE ary));
static void static void
push_pattern(path, ary) push_pattern(path, ary)
const char *path; const char *path;
@ -829,17 +837,19 @@ push_pattern(path, ary)
} }
static void static void
push_globs(ary, s) push_globs(ary, s, flags)
VALUE ary; VALUE ary;
char *s; char *s;
int flags;
{ {
rb_glob(s, push_pattern, ary); rb_glob2(s, flags, push_pattern, ary);
} }
static void static void
push_braces(ary, s) push_braces(ary, s, flags)
VALUE ary; VALUE ary;
char *s; char *s;
int flags;
{ {
char *buf; char *buf;
char *p, *t, *b; char *p, *t, *b;
@ -878,31 +888,35 @@ push_braces(ary, s)
} }
memcpy(b, t, p-t); memcpy(b, t, p-t);
strcpy(b+(p-t), rbrace+1); strcpy(b+(p-t), rbrace+1);
push_braces(ary, buf); push_braces(ary, buf, flags);
} }
free(buf); free(buf);
} }
else { else {
push_globs(ary, s); push_globs(ary, s, flags);
} }
} }
#define isdelim(c) ((c)=='\0') #define isdelim(c) ((c)=='\0')
static VALUE static VALUE
dir_s_glob(dir, str) rb_push_glob(str, flags)
VALUE dir, str; VALUE str;
int flags;
{ {
char *p, *pend; char *p, *pend;
char *buf; char *buf;
char *t; char *t;
int nest; int nest, maxnest;
VALUE ary = 0; int noescape = flags & FNM_NOESCAPE;
VALUE ary;
if (rb_block_given_p())
ary = Qnil;
else
ary = rb_ary_new();
SafeStringValue(str); SafeStringValue(str);
if (!rb_block_given_p()) {
ary = rb_ary_new();
}
buf = xmalloc(RSTRING(str)->len + 1); buf = xmalloc(RSTRING(str)->len + 1);
p = RSTRING(str)->ptr; p = RSTRING(str)->ptr;
@ -913,28 +927,50 @@ dir_s_glob(dir, str)
nest = 0; nest = 0;
while (p < pend && isdelim(*p)) p++; while (p < pend && isdelim(*p)) p++;
while (p < pend && !isdelim(*p)) { while (p < pend && !isdelim(*p)) {
if (*p == '{') nest+=2; if (*p == '{') nest++, maxnest++;
if (*p == '}') nest+=3; if (*p == '}') nest--;
if (*p == '\\') { if (!noescape && *p == '\\') {
*t++ = *p++; *t++ = *p++;
if (p == pend) break; if (p == pend) break;
} }
*t++ = *p++; *t++ = *p++;
} }
*t = '\0'; *t = '\0';
if (nest == 0) { if (maxnest == 0) {
push_globs(ary, buf); push_globs(ary, buf, flags);
} }
else if (nest % 5 == 0) { else if (nest == 0) {
push_braces(ary, buf); push_braces(ary, buf, flags);
} }
/* else unmatched braces */ /* else unmatched braces */
} }
free(buf); free(buf);
if (ary) {
return ary; return ary;
} }
return Qnil;
static VALUE
dir_s_aref(obj, str)
VALUE obj, str;
{
return rb_push_glob(str, 0);
}
static VALUE
dir_s_glob(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
VALUE str, rflags;
int flags;
if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2)
flags = NUM2INT(rflags);
else
flags = 0;
return rb_push_glob(str, flags);
} }
static VALUE static VALUE
@ -1014,14 +1050,14 @@ Init_Dir()
rb_define_singleton_method(rb_cDir,"delete", dir_s_rmdir, 1); rb_define_singleton_method(rb_cDir,"delete", dir_s_rmdir, 1);
rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1); rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1);
rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, 1); rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1);
rb_define_singleton_method(rb_cDir,"[]", dir_s_glob, 1); rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, 1);
rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1); rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1); rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE)); rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE));
rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME)); rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
rb_file_const("FNM_PERIOD", INT2FIX(FNM_PERIOD)); rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD)); rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
} }

View File

@ -1,13 +1,9 @@
: getopts.rb : Dir::glob
Rewrote to fix some bugs and complete features. Now accepts optional FNM_* flags via the second argument, whereas
- Accept options with the colon in the first argument; Dir::[] doesn't.
getopts("a:bcd:") is equivalent to getopts("bc", "a:", "d:").
- Do not discard the argument that caused an error. Dir.glob("makefile", File::FNM_CASEFOLD) #=> ['Makefile', 'makefile']
- Do not discard '-', which commonly stands for stdin or stdout.
- Allow specifying a long option with a value using '='.
(command --long-option=value)
- Stop reading options when it meets a non-option argument.
: tsort module : tsort module
@ -210,10 +206,13 @@
Added. Refer to the fnmatch(3) manpage for details. Added. Refer to the fnmatch(3) manpage for details.
Localism is FNM_DOTMATCH which has the opposite meaning of the
commonly known FNM_PERIOD, which does not exist in Ruby.
e.g. e.g.
# exclude files matching "*.bak". # exclude files matching "*.bak" case-insensitively.
files.reject! {|fn| File.fnmatch?("*.bak", fn) } files.reject! {|fn| File.fnmatch?("*.bak", fn, File::FNM_CASEFOLD) }
: File.lchmod : File.lchmod
: File.lchown : File.lchown