forked from OctaForge/OctaBuild
merge glob matching into main
parent
e8901e2fae
commit
f90a2fe474
3
Makefile
3
Makefile
|
@ -3,7 +3,7 @@ OB_CXXFLAGS = -g -Wall -Wextra -Wshadow -Wold-style-cast -O2
|
||||||
CUBESCRIPT_PATH = ../libcubescript
|
CUBESCRIPT_PATH = ../libcubescript
|
||||||
OCTASTD_PATH = ../octastd
|
OCTASTD_PATH = ../octastd
|
||||||
|
|
||||||
FILES = main.o globs.o
|
FILES = main.o
|
||||||
|
|
||||||
OB_CXXFLAGS += -std=c++14 -I. -I$(CUBESCRIPT_PATH) -I$(OCTASTD_PATH) -pthread
|
OB_CXXFLAGS += -std=c++14 -I. -I$(CUBESCRIPT_PATH) -I$(OCTASTD_PATH) -pthread
|
||||||
|
|
||||||
|
@ -20,4 +20,3 @@ clean:
|
||||||
rm -f $(FILES) obuild
|
rm -f $(FILES) obuild
|
||||||
|
|
||||||
main.o: tpool.hh $(CUBESCRIPT_PATH)/cubescript.hh
|
main.o: tpool.hh $(CUBESCRIPT_PATH)/cubescript.hh
|
||||||
globs.o: $(CUBESCRIPT_PATH)/cubescript.hh
|
|
||||||
|
|
182
globs.cc
182
globs.cc
|
@ -1,182 +0,0 @@
|
||||||
#include <ostd/types.hh>
|
|
||||||
#include <ostd/string.hh>
|
|
||||||
#include <ostd/vector.hh>
|
|
||||||
#include <ostd/filesystem.hh>
|
|
||||||
#include <ostd/io.hh>
|
|
||||||
|
|
||||||
#include <cubescript.hh>
|
|
||||||
|
|
||||||
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<ConstCharRange> &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<ConstCharRange> 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<ConstCharRange> 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<ConstCharRange> 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<String> 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());
|
|
||||||
});
|
|
||||||
}
|
|
169
main.cc
169
main.cc
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
#include "tpool.hh"
|
#include "tpool.hh"
|
||||||
|
|
||||||
void cs_register_globs(cscript::CsState &cs);
|
|
||||||
|
|
||||||
using ostd::ConstCharRange;
|
using ostd::ConstCharRange;
|
||||||
using ostd::Vector;
|
using ostd::Vector;
|
||||||
using ostd::Map;
|
using ostd::Map;
|
||||||
|
@ -33,6 +31,168 @@ using cscript::TvalRange;
|
||||||
using cscript::StackedValue;
|
using cscript::StackedValue;
|
||||||
using cscript::Bytecode;
|
using cscript::Bytecode;
|
||||||
|
|
||||||
|
/* glob matching code */
|
||||||
|
|
||||||
|
static void ob_get_path_parts(
|
||||||
|
Vector<ConstCharRange> &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<ConstCharRange> 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<ConstCharRange> 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<ConstCharRange> 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<String> const &src) {
|
||||||
|
String ret;
|
||||||
|
for (auto &s: src.iter()) {
|
||||||
|
ob_expand_glob(ret, s.iter());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* check funcs */
|
/* check funcs */
|
||||||
|
|
||||||
static bool ob_check_ts(ConstCharRange tname, Vector<String> const &deps) {
|
static bool ob_check_ts(ConstCharRange tname, Vector<String> const &deps) {
|
||||||
|
@ -533,7 +693,10 @@ int main(int argc, char **argv) {
|
||||||
os.result->set_int(os.exec_main(args[0].get_strr()));
|
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)) {
|
if ((!fcont.empty() && !os.run_bool(fcont)) || !os.run_file(deffile)) {
|
||||||
return os.error(1, "failed creating rules");
|
return os.error(1, "failed creating rules");
|
||||||
|
|
|
@ -5,7 +5,7 @@ OB_CXXFLAGS = "-g -Wall -Wextra -Wshadow -Wold-style-cast -O2"
|
||||||
CS_PATH = "../libcubescript"
|
CS_PATH = "../libcubescript"
|
||||||
OS_PATH = "../octastd"
|
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]
|
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 main_ob.o [tpool.hh @CS_PATH/cubescript.hh]
|
||||||
depend globs_ob.o [@CS_PATH/cubescript.hh]
|
|
||||||
|
|
||||||
rule default obuild
|
rule default obuild
|
||||||
|
|
Loading…
Reference in New Issue