diff --git a/compile.sh b/compile.sh index 49031bb..04103f5 100755 --- a/compile.sh +++ b/compile.sh @@ -5,5 +5,5 @@ OCTASTD_PATH="../octastd" CXXFLAGS="-g" -c++ main.cc $CUBESCRIPT_PATH/cubescript.cc -o main -std=c++11 -Wall -Wextra \ --I. -I$CUBESCRIPT_PATH -I$OCTASTD_PATH -pthread $CXXFLAGS \ No newline at end of file +c++ globs.cc main.cc $CUBESCRIPT_PATH/cubescript.cc -o main -std=c++11 \ +-Wall -Wextra -I. -I$CUBESCRIPT_PATH -I$OCTASTD_PATH -pthread $CXXFLAGS diff --git a/globs.cc b/globs.cc new file mode 100644 index 0000000..e3f1da5 --- /dev/null +++ b/globs.cc @@ -0,0 +1,162 @@ +#include +#include +#include +#include + +#include "globs.hh" + +using ostd::ConstCharRange; +using ostd::Vector; +using ostd::String; +using ostd::slice_until; + +static void ob_get_path_parts(Vector &parts, + ConstCharRange elem) { + ConstCharRange star = ostd::find(elem, '*'); + while (!star.empty()) { + ConstCharRange ep = slice_until(elem, star); + 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(ConstCharRange fn, + const Vector &parts) { + auto it = parts.iter(); + while (!it.empty()) { + 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(String &ret, ConstCharRange src, bool ne = false); + +static bool ob_expand_dir(String &ret, ConstCharRange dir, + const Vector &parts, + ConstCharRange slash) { + ostd::DirectoryStream d(dir); + bool appended = false; + if (!d.is_open()) + return false; + for (auto fi: d.iter()) { + ConstCharRange fn = fi.filename(); + /* check if filename matches */ + if (!ob_path_matches(fn, parts)) + continue; + String afn((dir == ".") ? "" : "./"); + afn.append(fn); + /* if we reach this, we match; try recursively matching */ + if (!slash.empty()) { + afn.append(slash); + ConstCharRange psl = slash; + psl.pop_front(); + if (!ostd::find(psl, '*').empty()) { + if (!appended) + appended = ob_expand_glob(ret, afn.iter()); + continue; + } + /* no further star, just do file test */ + if (!ostd::FileStream(afn, ostd::StreamMode::read).is_open()) + continue; + if (!ret.empty()) + ret.push(' '); + ret.append(afn); + appended = true; + continue; + } + if (!ret.empty()) + ret.push(' '); + ret.append(afn); + appended = true; + } + return appended; +} + +static bool ob_expand_glob(String &ret, ConstCharRange src, bool ne) { + ConstCharRange star = ostd::find(src, '*'); + /* no star use as-is */ + if (star.empty()) { + if (ne) return false; + if (!ret.empty()) + ret.push(' '); + ret.append(src); + return false; + } + /* part before star */ + ConstCharRange prestar = slice_until(src, star); + /* try finding slash before star */ + ConstCharRange slash = ostd::find_last(prestar, '/'); + /* directory to scan */ + ConstCharRange dir = "."; + /* part of name before star */ + ConstCharRange fnpre = prestar; + if (!slash.empty()) { + /* there was slash, adjust directory + prefix accordingly */ + dir = slice_until(src, slash); + fnpre = slash; + fnpre.pop_front(); + } + /* part after star */ + ConstCharRange fnpost = star; + fnpost.pop_front(); + /* if a slash follows, adjust */ + ConstCharRange nslash = ostd::find(fnpost, '/'); + if (!nslash.empty()) + fnpost = slice_until(fnpost, nslash); + /* retrieve the single element with whatever stars in it, chop it up */ + Vector parts; + ob_get_path_parts(parts, ConstCharRange(&fnpre[0], &fnpost[fnpost.size()])); + /* do a directory scan and match */ + if (!ob_expand_dir(ret, dir, parts, nslash)) { + if (ne) return false; + if (!ret.empty()) + ret.push(' '); + ret.append(src); + return false; + } + return true; +} + +static String ob_expand_globs(const Vector &src) { + String ret; + for (auto &s: src.iter()) + ob_expand_glob(ret, s.iter()); + return ret; +} + +void cs_register_globs(cscript::CsState &cs) { + cs.add_command("glob", "C", [](cscript::CsState &cs, ConstCharRange lst) { + auto fnames = cscript::util::list_explode(lst); + cs.result->set_str(ob_expand_globs(fnames).disown()); + }); +} \ No newline at end of file diff --git a/globs.hh b/globs.hh new file mode 100644 index 0000000..866ee7e --- /dev/null +++ b/globs.hh @@ -0,0 +1,8 @@ +#ifndef OCTABUILD_GLOBS_HH +#define OCTABUILD_GLOBS_HH + +#include + +void cs_register_globs(cscript::CsState &cs); + +#endif \ No newline at end of file diff --git a/main.cc b/main.cc index e3af13c..fe1f2d5 100644 --- a/main.cc +++ b/main.cc @@ -8,6 +8,7 @@ #include +#include "globs.hh" #include "tpool.hh" using ostd::ConstCharRange; @@ -142,151 +143,6 @@ static ConstCharRange ob_compare_subst(ConstCharRange expanded, return expanded; } -/* expand globs */ -static void ob_get_path_parts(Vector &parts, - ConstCharRange elem) { - ConstCharRange star = ostd::find(elem, '*'); - while (!star.empty()) { - ConstCharRange ep = slice_until(elem, star); - 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(ConstCharRange fn, - const Vector &parts) { - auto it = parts.iter(); - while (!it.empty()) { - 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(String &ret, ConstCharRange src, bool ne = false); - -static bool ob_expand_dir(String &ret, ConstCharRange dir, - const Vector &parts, - ConstCharRange slash) { - ostd::DirectoryStream d(dir); - bool appended = false; - if (!d.is_open()) - return false; - for (auto fi: d.iter()) { - ConstCharRange fn = fi.filename(); - /* check if filename matches */ - if (!ob_path_matches(fn, parts)) - continue; - String afn((dir == ".") ? "" : "./"); - afn.append(fn); - /* if we reach this, we match; try recursively matching */ - if (!slash.empty()) { - afn.append(slash); - ConstCharRange psl = slash; - psl.pop_front(); - if (!ostd::find(psl, '*').empty()) { - if (!appended) - appended = ob_expand_glob(ret, afn.iter()); - continue; - } - /* no further star, just do file test */ - if (!ob_check_file(afn.iter())) - continue; - if (!ret.empty()) - ret.push(' '); - ret.append(afn); - appended = true; - continue; - } - if (!ret.empty()) - ret.push(' '); - ret.append(afn); - appended = true; - } - return appended; -} - -static bool ob_expand_glob(String &ret, ConstCharRange src, bool ne) { - ConstCharRange star = ostd::find(src, '*'); - /* no star use as-is */ - if (star.empty()) { - if (ne) return false; - if (!ret.empty()) - ret.push(' '); - ret.append(src); - return false; - } - /* part before star */ - ConstCharRange prestar = slice_until(src, star); - /* try finding slash before star */ - ConstCharRange slash = ostd::find_last(prestar, '/'); - /* directory to scan */ - ConstCharRange dir = "."; - /* part of name before star */ - ConstCharRange fnpre = prestar; - if (!slash.empty()) { - /* there was slash, adjust directory + prefix accordingly */ - dir = slice_until(src, slash); - fnpre = slash; - fnpre.pop_front(); - } - /* part after star */ - ConstCharRange fnpost = star; - fnpost.pop_front(); - /* if a slash follows, adjust */ - ConstCharRange nslash = ostd::find(fnpost, '/'); - if (!nslash.empty()) - fnpost = slice_until(fnpost, nslash); - /* retrieve the single element with whatever stars in it, chop it up */ - Vector parts; - ob_get_path_parts(parts, ConstCharRange(&fnpre[0], &fnpost[fnpost.size()])); - /* do a directory scan and match */ - if (!ob_expand_dir(ret, dir, parts, nslash)) { - if (ne) return false; - if (!ret.empty()) - ret.push(' '); - ret.append(src); - return false; - } - return true; -} - -static String ob_expand_globs(const Vector &src) { - String ret; - for (auto &s: src.iter()) - ob_expand_glob(ret, s.iter()); - return ret; -} - struct ObState { cscript::CsState cs; ConstCharRange progname; @@ -485,10 +341,7 @@ int main(int argc, char **argv) { } }); - os.cs.add_command("glob", "C", [](cscript::CsState &cs, ConstCharRange lst) { - auto fnames = cscript::util::list_explode(lst); - cs.result->set_str(ob_expand_globs(fnames).disown()); - }); + cs_register_globs(os.cs); if (!os.cs.run_file(fname, true)) return os.error(1, "failed creating rules"); diff --git a/tpool.hh b/tpool.hh index 1d560fe..8cc4274 100644 --- a/tpool.hh +++ b/tpool.hh @@ -1,3 +1,6 @@ +#ifndef OCTABUILD_TPOOL_HH +#define OCTABUILD_TPOOL_HH + #include #include @@ -133,4 +136,6 @@ private: Task *tasks; Task *last_task; volatile bool running; -}; \ No newline at end of file +}; + +#endif /* OCTABUILD_TPOOL_HH */ \ No newline at end of file