diff options
author | 2017-02-22 23:11:38 -0500 | |
---|---|---|
committer | 2017-02-22 23:13:41 -0500 | |
commit | 8c53c1438eb893ee9291c73e2ee26d34b5f8f2d7 (patch) | |
tree | 0544cad69bee0bd41e232abac03ab0ee5347edeb /src/lib/util | |
parent | 28ab42fe7bce6449885f48a1baa3ae2000a79115 (diff) |
Fixed an issue where device options (e.g. -cart) were reported as unknown when they actually worked
This change also changes around how command line arguments are passed around; specifically I changed argc/argv to be std::vector<std::string>
Note this is not passed around 'const', the reason being that the command line processing will now "eat" the vector
Diffstat (limited to 'src/lib/util')
-rw-r--r-- | src/lib/util/options.cpp | 73 | ||||
-rw-r--r-- | src/lib/util/options.h | 6 |
2 files changed, 54 insertions, 25 deletions
diff --git a/src/lib/util/options.cpp b/src/lib/util/options.cpp index b0b5439c129..0f805c61a75 100644 --- a/src/lib/util/options.cpp +++ b/src/lib/util/options.cpp @@ -339,7 +339,7 @@ void core_options::set_description(const char *name, const char *description) // command line arguments //------------------------------------------------- -bool core_options::parse_command_line(int argc, char **argv, int priority, std::string &error_string) +bool core_options::parse_command_line(std::vector<std::string> &args, int priority, std::string &error_string) { // reset the errors and the command error_string.clear(); @@ -347,21 +347,28 @@ bool core_options::parse_command_line(int argc, char **argv, int priority, std:: // iterate through arguments int unadorned_index = 0; - bool retval = true; - for (int arg = 1; arg < argc; arg++) + size_t new_argc = 1; + for (size_t arg = 1; arg < args.size(); arg++) { // determine the entry name to search for - const char *curarg = argv[arg]; + const char *curarg = args[arg].c_str(); bool is_unadorned = (curarg[0] != '-'); const char *optionname = is_unadorned ? core_options::unadorned(unadorned_index++) : &curarg[1]; - // find our entry; if not found, indicate invalid option + // find our entry; if not found, continue auto curentry = m_entrymap.find(optionname); if (curentry == m_entrymap.end()) { - error_string.append(string_format("Error: unknown option: %s\n", curarg)); - retval = false; - if (!is_unadorned) arg++; + // we need to relocate this option + if (new_argc != arg) + args[new_argc++] = std::move(args[arg]); + + if (!is_unadorned) + { + arg++; + if (new_argc != arg && arg < args.size()) + args[new_argc++] = std::move(args[arg]); + } continue; } @@ -379,23 +386,33 @@ bool core_options::parse_command_line(int argc, char **argv, int priority, std:: } // get the data for this argument, special casing booleans - const char *newdata; + std::string newdata; if (curentry->second->type() == OPTION_BOOLEAN) + { newdata = (strncmp(&curarg[1], "no", 2) == 0) ? "0" : "1"; + } else if (is_unadorned) + { newdata = curarg; - else if (arg + 1 < argc) - newdata = argv[++arg]; + } + else if (arg + 1 < args.size()) + { + args[arg++].clear(); + newdata = std::move(args[arg]); + } else { error_string.append(string_format("Error: option %s expected a parameter\n", curarg)); return false; } + args[arg].clear(); // set the new data - validate_and_set_data(*curentry->second, newdata, priority, error_string); + validate_and_set_data(*curentry->second, std::move(newdata), priority, error_string); } - return retval; + + args.resize(new_argc); + return true; } @@ -465,11 +482,11 @@ bool core_options::parse_ini_file(util::core_file &inifile, int priority, int ig //------------------------------------------------- -// find_within_command_line - finds a specific +// pluck_from_command_line - finds a specific // value from within a command line //------------------------------------------------- -const char *core_options::find_within_command_line(int argc, char **argv, const char *optionname) +std::string core_options::pluck_from_command_line(std::vector<std::string> &args, const std::string &optionname) { // find this entry within the options (it is illegal to call this with a non-existant option // so we assert if not present) @@ -487,16 +504,30 @@ const char *core_options::find_within_command_line(int argc, char **argv, const } // find each of the targets in the argv array - for (int i = 1; i < argc - 1; i++) + std::string result; + for (int i = 1; i < args.size() - 1; i++) { auto const iter = std::find_if( targets.begin(), targets.end(), - [argv, i](const std::string &targ) { return targ == argv[i]; }); + [&args, i](const std::string &targ) { return targ == args[i]; }); if (iter != targets.end()) - return argv[i + 1]; + { + // get the result + result = std::move(args[i + 1]); + + // remove this arguments from the list (is there a standard + // way to do this?) + while (i < args.size() - 2) + { + args[i] = std::move(args[i + 2]); + i++; + } + args.resize(args.size() - 2); + break; + } } - return nullptr; + return result; } @@ -804,13 +835,11 @@ void core_options::copyfrom(const core_options &src) * @return true if it succeeds, false if it fails. */ -bool core_options::validate_and_set_data(core_options::entry &curentry, const char *newdata, int priority, std::string &error_string) +bool core_options::validate_and_set_data(core_options::entry &curentry, std::string &&data, int priority, std::string &error_string) { // trim any whitespace - std::string data(newdata); strtrimspace(data); - // trim quotes if (data.find_first_of('"') == 0 && data.find_last_of('"') == data.length() - 1) { diff --git a/src/lib/util/options.h b/src/lib/util/options.h index fc6ab9849eb..ccbb24b1225 100644 --- a/src/lib/util/options.h +++ b/src/lib/util/options.h @@ -147,9 +147,9 @@ public: void remove_entry(entry &delentry); // parsing/input - bool parse_command_line(int argc, char **argv, int priority, std::string &error_string); + bool parse_command_line(std::vector<std::string> &args, int priority, std::string &error_string); bool parse_ini_file(util::core_file &inifile, int priority, int ignore_priority, std::string &error_string); - const char *find_within_command_line(int argc, char **argv, const char *name); + std::string pluck_from_command_line(std::vector<std::string> &args, const std::string &name); // reverting void revert(int priority_hi = OPTION_PRIORITY_MAXIMUM, int priority_lo = OPTION_PRIORITY_DEFAULT); @@ -188,7 +188,7 @@ private: void reset(); void append_entry(entry &newentry); void copyfrom(const core_options &src); - bool validate_and_set_data(entry &curentry, const char *newdata, int priority, std::string &error_string); + bool validate_and_set_data(entry &curentry, std::string &&newdata, int priority, std::string &error_string); // internal state simple_list<entry> m_entrylist; // head of list of entries |