diff options
-rw-r--r-- | eval.cc | 44 | ||||
-rw-r--r-- | eval.h | 2 | ||||
-rw-r--r-- | fileutil.cc | 43 | ||||
-rw-r--r-- | fileutil.h | 4 | ||||
-rw-r--r-- | func.cc | 20 |
5 files changed, 72 insertions, 41 deletions
@@ -17,12 +17,12 @@ #include "eval.h" #include <errno.h> -#include <glob.h> #include <string.h> #include "ast.h" #include "file.h" #include "file_cache.h" +#include "fileutil.h" #include "parser.h" #include "rule.h" #include "strutil.h" @@ -217,22 +217,9 @@ void Evaluator::EvalIf(const IfAST* ast) { } } -void Evaluator::DoInclude(const char* fname, bool should_exist) { - if (!should_exist && g_ignore_optional_include_pattern && - Pattern(g_ignore_optional_include_pattern).Match(fname)) { - return; - } - +void Evaluator::DoInclude(const string& fname) { Makefile* mk = MakefileCacheManager::Get()->ReadMakefile(fname); - if (!mk->Exists()) { - if (should_exist) { - Error(StringPrintf( - "%s: %s\n" - "NOTE: kati does not support generating missing makefiles", - fname, strerror(errno))); - } - return; - } + CHECK(mk->Exists()); Var* var_list = LookupVar(Intern("MAKEFILE_LIST")); var_list->AppendVar(this, NewLiteral(Intern(TrimLeadingCurdir(fname)).str())); @@ -249,15 +236,24 @@ void Evaluator::EvalInclude(const IncludeAST* ast) { shared_ptr<string> pats = ast->expr->Eval(this); for (StringPiece pat : WordScanner(*pats)) { ScopedTerminator st(pat); - if (pat.find_first_of("?*[") != string::npos) { - glob_t gl; - glob(pat.data(), GLOB_NOSORT, NULL, &gl); - for (size_t i = 0; i < gl.gl_pathc; i++) { - DoInclude(gl.gl_pathv[i], ast->should_exist); + vector<string>* files; + Glob(pat.data(), &files); + + if (ast->should_exist) { + if (files->empty()) { + Error(StringPrintf( + "%s: %s\n" + "NOTE: kati does not support generating missing makefiles", + pat.data(), strerror(errno))); } - globfree(&gl); - } else { - DoInclude(pat.data(), ast->should_exist); + } + + for (const string& fname : *files) { + if (!ast->should_exist && g_ignore_optional_include_pattern && + Pattern(g_ignore_optional_include_pattern).Match(fname)) { + return; + } + DoInclude(fname); } } } @@ -79,7 +79,7 @@ class Evaluator { private: Var* EvalRHS(Symbol lhs, Value* rhs, StringPiece orig_rhs, AssignOp op, bool is_override = false); - void DoInclude(const char* fname, bool should_exist); + void DoInclude(const string& fname); const Vars* in_vars_; Vars* vars_; diff --git a/fileutil.cc b/fileutil.cc index 9a686e5..eb4fc22 100644 --- a/fileutil.cc +++ b/fileutil.cc @@ -17,12 +17,15 @@ #include "fileutil.h" #include <errno.h> +#include <glob.h> #include <limits.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> +#include <unordered_map> + #include "log.h" bool Exists(StringPiece filename) { @@ -91,3 +94,43 @@ int RunCommand(const string& shell, const string& cmd, bool redirect_stderr, } abort(); } + +namespace { + +class GlobCache { + public: + ~GlobCache() { + for (auto& p : cache_) { + delete p.second; + } + } + + void Get(const char* pat, vector<string>** files) { + auto p = cache_.emplace(pat, nullptr); + if (p.second) { + vector<string>* files = p.first->second = new vector<string>; + if (strcspn(pat, "?*[\\") != strlen(pat)) { + glob_t gl; + glob(pat, GLOB_NOSORT, NULL, &gl); + for (size_t i = 0; i < gl.gl_pathc; i++) { + files->push_back(gl.gl_pathv[i]); + } + globfree(&gl); + } else { + if (Exists(pat)) + files->push_back(pat); + } + } + *files = p.first->second; + } + + private: + unordered_map<string, vector<string>*> cache_; +}; + +} // namespace + +void Glob(const char* pat, vector<string>** files) { + static GlobCache gc; + gc.Get(pat, files); +} @@ -15,7 +15,9 @@ #ifndef FILEUTIL_H_ #define FILEUTIL_H_ +#include <memory> #include <string> +#include <vector> #include "string_piece.h" @@ -27,4 +29,6 @@ double GetTimestamp(StringPiece f); int RunCommand(const string& shell, const string& cmd, bool redirect_stderr, string* out); +void Glob(const char* pat, vector<string>** files); + #endif // FILEUTIL_H_ @@ -17,7 +17,6 @@ #include "func.h" #include <errno.h> -#include <glob.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> @@ -257,25 +256,14 @@ void WildcardFunc(const vector<Value*>& args, Evaluator* ev, string* s) { } WordWriter ww(s); - vector<const char*> files; + vector<string>* files; for (StringPiece tok : WordScanner(*pat)) { ScopedTerminator st(tok); - // TODO: Make this faster by not always using glob. - files.clear(); - glob_t gl; - glob(tok.data(), GLOB_NOSORT, NULL, &gl); - for (size_t i = 0; i < gl.gl_pathc; i++) { - files.push_back(gl.gl_pathv[i]); - } - sort(files.begin(), files.end(), - [](const char* a, const char* b) { - return strcmp(a, b) < 0; - }); - for (const char* file : files) { + Glob(tok.data(), &files); + sort(files->begin(), files->end()); + for (const string& file : *files) { ww.Write(file); } - - globfree(&gl); } } |