diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2020-05-26 02:08:20 -0500 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2020-05-26 02:08:20 -0500 |
commit | 82ca73034e9fc0756945ddbd9c9008a8b6443d69 (patch) | |
tree | 9cb88cbb63fc349b5a282ed143eeea652d3e36f7 | |
parent | db86a77b1d79824d2ee42d617f9a04bf8c3f7210 (diff) | |
download | horizon-82ca73034e9fc0756945ddbd9c9008a8b6443d69.tar.gz horizon-82ca73034e9fc0756945ddbd9c9008a8b6443d69.tar.bz2 horizon-82ca73034e9fc0756945ddbd9c9008a8b6443d69.tar.xz horizon-82ca73034e9fc0756945ddbd9c9008a8b6443d69.zip |
hscript: Implement (currently undocumented) 'inherit' key and tests
-rw-r--r-- | hscript/script.cc | 46 | ||||
-rw-r--r-- | hscript/script_i.hh | 1 | ||||
-rw-r--r-- | hscript/script_l.hh | 8 | ||||
-rw-r--r-- | tests/fixtures/0232-inherit-basic.installfile | 3 | ||||
-rw-r--r-- | tests/fixtures/0233-inherit-missing.installfile | 4 | ||||
-rw-r--r-- | tests/fixtures/0234-inherit-loop1.installfile | 3 | ||||
-rw-r--r-- | tests/fixtures/0235-inherit-loop2.installfile | 3 | ||||
-rw-r--r-- | tests/fixtures/0236-inherit-relative.installfile | 2 | ||||
-rw-r--r-- | tests/fixtures/0237-inherit-incomplete.installfile | 2 | ||||
-rw-r--r-- | tests/fixtures/0238-inherit-override.installfile | 3 |
10 files changed, 64 insertions, 11 deletions
diff --git a/hscript/script.cc b/hscript/script.cc index f775629..a3fb512 100644 --- a/hscript/script.cc +++ b/hscript/script.cc @@ -216,15 +216,19 @@ Script *Script::load(std::istream &sstream, const ScriptOptions &opts, char nextline[SCRIPT_LINE_MAX]; const std::string delim(" \t"); int errors = 0, warnings = 0; + std::string curr_name = fs::canonical(fs::path(name)); + std::set<std::string> seen = {curr_name}; + bool inherit = false; + std::istream *my_stream = &sstream; - while(sstream.getline(nextline, sizeof(nextline))) { + while(my_stream->getline(nextline, sizeof(nextline))) { lineno++; if(nextline[0] == '#') { /* This is a comment line; ignore it. */ continue; } - const ScriptLocation pos(name, lineno, false); + const ScriptLocation pos(curr_name, lineno, inherit); const std::string line(nextline); std::string key; std::string::size_type start, key_end, value_begin; @@ -246,6 +250,33 @@ Script *Script::load(std::istream &sstream, const ScriptOptions &opts, /* Normalise key to lower-case */ std::transform(key.begin(), key.end(), key.begin(), ::tolower); + if(key == "inherit") { + std::string next_name{line.substr(value_begin)}; + if(fs::path(next_name).is_relative()) { + fs::path better_path = fs::absolute(curr_name); + better_path.remove_filename(); + better_path /= next_name; + next_name = fs::absolute(better_path); + } + + if(seen.find(next_name) != seen.end()) { + PARSER_ERROR("attempt to inherit from already inherited file") + break; + } + seen.insert(next_name); + + if(!fs::exists(next_name)) { + PARSER_ERROR("attempt to inherit from non-existent file") + break; + } else { + if(my_stream != &sstream) delete my_stream; + curr_name = next_name; + inherit = true; + my_stream = new std::ifstream(curr_name); + } + continue; + } + if(valid_keys.find(key) == valid_keys.end()) { /* Invalid key */ if(opts.test(StrictMode)) { @@ -270,7 +301,7 @@ Script *Script::load(std::istream &sstream, const ScriptOptions &opts, } } - if(sstream.fail() && !sstream.eof()) { + if(my_stream->fail() && !my_stream->eof()) { output_error("installfile:" + std::to_string(lineno + 1), "line exceeds maximum length", "Maximum line length is " + @@ -278,7 +309,7 @@ Script *Script::load(std::istream &sstream, const ScriptOptions &opts, errors++; } - if(sstream.bad() && !sstream.eof()) { + if(my_stream->bad() && !my_stream->eof()) { output_error("installfile:" + std::to_string(lineno), "I/O error while reading installfile", ""); errors++; @@ -286,8 +317,7 @@ Script *Script::load(std::istream &sstream, const ScriptOptions &opts, /* Ensure all required keys are present. */ #define MISSING_ERROR(key) \ - output_error("installfile:" + std::to_string(lineno),\ - "expected value for key '" + std::string(key) + "'",\ + output_error(name, "expected value for key '" + std::string(key) + "'",\ "this key is required");\ errors++; @@ -310,10 +340,12 @@ Script *Script::load(std::istream &sstream, const ScriptOptions &opts, } #undef MISSING_ERROR - output_log("parser", "0", "installfile", + output_log("parser", "0", name, std::to_string(errors) + " error(s), " + std::to_string(warnings) + " warning(s).", ""); + if(my_stream != &sstream) delete my_stream; + if(errors > 0) { delete the_script; return nullptr; diff --git a/hscript/script_i.hh b/hscript/script_i.hh index b6fc371..2a86d71 100644 --- a/hscript/script_i.hh +++ b/hscript/script_i.hh @@ -116,6 +116,7 @@ struct Script::ScriptPrivate { const ScriptOptions &opts); #define DUPLICATE_ERROR(OBJ, KEY, OLD_VAL) \ + if(pos.inherited) return true;\ std::string err_str("previous value was ");\ err_str += OLD_VAL;\ err_str += " at " + OBJ->where().name;\ diff --git a/hscript/script_l.hh b/hscript/script_l.hh index 1f048c6..e1becc8 100644 --- a/hscript/script_l.hh +++ b/hscript/script_l.hh @@ -23,11 +23,11 @@ struct ScriptLocation { std::string name; /*! The line number of the current location. */ int line; - /*! Whether this script is nested or the original script. */ - bool nested; + /*! Whether this script is inherited or the original script. */ + bool inherited; - ScriptLocation(std::string _n, int _l, bool _nest = false) : - name{_n}, line{_l}, nested{_nest} {}; + ScriptLocation(std::string _n, int _l, bool _inherit = false) : + name{_n}, line{_l}, inherited{_inherit} {}; }; } diff --git a/tests/fixtures/0232-inherit-basic.installfile b/tests/fixtures/0232-inherit-basic.installfile new file mode 100644 index 0000000..64a4c6a --- /dev/null +++ b/tests/fixtures/0232-inherit-basic.installfile @@ -0,0 +1,3 @@ +arch ppc64 +pkginstall kde x11 +inherit 0222-complete.installfile diff --git a/tests/fixtures/0233-inherit-missing.installfile b/tests/fixtures/0233-inherit-missing.installfile new file mode 100644 index 0000000..f6e05c1 --- /dev/null +++ b/tests/fixtures/0233-inherit-missing.installfile @@ -0,0 +1,4 @@ +arch ppc64 +pkginstall kde x11 +# Purposefully misspelled. +inherit 0222-compleat.installfile diff --git a/tests/fixtures/0234-inherit-loop1.installfile b/tests/fixtures/0234-inherit-loop1.installfile new file mode 100644 index 0000000..14d00f6 --- /dev/null +++ b/tests/fixtures/0234-inherit-loop1.installfile @@ -0,0 +1,3 @@ +arch ppc64 +pkginstall kde x11 +inherit 0235-inherit-loop2.installfile diff --git a/tests/fixtures/0235-inherit-loop2.installfile b/tests/fixtures/0235-inherit-loop2.installfile new file mode 100644 index 0000000..6b82fe3 --- /dev/null +++ b/tests/fixtures/0235-inherit-loop2.installfile @@ -0,0 +1,3 @@ +hostname loopy +network false +inherit 0234-inherit-loop1.installfile diff --git a/tests/fixtures/0236-inherit-relative.installfile b/tests/fixtures/0236-inherit-relative.installfile new file mode 100644 index 0000000..eb6fe27 --- /dev/null +++ b/tests/fixtures/0236-inherit-relative.installfile @@ -0,0 +1,2 @@ +arch ppc64 +inherit ../fixtures/0222-complete.installfile diff --git a/tests/fixtures/0237-inherit-incomplete.installfile b/tests/fixtures/0237-inherit-incomplete.installfile new file mode 100644 index 0000000..a4b1309 --- /dev/null +++ b/tests/fixtures/0237-inherit-incomplete.installfile @@ -0,0 +1,2 @@ +arch ppc64 +inherit 0006-no-network.installfile diff --git a/tests/fixtures/0238-inherit-override.installfile b/tests/fixtures/0238-inherit-override.installfile new file mode 100644 index 0000000..161e8f8 --- /dev/null +++ b/tests/fixtures/0238-inherit-override.installfile @@ -0,0 +1,3 @@ +arch ppc64 +hostname overriden.hostname.local +inherit 0222-complete.installfile |