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 | */ |