Ejemplo n.º 1
0
static List *extractsinglematch(const char *subject, const char *pattern,
				const char *quoting, List *result) {
	int i;
	const char *s;

	if (!haswild(pattern, quoting) /* no wildcards, so no matches */
	    || !match(subject, pattern, quoting))
		return NULL;

	for (s = subject, i = 0; pattern[i] != '\0'; s++) {
		if (ISQUOTED(quoting, i))
			i++;
		else {
			int c = pattern[i++];
			switch (c) {
			    case '*': {
				const char *begin;
				if (pattern[i] == '\0')
					return mklist(mkstr(gcdup(s)), result);
				for (begin = s;; s++) {
					const char *q = TAILQUOTE(quoting, i);
					assert(*s != '\0');
					if (match(s, pattern + i, q)) {
						result = mklist(mkstr(gcndup(begin, s - begin)), result);
						return haswild(pattern + i, q)
							? extractsinglematch(s, pattern + i, q, result)
							: result;
					}
				}
			    }
			    case '[': {
				int j = rangematch(pattern + i, TAILQUOTE(quoting, i), *s);
				assert(j != RANGE_FAIL);
				if (j == RANGE_ERROR) {
					assert(*s == '[');
					break;
				}
				i += j;
			    }
			    /* FALLTHROUGH */
			    case '?':
				result = mklist(mkstr(str("%c", *s)), result);
				break;
			    default:
				break;
			}
		}
	}

	return result;
}
Ejemplo n.º 2
0
/* match -- match a single pattern against a single string. */
extern Boolean match(const char *s, const char *p, const char *q) {
	int i;
	if (q == QUOTED)
		return streq(s, p);
	for (i = 0;;) {
		int c = p[i++];
		if (c == '\0')
			return *s == '\0';
		else if (q == UNQUOTED || q[i - 1] == 'r') {
			switch (c) {
			case '?':
				if (*s++ == '\0')
					return FALSE;
				break;
			case '*':
				while (p[i] == '*' && (q == UNQUOTED || q[i] == 'r'))	/* collapse multiple stars */
					i++;
				if (p[i] == '\0') 	/* star at end of pattern? */
					return TRUE;
				while (*s != '\0')
					if (match(s++, p + i, TAILQUOTE(q, i)))
						return TRUE;
				return FALSE;
			case '[': {
				int j;
				if (*s == '\0')
					return FALSE;
				switch (j = rangematch(p + i, TAILQUOTE(q, i), *s)) {
				default:
					i += j;
					break;
				case RANGE_FAIL:
					return FALSE;
				case RANGE_ERROR:
					if (*s != '[')
						return FALSE;
				}
				s++;
				break;
			}
			default:
				if (c != *s++)
					return FALSE;
			}
		} else if (c != *s++)
			return FALSE;
	}
}
Ejemplo n.º 3
0
extern bool match(char *p, char *m, char *s) {
	int i, j;
	if (m == NULL)
		return streq(p, s);
	i = 0;
	while (1) {
		if (p[i] == '\0')
			return *s == '\0';
		else if (m[i]) {
			switch (p[i++]) {
			case '?':
				if (*s++ == '\0')
					return FALSE;
				break;
			case '*':
				while (p[i] == '*' && m[i] == 1)	/* collapse multiple stars */
					i++;
				if (p[i] == '\0') 	/* star at end of pattern? */
					return TRUE;
				while (*s != '\0')
					if (match(p + i, m + i, s++))
						return TRUE;
				return FALSE;
			case '[':
				if (*s == '\0')
					return FALSE;
				switch (j = rangematch(p + i, *s)) {
				default:
					i += j;
					break;
				case RANGE_FAIL:
					return FALSE;
				case RANGE_ERROR:
					if (*s != '[')
						return FALSE;
				}
				s++;
				break;
			default:
				panic("bad metacharacter in match");
				/* NOTREACHED */
				return FALSE; /* hush up gcc -Wall */
			}
		} else if (p[i++] != *s++)
			return FALSE;
	}
}
Ejemplo n.º 4
0
int
fnmatch(const char *pattern, const char *string, int flags)
{
	const char *stringstart;
	char *newp;
	char c, test;

	for (stringstart = string;;)
		switch (c = *pattern++) {
		case EOS:
			if ((flags & FNM_LEADING_DIR) && *string == '/')
				return (0);
			return (*string == EOS ? 0 : FNM_NOMATCH);
		case '?':
			if (*string == EOS)
				return (FNM_NOMATCH);
			if (*string == '/' && (flags & FNM_PATHNAME))
				return (FNM_NOMATCH);
			if (*string == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				return (FNM_NOMATCH);
			++string;
			break;
		case '*':
			c = *pattern;
			/* Collapse multiple stars. */
			while (c == '*')
				c = *++pattern;

			if (*string == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				return (FNM_NOMATCH);

			/* Optimize for pattern with * at end or before /. */
			if (c == EOS)
				if (flags & FNM_PATHNAME)
					return ((flags & FNM_LEADING_DIR) ||
					    strchr(string, '/') == NULL ?
					    0 : FNM_NOMATCH);
				else
					return (0);
			else if (c == '/' && flags & FNM_PATHNAME) {
				if ((string = strchr(string, '/')) == NULL)
					return (FNM_NOMATCH);
				break;
			}

			/* General case, use recursion. */
			while ((test = *string) != EOS) {
				if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
					return (0);
				if (test == '/' && flags & FNM_PATHNAME)
					break;
				++string;
			}
			return (FNM_NOMATCH);
		case '[':
			if (*string == EOS)
				return (FNM_NOMATCH);
			if (*string == '/' && (flags & FNM_PATHNAME))
				return (FNM_NOMATCH);
			if (*string == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				return (FNM_NOMATCH);

			switch (rangematch(pattern, *string, flags, &newp)) {
			case RANGE_ERROR:
				goto norm;
			case RANGE_MATCH:
				pattern = newp;
				break;
			case RANGE_NOMATCH:
				return (FNM_NOMATCH);
			}
			++string;
			break;
		case '\\':
			if (!(flags & FNM_NOESCAPE)) {
				if ((c = *pattern++) == EOS) {
					c = '\\';
					--pattern;
				}
			}
			/* FALLTHROUGH */
		default:
		norm:
			if (c == *string)
				;
			else if ((flags & FNM_CASEFOLD) &&
				 (tolower((unsigned char)c) ==
				  tolower((unsigned char)*string)))
				;
			else
				return (FNM_NOMATCH);
			string++;
			break;
		}
	/* NOTREACHED */
}
Ejemplo n.º 5
0
static int
fnmatch1(const char *pattern, const char *string, const char *stringstart,
    int flags, mbstate_t patmbs, mbstate_t strmbs)
{
	const char *bt_pattern, *bt_string;
	mbstate_t bt_patmbs, bt_strmbs;
	char *newp;
	char c;
	wchar_t pc, sc;
	size_t pclen, sclen;

	bt_pattern = bt_string = NULL;
	for (;;) {
		pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs);
		if (pclen == (size_t)-1 || pclen == (size_t)-2)
			return (FNM_NOMATCH);
		pattern += pclen;
		sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs);
		if (sclen == (size_t)-1 || sclen == (size_t)-2) {
			sc = (unsigned char)*string;
			sclen = 1;
			memset(&strmbs, 0, sizeof(strmbs));
		}
		switch (pc) {
		case EOS:
			if ((flags & FNM_LEADING_DIR) && sc == '/')
				return (0);
			if (sc == EOS)
				return (0);
			goto backtrack;
		case '?':
			if (sc == EOS)
				return (FNM_NOMATCH);
			if (sc == '/' && (flags & FNM_PATHNAME))
				goto backtrack;
			if (sc == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				goto backtrack;
			string += sclen;
			break;
		case '*':
			c = *pattern;
			/* Collapse multiple stars. */
			while (c == '*')
				c = *++pattern;

			if (sc == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				goto backtrack;

			/* Optimize for pattern with * at end or before /. */
			if (c == EOS)
				if (flags & FNM_PATHNAME)
					return ((flags & FNM_LEADING_DIR) ||
					    strchr(string, '/') == NULL ?
					    0 : FNM_NOMATCH);
				else
					return (0);
			else if (c == '/' && flags & FNM_PATHNAME) {
				if ((string = strchr(string, '/')) == NULL)
					return (FNM_NOMATCH);
				break;
			}

			/*
			 * 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_pattern = pattern, bt_patmbs = patmbs;
			bt_string = string, bt_strmbs = strmbs;
			break;
		case '[':
			if (sc == EOS)
				return (FNM_NOMATCH);
			if (sc == '/' && (flags & FNM_PATHNAME))
				goto backtrack;
			if (sc == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				goto backtrack;

			switch (rangematch(pattern, sc, flags, &newp,
			    &patmbs)) {
			case RANGE_ERROR:
				goto norm;
			case RANGE_MATCH:
				pattern = newp;
				break;
			case RANGE_NOMATCH:
				goto backtrack;
			}
			string += sclen;
			break;
		case '\\':
			if (!(flags & FNM_NOESCAPE)) {
				pclen = mbrtowc(&pc, pattern, MB_LEN_MAX,
				    &patmbs);
				if (pclen == (size_t)-1 || pclen == (size_t)-2)
					return (FNM_NOMATCH);
				pattern += pclen;
			}
			/* FALLTHROUGH */
		default:
		norm:
			string += sclen;
			if (pc == sc)
				;
			else if ((flags & FNM_CASEFOLD) &&
				 (towlower(pc) == towlower(sc)))
				;
			else {
		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_pattern == NULL)
					return (FNM_NOMATCH);
				sclen = mbrtowc(&sc, bt_string, MB_LEN_MAX,
				    &bt_strmbs);
				if (sclen == (size_t)-1 ||
				    sclen == (size_t)-2) {
					sc = (unsigned char)*bt_string;
					sclen = 1;
					memset(&bt_strmbs, 0,
					    sizeof(bt_strmbs));
				}
				if (sc == EOS)
					return (FNM_NOMATCH);
				if (sc == '/' && flags & FNM_PATHNAME)
					return (FNM_NOMATCH);
				bt_string += sclen;
				pattern = bt_pattern, patmbs = bt_patmbs;
				string = bt_string, strmbs = bt_strmbs;
			}
			break;
		}
	}
	/* NOTREACHED */
}
Ejemplo n.º 6
0
API_EXPORT(int) ap_fnmatch(const char *pattern, const char *string, int flags)
{
    const char *stringstart;
    char c, test;

    for (stringstart = string;;) {
	switch (c = *pattern++) {
	case EOS:
	    return (*string == EOS ? 0 : FNM_NOMATCH);
	case '?':
	    if (*string == EOS) {
		return (FNM_NOMATCH);
	    }
	    if (*string == '/' && (flags & FNM_PATHNAME)) {
		return (FNM_NOMATCH);
	    }
	    if (*string == '.' && (flags & FNM_PERIOD) &&
		(string == stringstart ||
		 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
		return (FNM_NOMATCH);
	    }
	    ++string;
	    break;
	case '*':
	    c = *pattern;
	    /* Collapse multiple stars. */
	    while (c == '*') {
		c = *++pattern;
	    }

	    if (*string == '.' && (flags & FNM_PERIOD) &&
		(string == stringstart ||
		 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
		return (FNM_NOMATCH);
	    }

	    /* Optimize for pattern with * at end or before /. */
	    if (c == EOS) {
		if (flags & FNM_PATHNAME) {
		    return (strchr(string, '/') == NULL ? 0 : FNM_NOMATCH);
		}
		else {
		    return (0);
		}
	    }
	    else if (c == '/' && flags & FNM_PATHNAME) {
	        if ((string = strchr(string, '/')) == NULL) {
		    return (FNM_NOMATCH);
		}
		break;
	    }

	    /* General case, use recursion. */
	    while ((test = *string) != EOS) {
	        if (!ap_fnmatch(pattern, string, flags & ~FNM_PERIOD)) {
		    return (0);
		}
		if (test == '/' && flags & FNM_PATHNAME) {
		    break;
		}
		++string;
	    }
	    return (FNM_NOMATCH);
	case '[':
	    if (*string == EOS) {
		return (FNM_NOMATCH);
	    }
	    if (*string == '/' && flags & FNM_PATHNAME) {
		return (FNM_NOMATCH);
	    }
	    if (*string == '.' && (flags & FNM_PERIOD) &&
		(string == stringstart ||
		 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
	        return (FNM_NOMATCH);
	    }
	    if ((pattern = rangematch(pattern, *string, flags)) == NULL) {
		return (FNM_NOMATCH);
	    }
	    ++string;
	    break;
	case '\\':
	    if (!(flags & FNM_NOESCAPE)) {
		if ((c = *pattern++) == EOS) {
		    c = '\\';
		    --pattern;
		}
	    }
	    /* FALLTHROUGH */
	default:
	    if (flags & FNM_CASE_BLIND) {
	        if (ap_tolower(c) != ap_tolower(*string)) {
		    return (FNM_NOMATCH);
		}
	    }
	    else if (c != *string) {
	        return (FNM_NOMATCH);
	    }
	    string++;
	    break;
	}
    /* NOTREACHED */
    }
}
Ejemplo n.º 7
0
EDITORCONFIG_LOCAL
int ec_fnmatch(const char *pattern, const char *string, int flags)
{
    const char *stringstart;
    char c, test;
    /* When multi stars presents, should_fnm_pathname will be set to 0
     * regardless of whether EC_FNM_PATHNAME is set into flags. Otherwise, the
     * value equals to flags & EC_FNM_PATHNAME */
    _Bool should_fnm_pathname = 0;

    for (stringstart = string;;)
        switch (c = *pattern++) {
        case EOS:
            if ((flags & EC_FNM_LEADING_DIR) && *string == '/')
                return (0);
            return (*string == EOS ? 0 : EC_FNM_NOMATCH);
        case '?':
            if (*string == EOS)
                return (EC_FNM_NOMATCH);
            if (*string == '/' && (flags & EC_FNM_PATHNAME))
                return (EC_FNM_NOMATCH);
            if (*string == '.' && (flags & EC_FNM_PERIOD) &&
                    (string == stringstart ||
                     ((flags & EC_FNM_PATHNAME) && *(string - 1) == '/')))
                return (EC_FNM_NOMATCH);
            ++string;
            break;
        case '*':
            c = *pattern;

            /* see the comments above the declaration of should_fnm_pathname */
            should_fnm_pathname = (_Bool)((c != '*') &&
                    (flags & EC_FNM_PATHNAME));

            /* Collapse multiple stars. */
            while (c == '*')
                c = *++pattern;

            if (*string == '.' && (flags & EC_FNM_PERIOD) &&
                    (string == stringstart ||
                     (should_fnm_pathname && *(string - 1) == '/')))
                return (EC_FNM_NOMATCH);

            /* Optimize for pattern with * at end or before /. */
            if (c == EOS)
                if (should_fnm_pathname)
                    return ((flags & EC_FNM_LEADING_DIR) ||
                            strchr(string, '/') == NULL ?
                            0 : EC_FNM_NOMATCH);
                else
                    return (0);
            else if (c == '/' && should_fnm_pathname) {
                if ((string = strchr(string, '/')) == NULL)
                    return (EC_FNM_NOMATCH);
                break;
            }

            /* General case, use recursion. */
            while ((test = *string) != EOS) {
                if (!ec_fnmatch(pattern, string, flags & ~EC_FNM_PERIOD))
                    return (0);
                if (test == '/' && should_fnm_pathname)
                    break;
                ++string;
            }
            return (EC_FNM_NOMATCH);
        case '[':
            if (*string == EOS)
                return (EC_FNM_NOMATCH);
            if (*string == '/' && flags & EC_FNM_PATHNAME)
                return (EC_FNM_NOMATCH);
            if ((pattern =
                        rangematch(pattern, *string, flags)) == NULL)
                return (EC_FNM_NOMATCH);
            ++string;
            break;
        case '\\':
            if (!(flags & EC_FNM_NOESCAPE)) {
                if ((c = *pattern++) == EOS) {
                    c = '\\';
                    --pattern;
                }
            }
            /* FALLTHROUGH */
        default:
            if (c == *string)
                ;
            else if ((flags & EC_FNM_CASEFOLD) &&
                    (tolower((unsigned char)c) ==
                     tolower((unsigned char)*string)))
                ;
            else if ((flags & EC_FNM_PREFIX_DIRS) && *string == EOS &&
                    ((c == '/' && string != stringstart) ||
                     (string == stringstart+1 && *stringstart == '/')))
                return (0);
            else
                return (EC_FNM_NOMATCH);
            string++;
            break;
        }
    /* NOTREACHED */
}
Ejemplo n.º 8
0
int
fnmatch(const char *pattern,const char *string,int flags)
	
{
	const char *stringstart;
	char c, test;

	//_DIAGASSERT(pattern != NULL);
	//_DIAGASSERT(string != NULL);

	for (stringstart = string;;)
		switch (c = FOLDCASE(*pattern++, flags)) {
		case EOS:
			if ((flags & FNM_LEADING_DIR) && *string == '/')
				return (0);
			return (*string == EOS ? 0 : FNM_NOMATCH);
		case '?':
			if (*string == EOS)
				return FNM_NOMATCH;
			if (*string == '/' && (flags & FNM_PATHNAME))
				return FNM_NOMATCH;
			if (*string == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				return FNM_NOMATCH;
			++string;
			break;
		case '*':
			c = FOLDCASE(*pattern, flags);
			/* Collapse multiple stars. */
			while (c == '*')
				c = FOLDCASE(*++pattern, flags);

			if (*string == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				return FNM_NOMATCH;

			/* Optimize for pattern with * at end or before /. */
			if (c == EOS) {
				if (flags & FNM_PATHNAME)
					return ((flags & FNM_LEADING_DIR) ||
					    strchr(string, '/') == NULL ?
					    0 : FNM_NOMATCH);
				else
					return (0);
			} else if (c == '/' && flags & FNM_PATHNAME) {
				if ((string = strchr(string, '/')) == NULL)
					return FNM_NOMATCH;
				break;
			}

			/* General case, use recursion. */
			while ((test = FOLDCASE(*string, flags)) != EOS) {
				if (!fnmatch(pattern, string,
					     flags & ~FNM_PERIOD))
					return (0);
				if (test == '/' && flags & FNM_PATHNAME)
					break;
				++string;
			}
			return FNM_NOMATCH;
		case '[':
			if (*string == EOS)
				return FNM_NOMATCH;
			if (*string == '/' && flags & FNM_PATHNAME)
				return FNM_NOMATCH;
			if ((pattern =
			    rangematch(pattern, FOLDCASE(*string, flags),
				       flags)) == NULL)
				return FNM_NOMATCH;
			++string;
			break;
		case '\\':
			if (!(flags & FNM_NOESCAPE)) {
				if ((c = FOLDCASE(*pattern++, flags)) == EOS) {
					c = '\\';
					--pattern;
				}
			}
			/* FALLTHROUGH */
		default:
			if (c != FOLDCASE(*string++, flags))
				return FNM_NOMATCH;
			break;
		}
	/* NOTREACHED */
}
Ejemplo n.º 9
0
int wildmatch(const char *pattern, const char *string, int flags)
{
    const char *stringstart;
    const char *newp;
    const char *slash;
    char c, test;
    char prev;
    int wild = 0;

    /* WM_WILDSTAR implies WM_PATHNAME. */
    if (check_flag(flags, WM_WILDSTAR)) {
        flags |= WM_PATHNAME;
    }

    for (stringstart = string;;) {
        switch (c = *pattern++) {
        case EOS:
            if (check_flag(flags, WM_LEADING_DIR) && *string == '/')
                return WM_MATCH;
            return (*string == EOS) ? WM_MATCH : WM_NOMATCH;
        case '?':
            if (*string == EOS)
                return WM_NOMATCH;
            if (*string == '/' && check_flag(flags, WM_PATHNAME))
                return WM_NOMATCH;
            if (*string == '.' && check_flag(flags, WM_PERIOD) &&
                (string == stringstart ||
                (check_flag(flags, WM_PATHNAME) && *(string - 1) == '/')))
                return WM_NOMATCH;
            ++string;
            break;
        case '*':
            c = *pattern;
            wild = check_flag(flags, WM_WILDSTAR) && c == '*';
            if (wild) {
                prev = pattern[-2];
                /* Collapse multiple stars and slash-** patterns,
                 * e.g. "** / *** / **** / **" (without spaces)
                 * is treated as a single ** wildstar.
                 */
                while (c == '*') {
                    c = *++pattern;
                }

                while (c == '/' && pattern[1] == '*' && pattern[2] == '*') {
                    prev = c;
                    c = *++pattern;
                    while (c == '*') {
                        c = *++pattern;
                    }
                }
                if (c == '/' &&
                        wildmatch(pattern+1, string, flags) == WM_MATCH) {
                    return WM_MATCH;
                }
            } else {
                /* Collapse multiple stars. */
                while (c == '*') {
                    c = *++pattern;
                }
            }

            if (!wild && *string == '.' && check_flag(flags, WM_PERIOD) &&
                (string == stringstart ||
                (check_flag(flags, WM_PATHNAME) && *(string - 1) == '/'))) {
                return WM_NOMATCH;
            }
            /* Optimize for pattern with * or ** at end or before /. */
            if (c == EOS) {
                if (wild && prev == '/') {
                    return WM_MATCH;
                }
                if (check_flag(flags, WM_PATHNAME)) {
                    return (check_flag(flags, WM_LEADING_DIR) ||
                        strchr(string, '/') == NULL ?  WM_MATCH : WM_NOMATCH);
                } else {
                    return WM_MATCH;
                }
            } else if (c == '/') {
                if (wild) {
                    slash = strchr(stringstart, '/');
                    if (!slash) {
                        return WM_NOMATCH;
                    }
                    while (slash) {
                        if (wildmatch(pattern+1, slash+1, flags) == 0) {
                            return WM_MATCH;
                        }
                        slash = strchr(slash+1, '/');
                    }
                } else {
                    if (check_flag(flags, WM_PATHNAME)) {
                        if ((string = strchr(string, '/')) == NULL) {
                            return WM_NOMATCH;
                        }
                    }
                }
            } else if (wild) {
                return WM_NOMATCH;
            }
            /* General case, use recursion. */
            while ((test = *string) != EOS) {
                if (!wildmatch(pattern, string, flags & ~WM_PERIOD))
                    return WM_MATCH;
                if (test == '/' && check_flag(flags, WM_PATHNAME))
                    break;
                ++string;
            }
            return WM_NOMATCH;
        case '[':
            if (*string == EOS)
                return WM_NOMATCH;
            if (*string == '/' && check_flag(flags, WM_PATHNAME))
                return WM_NOMATCH;
            if (*string == '.' && check_flag(flags, WM_PERIOD) &&
                    (string == stringstart ||
                     (check_flag(flags, WM_PATHNAME) && *(string - 1) == '/')))
                return WM_NOMATCH;

            switch (rangematch(pattern, *string, flags, &newp)) {
            case RANGE_ERROR:
                /* not a good range, treat as normal text */
                ++string;
                goto normal;
            case RANGE_MATCH:
                pattern = newp;
                break;
            case RANGE_NOMATCH:
                return (WM_NOMATCH);
            }
            ++string;
            break;
        case '\\':
            if (!check_flag(flags, WM_NOESCAPE)) {
                if ((c = *pattern++) == EOS) {
                    c = '\\';
                    --pattern;
                    if (*(string+1) == EOS) {
                        return WM_NOMATCH;
                    }
                }
            }
            /* FALLTHROUGH */
        default:
        normal:
            if (c != *string && !(check_flag(flags, WM_CASEFOLD) &&
                 (tolower((unsigned char)c) ==
                 tolower((unsigned char)*string))))
                return WM_NOMATCH;
            ++string;
            break;
        }
    /* NOTREACHED */
    }
}
Ejemplo n.º 10
0
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_fnmatch(const char *pattern, const char *string, int flags)
{
	const char *stringstart;
	char c, test;

	for (stringstart = string;;)
		switch (c = *pattern++) {
		case EOS:
			return (*string == EOS ? 0 : FNM_NOMATCH);
		case '?':
			if (*string == EOS)
				return (FNM_NOMATCH);
			if (*string == '/' && (flags & FNM_PATHNAME))
				return (FNM_NOMATCH);
			if (*string == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				return (FNM_NOMATCH);
			++string;
			break;
		case '*':
			c = *pattern;
			/* Collapse multiple stars. */
			while (c == '*')
				c = *++pattern;

			if (*string == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				return (FNM_NOMATCH);

			/* Optimize for pattern with * at end or before /. */
			if (c == EOS)
				if (flags & FNM_PATHNAME)
					return (strchr(string, '/') == NULL ?
					    0 : FNM_NOMATCH);
				else
					return (0);
			else if (c == '/' && flags & FNM_PATHNAME) {
				if ((string = strchr(string, '/')) == NULL)
					return (FNM_NOMATCH);
				break;
			}

			/* General case, use recursion. */
			while ((test = *string) != EOS) {
				if (!rk_fnmatch(pattern, string, flags & ~FNM_PERIOD))
					return (0);
				if (test == '/' && flags & FNM_PATHNAME)
					break;
				++string;
			}
			return (FNM_NOMATCH);
		case '[':
			if (*string == EOS)
				return (FNM_NOMATCH);
			if (*string == '/' && flags & FNM_PATHNAME)
				return (FNM_NOMATCH);
			if ((pattern =
			    rangematch(pattern, *string, flags)) == NULL)
				return (FNM_NOMATCH);
			++string;
			break;
		case '\\':
			if (!(flags & FNM_NOESCAPE)) {
				if ((c = *pattern++) == EOS) {
					c = '\\';
					--pattern;
				}
			}
			/* FALLTHROUGH */
		default:
			if (c != *string++)
				return (FNM_NOMATCH);
			break;
		}
	/* NOTREACHED */
}
Ejemplo n.º 11
0
static int
fnmatch1(const char *pattern, const char *string, const char *stringstart,
    int flags, mbstate_t patmbs, mbstate_t strmbs)
{
	char *newp;
	char c;
	wchar_t pc, sc;
	size_t pclen, sclen;

	for (;;) {
		pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs);
		if (pclen == (size_t)-1 || pclen == (size_t)-2)
			return (FNM_NOMATCH);
		pattern += pclen;
		sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs);
		if (sclen == (size_t)-1 || sclen == (size_t)-2) {
			sc = (unsigned char)*string;
			sclen = 1;
			memset(&strmbs, 0, sizeof(strmbs));
		}
		switch (pc) {
		case EOS:
			if ((flags & FNM_LEADING_DIR) && sc == '/')
				return (0);
			return (sc == EOS ? 0 : FNM_NOMATCH);
		case '?':
			if (sc == EOS)
				return (FNM_NOMATCH);
			if (sc == '/' && (flags & FNM_PATHNAME))
				return (FNM_NOMATCH);
			if (sc == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				return (FNM_NOMATCH);
			string += sclen;
			break;
		case '*':
			c = *pattern;
			/* Collapse multiple stars. */
			while (c == '*')
				c = *++pattern;

			if (sc == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				return (FNM_NOMATCH);

			/* Optimize for pattern with * at end or before /. */
			if (c == EOS)
				if (flags & FNM_PATHNAME)
					return ((flags & FNM_LEADING_DIR) ||
					    strchr(string, '/') == NULL ?
					    0 : FNM_NOMATCH);
				else
					return (0);
			else if (c == '/' && flags & FNM_PATHNAME) {
				if ((string = strchr(string, '/')) == NULL)
					return (FNM_NOMATCH);
				break;
			}

			/* General case, use recursion. */
			while (sc != EOS) {
				if (!fnmatch1(pattern, string, stringstart,
				    flags, patmbs, strmbs))
					return (0);
				sclen = mbrtowc(&sc, string, MB_LEN_MAX,
				    &strmbs);
				if (sclen == (size_t)-1 ||
				    sclen == (size_t)-2) {
					sc = (unsigned char)*string;
					sclen = 1;
					memset(&strmbs, 0, sizeof(strmbs));
				}
				if (sc == '/' && flags & FNM_PATHNAME)
					break;
				string += sclen;
			}
			return (FNM_NOMATCH);
		case '[':
			if (sc == EOS)
				return (FNM_NOMATCH);
			if (sc == '/' && (flags & FNM_PATHNAME))
				return (FNM_NOMATCH);
			if (sc == '.' && (flags & FNM_PERIOD) &&
			    (string == stringstart ||
			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
				return (FNM_NOMATCH);

			switch (rangematch(pattern, sc, flags, &newp,
			    &patmbs)) {
			case RANGE_ERROR:
				goto norm;
			case RANGE_MATCH:
				pattern = newp;
				break;
			case RANGE_NOMATCH:
				return (FNM_NOMATCH);
			}
			string += sclen;
			break;
		case '\\':
			if (!(flags & FNM_NOESCAPE)) {
				pclen = mbrtowc(&pc, pattern, MB_LEN_MAX,
				    &patmbs);
				if (pclen == (size_t)-1 || pclen == (size_t)-2)
					return (FNM_NOMATCH);
				pattern += pclen;
			}
			/* FALLTHROUGH */
		default:
		norm:
			if (pc == sc)
				;
			else if ((flags & FNM_CASEFOLD) &&
				 (towlower(pc) == towlower(sc)))
				;
			else
				return (FNM_NOMATCH);
			string += sclen;
			break;
		}
	}
	/* NOTREACHED */
}
Ejemplo n.º 12
0
int
fnmatch(const char *pattern, const char *string, int flags)
{
    char c;
    char test;

    for (;;)
    switch ((c = *pattern++))
    {
        case 0:
        return *string == 0 ? 0 : FNM_NOMATCH;

        case '?':
        if ((test = *string++) == 0 ||
                (isslash(test) && (flags & FNM_PATHNAME)))
        return(FNM_NOMATCH);
        break;

        case '*':
        c = *pattern;
        /* collapse multiple stars */
        while (c == '*')
        c = *++pattern;

        /* optimize for pattern with * at end or before / */
        if (c == 0)
        {
            if (flags & FNM_PATHNAME)
            return find_slash(string) ? FNM_NOMATCH : 0;
            else
            return 0;
        }
        else if (isslash(c) && flags & FNM_PATHNAME)
        {
            if ((string = find_slash(string)) == NULL)
            return FNM_NOMATCH;
            break;
        }

        /* general case, use recursion */
        while ((test = *string) != 0)
        {
            if (fnmatch(pattern, string, flags) == 0)
            return(0);
            if (isslash(test) && flags & FNM_PATHNAME)
            break;
            ++string;
        }
        return FNM_NOMATCH;

        case '[':
        if ((test = *string++) == 0 ||
                (isslash(test) && flags & FNM_PATHNAME))
        return FNM_NOMATCH;
        if ((pattern = rangematch(pattern, test, flags & FNM_NOCASE)) == NULL)
        return FNM_NOMATCH;
        break;

        case '\\':
        if (!(flags & FNM_NOESCAPE) && pattern[1] && strchr("*?[\\", pattern[1]))
        {
            if ((c = *pattern++) == 0)
            {
                c = '\\';
                --pattern;
            }
            if (c != *string++)
            return FNM_NOMATCH;
            break;
        }
        /* FALLTHROUGH */

        default:
        if (isslash(c) && isslash(*string))
        {
            string++;
            break;
        }
        if (flags & FNM_NOCASE)
        {
            if (toupper(c) != toupper(*string++))
            return FNM_NOMATCH;
        }
        else
        {
            if (c != *string++)
            return FNM_NOMATCH;
        }
        break;
    }
}