Annotation of gforth/engine/fnmatch.c, revision 1.2

1.2     ! anton       1: /* Copyright (C) 1991, 1992, 1993, 1996, 1997 Free Software Foundation, Inc.
1.1       anton       2: 
1.2     ! anton       3:    This program is free software; you can redistribute it and/or modify
        !             4:    it under the terms of the GNU General Public License as published by
        !             5:    the Free Software Foundation; either version 2, or (at your option)
        !             6:    any later version.
1.1       anton       7: 
1.2     ! anton       8:    This program is distributed in the hope that it will be useful,
1.1       anton       9:    but WITHOUT ANY WARRANTY; without even the implied warranty of
1.2     ! anton      10:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            11:    GNU General Public License for more details.
1.1       anton      12: 
1.2     ! anton      13:   You should have received a copy of the GNU General Public License
        !            14:   along with this program; if not, write to the Free Software Foundation,
        !            15:   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
1.1       anton      16: 
                     17: #if HAVE_CONFIG_H
                     18: # include <config.h>
                     19: #endif
                     20: 
                     21: /* Enable GNU extensions in fnmatch.h.  */
                     22: #ifndef _GNU_SOURCE
                     23: # define _GNU_SOURCE   1
                     24: #endif
                     25: 
                     26: #include <errno.h>
                     27: #include <fnmatch.h>
                     28: #include <ctype.h>
                     29: 
                     30: 
                     31: /* Comment out all this code if we are using the GNU C Library, and are not
                     32:    actually compiling the library itself.  This code is part of the GNU C
                     33:    Library, but also included in many other GNU distributions.  Compiling
                     34:    and linking in this code is a waste when using the GNU C library
                     35:    (especially if it is a shared library).  Rather than having every GNU
                     36:    program understand `configure --with-gnu-libc' and omit the object files,
                     37:    it is simpler to just do this in the source for each such file.  */
                     38: 
                     39: #if defined _LIBC || !defined __GNU_LIBRARY__
                     40: 
                     41: 
                     42: # if defined STDC_HEADERS || !defined isascii
                     43: #  define ISASCII(c) 1
                     44: # else
                     45: #  define ISASCII(c) isascii(c)
                     46: # endif
                     47: 
1.2     ! anton      48: # define ISUPPER(c) (ISASCII (c) && isupper (c))
1.1       anton      49: 
                     50: 
                     51: # ifndef errno
                     52: extern int errno;
                     53: # endif
                     54: 
                     55: /* Match STRING against the filename pattern PATTERN, returning zero if
                     56:    it matches, nonzero if not.  */
1.2     ! anton      57: int
        !            58: fnmatch (const char *pattern, const char *string, int flags)
