From f90a2fe4742db1d6344c64cdf49ae56b9045010e Mon Sep 17 00:00:00 2001 From: q66 Date: Tue, 2 Aug 2016 22:37:26 +0100 Subject: [PATCH] merge glob matching into main --- Makefile | 3 +- globs.cc | 182 ----------------------------------------------------- main.cc | 169 ++++++++++++++++++++++++++++++++++++++++++++++++- obuild.cfg | 3 +- 4 files changed, 168 insertions(+), 189 deletions(-) delete mode 100644 globs.cc diff --git a/Makefile b/Makefile index 889f395..7c93d34 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ OB_CXXFLAGS = -g -Wall -Wextra -Wshadow -Wold-style-cast -O2 CUBESCRIPT_PATH = ../libcubescript OCTASTD_PATH = ../octastd -FILES = main.o globs.o +FILES = main.o OB_CXXFLAGS += -std=c++14 -I. -I$(CUBESCRIPT_PATH) -I$(OCTASTD_PATH) -pthread @@ -20,4 +20,3 @@ clean: rm -f $(FILES) obuild main.o: tpool.hh $(CUBESCRIPT_PATH)/cubescript.hh -globs.o: $(CUBESCRIPT_PATH)/cubescript.hh diff --git a/globs.cc b/globs.cc deleted file mode 100644 index ea3b957..0000000 --- a/globs.cc +++ /dev/null @@ -1,182 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -using ostd::ConstCharRange; -using ostd::Vector; -using ostd::String; -using ostd::slice_until; - -using cscript::CsState; -using cscript::TvalRange; - -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; - star = ostd::find(elem, '*'); - } - if (!elem.empty()) { - parts.push(elem); - } -} - -static bool ob_path_matches( - ConstCharRange fn, Vector const &parts -) { - for (auto it = parts.iter(); !it.empty(); ++it) { - ConstCharRange elem = it.front(); - if (elem == "*") { - ++it; - /* skip multiple stars if present */ - while (!it.empty() && ((elem = it.front()) == "*")) { - ++it; - } - /* 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; - } - } - /* non-star here */ - if (fn.size() < elem.size()) { - return false; - } - if (fn.slice(0, elem.size()) != elem) { - return false; - } - fn += elem.size(); - } - /* 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, Vector const &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 + 1; - 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 + 1; - } - /* part after star */ - ConstCharRange fnpost = star + 1; - /* 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(Vector const &src) { - String ret; - for (auto &s: src.iter()) { - ob_expand_glob(ret, s.iter()); - } - return ret; -} - -void cs_register_globs(CsState &cs) { - cs.add_command("glob", "C", [&cs](TvalRange args) { - auto fnames = cscript::util::list_explode(args[0].get_strr()); - cs.result->set_str(ob_expand_globs(fnames).disown()); - }); -} diff --git a/main.cc b/main.cc index 031e5ce..f41a2cd 100644 --- a/main.cc +++ b/main.cc @@ -16,8 +16,6 @@ #include "tpool.hh" -void cs_register_globs(cscript::CsState &cs); - using ostd::ConstCharRange; using ostd::Vector; using ostd::Map; @@ -33,6 +31,168 @@ using cscript::TvalRange; using cscript::StackedValue; using cscript::Bytecode; +/* glob matching code */ + +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; + star = ostd::find(elem, '*'); + } + if (!elem.empty()) { + parts.push(elem); + } +} + +static bool ob_path_matches( + ConstCharRange fn, Vector const &parts +) { + for (auto it = parts.iter(); !it.empty(); ++it) { + ConstCharRange elem = it.front(); + if (elem == "*") { + ++it; + /* skip multiple stars if present */ + while (!it.empty() && ((elem = it.front()) == "*")) { + ++it; + } + /* 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; + } + } + /* non-star here */ + if (fn.size() < elem.size()) { + return false; + } + if (fn.slice(0, elem.size()) != elem) { + return false; + } + fn += elem.size(); + } + /* 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, Vector const &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 + 1; + 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 + 1; + } + /* part after star */ + ConstCharRange fnpost = star + 1; + /* 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(Vector const &src) { + String ret; + for (auto &s: src.iter()) { + ob_expand_glob(ret, s.iter()); + } + return ret; +} + /* check funcs */ static bool ob_check_ts(ConstCharRange tname, Vector const &deps) { @@ -533,7 +693,10 @@ int main(int argc, char **argv) { os.result->set_int(os.exec_main(args[0].get_strr())); }); - cs_register_globs(os); + os.add_command("glob", "C", [&os](TvalRange args) { + auto fnames = cscript::util::list_explode(args[0].get_strr()); + os.result->set_str(ob_expand_globs(fnames).disown()); + }); if ((!fcont.empty() && !os.run_bool(fcont)) || !os.run_file(deffile)) { return os.error(1, "failed creating rules"); diff --git a/obuild.cfg b/obuild.cfg index dc02b54..3cb1d84 100644 --- a/obuild.cfg +++ b/obuild.cfg @@ -5,7 +5,7 @@ OB_CXXFLAGS = "-g -Wall -Wextra -Wshadow -Wold-style-cast -O2" CS_PATH = "../libcubescript" OS_PATH = "../octastd" -FILES = [main_ob.o globs_ob.o] +FILES = [main_ob.o] OB_CXXFLAGS = [@OB_CXXFLAGS -std=c++14 -I. -I@CS_PATH -I@OS_PATH -pthread] @@ -25,6 +25,5 @@ action clean [ ] depend main_ob.o [tpool.hh @CS_PATH/cubescript.hh] -depend globs_ob.o [@CS_PATH/cubescript.hh] rule default obuild