mirror of
https://github.com/holub/mame
synced 2025-06-23 21:06:38 +03:00
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
This commit is contained in:
parent
28ab42fe7b
commit
8c53c1438e
@ -56,6 +56,7 @@ public:
|
|||||||
static const char * get_bare_build_version();
|
static const char * get_bare_build_version();
|
||||||
static const char * get_build_version();
|
static const char * get_build_version();
|
||||||
static void display_ui_chooser(running_machine& machine);
|
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 int start_frontend(emu_options &options, osd_interface &osd, int argc, char *argv[]);
|
||||||
static void draw_user_interface(running_machine& machine);
|
static void draw_user_interface(running_machine& machine);
|
||||||
static void periodic_check();
|
static void periodic_check();
|
||||||
|
@ -194,10 +194,10 @@ cli_frontend::~cli_frontend()
|
|||||||
mame_options::remove_device_options(m_options);
|
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
|
// 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 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)
|
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());
|
osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors).c_str());
|
||||||
|
|
||||||
// determine the base name of the EXE
|
// 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 we have a command, execute that
|
||||||
if (*(m_options.command()) != 0)
|
if (*(m_options.command()) != 0)
|
||||||
@ -244,7 +244,7 @@ void cli_frontend::start_execution(mame_machine_manager *manager,int argc, char
|
|||||||
// command line interface
|
// 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
|
// wrap the core execution in a try/catch to field all fatal errors
|
||||||
m_result = EMU_ERR_NONE;
|
m_result = EMU_ERR_NONE;
|
||||||
@ -263,7 +263,7 @@ int cli_frontend::execute(int argc, char **argv)
|
|||||||
|
|
||||||
manager->start_context();
|
manager->start_context();
|
||||||
|
|
||||||
start_execution(manager, argc, argv, option_errors);
|
start_execution(manager, args, option_errors);
|
||||||
}
|
}
|
||||||
// handle exceptions of various types
|
// handle exceptions of various types
|
||||||
catch (emu_fatalerror &fatal)
|
catch (emu_fatalerror &fatal)
|
||||||
|
@ -31,7 +31,7 @@ public:
|
|||||||
~cli_frontend();
|
~cli_frontend();
|
||||||
|
|
||||||
// execute based on the incoming argc/argv
|
// 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
|
// direct access to the command operations
|
||||||
void listxml(const char *gamename = "*");
|
void listxml(const char *gamename = "*");
|
||||||
@ -59,7 +59,7 @@ private:
|
|||||||
void display_help(const char *exename);
|
void display_help(const char *exename);
|
||||||
void display_suggestions(const char *gamename);
|
void display_suggestions(const char *gamename);
|
||||||
void output_single_softlist(FILE *out, software_list_device &swlist);
|
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
|
// internal state
|
||||||
emu_options & m_options;
|
emu_options & m_options;
|
||||||
|
@ -318,10 +318,18 @@ void emulator_info::display_ui_chooser(running_machine& machine)
|
|||||||
ui::menu_select_game::force_game_select(mui, container);
|
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);
|
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)
|
void emulator_info::draw_user_interface(running_machine& machine)
|
||||||
|
@ -206,35 +206,48 @@ bool mame_options::parse_slot_devices(emu_options &options, std::function<void(e
|
|||||||
// and update the devices
|
// 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
|
// 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
|
// identify any options as a result of softlists
|
||||||
auto softlist_opts = evaluate_initial_softlist_options(options);
|
auto softlist_opts = evaluate_initial_softlist_options(options);
|
||||||
|
|
||||||
// assemble a "value specifier" that will be used to specify options set up as a consequence
|
// assemble a "value specifier" that will be used to specify options set up as a consequence
|
||||||
// of slot and device setup
|
// 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
|
// 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
|
// next try to find within softlist-specified options
|
||||||
if (!arg_value)
|
if (arg_value.empty())
|
||||||
{
|
{
|
||||||
auto iter = softlist_opts.find(arg);
|
auto iter = softlist_opts.find(arg);
|
||||||
if (iter != softlist_opts.end())
|
if (iter != softlist_opts.end())
|
||||||
arg_value = iter->second.c_str();
|
arg_value = iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
// did we find something?
|
// did we find something?
|
||||||
if (arg_value)
|
if (!arg_value.empty())
|
||||||
options.set_value(arg.c_str(), arg_value, OPTION_PRIORITY_MAXIMUM, error_string);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class mame_options
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// parsing wrappers
|
// 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);
|
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
|
// FIXME: Couriersud: This should be in image_device_exit
|
||||||
static void remove_device_options(emu_options &options);
|
static void remove_device_options(emu_options &options);
|
||||||
|
@ -339,7 +339,7 @@ void core_options::set_description(const char *name, const char *description)
|
|||||||
// command line arguments
|
// 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
|
// reset the errors and the command
|
||||||
error_string.clear();
|
error_string.clear();
|
||||||
@ -347,21 +347,28 @@ bool core_options::parse_command_line(int argc, char **argv, int priority, std::
|
|||||||
|
|
||||||
// iterate through arguments
|
// iterate through arguments
|
||||||
int unadorned_index = 0;
|
int unadorned_index = 0;
|
||||||
bool retval = true;
|
size_t new_argc = 1;
|
||||||
for (int arg = 1; arg < argc; arg++)
|
for (size_t arg = 1; arg < args.size(); arg++)
|
||||||
{
|
{
|
||||||
// determine the entry name to search for
|
// determine the entry name to search for
|
||||||
const char *curarg = argv[arg];
|
const char *curarg = args[arg].c_str();
|
||||||
bool is_unadorned = (curarg[0] != '-');
|
bool is_unadorned = (curarg[0] != '-');
|
||||||
const char *optionname = is_unadorned ? core_options::unadorned(unadorned_index++) : &curarg[1];
|
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);
|
auto curentry = m_entrymap.find(optionname);
|
||||||
if (curentry == m_entrymap.end())
|
if (curentry == m_entrymap.end())
|
||||||
{
|
{
|
||||||
error_string.append(string_format("Error: unknown option: %s\n", curarg));
|
// we need to relocate this option
|
||||||
retval = false;
|
if (new_argc != arg)
|
||||||
if (!is_unadorned) 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;
|
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
|
// get the data for this argument, special casing booleans
|
||||||
const char *newdata;
|
std::string newdata;
|
||||||
if (curentry->second->type() == OPTION_BOOLEAN)
|
if (curentry->second->type() == OPTION_BOOLEAN)
|
||||||
|
{
|
||||||
newdata = (strncmp(&curarg[1], "no", 2) == 0) ? "0" : "1";
|
newdata = (strncmp(&curarg[1], "no", 2) == 0) ? "0" : "1";
|
||||||
|
}
|
||||||
else if (is_unadorned)
|
else if (is_unadorned)
|
||||||
|
{
|
||||||
newdata = curarg;
|
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
|
else
|
||||||
{
|
{
|
||||||
error_string.append(string_format("Error: option %s expected a parameter\n", curarg));
|
error_string.append(string_format("Error: option %s expected a parameter\n", curarg));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
args[arg].clear();
|
||||||
|
|
||||||
// set the new data
|
// 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
|
// 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
|
// find this entry within the options (it is illegal to call this with a non-existant option
|
||||||
// so we assert if not present)
|
// 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
|
// 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(
|
auto const iter = std::find_if(
|
||||||
targets.begin(),
|
targets.begin(),
|
||||||
targets.end(),
|
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())
|
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++;
|
||||||
}
|
}
|
||||||
return nullptr;
|
args.resize(args.size() - 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -804,13 +835,11 @@ void core_options::copyfrom(const core_options &src)
|
|||||||
* @return true if it succeeds, false if it fails.
|
* @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
|
// trim any whitespace
|
||||||
std::string data(newdata);
|
|
||||||
strtrimspace(data);
|
strtrimspace(data);
|
||||||
|
|
||||||
|
|
||||||
// trim quotes
|
// trim quotes
|
||||||
if (data.find_first_of('"') == 0 && data.find_last_of('"') == data.length() - 1)
|
if (data.find_first_of('"') == 0 && data.find_last_of('"') == data.length() - 1)
|
||||||
{
|
{
|
||||||
|
@ -147,9 +147,9 @@ public:
|
|||||||
void remove_entry(entry &delentry);
|
void remove_entry(entry &delentry);
|
||||||
|
|
||||||
// parsing/input
|
// 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);
|
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
|
// reverting
|
||||||
void revert(int priority_hi = OPTION_PRIORITY_MAXIMUM, int priority_lo = OPTION_PRIORITY_DEFAULT);
|
void revert(int priority_hi = OPTION_PRIORITY_MAXIMUM, int priority_lo = OPTION_PRIORITY_DEFAULT);
|
||||||
@ -188,7 +188,7 @@ private:
|
|||||||
void reset();
|
void reset();
|
||||||
void append_entry(entry &newentry);
|
void append_entry(entry &newentry);
|
||||||
void copyfrom(const core_options &src);
|
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
|
// internal state
|
||||||
simple_list<entry> m_entrylist; // head of list of entries
|
simple_list<entry> m_entrylist; // head of list of entries
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#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
|
// main
|
||||||
//============================================================
|
//============================================================
|
||||||
@ -30,17 +30,13 @@ extern "C" int _tmain(int argc, TCHAR **argv)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
std::vector<std::string> argv_vectors(argc);
|
std::vector<std::string> argv_vectors(argc);
|
||||||
char **utf8_argv = (char **) alloca(argc * sizeof(char *));
|
|
||||||
|
|
||||||
// convert arguments to UTF-8
|
// convert arguments to UTF-8
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
{
|
|
||||||
argv_vectors[i] = osd::text::from_tstring(argv[i]);
|
argv_vectors[i] = osd::text::from_tstring(argv[i]);
|
||||||
utf8_argv[i] = (char *) argv_vectors[i].c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// run utf8_main
|
// run utf8_main
|
||||||
return utf8_main(argc, utf8_argv);
|
return utf8_main(argv_vectors);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ const options_entry windows_options::s_option_entries[] =
|
|||||||
// utf8_main
|
// 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)
|
// use small output buffers on non-TTYs (i.e. pipes)
|
||||||
if (!isatty(fileno(stdout)))
|
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
|
// Initialize this after the osd interface so that we are first in the
|
||||||
// output order
|
// output order
|
||||||
winui_output_error winerror;
|
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
|
// if we are a GUI app, output errors to message boxes
|
||||||
osd_output::push(&winerror);
|
osd_output::push(&winerror);
|
||||||
@ -310,7 +310,7 @@ int main(int argc, char *argv[])
|
|||||||
FreeConsole();
|
FreeConsole();
|
||||||
}
|
}
|
||||||
osd.register_options();
|
osd.register_options();
|
||||||
result = emulator_info::start_frontend(options, osd, argc, argv);
|
result = emulator_info::start_frontend(options, osd, args);
|
||||||
osd_output::pop(&winerror);
|
osd_output::pop(&winerror);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user