/* private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or MATCH_ABORT. */ static int _shellStyleMatch(char *text, char *p) { int last, matched, reverse; for(; *p; text++, p++){ if(*text == 0 && *p != '*') return MATCH_ABORT; switch(*p){ case '\\': /* Literal match with following character. */ p++; /* FALLTHROUGH */ default: if(*text != *p) return MATCH_FAILED; continue; case '?': /* Match anything. */ continue; case '*': while(*++p == '*') /* Consecutive stars act just like one. */ continue; if(*p == 0) /* Trailing star matches everything. */ return MATCH_SUCCESS; while(*text) if((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED) return matched; return MATCH_ABORT; case '[': reverse = p[1] == '^'; if(reverse) /* Inverted character class. */ p++; matched = MATCH_FAILED; if(p[1] == ']' || p[1] == '-') if(*++p == *text) matched = MATCH_SUCCESS; for(last = *p; *++p && *p != ']'; last = *p) if (*p == '-' && p[1] != ']' ? *text <= *++p && *text >= last : *text == *p) matched = MATCH_SUCCESS; if(matched == reverse) return MATCH_FAILED; continue; } } return *text == 0; }
/* частный интерфейс (private interface): проверка на соответсвие text and p, возврат MATCH_SUCCESS, MATCH_FAILED или MATCH_ABORT. */ static int _shellStyleMatch(char *text, char *p) { int last, matched, reverse; for(; *p; text++, p++){ if(*text == 0 && *p != '*') return MATCH_ABORT; switch(*p){ case '\\': /* Буквенное (literal) соответствие со следующим символом. */ p++; /* FALLTHROUGH */ default: if(*text != *p) return MATCH_FAILED; continue; case '?': /* Соответсвие с любым символом. */ continue; case '*': while(*++p == '*') /* Следующие друг за другом звездочки срабатывают как одна. */ continue; if(*p == 0) /* Последняя звездочка совпадает с любым набором символов. */ return MATCH_SUCCESS; while(*text) if((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED) return matched; return MATCH_ABORT; case '[': reverse = p[1] == '^'; if(reverse) /* Инвертированный класс символа. */ p++; matched = MATCH_FAILED; if(p[1] == ']' || p[1] == '-') if(*++p == *text) matched = MATCH_SUCCESS; for(last = *p; *++p && *p != ']'; last = *p) if (*p == '-' && p[1] != ']' ? *text <= *++p && *text >= last : *text == *p) matched = MATCH_SUCCESS; if(matched == reverse) return MATCH_FAILED; continue; } } return *text == 0; }
/* * public interface for shell style matching: returns 0 if fails, 1 if matches */ static int shellStyleMatch(char *text, char *pattern) { if (pattern == NULL) /* NULL pattern is synonymous to "*" */ return 1; return _shellStyleMatch(text, pattern) == MATCH_SUCCESS; }
/* Публичный интерфейс (public interface) для совпадения в стиле шелла (shell): возврат 0 если нет совпадения, 1 если совпадение */ static int shellStyleMatch(char *text, char *pattern) { if(pattern == NULL) /* маска NULL является синонимом звездочки "*" */ return 1; return _shellStyleMatch(text, pattern) == MATCH_SUCCESS; }