From ec6b316cf26eae7eb36e3f9bce24110319e33e35 Mon Sep 17 00:00:00 2001 From: matz Date: Fri, 15 May 1998 09:36:49 +0000 Subject: glob/fnmatch git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/v1_1r@214 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- fnmatch.c | 79 +++++++++++++++++++++++++++++++++++++--------- glob.c | 106 ++++++++++++++++++++++++++++++++------------------------------ 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 -#include +#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) + #pragma alloca +#endif /* _AIX && RISC6000 && !__GNUC__ */ + +#if defined (HAVE_UNISTD_H) +# include +#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 +#else +# if defined (SHELL) +# include "ansi_stdlib.h" +# endif /* SHELL */ +#endif + +#include #if defined (HAVE_DIRENT_H) # include -# 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 -# 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 +# endif +# if defined (HAVE_SYS_DIR_H) # include -# endif /* !NT */ -# endif /* !USG */ +# endif /* HAVE_SYS_DIR_H */ +# if defined (HAVE_NDIR_H) +# include +# 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 #else /* !HAVE_STRING_H */ # include #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 -#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); } -- cgit v1.2.3