fnmatch.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <errno.h>
00021 #include <fnmatch.h>
00022
00023 #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
00024 extern int errno;
00025 #endif
00026
00027
00028
00029
00030 #ifdef __STDC__
00031 int
00032 fnmatch(char *pattern, char *string, int flags)
00033 #else
00034 int fnmatch(pattern, string, flags)
00035 char *pattern;
00036 char *string;
00037 int flags;
00038 #endif
00039 {
00040 register char *p = pattern, *n = string;
00041 register char c;
00042
00043 if ((flags & ~__FNM_FLAGS) != 0)
00044 {
00045 errno = EINVAL;
00046 return -1;
00047 }
00048
00049 while ((c = *p++) != '\0')
00050 switch (c)
00051 {
00052 case '?':
00053 if (*n == '\0')
00054 return FNM_NOMATCH;
00055 else if ((flags & FNM_PATHNAME) && *n == '/')
00056 return FNM_NOMATCH;
00057 else if ((flags & FNM_PERIOD) && *n == '.' &&
00058 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
00059 return FNM_NOMATCH;
00060 else
00061 ++n;
00062 break;
00063
00064 case '\\':
00065 if (!(flags & FNM_NOESCAPE))
00066 c = *p++;
00067 if (*n++ != c)
00068 return FNM_NOMATCH;
00069 break;
00070
00071 case '*':
00072 if ((flags & FNM_PERIOD) && *n == '.' &&
00073 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
00074 return FNM_NOMATCH;
00075
00076 for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
00077 if (((flags & FNM_PATHNAME) && *n == '/') ||
00078 (c == '?' && *n == '\0'))
00079 return FNM_NOMATCH;
00080
00081 if (c == '\0')
00082 return 0;
00083
00084 {
00085 char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
00086 for (--p; *n != '\0'; ++n)
00087 if ((c == '[' || *n == c1) &&
00088 fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
00089 return 0;
00090 return FNM_NOMATCH;
00091 }
00092
00093 case '[':
00094 {
00095
00096
00097 register int not;
00098
00099 if (*n == '\0')
00100 return FNM_NOMATCH;
00101
00102 if ((flags & FNM_PERIOD) && *n == '.' &&
00103 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
00104 return FNM_NOMATCH;
00105
00106 not = *p == '!';
00107 if (not)
00108 ++p;
00109
00110 c = *p++;
00111 for (;;)
00112 {
00113 register char cstart = c, cend = c;
00114
00115 if (!(flags & FNM_NOESCAPE) && c == '\\')
00116 cstart = cend = *p++;
00117
00118 if (c == '\0')
00119
00120 return FNM_NOMATCH;
00121
00122 c = *p++;
00123 if ((flags & FNM_PATHNAME) && c == '/')
00124
00125 return FNM_NOMATCH;
00126
00127 if (c == '-')
00128 {
00129 cend = *p++;
00130 if (!(flags & FNM_NOESCAPE) && cend == '\\')
00131 cend = *p++;
00132 if (cend == '\0')
00133 return FNM_NOMATCH;
00134 c = *p++;
00135 }
00136 if (*n >= cstart && *n <= cend)
00137 goto matched;
00138
00139 if (c == ']')
00140 break;
00141 }
00142 if (!not)
00143 return FNM_NOMATCH;
00144 break;
00145
00146 matched:;
00147
00148 while (c != ']')
00149 {
00150 if (c == '\0')
00151
00152 return FNM_NOMATCH;
00153
00154 c = *p++;
00155 if (!(flags & FNM_NOESCAPE) && c == '\\')
00156
00157 ++p;
00158 }
00159 if (not)
00160 return FNM_NOMATCH;
00161
00162 ++n;
00163 }
00164 break;
00165
00166 default:
00167 if (c != *n++)
00168 return FNM_NOMATCH;
00169 }
00170
00171 if (*n == '\0')
00172 return 0;
00173
00174 return FNM_NOMATCH;
00175 }