summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1998-05-15 09:36:49 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1998-05-15 09:36:49 +0000
commitec6b316cf26eae7eb36e3f9bce24110319e33e35 (patch)
treee02426b8182053cc72920dee2b5b6b6f128fcd04
parent56911b10307fe2137a7b38d30d80bdeba4485ac4 (diff)
glob/fnmatch
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/v1_1r@214 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--fnmatch.c79
-rw-r--r--glob.c106
2 files changed, 119 insertions, 66 deletions
diff --git a/fnmatch.c b/fnmatch.c
index baa6c9a543..f031749c3d 100644
--- a/fnmatch.c
+++ b/fnmatch.c
@@ -55,15 +55,23 @@ fnmatch (pattern, string, flags)
if (*n == '\0')
return (FNM_NOMATCH);
else if ((flags & FNM_PATHNAME) && *n == '/')
+ /* If we are matching a pathname, `?' can never match a `/'. */
return (FNM_NOMATCH);
else if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
+ /* `?' cannot match a `.' if it is the first character of the
+ string or if it is the first character following a slash and
+ we are matching a pathname. */
return (FNM_NOMATCH);
break;
case '\\':
if (!(flags & FNM_NOESCAPE))
- c = *p++;
+ {
+ c = *p++;
+ if (c == '\0')
+ return (FNM_NOMATCH);
+ }
if (*n != c)
return (FNM_NOMATCH);
break;
@@ -71,19 +79,38 @@ fnmatch (pattern, string, flags)
case '*':
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
+ /* `*' cannot match a `.' if it is the first character of the
+ string or if it is the first character following a slash and
+ we are matching a pathname. */
return (FNM_NOMATCH);
- for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
- if (((flags & FNM_PATHNAME) && *n == '/') ||
- (c == '?' && *n == '\0'))
- return (FNM_NOMATCH);
+ /* Collapse multiple consecutive, `*' and `?', but make sure that
+ one character of the string is consumed for each `?'. */
+ for (c = *p++; c == '?' || c == '*'; c = *p++)
+ {
+ if ((flags & FNM_PATHNAME) && *n == '/')
+ /* A slash does not match a wildcard under FNM_PATHNAME. */
+ return (FNM_NOMATCH);
+ else if (c == '?')
+ {
+ if (*n == '\0')
+ return (FNM_NOMATCH);
+ /* One character of the string is consumed in matching
+ this ? wildcard, so *??? won't match if there are
+ fewer than three characters. */
+ n++;
+ }
+ }
if (c == '\0')
return (0);
+ /* General case, use recursion. */
{
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
for (--p; *n != '\0'; ++n)
+ /* Only call fnmatch if the first character indicates a
+ possible match. */
if ((c == '[' || *n == c1) &&
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
return (0);
@@ -98,22 +125,30 @@ fnmatch (pattern, string, flags)
if (*n == '\0')
return (FNM_NOMATCH);
+ /* A character class cannot match a `.' if it is the first
+ character of the string or if it is the first character
+ following a slash and we are matching a pathname. */
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return (FNM_NOMATCH);
- /* Make sure there is a closing `]'. If there isn't, the `['
- is just a character to be matched. */
+ /* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
+ is not preceded by a backslash and is not part of a bracket
+ expression produces undefined results.' This implementation
+ treats the `[' as just a character to be matched if there is
+ not a closing `]'. This code will have to be changed when
+ POSIX.2 character classes are implemented. */
{
register char *np;
- for (np = p; np && *np && *np != ']'; np++);
+ for (np = p; np && *np && *np != ']'; np++)
+ ;
if (np && !*np)
{
if (*n != '[')
return (FNM_NOMATCH);
- goto next_char;
+ break;
}
}
@@ -124,10 +159,18 @@ fnmatch (pattern, string, flags)
c = *p++;
for (;;)
{
- register char cstart = c, cend = c;
+ register char cstart, cend;
+
+ /* Initialize cstart and cend in case `-' is the last
+ character of the pattern. */
+ cstart = cend = c;
if (!(flags & FNM_NOESCAPE) && c == '\\')
- cstart = cend = *p++;
+ {
+ if (*p == '\0')
+ return FNM_NOMATCH;
+ cstart = cend = *p++;
+ }
if (c == '\0')
/* [ (unterminated) loses. */
@@ -139,6 +182,9 @@ fnmatch (pattern, string, flags)
/* [/] can never match. */
return (FNM_NOMATCH);
+ /* This introduces a range, unless the `-' is the last
+ character of the class. Find the end of the range
+ and move past it. */
if (c == '-' && *p != ']')
{
cend = *p++;
@@ -146,6 +192,7 @@ fnmatch (pattern, string, flags)
cend = *p++;
if (cend == '\0')
return (FNM_NOMATCH);
+
c = *p++;
}
@@ -157,8 +204,6 @@ fnmatch (pattern, string, flags)
}
if (!not)
return (FNM_NOMATCH);
-
- next_char:
break;
matched:
@@ -171,8 +216,12 @@ fnmatch (pattern, string, flags)
c = *p++;
if (!(flags & FNM_NOESCAPE) && c == '\\')
- /* 1003.2d11 is unclear if this is right. %%% */
- ++p;
+ {
+ if (*p == '\0')
+ return FNM_NOMATCH;
+ /* XXX 1003.2d11 is unclear if this is right. */
+ ++p;
+ }
}
if (not)
return (FNM_NOMATCH);
diff --git a/glob.c b/glob.c
index 7e48620e58..33051214df 100644
--- a/glob.c
+++ b/glob.c
@@ -14,42 +14,48 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
+
/* To whomever it may concern: I have never seen the code which most
Unix programs use to perform this function. I wrote this from scratch
based on specifications for the pattern matching. --RMS. */
-#include "config.h"
+#include <config.h>
-#include <sys/types.h>
+#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
+ #pragma alloca
+#endif /* _AIX && RISC6000 && !__GNUC__ */
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
-#if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3))
-# if !defined (HAVE_DIRENT_H)
-# define HAVE_DIRENT_H
-# endif /* !HAVE_DIRENT_H */
-#endif /* !SHELL && (_POSIX_VERSION || USGr3) */
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# if defined (SHELL)
+# include "ansi_stdlib.h"
+# endif /* SHELL */
+#endif
+
+#include <sys/types.h>
#if defined (HAVE_DIRENT_H)
# include <dirent.h>
-# if !defined (direct)
-# define direct dirent
-# endif /* !direct */
# define D_NAMLEN(d) strlen ((d)->d_name)
#else /* !HAVE_DIRENT_H */
# define D_NAMLEN(d) ((d)->d_namlen)
-# if defined (USG)
-# if defined (Xenix)
-# include <sys/ndir.h>
-# else /* !Xenix (but USG...) */
-# include "ndir.h"
-# endif /* !Xenix */
-# else /* !USG */
-# if defined(NT)
-# include "missing/dir.h"
-# else
+# if defined (HAVE_SYS_NDIR_H)
+# include <sys/ndir.h>
+# endif
+# if defined (HAVE_SYS_DIR_H)
# include <sys/dir.h>
-# endif /* !NT */
-# endif /* !USG */
+# endif /* HAVE_SYS_DIR_H */
+# if defined (HAVE_NDIR_H)
+# include <ndir.h>
+# endif
+# if !defined (dirent)
+# define dirent direct
+# endif
#endif /* !HAVE_DIRENT_H */
#if defined (_POSIX_SOURCE) || defined(DJGPP) || defined(USE_CWGUSI)
@@ -60,37 +66,18 @@
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
#endif /* _POSIX_SOURCE */
-#if defined (USG) || defined (NeXT)
-# if !defined (HAVE_STRING_H)
-# define HAVE_STRING_H
-# endif /* !HAVE_STRING_H */
-#endif /* USG || NeXT */
-
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
-#ifndef bcopy
-# define bcopy(s, d, n) (memcpy ((d), (s), (n)))
-#endif
-
-#ifdef _AIX
-#pragma alloca
-#else
-#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
-#include <alloca.h>
-#else
-char *alloca ();
-#endif
-#endif
-
-#include "fnmatch.h"
+#if !defined (HAVE_BCOPY)
+# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
+#endif /* !HAVE_BCOPY */
/* If the opendir () on your system lets you open non-directory files,
- then we consider that not robust. Define OPENDIR_NOT_ROBUST in the
- SYSDEP_CFLAGS for your machines entry in machines.h. */
+ then we consider that not robust. */
#if defined (OPENDIR_NOT_ROBUST)
# if defined (SHELL)
# include "posixstat.h"
@@ -99,6 +86,8 @@ char *alloca ();
# endif /* !SHELL */
#endif /* OPENDIR_NOT_ROBUST */
+#include "fnmatch.h"
+
extern void *xmalloc (), *xrealloc ();
#if !defined (HAVE_STDLIB_H)
extern void free ();
@@ -113,6 +102,8 @@ extern void free ();
#endif /* !NULL */
#if defined (SHELL)
+extern void throw_to_top_level ();
+
extern int interrupt_state;
#endif /* SHELL */
@@ -123,7 +114,6 @@ int noglob_dot_filenames = 1;
/* Global variable to return to signify an error in globbing. */
char *glob_error_return;
-
/* Return nonzero if PATTERN has any special globbing chars in it. */
int
glob_pattern_p (pattern)
@@ -205,7 +195,7 @@ glob_vector (pat, dir)
};
DIR *d;
- register struct direct *dp;
+ register struct dirent *dp;
struct globval *lastlink;
register struct globval *nextlink;
register char *nextname;
@@ -276,7 +266,8 @@ glob_vector (pat, dir)
continue;
/* If a dot must be explicity matched, check to see if they do. */
- if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.')
+ if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' &&
+ (pat[0] != '\\' || pat[1] != '.'))
continue;
flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
@@ -306,7 +297,9 @@ glob_vector (pat, dir)
}
/* Have we run out of memory? */
+#if defined (SHELL)
lost:
+#endif
if (lose)
{
/* Here free the strings we have got. */
@@ -365,7 +358,14 @@ glob_dir_to_array (dir, array)
+ strlen (array[i]) + 1);
if (result[i] == NULL)
return (NULL);
- sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
+#if 1
+ strcpy (result[i], dir);
+ if (add_slash)
+ result[i][l] = '/';
+ strcpy (result[i] + l + add_slash, array[i]);
+#else
+ (void)sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
+#endif
}
result[i] = NULL;
@@ -435,10 +435,14 @@ glob_filename (pathname)
if (directories == NULL)
goto memory_error;
else if (directories == (char **)&glob_error_return)
- return ((char **) &glob_error_return);
+ {
+ free ((char *) result);
+ return ((char **) &glob_error_return);
+ }
else if (*directories == NULL)
{
free ((char *) directories);
+ free ((char *) result);
return ((char **) &glob_error_return);
}