summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-03-13 10:11:09 +0000
committerknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-03-13 10:11:09 +0000
commitb9522c168763806cf119c57acdd6293efe60fe0e (patch)
treedb4ea77487df61d9d208058f9ef9b2834055a038
parent14461ddae6530c5574e9899a42c92817b180d3d2 (diff)
* 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
-rw-r--r--ChangeLog8
-rw-r--r--dir.c102
-rw-r--r--doc/NEWS21
3 files changed, 87 insertions, 44 deletions
diff --git a/ChangeLog b/ChangeLog
index 8751203384..f1e1009439 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
* lib/getopts.rb: single_options can be nil[*], and is not not
diff --git a/dir.c b/dir.c
index b56198633e..587d96d456 100644
--- a/dir.c
+++ b/dir.c
@@ -69,7 +69,7 @@ char *strchr _((char*,char));
#define FNM_NOESCAPE 0x01
#define FNM_PATHNAME 0x02
-#define FNM_PERIOD 0x04
+#define FNM_DOTMATCH 0x04
#define FNM_CASEFOLD 0x08
#define FNM_NOMATCH 1
@@ -153,7 +153,7 @@ fnmatch(pat, string, flags)
const char *s = string;
int escape = !(flags & FNM_NOESCAPE);
int pathname = flags & FNM_PATHNAME;
- int period = flags & FNM_PERIOD;
+ int period = !(flags & FNM_DOTMATCH);
int nocase = flags & FNM_CASEFOLD;
while (c = *pat++) {
@@ -188,7 +188,7 @@ fnmatch(pat, string, flags)
pat--;
while (*s) {
if ((c == '[' || downcase(*s) == test) &&
- !fnmatch(pat, s, flags & ~FNM_PERIOD))
+ !fnmatch(pat, s, flags | FNM_DOTMATCH))
return 0;
else if (ISDIRSEP(*s))
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
rb_glob(path, func, arg)
char *path;
void (*func) _((const char*, VALUE));
VALUE arg;
{
- glob_helper(path, 0, FNM_PERIOD, func, arg);
+ rb_glob2(path, 0, func, arg);
}
void
@@ -808,11 +818,9 @@ rb_globi(path, func, arg)
void (*func) _((const char*, VALUE));
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
push_pattern(path, ary)
const char *path;
@@ -829,17 +837,19 @@ push_pattern(path, ary)
}
static void
-push_globs(ary, s)
+push_globs(ary, s, flags)
VALUE ary;
char *s;
+ int flags;
{
- rb_glob(s, push_pattern, ary);
+ rb_glob2(s, flags, push_pattern, ary);
}
static void
-push_braces(ary, s)
+push_braces(ary, s, flags)
VALUE ary;
char *s;
+ int flags;
{
char *buf;
char *p, *t, *b;
@@ -878,31 +888,35 @@ push_braces(ary, s)
}
memcpy(b, t, p-t);
strcpy(b+(p-t), rbrace+1);
- push_braces(ary, buf);
+ push_braces(ary, buf, flags);
}
free(buf);
}
else {
- push_globs(ary, s);
+ push_globs(ary, s, flags);
}
}
#define isdelim(c) ((c)=='\0')
static VALUE
-dir_s_glob(dir, str)
- VALUE dir, str;
+rb_push_glob(str, flags)
+ VALUE str;
+ int flags;
{
char *p, *pend;
char *buf;
char *t;
- int nest;
- VALUE ary = 0;
+ int nest, maxnest;
+ int noescape = flags & FNM_NOESCAPE;
+ VALUE ary;
- SafeStringValue(str);
- if (!rb_block_given_p()) {
+ if (rb_block_given_p())
+ ary = Qnil;
+ else
ary = rb_ary_new();
- }
+
+ SafeStringValue(str);
buf = xmalloc(RSTRING(str)->len + 1);
p = RSTRING(str)->ptr;
@@ -913,28 +927,50 @@ dir_s_glob(dir, str)
nest = 0;
while (p < pend && isdelim(*p)) p++;
while (p < pend && !isdelim(*p)) {
- if (*p == '{') nest+=2;
- if (*p == '}') nest+=3;
- if (*p == '\\') {
+ if (*p == '{') nest++, maxnest++;
+ if (*p == '}') nest--;
+ if (!noescape && *p == '\\') {
*t++ = *p++;
if (p == pend) break;
}
*t++ = *p++;
}
*t = '\0';
- if (nest == 0) {
- push_globs(ary, buf);
+ if (maxnest == 0) {
+ push_globs(ary, buf, flags);
}
- else if (nest % 5 == 0) {
- push_braces(ary, buf);
+ else if (nest == 0) {
+ push_braces(ary, buf, flags);
}
/* else unmatched braces */
}
free(buf);
- if (ary) {
- return ary;
- }
- return Qnil;
+
+ return ary;
+}
+
+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
@@ -1014,14 +1050,14 @@ Init_Dir()
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,"glob", dir_s_glob, 1);
- rb_define_singleton_method(rb_cDir,"[]", dir_s_glob, 1);
+ rb_define_singleton_method(rb_cDir,"glob", 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_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE));
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));
}
diff --git a/doc/NEWS b/doc/NEWS
index bd3e7feb25..3c1fbb7c99 100644
--- a/doc/NEWS
+++ b/doc/NEWS
@@ -1,13 +1,9 @@
-: getopts.rb
+: Dir::glob
- Rewrote to fix some bugs and complete features.
- - Accept options with the colon in the first argument;
- getopts("a:bcd:") is equivalent to getopts("bc", "a:", "d:").
- - Do not discard the argument that caused an error.
- - 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.
+ Now accepts optional FNM_* flags via the second argument, whereas
+ Dir::[] doesn't.
+
+ Dir.glob("makefile", File::FNM_CASEFOLD) #=> ['Makefile', 'makefile']
: tsort module
@@ -210,10 +206,13 @@
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.
- # exclude files matching "*.bak".
- files.reject! {|fn| File.fnmatch?("*.bak", fn) }
+ # exclude files matching "*.bak" case-insensitively.
+ files.reject! {|fn| File.fnmatch?("*.bak", fn, File::FNM_CASEFOLD) }
: File.lchmod
: File.lchown