Index: FilterVisitor.cc =================================================================== RCS file: FilterVisitor.cc diff -N FilterVisitor.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ FilterVisitor.cc 18 Mar 2003 14:01:36 -0000 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2003 Igor Pechtchanski. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * A copy of the GNU General Public License can be found at + * http://www.gnu.org/ + * + * Written by Igor Pechtchanski + * + */ + +#if 0 +static const char *cvsid = + "\n%%% $Id$\n"; +#endif + +#include "FilterVisitor.h" +#include "String++.h" +#include "find.h" + +#include + +FilterVisitor::FilterVisitor(FindVisitor *visitor, Filter *filter) + : _visitor(visitor), _filter(filter) {} + +FilterVisitor::~FilterVisitor() {} + +void +FilterVisitor::visitFile(String const &basePath, WIN32_FIND_DATA const *aFile) +{ + if (_filter->matchFile(basePath, aFile)) + _visitor->visitFile(basePath, aFile); +} + +void +FilterVisitor::visitDirectory(String const &basePath, WIN32_FIND_DATA const *aDir) +{ + if (_filter->matchDirectory(basePath, aDir)) + _visitor->visitDirectory(basePath, aDir); +} + +Filter::Filter() {} +Filter::~Filter() {} + +bool +Filter::matchFile(String const &basePath, WIN32_FIND_DATA const *aFile) +{ + return true; +} + +bool +Filter::matchDirectory(String const &basePath, WIN32_FIND_DATA const *aDir) +{ + return true; +} + +ExcludeNameFilter::ExcludeNameFilter() : _filePattern(""), _dirPattern("") {} + +ExcludeNameFilter::~ExcludeNameFilter(){} + +ExcludeNameFilter::ExcludeNameFilter(String const &filePattern, + String const &dirPattern) + : _filePattern(filePattern), _dirPattern(dirPattern) {} + +bool +ExcludeNameFilter::matchFile(String const &basePath, WIN32_FIND_DATA const *aFile) +{ + return !(basePath + aFile->cFileName).matches(_filePattern); +} + +bool +ExcludeNameFilter::matchDirectory(String const &basePath, WIN32_FIND_DATA const *aDir) +{ + return !(basePath + aDir->cFileName).matches(_dirPattern); +} + Index: FilterVisitor.h =================================================================== RCS file: FilterVisitor.h diff -N FilterVisitor.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ FilterVisitor.h 18 Mar 2003 14:01:36 -0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003 Igor Pechtchanski. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * A copy of the GNU General Public License can be found at + * http://www.gnu.org/ + * + * Written by Igor Pechtchanski + * + */ + +#ifndef _FILTERVISITOR_H_ +#define _FILTERVISITOR_H_ + +#include "FindVisitor.h" +#include "String++.h" + +/* For the wfd definition. See the TODO in find.cc */ +#include "win32.h" + +class Filter +{ +public: + virtual bool matchFile(String const &basePath, WIN32_FIND_DATA const *); + virtual bool matchDirectory(String const &basePath, WIN32_FIND_DATA const *); + virtual ~ Filter(); +protected: + Filter(); + Filter(Filter const &); + Filter & operator= (Filter const &); +}; + +class FilterVisitor : public FindVisitor +{ +public: + virtual void visitFile(String const &basePath, WIN32_FIND_DATA const *); + virtual void visitDirectory(String const &basePath, WIN32_FIND_DATA const *); + FilterVisitor (FindVisitor *visitor, Filter *filter); + virtual ~ FilterVisitor (); +protected: + FilterVisitor (); + FilterVisitor (FilterVisitor const &); + FilterVisitor & operator= (FilterVisitor const &); +private: + FindVisitor *_visitor; + Filter *_filter; +}; + +class ExcludeNameFilter : public Filter +{ +public: + ExcludeNameFilter (String const &filePattern, String const &dirPattern = ""); + virtual ~ ExcludeNameFilter (); + + virtual bool matchFile(String const &basePath, WIN32_FIND_DATA const *); + virtual bool matchDirectory(String const &basePath, WIN32_FIND_DATA const *); +protected: + ExcludeNameFilter (); + ExcludeNameFilter (ExcludeNameFilter const &); + ExcludeNameFilter & operator= (ExcludeNameFilter const &); +private: + String _filePattern; + String _dirPattern; +}; + +#endif // _FILTERVISITOR_H_ Index: Makefile.am =================================================================== RCS file: /cvs/cygwin-apps/setup/Makefile.am,v retrieving revision 2.27 diff -u -p -r2.27 Makefile.am --- Makefile.am 10 Mar 2003 15:47:53 -0000 2.27 +++ Makefile.am 18 Mar 2003 14:01:36 -0000 @@ -153,6 +153,8 @@ setup_SOURCES = \ find.h \ FindVisitor.cc \ FindVisitor.h \ + FilterVisitor.cc \ + FilterVisitor.h \ filemanip.cc \ filemanip.h \ fromcwd.cc \ Index: String++.cc =================================================================== RCS file: /cvs/cygwin-apps/setup/String++.cc,v retrieving revision 2.9 diff -u -p -r2.9 String++.cc --- String++.cc 17 Mar 2003 22:23:33 -0000 2.9 +++ String++.cc 18 Mar 2003 14:01:36 -0000 @@ -252,6 +252,149 @@ String::casecompare (String const lhs, S return lhs.casecompare (rhs); } +/* + * This supports two wildcard characters, '*' and '?', as well as the + * '[]'-style character sets ('^' to invert). + * Use '\' to escape special characters. + * Shamelessly stolen from fileutils-4.1 (adapted for strings). + */ +static bool +strmatch (const unsigned char *pattern, size_t plen, + const unsigned char *name, size_t nlen) +{ + register const unsigned char *pend = pattern + plen, *nend = name + nlen; + register const unsigned char *p = pattern, *n = name; + register unsigned char c; + + while (p < pend) + { + c = *p++; + switch (c) + { + case '?': /* A '?' matches exactly one character */ + if (n == nend) + return false; + break; + + case '\\': /* Escape next character */ + if (p == pend) + return false; + c = *p++; + if (n == nend || *n != c) + return false; + break; + + case '*': /* A '*' matches any number of characters */ + while (p < pend && (c == '?' || c == '*')) + { + c = *p++; + if (c == '?') + { + /* A '?' needs to match one character. */ + if (n == nend) + /* There isn't another character; no match. */ + return false; + else + /* One character of the name is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (p == pend) + return true; + + { + unsigned char c1 = (c == '\\') ? *p : c; + for (--p; n != nend; ++n) /* Eat up all chars */ + if ((c == '[' || *n == c1) && strmatch (p, pend-p, n, nend-n)) + return true; + return false; + } + + case '[': /* A '[A-Z]' matches any char between 'A' and 'Z' */ + { + /* Nonzero if the sense of the character class is inverted. */ + register bool invert; + + if (n == nend) + return false; + + invert = (*p == '^'); + if (invert) + ++p; + + if (p == pend) + /* [ (unterminated) loses. */ + return false; + + c = *p++; + for (;;) + { + register unsigned char cstart = c, cend = c; + + if (p == pend) + /* [ (unterminated) loses. */ + return false; + + c = *p++; + + if (c == '-' && *p != ']') + { + if (p == pend) + return false; + cend = *p++; + + c = *p++; + } + + if (*n >= cstart && *n <= cend) + goto matched; + + if (c == ']') + break; + } + if (!invert) + return false; + break; + + matched:; + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { + if (p == pend) + /* [... (unterminated) loses. */ + return false; + + c = *p++; + } + if (invert) + return false; + } + break; + + default: + if (n == nend || c != *n) + return false; + } + + ++n; + } + + if (n == nend) + return true; + + return false; +} + +bool +String::matches (String const &pattern) const +{ + return strmatch (pattern.theData->theString, pattern.theData->length, + theData->theString, theData->length); +} + /* TODO: research how wide char and unicode interoperate with * C++ streams */ Index: String++.h =================================================================== RCS file: /cvs/cygwin-apps/setup/String++.h,v retrieving revision 2.9 diff -u -p -r2.9 String++.h --- String++.h 17 Mar 2003 22:23:33 -0000 2.9 +++ String++.h 18 Mar 2003 14:01:36 -0000 @@ -62,6 +62,7 @@ public: { return s1.casecompare (s2) < 0; }}; + bool matches (String const &pattern) const; private: class _data { Index: postinstall.cc =================================================================== RCS file: /cvs/cygwin-apps/setup/postinstall.cc,v retrieving revision 2.9 diff -u -p -r2.9 postinstall.cc --- postinstall.cc 19 May 2002 03:07:51 -0000 2.9 +++ postinstall.cc 17 Mar 2003 18:01:51 -0000 @@ -26,6 +26,7 @@ static const char *cvsid = #include "mount.h" #include "script.h" #include "FindVisitor.h" +#include "FilterVisitor.h" class RunFindVisitor : public FindVisitor { @@ -48,6 +49,8 @@ do_postinstall (HINSTANCE h, HWND owner) init_run_script (); SetCurrentDirectory (get_root_dir ().cstr_oneuse()); RunFindVisitor myVisitor; + ExcludeNameFilter notDone("*.done"); + FilterVisitor excludeDoneVisitor(&myVisitor, ¬Done); String postinst = cygpath ("/etc/postinstall"); - Find (postinst).accept (myVisitor); + Find (postinst).accept (excludeDoneVisitor); }