summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hscript/script.cc46
-rw-r--r--hscript/script_i.hh1
-rw-r--r--hscript/script_l.hh8
-rw-r--r--tests/fixtures/0232-inherit-basic.installfile3
-rw-r--r--tests/fixtures/0233-inherit-missing.installfile4
-rw-r--r--tests/fixtures/0234-inherit-loop1.installfile3
-rw-r--r--tests/fixtures/0235-inherit-loop2.installfile3
-rw-r--r--tests/fixtures/0236-inherit-relative.installfile2
-rw-r--r--tests/fixtures/0237-inherit-incomplete.installfile2
-rw-r--r--tests/fixtures/0238-inherit-override.installfile3
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