diff options
author | 2017-02-22 23:11:38 -0500 | |
---|---|---|
committer | 2017-02-22 23:13:41 -0500 | |
commit | 8c53c1438eb893ee9291c73e2ee26d34b5f8f2d7 (patch) | |
tree | 0544cad69bee0bd41e232abac03ab0ee5347edeb /src | |
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')
-rw-r--r-- | src/emu/main.h | 1 | ||||
-rw-r--r-- | src/frontend/mame/clifront.cpp | 10 | ||||
-rw-r--r-- | src/frontend/mame/clifront.h | 4 | ||||
-rw-r--r-- | src/frontend/mame/mame.cpp | 12 | ||||
-rw-r--r-- | src/frontend/mame/mameopts.cpp | 31 | ||||
-rw-r--r-- | src/frontend/mame/mameopts.h | 2 | ||||
-rw-r--r-- | src/lib/util/options.cpp | 73 | ||||
-rw-r--r-- | src/lib/util/options.h | 6 | ||||
-rw-r--r-- | src/osd/windows/main.cpp | 8 | ||||
-rw-r--r-- | src/osd/windows/winmain.cpp | 6 |
10 files changed, 100 insertions, 53 deletions
diff --git a/src/emu/main.h b/src/emu/main.h index 9d6f0e01459..dd3dcced68d 100644 --- a/src/emu/main.h +++ b/src/emu/main.h @@ -56,6 +56,7 @@ public: static const char * get_bare_build_version(); static const char * get_build_version(); static void display_ui_chooser(running_machine& machine); + static int start_frontend(emu_options &options, osd_interface &osd, std::vector<std::string> &args); static int start_frontend(emu_options &options, osd_interface &osd, int argc, char *argv[]); static void draw_user_interface(running_machine& machine); static void periodic_check(); diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index 450a8384b0f..051fa3f7a92 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -194,10 +194,10 @@ cli_frontend::~cli_frontend() mame_options::remove_device_options(m_options); } -void cli_frontend::start_execution(mame_machine_manager *manager,int argc, char **argv,std::string &option_errors) +void cli_frontend::start_execution(mame_machine_manager *manager, std::vector<std::string> &args, std::string &option_errors) { // parse the command line, adding any system-specific options - if (!mame_options::parse_command_line(m_options, argc, argv, option_errors)) + if (!mame_options::parse_command_line(m_options, args, option_errors)) { // if we failed, check for no command and a system name first; in that case error on the name if (*(m_options.command()) == 0 && mame_options::system(m_options) == nullptr && *(m_options.system_name()) != 0) @@ -210,7 +210,7 @@ void cli_frontend::start_execution(mame_machine_manager *manager,int argc, char osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors).c_str()); // determine the base name of the EXE - std::string exename = core_filename_extract_base(argv[0], true); + std::string exename = core_filename_extract_base(args[0], true); // if we have a command, execute that if (*(m_options.command()) != 0) @@ -244,7 +244,7 @@ void cli_frontend::start_execution(mame_machine_manager *manager,int argc, char // command line interface //------------------------------------------------- -int cli_frontend::execute(int argc, char **argv) +int cli_frontend::execute(std::vector<std::string> &args) { // wrap the core execution in a try/catch to field all fatal errors m_result = EMU_ERR_NONE; @@ -263,7 +263,7 @@ int cli_frontend::execute(int argc, char **argv) manager->start_context(); - start_execution(manager, argc, argv, option_errors); + start_execution(manager, args, option_errors); } // handle exceptions of various types catch (emu_fatalerror &fatal) diff --git a/src/frontend/mame/clifront.h b/src/frontend/mame/clifront.h index 33dab55576c..7c3f2e4519e 100644 --- a/src/frontend/mame/clifront.h +++ b/src/frontend/mame/clifront.h @@ -31,7 +31,7 @@ public: ~cli_frontend(); // execute based on the incoming argc/argv - int execute(int argc, char **argv); + int execute(std::vector<std::string> &args); // direct access to the command operations void listxml(const char *gamename = "*"); @@ -59,7 +59,7 @@ private: void display_help(const char *exename); void display_suggestions(const char *gamename); void output_single_softlist(FILE *out, software_list_device &swlist); - void start_execution(mame_machine_manager *manager, int argc, char **argv, std::string &option_errors); + void start_execution(mame_machine_manager *manager, std::vector<std::string> &args, std::string &option_errors); // internal state emu_options & m_options; diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp index c8e73eba670..10960cd0446 100644 --- a/src/frontend/mame/mame.cpp +++ b/src/frontend/mame/mame.cpp @@ -318,10 +318,18 @@ void emulator_info::display_ui_chooser(running_machine& machine) ui::menu_select_game::force_game_select(mui, container); } -int emulator_info::start_frontend(emu_options &options, osd_interface &osd, int argc, char *argv[]) +int emulator_info::start_frontend(emu_options &options, osd_interface &osd, std::vector<std::string> &args) { cli_frontend frontend(options, osd); - return frontend.execute(argc, argv); + return frontend.execute(args); +} + +int emulator_info::start_frontend(emu_options &options, osd_interface &osd, int argc, char *argv[]) +{ + std::vector<std::string> args(argc); + for (int i = 0; i < argc; i++) + args[i] = argv[i]; + return start_frontend(options, osd, args); } void emulator_info::draw_user_interface(running_machine& machine) diff --git a/src/frontend/mame/mameopts.cpp b/src/frontend/mame/mameopts.cpp index 0f9a9584716..e3aed3d751e 100644 --- a/src/frontend/mame/mameopts.cpp +++ b/src/frontend/mame/mameopts.cpp @@ -206,35 +206,48 @@ bool mame_options::parse_slot_devices(emu_options &options, std::function<void(e // and update the devices //------------------------------------------------- -bool mame_options::parse_command_line(emu_options &options, int argc, char *argv[], std::string &error_string) +bool mame_options::parse_command_line(emu_options &options, std::vector<std::string> &args, std::string &error_string) { // parse the command line - options.parse_command_line(argc, argv, OPTION_PRIORITY_CMDLINE, error_string); + if (!options.parse_command_line(args, OPTION_PRIORITY_CMDLINE, error_string)) + return false; // identify any options as a result of softlists auto softlist_opts = evaluate_initial_softlist_options(options); // assemble a "value specifier" that will be used to specify options set up as a consequence // of slot and device setup - auto value_specifier = [&softlist_opts, argc, argv, &error_string](emu_options &options, const std::string &arg) + auto value_specifier = [&softlist_opts, &args, &error_string](emu_options &options, const std::string &arg) { // first find within the command line - const char *arg_value = options.find_within_command_line(argc, argv, arg.c_str()); + std::string arg_value = options.pluck_from_command_line(args, arg); // next try to find within softlist-specified options - if (!arg_value) + if (arg_value.empty()) { auto iter = softlist_opts.find(arg); if (iter != softlist_opts.end()) - arg_value = iter->second.c_str(); + arg_value = iter->second; } // did we find something? - if (arg_value) - options.set_value(arg.c_str(), arg_value, OPTION_PRIORITY_MAXIMUM, error_string); + if (!arg_value.empty()) + options.set_value(arg.c_str(), arg_value.c_str(), OPTION_PRIORITY_MAXIMUM, error_string); }; - return parse_slot_devices(options, value_specifier); + // parse the slot devices + if (!parse_slot_devices(options, value_specifier)) + return false; + + // at this point, we should have handled all arguments; the only argument that shouldn't have + // been handled is the file name + if (args.size() > 1) + { + error_string.append(string_format("Error: unknown option: %s\n", args[1])); + return false; + } + + return true; } diff --git a/src/frontend/mame/mameopts.h b/src/frontend/mame/mameopts.h index 1fbf14e78e6..69e6e7ec931 100644 --- a/src/frontend/mame/mameopts.h +++ b/src/frontend/mame/mameopts.h @@ -54,7 +54,7 @@ class mame_options public: // parsing wrappers - static bool parse_command_line(emu_options &options, int argc, char *argv[], std::string &error_string); + static bool parse_command_line(emu_options &options, std::vector<std::string> &args, std::string &error_string); static void parse_standard_inis(emu_options &options, std::string &error_string, const game_driver *driver = nullptr); // FIXME: Couriersud: This should be in image_device_exit static void remove_device_options(emu_options &options); 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 diff --git a/src/osd/windows/main.cpp b/src/osd/windows/main.cpp index 7c33434c005..e87fa24e57c 100644 --- a/src/osd/windows/main.cpp +++ b/src/osd/windows/main.cpp @@ -20,7 +20,7 @@ #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -extern int utf8_main(int argc, char *argv[]); +extern int utf8_main(std::vector<std::string> &args); //============================================================ // main //============================================================ @@ -30,17 +30,13 @@ extern "C" int _tmain(int argc, TCHAR **argv) { int i; std::vector<std::string> argv_vectors(argc); - char **utf8_argv = (char **) alloca(argc * sizeof(char *)); // convert arguments to UTF-8 for (i = 0; i < argc; i++) - { argv_vectors[i] = osd::text::from_tstring(argv[i]); - utf8_argv[i] = (char *) argv_vectors[i].c_str(); - } // run utf8_main - return utf8_main(argc, utf8_argv); + return utf8_main(argv_vectors); } #endif diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp index b146e8b6357..665ec73f13b 100644 --- a/src/osd/windows/winmain.cpp +++ b/src/osd/windows/winmain.cpp @@ -276,7 +276,7 @@ const options_entry windows_options::s_option_entries[] = // utf8_main //============================================================ -int main(int argc, char *argv[]) +int main(std::vector<std::string> &args) { // use small output buffers on non-TTYs (i.e. pipes) if (!isatty(fileno(stdout))) @@ -302,7 +302,7 @@ int main(int argc, char *argv[]) // Initialize this after the osd interface so that we are first in the // output order winui_output_error winerror; - if (win_is_gui_application() || is_double_click_start(argc)) + if (win_is_gui_application() || is_double_click_start(args.size())) { // if we are a GUI app, output errors to message boxes osd_output::push(&winerror); @@ -310,7 +310,7 @@ int main(int argc, char *argv[]) FreeConsole(); } osd.register_options(); - result = emulator_info::start_frontend(options, osd, argc, argv); + result = emulator_info::start_frontend(options, osd, args); osd_output::pop(&winerror); } |