char *cclenter(const char *argp) /* add a character class */ { int i, c, c2; int j; uschar *p = (uschar *) argp; uschar *op, *bp; static uschar *buf = 0; static int bufsz = 100; op = p; if (buf == 0 && (buf = (uschar *) malloc(bufsz)) == NULL) FATAL("out of space for character class [%.10s...] 1", p); bp = buf; for (i = 0; (c = *p++) != 0; ) { if (c == '\\') { c = quoted(&p); } else if (c == '-' && i > 0 && bp[-1] != 0) { if (*p != 0) { c = bp[-1]; c2 = *p++; if (c2 == '\\') c2 = quoted(&p); if (collate_range_cmp(c, c2) > 0) { bp--; i--; continue; } for (j = 0; j < NCHARS; j++) { if ((collate_range_cmp(c, j) > 0) || collate_range_cmp(j, c2) > 0) continue; if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, "cclenter1")) FATAL("out of space for character class [%.10s...] 2", p); *bp++ = j; i++; } continue; } } if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, "cclenter2")) FATAL("out of space for character class [%.10s...] 3", p); *bp++ = c; i++; } *bp = 0; dprintf( ("cclenter: in = |%s|, out = |%s|\n", op, buf) ); xfree(op); return (char *) tostring((char *) buf); }
static int patmatch(const char *pattern, const char *string, int squoted) { const char *p, *q, *end; const char *bt_p, *bt_q; char c; wchar_t wc, wc2; p = pattern; q = string; bt_p = NULL; bt_q = NULL; for (;;) { switch (c = *p++) { case '\0': if (*q != '\0') goto backtrack; return 1; case CTLESC: if (squoted && *q == CTLESC) q++; if (*q++ != *p++) goto backtrack; break; case CTLQUOTEMARK: continue; case '?': if (squoted && *q == CTLESC) q++; if (*q == '\0') return 0; if (localeisutf8) { wc = get_wc(&q); /* * A '?' does not match invalid UTF-8 but a * '*' does, so backtrack. */ if (wc == 0) goto backtrack; } else wc = (unsigned char)*q++; break; case '*': c = *p; while (c == CTLQUOTEMARK || c == '*') c = *++p; /* * If the pattern ends here, we know the string * matches without needing to look at the rest of it. */ if (c == '\0') return 1; /* * First try the shortest match for the '*' that * could work. We can forget any earlier '*' since * there is no way having it match more characters * can help us, given that we are already here. */ bt_p = p; bt_q = q; break; case '[': { const char *endp; int invert, found; wchar_t chr; endp = p; if (*endp == '!' || *endp == '^') endp++; do { while (*endp == CTLQUOTEMARK) endp++; if (*endp == 0) goto dft; /* no matching ] */ if (*endp == CTLESC) endp++; } while (*++endp != ']'); invert = 0; if (*p == '!' || *p == '^') { invert++; p++; } found = 0; if (squoted && *q == CTLESC) q++; if (*q == '\0') return 0; if (localeisutf8) { chr = get_wc(&q); if (chr == 0) goto backtrack; } else chr = (unsigned char)*q++; c = *p++; do { if (c == CTLQUOTEMARK) continue; if (c == '[' && *p == ':') { found |= match_charclass(p, chr, &end); if (end != NULL) p = end; } if (c == CTLESC) c = *p++; if (localeisutf8 && c & 0x80) { p--; wc = get_wc(&p); if (wc == 0) /* bad utf-8 */ return 0; } else wc = (unsigned char)c; if (*p == '-' && p[1] != ']') { p++; while (*p == CTLQUOTEMARK) p++; if (*p == CTLESC) p++; if (localeisutf8) { wc2 = get_wc(&p); if (wc2 == 0) /* bad utf-8 */ return 0; } else wc2 = (unsigned char)*p++; if ( collate_range_cmp(chr, wc) >= 0 && collate_range_cmp(chr, wc2) <= 0 ) found = 1; } else { if (chr == wc) found = 1; } } while ((c = *p++) != ']'); if (found == invert) goto backtrack; break; } dft: default: if (squoted && *q == CTLESC) q++; if (*q == '\0') return 0; if (*q++ == c) break; backtrack: /* * If we have a mismatch (other than hitting the end * of the string), go back to the last '*' seen and * have it match one additional character. */ if (bt_p == NULL) return 0; if (squoted && *bt_q == CTLESC) bt_q++; if (*bt_q == '\0') return 0; bt_q++; p = bt_p; q = bt_q; break; } } }
int CMacFindFile::pmatch(const char* pattern, const char* string) { const char *p, *q; char c; p = pattern; q = string; for (;;) { switch (c = *p++) { case '\0': goto breakloop; case '?': if (*q++ == '\0') return 0; break; case '*': c = *p; if (c != '?' && c != '*' && c != '[') { while (*q != c) { if (*q == '\0') return 0; q++; } } do { if (pmatch(p, q)) return 1; } while (*q++ != '\0'); return 0; case '[': { const char *endp; int invert, found; char chr; endp = p; if (*endp == '!') endp++; for (;;) { if (*endp == '\0') goto dft; /* no matching ] */ if (*++endp == ']') break; } invert = 0; if (*p == '!') { invert++; p++; } found = 0; chr = *q++; if (chr == '\0') return 0; c = *p++; do { if (*p == '-' && p[1] != ']') { p++; #if 0 if ( collate_range_cmp(chr, c) >= 0 && collate_range_cmp(chr, *p) <= 0 ) found = 1; #endif p++; } else { if (chr == c) found = 1; } } while ((c = *p++) != ']'); if (found == invert) return 0; break; } dft: default: if (*q++ != c) return 0; break; } } breakloop: if (*q != '\0') return 0; return 1; }
STATIC int pmatch(char *pattern, char *string, int squoted) { char *p, *q; char c; p = pattern; q = string; for (;;) { switch (c = *p++) { case '\0': goto breakloop; case CTLESC: if (squoted && *q == CTLESC) q++; if (*q++ != *p++) return 0; break; case CTLQUOTEMARK: continue; case '?': if (squoted && *q == CTLESC) q++; if (*q++ == '\0') return 0; break; case '*': c = *p; while (c == CTLQUOTEMARK || c == '*') c = *++p; if (c != CTLESC && c != CTLQUOTEMARK && c != '?' && c != '*' && c != '[') { while (*q != c) { if (squoted && *q == CTLESC && q[1] == c) break; if (*q == '\0') return 0; if (squoted && *q == CTLESC) q++; q++; } } do { if (pmatch(p, q, squoted)) return 1; if (squoted && *q == CTLESC) q++; } while (*q++ != '\0'); return 0; case '[': { char *endp; int invert, found; char chr; endp = p; if (*endp == '!' || *endp == '^') endp++; for (;;) { while (*endp == CTLQUOTEMARK) endp++; if (*endp == '\0') goto dft; /* no matching ] */ if (*endp == CTLESC) endp++; if (*++endp == ']') break; } invert = 0; if (*p == '!' || *p == '^') { invert++; p++; } found = 0; chr = *q++; if (squoted && chr == CTLESC) chr = *q++; if (chr == '\0') return 0; c = *p++; do { if (c == CTLQUOTEMARK) continue; if (c == CTLESC) c = *p++; if (*p == '-' && p[1] != ']') { p++; while (*p == CTLQUOTEMARK) p++; if (*p == CTLESC) p++; if ( collate_range_cmp(chr, c) >= 0 && collate_range_cmp(chr, *p) <= 0 ) found = 1; p++; } else { if (chr == c) found = 1; } } while ((c = *p++) != ']'); if (found == invert) return 0; break; } dft: default: if (squoted && *q == CTLESC) q++; if (*q++ != c) return 0; break; } } breakloop: if (*q != '\0') return 0; return 1; }