134676ba8f382cbbb4186c9de4024bcc82150c58
[platform/upstream/bash.git] / lib / glob / fnmatch.c
1 /* fnmatch.c -- ksh-like extended pattern matching for the shell and filename
2                 globbing. */
3
4 /* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
5
6    This file is part of GNU Bash, the Bourne Again SHell.
7    
8    Bash is free software; you can redistribute it and/or modify it under
9    the terms of the GNU General Public License as published by the Free
10    Software Foundation; either version 2, or (at your option) any later
11    version.
12               
13    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14    WARRANTY; without even the implied warranty of MERCHANTABILITY or
15    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16    for more details.
17                          
18    You should have received a copy of the GNU General Public License along
19    with Bash; see the file COPYING.  If not, write to the Free Software
20    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22 #include <config.h>
23                                 
24 #include "fnmatch.h"
25 #include "collsyms.h"
26 #include <ctype.h>
27
28 static int gmatch ();
29 static char *brackmatch ();
30 #ifdef EXTENDED_GLOB
31 static int extmatch ();
32 #endif
33   
34 #if !defined (isascii)
35 #  define isascii(c)    ((unsigned int)(c) <= 0177)
36 #endif
37
38 /* Note that these evaluate C many times.  */
39
40 #ifndef isblank
41 #  define isblank(c)    ((c) == ' ' || (c) == '\t')
42 #endif
43
44 #ifndef isgraph
45 #  define isgraph(c)    ((c) != ' ' && isprint((c)))
46 #endif
47
48 #ifndef isxdigit
49 #  define isxdigit(c)   (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
50 #endif
51
52 /* The result of FOLD is an `unsigned char' */
53 # define FOLD(c) ((flags & FNM_CASEFOLD) && isupper ((unsigned char)c) \
54         ? tolower ((unsigned char)c) \
55         : ((unsigned char)c))
56
57 #ifndef STREQ
58 #define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
59 #define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
60 #endif
61
62 #if defined (HAVE_STRCOLL)
63 static int rangecmp (c1, c2)
64      int c1, c2;
65 {
66   static char s1[2] = { ' ', '\0' };
67   static char s2[2] = { ' ', '\0' };
68   int ret;
69
70   /* Eight bits only.  Period. */
71   c1 &= 0xFF;
72   c2 &= 0xFF;
73
74   if (c1 == c2)
75     return (0);
76
77   s1[0] = c1;
78   s2[0] = c2;
79
80   if ((ret = strcoll (s1, s2)) != 0)
81     return ret;
82   return (c1 - c2);
83 }
84 #else /* !HAVE_STRCOLL */
85 #  define rangecmp(c1, c2)      ((c1) - (c2))
86 #endif /* !HAVE_STRCOLL */
87
88 #if defined (HAVE_STRCOLL)
89 static int collequiv (c1, c2)
90      int c1, c2;
91 {
92   return (rangecmp (c1, c2) == 0);
93 }
94 #else
95 #  define collequiv(c1, c2)     ((c1) == (c2))
96 #endif
97
98 static int
99 collsym (s, len)
100      char *s;
101      int len;
102 {
103   register struct _collsym *csp;
104
105   for (csp = posix_collsyms; csp->name; csp++)
106     {
107       if (STREQN(csp->name, s, len) && csp->name[len] == '\0')
108         return (csp->code);
109     }
110   if (len == 1)
111     return s[0];
112   return -1;
113 }
114
115 int
116 fnmatch (pattern, string, flags)
117      char *pattern;
118      char *string;
119      int flags;
120 {
121   char *se, *pe;
122
123   if (string == 0 || pattern == 0)
124     return FNM_NOMATCH;
125
126   se = string + strlen (string);
127   pe = pattern + strlen (pattern);
128
129   return (gmatch (string, se, pattern, pe, flags));
130 }
131
132 /* Match STRING against the filename pattern PATTERN, returning zero if
133    it matches, FNM_NOMATCH if not.  */
134 static int
135 gmatch (string, se, pattern, pe, flags)
136      char *string, *se;
137      char *pattern, *pe;
138      int flags;
139 {
140   register char *p, *n;         /* pattern, string */
141   register char c;              /* current pattern character */
142   register char sc;             /* current string character */
143
144   p = pattern;
145   n = string;
146
147   if (string == 0 || pattern == 0)
148     return FNM_NOMATCH;
149
150   while (p < pe)
151     {
152       c = *p++;
153       c = FOLD (c);
154
155       sc = n < se ? *n : '\0';
156
157 #ifdef EXTENDED_GLOB
158       if ((flags & FNM_EXTMATCH) && *p == '(' &&
159           (c == '+' || c == '*' || c == '?' || c == '@' || c == '!')) /* ) */
160         /* extmatch () will handle recursively calling gmatch, so we can
161            just return what extmatch() returns. */
162         return (extmatch (c, n, se, p, pe, flags));
163 #endif
164
165       switch (c)
166         {
167         case '?':               /* Match single character */
168           if (sc == '\0')
169             return FNM_NOMATCH;
170           else if ((flags & FNM_PATHNAME) && sc == '/')
171             /* If we are matching a pathname, `?' can never match a `/'. */
172             return FNM_NOMATCH;
173           else if ((flags & FNM_PERIOD) && sc == '.' &&
174                    (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
175             /* `?' cannot match a `.' if it is the first character of the
176                string or if it is the first character following a slash and
177                we are matching a pathname. */
178             return FNM_NOMATCH;
179           break;
180
181         case '\\':              /* backslash escape removes special meaning */
182           if (p == pe)
183             return FNM_NOMATCH;
184
185           if ((flags & FNM_NOESCAPE) == 0)
186             {
187               c = *p++;
188               /* A trailing `\' cannot match. */
189               if (p > pe)
190                 return FNM_NOMATCH;
191               c = FOLD (c);
192             }
193           if (FOLD (sc) != (unsigned char)c)
194             return FNM_NOMATCH;
195           break;
196
197         case '*':               /* Match zero or more characters */
198           if (p == pe)
199             return 0;
200           
201           if ((flags & FNM_PERIOD) && sc == '.' &&
202               (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
203             /* `*' cannot match a `.' if it is the first character of the
204                string or if it is the first character following a slash and
205                we are matching a pathname. */
206             return FNM_NOMATCH;
207
208           /* Collapse multiple consecutive, `*' and `?', but make sure that
209              one character of the string is consumed for each `?'. */
210           for (c = *p++; (c == '?' || c == '*'); c = *p++)
211             {
212               if ((flags & FNM_PATHNAME) && sc == '/')
213                 /* A slash does not match a wildcard under FNM_PATHNAME. */
214                 return FNM_NOMATCH;
215               else if (c == '?')
216                 {
217                   if (sc == '\0')
218                     return FNM_NOMATCH;
219                   /* One character of the string is consumed in matching
220                      this ? wildcard, so *??? won't match if there are
221                      fewer than three characters. */
222                   n++;
223                   sc = n < se ? *n : '\0';
224                 }
225
226 #ifdef EXTENDED_GLOB
227               /* Handle ******(patlist) */
228               if ((flags & FNM_EXTMATCH) && c == '*' && *p == '(')  /*)*/
229                 return (extmatch (c, n, se, p, pe, flags));
230 #endif
231               if (p == pe)
232                 break;
233             }
234
235           /* If we've hit the end of the pattern and the last character of
236              the pattern was handled by the loop above, we've succeeded.
237              Otherwise, we need to match that last character. */
238           if (p == pe && (c == '?' || c == '*'))
239             return (0);
240
241           /* General case, use recursion. */
242           {
243             unsigned char c1;
244
245             c1 = (unsigned char)((flags & FNM_NOESCAPE) == 0 && c == '\\') ? *p : c;
246             c1 = FOLD (c1);
247             for (--p; n < se; ++n)
248               /* Only call fnmatch if the first character indicates a
249                  possible match. */
250               if ((c == '[' || FOLD (*n) == c1) &&
251                   gmatch (n, se, p, pe, flags & ~FNM_PERIOD) == 0)
252                 return (0);
253             return FNM_NOMATCH;
254           }
255
256         case '[':
257           {
258             if (sc == '\0' || n == se)
259               return FNM_NOMATCH;
260
261             /* A character class cannot match a `.' if it is the first
262                character of the string or if it is the first character
263                following a slash and we are matching a pathname. */
264             if ((flags & FNM_PERIOD) && sc == '.' &&
265                 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
266               return (FNM_NOMATCH);
267
268             p = brackmatch (p, sc, flags);
269             if (p == 0)
270               return FNM_NOMATCH;
271           }
272           break;
273
274         default:
275           if ((unsigned char)c != FOLD (sc))
276             return (FNM_NOMATCH);
277         }
278
279       ++n;
280     }
281
282   if (n == se)
283     return (0);
284
285   if ((flags & FNM_LEADING_DIR) && *n == '/')
286     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
287     return 0;
288           
289   return (FNM_NOMATCH);
290 }
291
292 /* Parse a bracket expression collating symbol ([.sym.]) starting at P, find
293    the value of the symbol, and move P past the collating symbol expression.
294    The value is returned in *VP, if VP is not null. */
295 static char *
296 parse_collsym (p, vp)
297      char *p;
298      int *vp;
299 {
300   register int pc;
301   int val;
302
303   p++;                          /* move past the `.' */
304           
305   for (pc = 0; p[pc]; pc++)
306     if (p[pc] == '.' && p[pc+1] == ']')
307       break;
308    val = collsym (p, pc);
309    if (vp)
310      *vp = val;
311    return (p + pc + 2);
312 }
313
314 static char *
315 brackmatch (p, test, flags)
316      char *p;
317      unsigned char test;
318      int flags;
319 {
320   register char cstart, cend, c;
321   register int not;    /* Nonzero if the sense of the character class is inverted.  */
322   int pc, brcnt;
323   char *savep;
324
325   test = FOLD (test);
326
327   savep = p;
328
329   /* POSIX.2 3.13.1 says that an exclamation mark (`!') shall replace the
330      circumflex (`^') in its role in a `nonmatching list'.  A bracket
331      expression starging with an unquoted circumflex character produces
332      unspecified results.  This implementation treats the two identically. */
333   if (not = (*p == '!' || *p == '^'))
334     ++p;
335
336   c = *p++;
337   for (;;)
338     {
339       /* Initialize cstart and cend in case `-' is the last
340          character of the pattern. */
341       cstart = cend = c;
342
343       /* POSIX.2 equivalence class:  [=c=].  See POSIX.2 2.8.3.2.  Find
344          the end of the equivalence class, move the pattern pointer past
345          it, and check for equivalence.  XXX - this handles only
346          single-character equivalence classes, which is wrong, or at
347          least incomplete. */
348       if (c == '[' && *p == '=' && p[2] == '=' && p[3] == ']')
349         {
350           pc = FOLD (p[1]);
351           p += 4;
352           if (collequiv (test, pc))
353             goto matched;
354           else
355             {
356               c = *p++;
357               if (c == '\0')
358                 return ((test == '[') ? savep : (char *)0);
359               c = FOLD (c);
360               continue;
361             }
362         }
363
364       /* POSIX.2 character class expression.  See POSIX.2 2.8.3.2. */
365       if (c == '[' && *p == ':')
366         {
367           pc = 0;       /* make sure invalid char classes don't match. */
368           if (STREQN (p+1, "alnum:]", 7))
369             { pc = isalnum (test); p += 8; }
370           else if (STREQN (p+1, "alpha:]", 7))
371             { pc = isalpha (test); p += 8; }
372           else if (STREQN (p+1, "blank:]", 7))
373             { pc = isblank (test); p += 8; }
374           else if (STREQN (p+1, "cntrl:]", 7))
375             { pc = iscntrl (test); p += 8; }
376           else if (STREQN (p+1, "digit:]", 7))
377             { pc = isdigit (test); p += 8; }
378           else if (STREQN (p+1, "graph:]", 7))
379             { pc = isgraph (test); p += 8; }
380           else if (STREQN (p+1, "lower:]", 7))
381             { pc = islower (test); p += 8; }
382           else if (STREQN (p+1, "print:]", 7))
383             { pc = isprint (test); p += 8; }
384           else if (STREQN (p+1, "punct:]", 7))
385             { pc = ispunct (test); p += 8; }
386           else if (STREQN (p+1, "space:]", 7))
387             { pc = isspace (test); p += 8; }
388           else if (STREQN (p+1, "upper:]", 7))
389             { pc = isupper (test); p += 8; }
390           else if (STREQN (p+1, "xdigit:]", 8))
391             { pc = isxdigit (test); p += 9; }
392           else if (STREQN (p+1, "ascii:]", 7))
393             { pc = isascii (test); p += 8; }
394           if (pc)
395               goto matched;
396           else
397             {
398               /* continue the loop here, since this expression can't be
399                  the first part of a range expression. */
400               c = *p++;
401               if (c == '\0')
402                 return ((test == '[') ? savep : (char *)0);
403               else if (c == ']')
404                 break;
405               c = FOLD (c);
406               continue;
407             }
408         }
409  
410       /* POSIX.2 collating symbols.  See POSIX.2 2.8.3.2.  Find the end of
411          the symbol name, make sure it is terminated by `.]', translate
412          the name to a character using the external table, and do the
413          comparison. */
414       if (c == '[' && *p == '.')
415         {
416           p = parse_collsym (p, &pc);
417           /* An invalid collating symbol cannot be the first point of a
418              range.  If it is, we set cstart to one greater than `test',
419              so any comparisons later will fail. */
420           cstart = (pc == -1) ? test + 1 : pc;
421         }
422
423       if (!(flags & FNM_NOESCAPE) && c == '\\')
424         {
425           if (*p == '\0')
426             return (char *)0;
427           cstart = cend = *p++;
428         }
429
430       cstart = cend = FOLD (cstart);
431
432       /* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
433          is not preceded by a backslash and is not part of a bracket
434          expression produces undefined results.'  This implementation
435          treats the `[' as just a character to be matched if there is
436          not a closing `]'. */
437       if (c == '\0')
438         return ((test == '[') ? savep : (char *)0);
439
440       c = *p++;
441       c = FOLD (c);
442
443       if ((flags & FNM_PATHNAME) && c == '/')
444         /* [/] can never match when matching a pathname.  */
445         return (char *)0;
446
447       /* This introduces a range, unless the `-' is the last
448          character of the class.  Find the end of the range
449          and move past it. */
450       if (c == '-' && *p != ']')
451         {
452           cend = *p++;
453           if (!(flags & FNM_NOESCAPE) && cend == '\\')
454             cend = *p++;
455           if (cend == '\0')
456             return (char *)0;
457           if (cend == '[' && *p == '.')
458             {
459               p = parse_collsym (p, &pc);
460               /* An invalid collating symbol cannot be the second part of a
461                  range expression.  If we get one, we set cend to one fewer
462                  than the test character to make sure the range test fails. */
463               cend = (pc == -1) ? test - 1 : pc;
464             }
465           cend = FOLD (cend);
466
467           c = *p++;
468
469           /* POSIX.2 2.8.3.2:  ``The ending range point shall collate
470              equal to or higher than the starting range point; otherwise
471              the expression shall be treated as invalid.''  Note that this
472              applies to only the range expression; the rest of the bracket
473              expression is still checked for matches. */
474           if (rangecmp (cstart, cend) > 0)
475             {
476               if (c == ']')
477                 break;
478               c = FOLD (c);
479               continue;
480             }
481         }
482
483       if (rangecmp (test, cstart) >= 0 && rangecmp (test, cend) <= 0)
484         goto matched;
485
486       if (c == ']')
487         break;
488     }
489   /* No match. */
490   return (!not ? (char *)0 : p);
491
492 matched:
493   /* Skip the rest of the [...] that already matched.  */
494   brcnt = (c != ']') + (c == '[' && (*p == '=' || *p == ':' || *p == '.'));
495   while (brcnt > 0)
496     {
497       /* A `[' without a matching `]' is just another character to match. */
498       if (c == '\0')
499         return ((test == '[') ? savep : (char *)0);
500
501       c = *p++;
502       if (c == '[' && (*p == '=' || *p == ':' || *p == '.'))
503         brcnt++;
504       else if (c == ']')
505         brcnt--;
506       else if (!(flags & FNM_NOESCAPE) && c == '\\')
507         {
508           if (*p == '\0')
509             return (char *)0;
510           /* XXX 1003.2d11 is unclear if this is right. */
511           ++p;
512         }
513     }
514   return (not ? (char *)0 : p);
515 }
516
517 #if defined (EXTENDED_GLOB)
518 /* ksh-like extended pattern matching:
519
520         [?*+@!](pat-list)
521
522    where pat-list is a list of one or patterns separated by `|'.  Operation
523    is as follows:
524
525         ?(patlist)      match zero or one of the given patterns
526         *(patlist)      match zero or more of the given patterns
527         +(patlist)      match one or more of the given patterns
528         @(patlist)      match exactly one of the given patterns
529         !(patlist)      match anything except one of the given patterns
530 */
531
532 /* Scan a pattern starting at STRING and ending at END, keeping track of
533    embedded () and [].  If DELIM is 0, we scan until a matching `)'
534    because we're scanning a `patlist'.  Otherwise, we scan until we see
535    DELIM.  In all cases, we never scan past END.  The return value is the
536    first character after the matching DELIM. */
537 static char *
538 patscan (string, end, delim)
539      char *string, *end;
540      int delim;
541 {
542   int pnest, bnest;
543   char *s, c;
544
545   pnest = bnest = 0;
546   for (s = string; c = *s; s++)
547     {
548       switch (c)
549         {
550         case '\0':
551           return ((char *)0);
552         case '[':
553           bnest++;
554           break;
555         case ']':
556           if (bnest)
557             bnest--;
558           break;
559         case '(':
560           if (bnest == 0)
561             pnest++;
562           break;
563         case ')':
564           if (bnest == 0)
565             pnest--;
566           if (pnest <= 0)
567             return ++s;
568           break;
569         case '|':
570           if (bnest == 0 && pnest == 0 && delim == '|')
571             return ++s;
572           break;
573         }
574     }
575   return (char *)0;
576 }
577
578 /* Return 0 if dequoted pattern matches S in the current locale. */
579 static int
580 strcompare (p, pe, s, se)
581      char *p, *pe, *s, *se;
582 {
583   int ret;
584   char c1, c2;
585
586   c1 = *pe;
587   c2 = *se;
588
589   *pe = *se = '\0';
590 #if defined (HAVE_STRCOLL)
591   ret = strcoll (p, s);
592 #else
593   ret = strcmp (p, s);
594 #endif
595
596   *pe = c1;
597   *se = c2;
598
599   return (ret == 0 ? ret : FNM_NOMATCH);
600 }
601
602 /* Match a ksh extended pattern specifier.  Return FNM_NOMATCH on failure or
603    0 on success.  This is handed the entire rest of the pattern and string
604    the first time an extended pattern specifier is encountered, so it calls
605    gmatch recursively. */
606 static int
607 extmatch (xc, s, se, p, pe, flags)
608      int xc;            /* select which operation */
609      char *s, *se;
610      char *p, *pe;
611      int flags;
612 {
613   char *prest;                  /* pointer to rest of pattern */
614   char *psub;                   /* pointer to sub-pattern */
615   char *pnext;                  /* pointer to next sub-pattern */
616   char *srest;                  /* pointer to rest of string */
617   int m1, m2;
618
619   switch (xc)
620     {
621     case '+':                   /* match one or more occurrences */
622     case '*':                   /* match zero or more occurrences */
623       prest = patscan (p, pe, 0);
624       if (prest == 0)
625         /* If PREST is 0, we failed to scan a valid pattern.  In this
626            case, we just want to compare the two as strings. */
627         return (strcompare (p - 1, pe, s, se));
628
629       /* If we can get away with no matches, don't even bother.  Just
630          call gmatch on the rest of the pattern and return success if
631          it succeeds. */
632       if (xc == '*' && (gmatch (s, se, prest, pe, flags) == 0))
633         return 0;
634
635       /* OK, we have to do this the hard way.  First, we make sure one of
636          the subpatterns matches, then we try to match the rest of the
637          string. */
638       for (psub = p + 1; ; psub = pnext)
639         {
640           pnext = patscan (psub, pe, '|');
641           for (srest = s; srest <= se; srest++)
642             {
643               /* Match this substring (S -> SREST) against this
644                  subpattern (psub -> pnext - 1) */
645               m1 = gmatch (s, srest, psub, pnext - 1, flags) == 0;
646               /* OK, we matched a subpattern, so make sure the rest of the
647                  string matches the rest of the pattern.  Also handle
648                  multiple matches of the pattern. */
649               if (m1)
650                 m2 = (gmatch (srest, se, prest, pe, flags) == 0) ||
651                       (s != srest && gmatch (srest, se, p - 1, pe, flags) == 0);
652               if (m1 && m2)
653                 return (0);
654             }
655           if (pnext == prest)
656             break;
657         }
658       return (FNM_NOMATCH);
659
660     case '?':           /* match zero or one of the patterns */
661     case '@':           /* match exactly one of the patterns */
662       prest = patscan (p, pe, 0);
663       if (prest == 0)
664         return (strcompare (p - 1, pe, s, se));
665       
666       /* If we can get away with no matches, don't even bother.  Just
667          call gmatch on the rest of the pattern and return success if
668          it succeeds. */
669       if (xc == '?' && (gmatch (s, se, prest, pe, flags) == 0))
670         return 0;
671
672       /* OK, we have to do this the hard way.  First, we see if one of
673          the subpatterns matches, then, if it does, we try to match the
674          rest of the string. */
675       for (psub = p + 1; ; psub = pnext)
676         {
677           pnext = patscan (psub, pe, '|');
678           srest = (prest == pe) ? se : s;
679           for ( ; srest <= se; srest++)
680             {
681               if (gmatch (s, srest, psub, pnext - 1, flags) == 0 &&
682                   gmatch (srest, se, prest, pe, flags) == 0)
683                 return (0);
684             }
685           if (pnext == prest)
686             break;
687         }
688       return (FNM_NOMATCH);
689
690     case '!':           /* match anything *except* one of the patterns */
691       prest = patscan (p, pe, 0);
692       if (prest == 0)
693         return (strcompare (p - 1, pe, s, se));
694
695       for (srest = s; srest <= se; srest++)
696         {
697           m1 = 0;
698           for (psub = p + 1; ; psub = pnext)
699             {
700               pnext = patscan (psub, pe, '|');
701               /* If one of the patterns matches, just bail immediately. */
702               if (m1 = (gmatch (s, srest, psub, pnext - 1, flags) == 0))
703                 break;
704               if (pnext == prest)
705                 break;
706             }
707           if (m1 == 0 && gmatch (srest, se, prest, pe, flags) == 0)
708             return (0); 
709         }
710       return (FNM_NOMATCH);
711     }
712
713   return (FNM_NOMATCH);
714 }
715 #endif /* EXTENDED_GLOB */
716
717 #ifdef TEST
718 main (c, v)
719      int c;
720      char **v;
721 {
722   char *string, *pat;
723
724   string = v[1];
725   pat = v[2];
726
727   if (fnmatch (pat, string, 0) == 0)
728     {
729       printf ("%s matches %s\n", string, pat);
730       exit (0);
731     }
732   else
733     {
734       printf ("%s does not match %s\n", string, pat);
735       exit (1);
736     }
737 }
738 #endif