Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
26 | pmbaty | 1 | /* ACC -- Automatic Compiler Configuration |
2 | |||
3 | Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer |
||
4 | All Rights Reserved. |
||
5 | |||
6 | This software is a copyrighted work licensed under the terms of |
||
7 | the GNU General Public License. Please consult the file "ACC_LICENSE" |
||
8 | for details. |
||
9 | |||
10 | Markus F.X.J. Oberhumer |
||
11 | <markus@oberhumer.com> |
||
12 | http://www.oberhumer.com/ |
||
13 | */ |
||
14 | |||
15 | |||
16 | #define __ACCLIB_FNMATCH_CH_INCLUDED 1 |
||
17 | #if !defined(ACCLIB_PUBLIC) |
||
18 | # define ACCLIB_PUBLIC(r,f) r __ACCLIB_FUNCNAME(f) |
||
19 | #endif |
||
20 | |||
21 | |||
22 | /************************************************************************* |
||
23 | // |
||
24 | **************************************************************************/ |
||
25 | |||
26 | typedef struct { |
||
27 | const acc_hbyte_p s; |
||
28 | const acc_hbyte_p s_start; |
||
29 | int f; |
||
30 | int f_escape; |
||
31 | int f_casefold; |
||
32 | } acc_fnmatch_internal_t; |
||
33 | |||
34 | |||
35 | static int __ACCLIB_FUNCNAME(acc_fnmatch_internal) (const acc_hbyte_p p, acc_fnmatch_internal_t* a) |
||
36 | { |
||
37 | const acc_hbyte_p s = a->s; |
||
38 | int f_pathname = (a->f & (ACC_FNMATCH_PATHNAME | ACC_FNMATCH_PATHSTAR)); |
||
39 | |||
40 | while (*p) { |
||
41 | switch (*p) { |
||
42 | case '?': case '[': |
||
43 | if (*s == 0) return 0; |
||
44 | if (*s == '/' && f_pathname) return 0; |
||
45 | if (*s == '.' && (a->f & ACC_FNMATCH_PERIOD) && (s == a->s_start || (f_pathname && s[-1] == '/'))) return 0; |
||
46 | if (*p == '?') break; |
||
47 | { |
||
48 | int r = 0, fail = 0; unsigned char last = 0; |
||
49 | if (*++p == '^' || *p == '!') |
||
50 | fail = 1, ++p; |
||
51 | do { |
||
52 | switch (*p) { |
||
53 | case 0: |
||
54 | return -1; |
||
55 | case '-': |
||
56 | if (last == 0 || p[1] == ']') goto acc_label_default; |
||
57 | if (a->f_escape && p[1] == '\\') ++p; |
||
58 | if (*++p == 0) return -1; |
||
59 | if (!a->f_casefold && last <= *s && *s <= *p) r = 1; |
||
60 | else if (a->f_casefold && acc_ascii_tolower(last) <= acc_ascii_tolower(*s) && acc_ascii_tolower(*s) <= acc_ascii_tolower(*p)) r = 1; |
||
61 | last = 0; |
||
62 | continue; |
||
63 | /* TODO: implement sets like [:alpha:] ??? */ |
||
64 | case '\\': |
||
65 | if (a->f_escape && *++p == 0) return -1; |
||
66 | default: acc_label_default: |
||
67 | if (*s == *p) r = 1; |
||
68 | else if (a->f_casefold && acc_ascii_tolower(*s) == acc_ascii_tolower(*p)) r = 1; |
||
69 | break; |
||
70 | } |
||
71 | last = *p; |
||
72 | } while (*++p != ']'); |
||
73 | if (r == fail) |
||
74 | return 0; |
||
75 | break; |
||
76 | } |
||
77 | case '*': |
||
78 | while (*++p == '*') if (a->f & ACC_FNMATCH_PATHSTAR) f_pathname = 0; |
||
79 | if (*s == '.' && (a->f & ACC_FNMATCH_PERIOD) && (s == a->s_start || (f_pathname && s[-1] == '/'))) return 0; |
||
80 | if (*p == 0) { |
||
81 | if (f_pathname) while (*s) if (*s++ == '/') return 0; |
||
82 | return 1; |
||
83 | } |
||
84 | for ( ; *s; ++s) { |
||
85 | int r; |
||
86 | a->s = s; r = __ACCLIB_FUNCNAME(acc_fnmatch_internal)(p, a); |
||
87 | switch (r) { |
||
88 | case 0: if (*s == '/' && f_pathname) return 2; break; |
||
89 | case 2: if (!f_pathname) break; |
||
90 | default: return r; |
||
91 | } |
||
92 | } |
||
93 | return 0; |
||
94 | case '\\': |
||
95 | if (a->f_escape && *++p == 0) return -1; |
||
96 | default: |
||
97 | if (*s == *p) break; |
||
98 | if (a->f_casefold && acc_ascii_tolower(*s) == acc_ascii_tolower(*p)) break; |
||
99 | return 0; |
||
100 | } |
||
101 | ++p, ++s; |
||
102 | } |
||
103 | return *s == 0; |
||
104 | } |
||
105 | |||
106 | |||
107 | ACCLIB_PUBLIC(int, acc_fnmatch) (const acc_hchar_p p, const acc_hchar_p s, int flags) |
||
108 | { |
||
109 | int r; |
||
110 | acc_fnmatch_internal_t args; |
||
111 | args.s = args.s_start = (const acc_hbyte_p) s; |
||
112 | args.f = flags; |
||
113 | args.f_escape = !(flags & ACC_FNMATCH_NOESCAPE); |
||
114 | args.f_casefold = (flags & ACC_FNMATCH_ASCII_CASEFOLD); |
||
115 | r = __ACCLIB_FUNCNAME(acc_fnmatch_internal)((const acc_hbyte_p)p, &args); |
||
116 | if (r < 0) return r; |
||
117 | return r != 1; |
||
118 | } |
||
119 | |||
120 | |||
121 | /* |
||
122 | vi:ts=4:et |
||
123 | */ |