diff options
-rw-r--r-- | engines/sci/scicore/fnmatch.cpp | 847 |
1 files changed, 0 insertions, 847 deletions
diff --git a/engines/sci/scicore/fnmatch.cpp b/engines/sci/scicore/fnmatch.cpp deleted file mode 100644 index a3b5a0ad69..0000000000 --- a/engines/sci/scicore/fnmatch.cpp +++ /dev/null @@ -1,847 +0,0 @@ -/* fnmatch.c -- ksh-like extended pattern matching for the shell and filename - globbing. */ - -/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. - - This file is part of GNU Bash, the Bourne Again SHell. - - Bash is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2, or (at your option) any later - version. - - Bash is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License along - with Bash; see the file COPYING. If not, write to the Free Software - Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#ifndef HAVE_FNMATCH - -#include <stdio.h> /* for debugging */ - -#include <ctype.h> - -#if defined (HAVE_STRING_H) -# include <string.h> -#else -# include <strings.h> -#endif /* HAVE_STRING_H */ - -static int gmatch (); -static char *brackmatch (); -#ifdef EXTENDED_GLOB -static int extmatch (); -static char *patscan (); -#endif - -#if !defined (isascii) -# define isascii(c) ((unsigned int)(c) <= 0177) -#endif - -/* Note that these evaluate C many times. */ - -#ifndef isblank -# define isblank(c) ((c) == ' ' || (c) == '\t') -#endif - -#ifndef isgraph -# define isgraph(c) ((c) != ' ' && isprint((c))) -#endif - -#ifndef isxdigit -# define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) -#endif - -/* The result of FOLD is an `unsigned char' */ -# define FOLD(c) ((flags & FNM_CASEFOLD) && isupper ((unsigned char)c) \ - ? tolower ((unsigned char)c) \ - : ((unsigned char)c)) - -#ifndef STREQ -#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0) -#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0) -#endif - -/* We use strcoll(3) for range comparisons in bracket expressions, - even though it can have unwanted side effects in locales - other than POSIX or US. For instance, in the de locale, [A-Z] matches - all characters. */ - -#if defined (HAVE_STRCOLL) -/* Helper function for collating symbol equivalence. */ -static int rangecmp (c1, c2) - int c1, c2; -{ - static char s1[2] = { ' ', '\0' }; - static char s2[2] = { ' ', '\0' }; - int ret; - - /* Eight bits only. Period. */ - c1 &= 0xFF; - c2 &= 0xFF; - - if (c1 == c2) - return (0); - - s1[0] = c1; - s2[0] = c2; - - if ((ret = strcoll (s1, s2)) != 0) - return ret; - return (c1 - c2); -} -#else /* !HAVE_STRCOLL */ -# define rangecmp(c1, c2) ((int)(c1) - (int)(c2)) -#endif /* !HAVE_STRCOLL */ - -#if defined (HAVE_STRCOLL) -static int collequiv (c1, c2) - int c1, c2; -{ - return (rangecmp (c1, c2) == 0); -} -#else -# define collequiv(c1, c2) ((c1) == (c2)) -#endif - -static int -collsym (s, len) - char *s; - int len; -{ - register struct _collsym *csp; - - for (csp = posix_collsyms; csp->name; csp++) - { - if (STREQN(csp->name, s, len) && csp->name[len] == '\0') - return (csp->code); - } - if (len == 1) - return s[0]; - return -1; -} - -int -fnmatch (pattern, string, flags) - char *pattern; - char *string; - int flags; -{ - char *se, *pe; - - if (string == 0 || pattern == 0) - return FNM_NOMATCH; - - se = string + strlen (string); - pe = pattern + strlen (pattern); - - return (gmatch (string, se, pattern, pe, flags)); -} - -/* Match STRING against the filename pattern PATTERN, returning zero if - it matches, FNM_NOMATCH if not. */ -static int -gmatch (string, se, pattern, pe, flags) - char *string, *se; - char *pattern, *pe; - int flags; -{ - register char *p, *n; /* pattern, string */ - register char c; /* current pattern character */ - register char sc; /* current string character */ - - p = pattern; - n = string; - - if (string == 0 || pattern == 0) - return FNM_NOMATCH; - -#if DEBUG_MATCHING -fprintf(stderr, "gmatch: string = %s; se = %s\n", string, se); -fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); -#endif - - while (p < pe) - { - c = *p++; - c = FOLD (c); - - sc = n < se ? *n : '\0'; - -#ifdef EXTENDED_GLOB - /* extmatch () will handle recursively calling gmatch, so we can - just return what extmatch() returns. */ - if ((flags & FNM_EXTMATCH) && *p == '(' && - (c == '+' || c == '*' || c == '?' || c == '@' || c == '!')) /* ) */ - { - int lflags; - /* If we're not matching the start of the string, we're not - concerned about the special cases for matching `.' */ - lflags = (n == string) ? flags : (flags & ~FNM_PERIOD); - return (extmatch (c, n, se, p, pe, lflags)); - } -#endif - - switch (c) - { - case '?': /* Match single character */ - if (sc == '\0') - return FNM_NOMATCH; - else if ((flags & FNM_PATHNAME) && sc == '/') - /* If we are matching a pathname, `?' can never match a `/'. */ - return FNM_NOMATCH; - else if ((flags & FNM_PERIOD) && sc == '.' && - (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 '\\': /* backslash escape removes special meaning */ - if (p == pe) - return FNM_NOMATCH; - - if ((flags & FNM_NOESCAPE) == 0) - { - c = *p++; - /* A trailing `\' cannot match. */ - if (p > pe) - return FNM_NOMATCH; - c = FOLD (c); - } - if (FOLD (sc) != (unsigned char)c) - return FNM_NOMATCH; - break; - - case '*': /* Match zero or more characters */ - if (p == pe) - return 0; - - if ((flags & FNM_PERIOD) && sc == '.' && - (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; - - /* 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) && sc == '/') - /* A slash does not match a wildcard under FNM_PATHNAME. */ - return FNM_NOMATCH; - else if (c == '?') - { - if (sc == '\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++; - sc = n < se ? *n : '\0'; - } - -#ifdef EXTENDED_GLOB - /* Handle ******(patlist) */ - if ((flags & FNM_EXTMATCH) && c == '*' && *p == '(') /*)*/ - { - char *newn; - /* We need to check whether or not the extended glob - pattern matches the remainder of the string. - If it does, we match the entire pattern. */ - for (newn = n; newn < se; ++newn) - { - if (extmatch (c, newn, se, p, pe, flags) == 0) - return (0); - } - /* We didn't match the extended glob pattern, but - that's OK, since we can match 0 or more occurrences. - We need to skip the glob pattern and see if we - match the rest of the string. */ - newn = patscan (p + 1, pe, 0); - p = newn; - } -#endif - if (p == pe) - break; - } - - /* If we've hit the end of the pattern and the last character of - the pattern was handled by the loop above, we've succeeded. - Otherwise, we need to match that last character. */ - if (p == pe && (c == '?' || c == '*')) - return (0); - - /* General case, use recursion. */ - { - unsigned char c1; - - c1 = (unsigned char)((flags & FNM_NOESCAPE) == 0 && c == '\\') ? *p : c; - c1 = FOLD (c1); - for (--p; n < se; ++n) - { - /* Only call fnmatch if the first character indicates a - possible match. We can check the first character if - we're not doing an extended glob match. */ - if ((flags & FNM_EXTMATCH) == 0 && c != '[' && FOLD (*n) != c1) /*]*/ - continue; - - /* If we're doing an extended glob match and the pattern is not - one of the extended glob patterns, we can check the first - character. */ - if ((flags & FNM_EXTMATCH) && p[1] != '(' && /*)*/ - strchr ("?*+@!", *p) == 0 && c != '[' && FOLD (*n) != c1) /*]*/ - continue; - - /* Otherwise, we just recurse. */ - if (gmatch (n, se, p, pe, flags & ~FNM_PERIOD) == 0) - return (0); - } - return FNM_NOMATCH; - } - - case '[': - { - if (sc == '\0' || n == se) - 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) && sc == '.' && - (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) - return (FNM_NOMATCH); - - p = brackmatch (p, sc, flags); - if (p == 0) - return FNM_NOMATCH; - } - break; - - default: - if ((unsigned char)c != FOLD (sc)) - return (FNM_NOMATCH); - } - - ++n; - } - - if (n == se) - return (0); - - if ((flags & FNM_LEADING_DIR) && *n == '/') - /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ - return 0; - - return (FNM_NOMATCH); -} - -/* Parse a bracket expression collating symbol ([.sym.]) starting at P, find - the value of the symbol, and move P past the collating symbol expression. - The value is returned in *VP, if VP is not null. */ -static char * -parse_collsym (p, vp) - char *p; - int *vp; -{ - register int pc; - int val; - - p++; /* move past the `.' */ - - for (pc = 0; p[pc]; pc++) - if (p[pc] == '.' && p[pc+1] == ']') - break; - val = collsym (p, pc); - if (vp) - *vp = val; - return (p + pc + 2); -} - -static char * -brackmatch (p, test, flags) - char *p; - unsigned char test; - int flags; -{ - register char cstart, cend, c; - register int not; /* Nonzero if the sense of the character class is inverted. */ - int pc, brcnt; - char *savep; - - test = FOLD (test); - - savep = p; - - /* POSIX.2 3.13.1 says that an exclamation mark (`!') shall replace the - circumflex (`^') in its role in a `nonmatching list'. A bracket - expression starting with an unquoted circumflex character produces - unspecified results. This implementation treats the two identically. */ - if (not = (*p == '!' || *p == '^')) - ++p; - - c = *p++; - for (;;) - { - /* Initialize cstart and cend in case `-' is the last - character of the pattern. */ - cstart = cend = c; - - /* POSIX.2 equivalence class: [=c=]. See POSIX.2 2.8.3.2. Find - the end of the equivalence class, move the pattern pointer past - it, and check for equivalence. XXX - this handles only - single-character equivalence classes, which is wrong, or at - least incomplete. */ - if (c == '[' && *p == '=' && p[2] == '=' && p[3] == ']') - { - pc = FOLD (p[1]); - p += 4; - if (collequiv (test, pc)) - { -/*[*/ /* Move past the closing `]', since the first thing we do at - the `matched:' label is back p up one. */ - p++; - goto matched; - } - else - { - c = *p++; - if (c == '\0') - return ((test == '[') ? savep : (char *)0); /*]*/ - c = FOLD (c); - continue; - } - } - - /* POSIX.2 character class expression. See POSIX.2 2.8.3.2. */ - if (c == '[' && *p == ':') /*]*/ - { - pc = 0; /* make sure invalid char classes don't match. */ - if (STREQN (p+1, "alnum:]", 7)) - { pc = isalnum (test); p += 8; } - else if (STREQN (p+1, "alpha:]", 7)) - { pc = isalpha (test); p += 8; } - else if (STREQN (p+1, "blank:]", 7)) - { pc = isblank (test); p += 8; } - else if (STREQN (p+1, "cntrl:]", 7)) - { pc = iscntrl (test); p += 8; } - else if (STREQN (p+1, "digit:]", 7)) - { pc = isdigit (test); p += 8; } - else if (STREQN (p+1, "graph:]", 7)) - { pc = isgraph (test); p += 8; } - else if (STREQN (p+1, "lower:]", 7)) - { pc = islower (test); p += 8; } - else if (STREQN (p+1, "print:]", 7)) - { pc = isprint (test); p += 8; } - else if (STREQN (p+1, "punct:]", 7)) - { pc = ispunct (test); p += 8; } - else if (STREQN (p+1, "space:]", 7)) - { pc = isspace (test); p += 8; } - else if (STREQN (p+1, "upper:]", 7)) - { pc = isupper (test); p += 8; } - else if (STREQN (p+1, "xdigit:]", 8)) - { pc = isxdigit (test); p += 9; } - else if (STREQN (p+1, "ascii:]", 7)) - { pc = isascii (test); p += 8; } - if (pc) - { -/*[*/ /* Move past the closing `]', since the first thing we do at - the `matched:' label is back p up one. */ - p++; - goto matched; - } - else - { - /* continue the loop here, since this expression can't be - the first part of a range expression. */ - c = *p++; - if (c == '\0') - return ((test == '[') ? savep : (char *)0); - else if (c == ']') - break; - c = FOLD (c); - continue; - } - } - - /* POSIX.2 collating symbols. See POSIX.2 2.8.3.2. Find the end of - the symbol name, make sure it is terminated by `.]', translate - the name to a character using the external table, and do the - comparison. */ - if (c == '[' && *p == '.') - { - p = parse_collsym (p, &pc); - /* An invalid collating symbol cannot be the first point of a - range. If it is, we set cstart to one greater than `test', - so any comparisons later will fail. */ - cstart = (pc == -1) ? test + 1 : pc; - } - - if (!(flags & FNM_NOESCAPE) && c == '\\') - { - if (*p == '\0') - return (char *)0; - cstart = cend = *p++; - } - - cstart = cend = FOLD (cstart); - - /* 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 `]'. */ - if (c == '\0') - return ((test == '[') ? savep : (char *)0); - - c = *p++; - c = FOLD (c); - - if ((flags & FNM_PATHNAME) && c == '/') - /* [/] can never match when matching a pathname. */ - return (char *)0; - - /* 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++; - if (!(flags & FNM_NOESCAPE) && cend == '\\') - cend = *p++; - if (cend == '\0') - return (char *)0; - if (cend == '[' && *p == '.') - { - p = parse_collsym (p, &pc); - /* An invalid collating symbol cannot be the second part of a - range expression. If we get one, we set cend to one fewer - than the test character to make sure the range test fails. */ - cend = (pc == -1) ? test - 1 : pc; - } - cend = FOLD (cend); - - c = *p++; - - /* POSIX.2 2.8.3.2: ``The ending range point shall collate - equal to or higher than the starting range point; otherwise - the expression shall be treated as invalid.'' Note that this - applies to only the range expression; the rest of the bracket - expression is still checked for matches. */ - if (rangecmp (cstart, cend) > 0) - { - if (c == ']') - break; - c = FOLD (c); - continue; - } - } - - if (rangecmp (test, cstart) >= 0 && rangecmp (test, cend) <= 0) - goto matched; - - if (c == ']') - break; - } - /* No match. */ - return (!not ? (char *)0 : p); - -matched: - /* Skip the rest of the [...] that already matched. */ -#if 0 - brcnt = (c != ']') + (c == '[' && (*p == '=' || *p == ':' || *p == '.')); -#else - c = *--p; - brcnt = 1; -#endif - while (brcnt > 0) - { - /* A `[' without a matching `]' is just another character to match. */ - if (c == '\0') - return ((test == '[') ? savep : (char *)0); - - c = *p++; - if (c == '[' && (*p == '=' || *p == ':' || *p == '.')) - brcnt++; - else if (c == ']') - brcnt--; - else if (!(flags & FNM_NOESCAPE) && c == '\\') - { - if (*p == '\0') - return (char *)0; - /* XXX 1003.2d11 is unclear if this is right. */ - ++p; - } - } - return (not ? (char *)0 : p); -} - -#if defined (EXTENDED_GLOB) -/* ksh-like extended pattern matching: - - [?*+@!](pat-list) - - where pat-list is a list of one or patterns separated by `|'. Operation - is as follows: - - ?(patlist) match zero or one of the given patterns - *(patlist) match zero or more of the given patterns - +(patlist) match one or more of the given patterns - @(patlist) match exactly one of the given patterns - !(patlist) match anything except one of the given patterns -*/ - -/* Scan a pattern starting at STRING and ending at END, keeping track of - embedded () and []. If DELIM is 0, we scan until a matching `)' - because we're scanning a `patlist'. Otherwise, we scan until we see - DELIM. In all cases, we never scan past END. The return value is the - first character after the matching DELIM. */ -static char * -patscan (string, end, delim) - char *string, *end; - int delim; -{ - int pnest, bnest, cchar; - char *s, c, *bfirst; - - pnest = bnest = cchar = 0; - bfirst = 0; - for (s = string; c = *s; s++) - { - if (s >= end) - return (s); - switch (c) - { - case '\0': - return ((char *)0); - - /* `[' is not special inside a bracket expression, but it may - introduce one of the special POSIX bracket expressions - ([.SYM.], [=c=], [: ... :]) that needs special handling. */ - case '[': - if (bnest == 0) - { - bfirst = s + 1; - if (*bfirst == '!' || *bfirst == '^') - bfirst++; - bnest++; - } - else if (s[1] == ':' || s[1] == '.' || s[1] == '=') - cchar = s[1]; - break; - - /* `]' is not special if it's the first char (after a leading `!' - or `^') in a bracket expression or if it's part of one of the - special POSIX bracket expressions ([.SYM.], [=c=], [: ... :]) */ - case ']': - if (bnest) - { - if (cchar && s[-1] == cchar) - cchar = 0; - else if (s != bfirst) - { - bnest--; - bfirst = 0; - } - } - break; - - case '(': - if (bnest == 0) - pnest++; - break; - - case ')': -#if 0 - if (bnest == 0) - pnest--; - if (pnest <= 0) - return ++s; -#else - if (bnest == 0 && pnest-- <= 0) - return ++s; -#endif - break; - - case '|': - if (bnest == 0 && pnest == 0 && delim == '|') - return ++s; - break; - } - } - - return (char *)0; -} - -/* Return 0 if dequoted pattern matches S in the current locale. */ -static int -strcompare (p, pe, s, se) - char *p, *pe, *s, *se; -{ - int ret; - char c1, c2; - - c1 = *pe; - c2 = *se; - - *pe = *se = '\0'; -#if defined (HAVE_STRCOLL) - ret = strcoll (p, s); -#else - ret = strcmp (p, s); -#endif - - *pe = c1; - *se = c2; - - return (ret == 0 ? ret : FNM_NOMATCH); -} - -/* Match a ksh extended pattern specifier. Return FNM_NOMATCH on failure or - 0 on success. This is handed the entire rest of the pattern and string - the first time an extended pattern specifier is encountered, so it calls - gmatch recursively. */ -static int -extmatch (xc, s, se, p, pe, flags) - int xc; /* select which operation */ - char *s, *se; - char *p, *pe; - int flags; -{ - char *prest; /* pointer to rest of pattern */ - char *psub; /* pointer to sub-pattern */ - char *pnext; /* pointer to next sub-pattern */ - char *srest; /* pointer to rest of string */ - int m1, m2; - -#if DEBUG_MATCHING -fprintf(stderr, "extmatch: xc = %c\n", xc); -fprintf(stderr, "extmatch: s = %s; se = %s\n", s, se); -fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe); -#endif - - prest = patscan (p + (*p == '('), pe, 0); /* ) */ - if (prest == 0) - /* If PREST is 0, we failed to scan a valid pattern. In this - case, we just want to compare the two as strings. */ - return (strcompare (p - 1, pe, s, se)); - - switch (xc) - { - case '+': /* match one or more occurrences */ - case '*': /* match zero or more occurrences */ - /* If we can get away with no matches, don't even bother. Just - call gmatch on the rest of the pattern and return success if - it succeeds. */ - if (xc == '*' && (gmatch (s, se, prest, pe, flags) == 0)) - return 0; - - /* OK, we have to do this the hard way. First, we make sure one of - the subpatterns matches, then we try to match the rest of the - string. */ - for (psub = p + 1; ; psub = pnext) - { - pnext = patscan (psub, pe, '|'); - for (srest = s; srest <= se; srest++) - { - /* Match this substring (S -> SREST) against this - subpattern (psub -> pnext - 1) */ - m1 = gmatch (s, srest, psub, pnext - 1, flags) == 0; - /* OK, we matched a subpattern, so make sure the rest of the - string matches the rest of the pattern. Also handle - multiple matches of the pattern. */ - if (m1) - m2 = (gmatch (srest, se, prest, pe, flags) == 0) || - (s != srest && gmatch (srest, se, p - 1, pe, flags) == 0); - if (m1 && m2) - return (0); - } - if (pnext == prest) - break; - } - return (FNM_NOMATCH); - - case '?': /* match zero or one of the patterns */ - case '@': /* match exactly one of the patterns */ - /* If we can get away with no matches, don't even bother. Just - call gmatch on the rest of the pattern and return success if - it succeeds. */ - if (xc == '?' && (gmatch (s, se, prest, pe, flags) == 0)) - return 0; - - /* OK, we have to do this the hard way. First, we see if one of - the subpatterns matches, then, if it does, we try to match the - rest of the string. */ - for (psub = p + 1; ; psub = pnext) - { - pnext = patscan (psub, pe, '|'); - srest = (prest == pe) ? se : s; - for ( ; srest <= se; srest++) - { - if (gmatch (s, srest, psub, pnext - 1, flags) == 0 && - gmatch (srest, se, prest, pe, flags) == 0) - return (0); - } - if (pnext == prest) - break; - } - return (FNM_NOMATCH); - - case '!': /* match anything *except* one of the patterns */ - for (srest = s; srest <= se; srest++) - { - m1 = 0; - for (psub = p + 1; ; psub = pnext) - { - pnext = patscan (psub, pe, '|'); - /* If one of the patterns matches, just bail immediately. */ - if (m1 = (gmatch (s, srest, psub, pnext - 1, flags) == 0)) - break; - if (pnext == prest) - break; - } - if (m1 == 0 && gmatch (srest, se, prest, pe, flags) == 0) - return (0); - } - return (FNM_NOMATCH); - } - - return (FNM_NOMATCH); -} -#endif /* EXTENDED_GLOB */ - -#ifdef TEST -main (c, v) - int c; - char **v; -{ - char *string, *pat; - - string = v[1]; - pat = v[2]; - - if (fnmatch (pat, string, 0) == 0) - { - printf ("%s matches %s\n", string, pat); - exit (0); - } - else - { - printf ("%s does not match %s\n", string, pat); - exit (1); - } -} -#endif - -#endif - |