forked from OctaForge/OctaBuild
more correct glob matching
parent
8b741cb99d
commit
9c272792ac
82
main.cc
82
main.cc
|
@ -87,12 +87,53 @@ static ostd::ConstCharRange ob_compare_subst(ostd::ConstCharRange expanded,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* expand globs */
|
/* expand globs */
|
||||||
static bool ob_one_star(ostd::ConstCharRange st) {
|
static void ob_get_path_parts(ostd::Vector<ostd::ConstCharRange> &parts,
|
||||||
st.pop_front();
|
ostd::ConstCharRange elem) {
|
||||||
ostd::ConstCharRange slash = ostd::find(st, '/');
|
ostd::ConstCharRange star = ostd::find(elem, '*');
|
||||||
if (!slash.empty())
|
while (!star.empty()) {
|
||||||
st = ostd::slice_until(st, slash);
|
ostd::ConstCharRange ep = ostd::slice_until(elem, star);
|
||||||
return ostd::find(st, '*').empty();
|
if (!ep.empty())
|
||||||
|
parts.push(ep);
|
||||||
|
parts.push("*");
|
||||||
|
elem = star;
|
||||||
|
elem.pop_front();
|
||||||
|
star = ostd::find(elem, '*');
|
||||||
|
}
|
||||||
|
if (!elem.empty())
|
||||||
|
parts.push(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ob_path_matches(ostd::ConstCharRange fn,
|
||||||
|
const ostd::Vector<ostd::ConstCharRange> &parts) {
|
||||||
|
auto it = parts.iter();
|
||||||
|
while (!it.empty()) {
|
||||||
|
ostd::ConstCharRange elem = it.front();
|
||||||
|
if (elem == "*") {
|
||||||
|
it.pop_front();
|
||||||
|
/* skip multiple stars if present */
|
||||||
|
while (!it.empty() && ((elem = it.front()) == "*"))
|
||||||
|
it.pop_front();
|
||||||
|
/* trailing stars, we match */
|
||||||
|
if (it.empty())
|
||||||
|
return true;
|
||||||
|
/* skip about as much as we can until the elem part matches */
|
||||||
|
while (fn.size() > elem.size()) {
|
||||||
|
if (fn.slice(0, elem.size()) == elem)
|
||||||
|
break;
|
||||||
|
fn.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* non-star here */
|
||||||
|
if (fn.size() < elem.size())
|
||||||
|
return false;
|
||||||
|
if (fn.slice(0, elem.size()) != elem)
|
||||||
|
return false;
|
||||||
|
fn.pop_front_n(elem.size());
|
||||||
|
/* try next element */
|
||||||
|
it.pop_front();
|
||||||
|
}
|
||||||
|
/* if there are no chars in the fname remaining, we fully matched */
|
||||||
|
return fn.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ob_expand_glob(ostd::String &ret, ostd::ConstCharRange src,
|
static bool ob_expand_glob(ostd::String &ret, ostd::ConstCharRange src,
|
||||||
|
@ -100,8 +141,7 @@ static bool ob_expand_glob(ostd::String &ret, ostd::ConstCharRange src,
|
||||||
|
|
||||||
static bool ob_expand_dir(ostd::String &ret,
|
static bool ob_expand_dir(ostd::String &ret,
|
||||||
ostd::ConstCharRange dir,
|
ostd::ConstCharRange dir,
|
||||||
ostd::ConstCharRange pre,
|
const ostd::Vector<ostd::ConstCharRange> &parts,
|
||||||
ostd::ConstCharRange post,
|
|
||||||
ostd::ConstCharRange slash) {
|
ostd::ConstCharRange slash) {
|
||||||
DIR *d = opendir(ostd::String(dir).data());
|
DIR *d = opendir(ostd::String(dir).data());
|
||||||
bool appended = false;
|
bool appended = false;
|
||||||
|
@ -112,19 +152,9 @@ static bool ob_expand_dir(ostd::String &ret,
|
||||||
ostd::ConstCharRange fn = (const char *)dirp->d_name;
|
ostd::ConstCharRange fn = (const char *)dirp->d_name;
|
||||||
if (fn.empty() || (fn == ".") || (fn == ".."))
|
if (fn.empty() || (fn == ".") || (fn == ".."))
|
||||||
continue;
|
continue;
|
||||||
/* check if prefix matches */
|
/* check if filename matches */
|
||||||
if (!pre.empty()) {
|
if (!ob_path_matches(fn, parts))
|
||||||
if ((pre.size() > fn.size()) || (fn.slice(0, pre.size()) != pre))
|
continue;
|
||||||
continue;
|
|
||||||
fn = fn.slice(pre.size(), fn.size());
|
|
||||||
}
|
|
||||||
/* check if postfix matches */
|
|
||||||
if (!post.empty()) {
|
|
||||||
if (post.size() > fn.size())
|
|
||||||
continue;
|
|
||||||
if (fn.slice(fn.size() - post.size(), fn.size()) != post)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ostd::String afn((dir == ".") ? "" : "./");
|
ostd::String afn((dir == ".") ? "" : "./");
|
||||||
afn.append(fn);
|
afn.append(fn);
|
||||||
/* if we reach this, we match; try recursively matching */
|
/* if we reach this, we match; try recursively matching */
|
||||||
|
@ -157,8 +187,8 @@ static bool ob_expand_dir(ostd::String &ret,
|
||||||
|
|
||||||
static bool ob_expand_glob(ostd::String &ret, ostd::ConstCharRange src, bool ne) {
|
static bool ob_expand_glob(ostd::String &ret, ostd::ConstCharRange src, bool ne) {
|
||||||
ostd::ConstCharRange star = ostd::find(src, '*');
|
ostd::ConstCharRange star = ostd::find(src, '*');
|
||||||
/* no star or multiple stars within the section, use as-is */
|
/* no star use as-is */
|
||||||
if (star.empty() || !ob_one_star(star)) {
|
if (star.empty()) {
|
||||||
if (ne) return false;
|
if (ne) return false;
|
||||||
if (!ret.empty())
|
if (!ret.empty())
|
||||||
ret.push(' ');
|
ret.push(' ');
|
||||||
|
@ -186,8 +216,12 @@ static bool ob_expand_glob(ostd::String &ret, ostd::ConstCharRange src, bool ne)
|
||||||
ostd::ConstCharRange nslash = ostd::find(fnpost, '/');
|
ostd::ConstCharRange nslash = ostd::find(fnpost, '/');
|
||||||
if (!nslash.empty())
|
if (!nslash.empty())
|
||||||
fnpost = ostd::slice_until(fnpost, nslash);
|
fnpost = ostd::slice_until(fnpost, nslash);
|
||||||
|
/* retrieve the single element with whatever stars in it, chop it up */
|
||||||
|
ostd::Vector<ostd::ConstCharRange> parts;
|
||||||
|
ob_get_path_parts(parts, ostd::ConstCharRange(&fnpre[0],
|
||||||
|
&fnpost[fnpost.size()]));
|
||||||
/* do a directory scan and match */
|
/* do a directory scan and match */
|
||||||
if (!ob_expand_dir(ret, dir, fnpre, fnpost, nslash)) {
|
if (!ob_expand_dir(ret, dir, parts, nslash)) {
|
||||||
if (ne) return false;
|
if (ne) return false;
|
||||||
if (!ret.empty())
|
if (!ret.empty())
|
||||||
ret.push(' ');
|
ret.push(' ');
|
||||||
|
|
Loading…
Reference in New Issue