diff options
Diffstat (limited to 'hscript')
-rw-r--r-- | hscript/script.cc | 74 | ||||
-rw-r--r-- | hscript/script.hh | 29 |
2 files changed, 72 insertions, 31 deletions
diff --git a/hscript/script.cc b/hscript/script.cc index 748b09a..a9c39ab 100644 --- a/hscript/script.cc +++ b/hscript/script.cc @@ -18,6 +18,10 @@ #include "network.hh" #include "user.hh" +#include "util/output.hh" + +#define LINE_MAX 512 + namespace Horizon { struct Script::ScriptPrivate { @@ -34,35 +38,67 @@ struct Script::ScriptPrivate { }; Script::Script() { + internal = new ScriptPrivate; } const Script *Script::load(std::string path, ScriptOptions opts) { - std::ifstream file; - std::string maybe_error; - - file.exceptions(std::ios::badbit); - try { - file.open(path); - } catch(const std::ios::failure &error) { - maybe_error = error.what(); - } catch(const std::exception &error) { - maybe_error = error.what(); - } + std::ifstream file(path); if(!file) { - std::cerr << "Cannot open installfile at \"" << path << "\": "; - std::cerr << maybe_error; - std::cerr << std::endl; + output_error(path, "Cannot open installfile", "", + (opts.test(Pretty))); return nullptr; } return Script::load(file, opts); } -const Script *Script::load(std::istream &, ScriptOptions) { - Script *foo = new Script; - delete foo; - std::cout << "loaded" << std::endl; - return nullptr; +const Script *Script::load(std::istream &sstream, ScriptOptions opts) { + Script *the_script = new Script; + + int lineno = 0; + char nextline[LINE_MAX]; + const std::string delim(" \t"); + + while(sstream.getline(nextline, sizeof(nextline))) { + lineno++; + if(nextline[0] == '#') { + /* This is a comment line; ignore it. */ + continue; + } + + const std::string line(nextline); + std::string::size_type start, key_end; + start = line.find_first_not_of(delim); + if(start == std::string::npos) { + /* This is a blank line; ignore it. */ + continue; + } + + key_end = line.find_first_of(delim, start); + if(key_end == std::string::npos) { + /* Key without value */ + output_error("installfile:" + std::to_string(lineno), + "key '" + line.substr(start) + "' has no value", + "", (opts.test(Pretty))); + } + } + + if(sstream.fail() && !sstream.eof()) { + output_error("installfile:" + std::to_string(lineno + 1), + "line exceeds maximum length", + "Maximum length for line is " + std::to_string(LINE_MAX), + (opts.test(Pretty))); + delete the_script; + return nullptr; + } + + if(sstream.bad() && !sstream.eof()) { + output_error("installfile:" + std::to_string(lineno), + "I/O error reading installfile", "", + (opts.test(Pretty))); + } + + return the_script; } bool Script::validate() { diff --git a/hscript/script.hh b/hscript/script.hh index 1150e78..8c0f619 100644 --- a/hscript/script.hh +++ b/hscript/script.hh @@ -16,24 +16,29 @@ #include <string> #include <vector> #include <memory> +#include <bitset> namespace Horizon { /**** Script option flags ****/ -/*! Don't stop after the first error. */ -#define SCRIPT_KEEP_GOING 0x0001 -/*! Ensure network resources are available. */ -#define SCRIPT_USE_NETWORK 0x0002 -/*! Treat warnings as errors. */ -#define SCRIPT_STRICT_MODE 0x0004 -/*! This is an Installation Environment - validate more keys. */ -#define SCRIPT_INSTALL_ENV 0x0008 -/*! "Pretty" output - used in interactive tooling only. */ -#define SCRIPT_PRETTY 0x0010 +enum ScriptOptionFlags { + /*! Don't stop after the first error. */ + KeepGoing, + /*! Ensure network resources are available. */ + UseNetwork, + /*! Treat warnings as errors. */ + StrictMode, + /*! This is an Installation Environment - validate more keys. */ + InstallEnvironment, + /*! "Pretty" output - used in interactive tooling only. */ + Pretty, + /*! Count of flags */ + NumFlags +}; -typedef uint32_t ScriptOptions; +typedef std::bitset<ScriptOptionFlags::NumFlags> ScriptOptions; /*! Defines the Script class, which represents a HorizonScript. */ @@ -61,7 +66,7 @@ public: private: struct ScriptPrivate; /*! Internal data. */ - const std::unique_ptr<ScriptPrivate> internal; + ScriptPrivate *internal; }; } |