1.1       anton      59: {
                     60:   register const char *p = pattern, *n = string;
1.2     ! anton      61:   register char c;
1.1       anton      62: 
                     63: /* Note that this evaluates C many times.  */
1.2     ! anton      64: # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
1.1       anton      65: 
                     66:   while ((c = *p++) != '\0')
                     67:     {
                     68:       c = FOLD (c);
                     69: 
                     70:       switch (c)
                     71:        {
                     72:        case '?':
                     73:          if (*n == '\0')
                     74:            return FNM_NOMATCH;
1.2     ! anton      75:          else if ((flags & FNM_FILE_NAME) && *n == '/')
1.1       anton      76:            return FNM_NOMATCH;
1.2     ! anton      77:          else if ((flags & FNM_PERIOD) && *n == '.' &&
        !            78:                   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1.1       anton      79:            return FNM_NOMATCH;
                     80:          break;
                     81: 
                     82:        case '\\':
                     83:          if (!(flags & FNM_NOESCAPE))
                     84:            {
                     85:              c = *p++;
                     86:              if (c == '\0')
                     87:                /* Trailing \ loses.  */
                     88:                return FNM_NOMATCH;
                     89:              c = FOLD (c);
                     90:            }
1.2     ! anton      91:          if (FOLD (*n) != c)
1.1       anton      92:            return FNM_NOMATCH;
                     93:          break;
                     94: 
                     95:        case '*':
1.2     ! anton      96:          if ((flags & FNM_PERIOD) && *n == '.' &&
        !            97:              (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1.1       anton      98:            return FNM_NOMATCH;
                     99: 
                    100:          for (c = *p++; c == '?' || c == '*'; c = *p++)
                    101:            {
1.2     ! anton     102:              if ((flags & FNM_FILE_NAME) && *n == '/')
1.1       anton     103:                /* A slash does not match a wildcard under FNM_FILE_NAME.  */
                    104:                return FNM_NOMATCH;
                    105:              else if (c == '?')
                    106:                {
                    107:                  /* A ? needs to match one character.  */
                    108:                  if (*n == '\0')
                    109:                    /* There isn't another character; no match.  */
                    110:                    return FNM_NOMATCH;
                    111:                  else
                    112:                    /* One character of the string is consumed in matching
                    113:                       this ? wildcard, so *??? won't match if there are
                    114:                       less than three characters.  */
                    115:                    ++n;
                    116:                }
                    117:            }
                    118: 
                    119:          if (c == '\0')
1.2     ! anton     120:            return 0;
1.1       anton     121: 
1.2     ! anton     122:          {
        !           123:            char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
        !           124:            c1 = FOLD (c1);
        !           125:            for (--p; *n != '\0'; ++n)
        !           126:              if ((c == '[' || FOLD (*n) == c1) &&
        !           127:                  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
        !           128:                return 0;
        !           129:            return FNM_NOMATCH;
        !           130:          }
1.1       anton     131: 
                    132:        case '[':
                    133:          {
                    134:            /* Nonzero if the sense of the character class is inverted.  */
                    135:            register int not;
                    136: 
                    137:            if (*n == '\0')
                    138:              return FNM_NOMATCH;
                    139: 
1.2     ! anton     140:            if ((flags & FNM_PERIOD) && *n == '.' &&
        !           141:                (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1.1       anton     142:              return FNM_NOMATCH;
                    143: 
1.2     ! anton     144:            not = (*p == '!' || *p == '^');
1.1       anton     145:            if (not)
                    146:              ++p;
                    147: 
                    148:            c = *p++;
                    149:            for (;;)
                    150:              {
1.2     ! anton     151:                register char cstart = c, cend = c;
1.1       anton     152: 
                    153:                if (!(flags & FNM_NOESCAPE) && c == '\\')
                    154:                  {
                    155:                    if (*p == '\0')
                    156:                      return FNM_NOMATCH;
1.2     ! anton     157:                    cstart = cend = *p++;
1.1       anton     158:                  }
                    159: 
1.2     ! anton     160:                cstart = cend = FOLD (cstart);
1.1       anton     161: 
1.2     ! anton     162:                if (c == '\0')
1.1       anton     163:                  /* [ (unterminated) loses.  */
                    164:                  return FNM_NOMATCH;
1.2     ! anton     165: 
        !           166:                c = *p++;
        !           167:                c = FOLD (c);
        !           168: 
        !           169:                if ((flags & FNM_FILE_NAME) && c == '/')
        !           170:                  /* [/] can never match.  */
        !           171:                  return FNM_NOMATCH;
        !           172: 
        !           173:                if (c == '-' && *p != ']')
1.1       anton     174:                  {
1.2     ! anton     175:                    cend = *p++;
        !           176:                    if (!(flags & FNM_NOESCAPE) && cend == '\\')
        !           177:                      cend = *p++;
        !           178:                    if (cend == '\0')
        !           179:                      return FNM_NOMATCH;
        !           180:                    cend = FOLD (cend);
1.1       anton     181: 
                    182:                    c = *p++;
1.2     ! anton     183:                  }
1.1       anton     184: 
1.2     ! anton     185:                if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
        !           186:                  goto matched;
1.1       anton     187: 
                    188:                if (c == ']')
                    189:                  break;
                    190:              }
                    191:            if (!not)
                    192:              return FNM_NOMATCH;
                    193:            break;
                    194: 
1.2     ! anton     195:          matched:;
1.1       anton     196:            /* Skip the rest of the [...] that already matched.  */
                    197:            while (c != ']')
                    198:              {
                    199:                if (c == '\0')
                    200:                  /* [... (unterminated) loses.  */
                    201:                  return FNM_NOMATCH;
                    202: 
                    203:                c = *p++;
                    204:                if (!(flags & FNM_NOESCAPE) && c == '\\')
                    205:                  {
                    206:                    if (*p == '\0')
                    207:                      return FNM_NOMATCH;
                    208:                    /* XXX 1003.2d11 is unclear if this is right.  */
                    209:                    ++p;
                    210:                  }
                    211:              }
                    212:            if (not)
                    213:              return FNM_NOMATCH;
                    214:          }
                    215:          break;
                    216: 
                    217:        default:
1.2     ! anton     218:          if (c != FOLD (*n))
1.1       anton     219:            return FNM_NOMATCH;
                    220:        }
                    221: 
                    222:       ++n;
                    223:     }
                    224: 
                    225:   if (*n == '\0')
                    226:     return 0;
                    227: 
                    228:   if ((flags & FNM_LEADING_DIR) && *n == '/')
                    229:     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
                    230:     return 0;
                    231: 
                    232:   return FNM_NOMATCH;
                    233: 
                    234: # undef FOLD
                    235: }
                    236: 
                    237: #endif /* _LIBC or not __GNU_LIBRARY__.  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>