Loading parser.cpp +33 −12 Changes for parser.cpp: 33 added lines, 12 removed lines. Original line number Diff line number Diff line Loading @@ -1474,28 +1474,49 @@ std::string Parser::func_wildcard(const std::string& pattern) const { continue; } fs::path p(pat); fs::path dir = p.parent_path(); std::string name_pat = p.filename().string(); if (dir.empty()) dir = "."; // Glob component by component: wildcards may sit in any directory // part ($(wildcard arch/*/Makefile)), and a trailing slash matches // directories only and keeps the slash -- Kbuild's // Makefile.headersinst finds the UAPI subdirs with $(wildcard $(src)/*/). bool dir_only = pat.back() == '/'; std::vector<std::string> parts; size_t pos = 0; while (pos < pat.size()) { size_t slash = pat.find('/', pos); if (slash == std::string::npos) slash = pat.size(); if (slash > pos) parts.push_back(pat.substr(pos, slash - pos)); pos = slash + 1; } std::vector<std::string> paths{pat[0] == '/' ? "/" : ""}; for (const auto& part : parts) { std::vector<std::string> next; bool meta = part.find_first_of("*?[") != std::string::npos; for (const auto& base : paths) { if (!meta) { next.push_back(base + part + "/"); continue; } std::error_code ec; if (fs::exists(dir, ec) && fs::is_directory(dir, ec)) { fs::path dir = base.empty() ? fs::path(".") : fs::path(base); if (!fs::is_directory(dir, ec)) continue; for (const auto& entry : fs::directory_iterator(dir, ec)) { std::string fname = entry.path().filename().string(); // POSIX glob: a leading dot in a filename is only matched by a // pattern that also starts with a dot. $(wildcard *.h) must NOT // match `.tmp_foo.h`. GNU make behaves the same way. if (!fname.empty() && fname[0] == '.' && !name_pat.empty() && name_pat[0] != '.') if (!fname.empty() && fname[0] == '.' && part[0] != '.') continue; if (glob_match(name_pat, fname)) { if (dir == ".") { results.push_back(fname); } else { results.push_back((dir / fname).string()); if (glob_match(part, fname)) next.push_back(base + fname + "/"); } } paths.swap(next); } for (auto& path : paths) { path.pop_back(); std::error_code ec; if (dir_only ? fs::is_directory(path, ec) : fs::exists(fs::symlink_status(path, ec))) results.push_back(dir_only ? path + "/" : path); } } std::sort(results.begin(), results.end()); Loading Loading
parser.cpp +33 −12 Changes for parser.cpp: 33 added lines, 12 removed lines. Original line number Diff line number Diff line Loading @@ -1474,28 +1474,49 @@ std::string Parser::func_wildcard(const std::string& pattern) const { continue; } fs::path p(pat); fs::path dir = p.parent_path(); std::string name_pat = p.filename().string(); if (dir.empty()) dir = "."; // Glob component by component: wildcards may sit in any directory // part ($(wildcard arch/*/Makefile)), and a trailing slash matches // directories only and keeps the slash -- Kbuild's // Makefile.headersinst finds the UAPI subdirs with $(wildcard $(src)/*/). bool dir_only = pat.back() == '/'; std::vector<std::string> parts; size_t pos = 0; while (pos < pat.size()) { size_t slash = pat.find('/', pos); if (slash == std::string::npos) slash = pat.size(); if (slash > pos) parts.push_back(pat.substr(pos, slash - pos)); pos = slash + 1; } std::vector<std::string> paths{pat[0] == '/' ? "/" : ""}; for (const auto& part : parts) { std::vector<std::string> next; bool meta = part.find_first_of("*?[") != std::string::npos; for (const auto& base : paths) { if (!meta) { next.push_back(base + part + "/"); continue; } std::error_code ec; if (fs::exists(dir, ec) && fs::is_directory(dir, ec)) { fs::path dir = base.empty() ? fs::path(".") : fs::path(base); if (!fs::is_directory(dir, ec)) continue; for (const auto& entry : fs::directory_iterator(dir, ec)) { std::string fname = entry.path().filename().string(); // POSIX glob: a leading dot in a filename is only matched by a // pattern that also starts with a dot. $(wildcard *.h) must NOT // match `.tmp_foo.h`. GNU make behaves the same way. if (!fname.empty() && fname[0] == '.' && !name_pat.empty() && name_pat[0] != '.') if (!fname.empty() && fname[0] == '.' && part[0] != '.') continue; if (glob_match(name_pat, fname)) { if (dir == ".") { results.push_back(fname); } else { results.push_back((dir / fname).string()); if (glob_match(part, fname)) next.push_back(base + fname + "/"); } } paths.swap(next); } for (auto& path : paths) { path.pop_back(); std::error_code ec; if (dir_only ? fs::is_directory(path, ec) : fs::exists(fs::symlink_status(path, ec))) results.push_back(dir_only ? path + "/" : path); } } std::sort(results.begin(), results.end()); Loading