diff --git a/core/app.cpp b/core/app.cpp index df10424fb6..d2c49e53fb 100644 --- a/core/app.cpp +++ b/core/app.cpp @@ -896,7 +896,8 @@ void sort_arguments(const std::vector &arguments) { throw Exception(std::string("not enough parameters to option \"-") + opt->id + "\""); } std::copy_n(it, opt->size(), std::back_inserter(option_args)); - option.push_back(ParsedOption(opt, option_args)); + const size_t index = std::distance(arguments.begin(), it); + option.push_back(ParsedOption(opt, option_args, index)); it += opt->size(); } else { argument.push_back(ParsedArgument(nullptr, nullptr, *it)); @@ -1200,7 +1201,7 @@ const std::vector get_options(const std::string &name) { for (size_t i = 0; i < option.size(); ++i) { assert(option[i].opt); if (option[i].opt->is(name)) - matches.push_back({option[i].opt, option[i].args}); + matches.push_back({option[i].opt, option[i].args, option[i].index}); } return matches; } @@ -1373,8 +1374,8 @@ void check_overwrite(const std::string &name) { } } - -ParsedOption::ParsedOption(const Option *option, const std::vector &arguments) : opt(option), args(arguments) { +ParsedOption::ParsedOption(const Option *option, const std::vector &arguments, size_t i) + : opt(option), args(arguments), index(i) { for (size_t i = 0; i != option->size(); ++i) { const auto &p = arguments[i]; if (!is_dash(p)) diff --git a/core/app.h b/core/app.h index 26b64744e3..767a9f1904 100644 --- a/core/app.h +++ b/core/app.h @@ -192,12 +192,14 @@ class ParsedArgument { * returned by App::get_options(). */ class ParsedOption { public: - ParsedOption(const Option *option, const std::vector &arguments); + ParsedOption(const Option *option, const std::vector &arguments, size_t index); //! reference to the corresponding Option entry in the OPTIONS section const Option *opt; - //! pointer into \c argv corresponding to the option's first argument + //! list of arguments supplied to the option std::vector args; + //! the index of this option in the raw command-line arguments list + size_t index; ParsedArgument operator[](size_t num) const; diff --git a/src/gui/mrview/window.cpp b/src/gui/mrview/window.cpp index 9b44f11794..c7bc32078a 100644 --- a/src/gui/mrview/window.cpp +++ b/src/gui/mrview/window.cpp @@ -721,22 +721,26 @@ void Window::parse_arguments() { if (!MR::App::argument.empty()) { if (!MR::App::option.empty()) { // check that first non-standard option appears after last argument: - size_t last_arg_pos = 1; - for (; MR::App::argv[last_arg_pos] != MR::App::argument.back().c_str(); ++last_arg_pos) - if (MR::App::argv[last_arg_pos] == nullptr) - throw Exception("FIXME: error determining position of last argument!"); - - // identify first non-standard option: - size_t first_option = 0; - for (; first_option < MR::App::option.size(); ++first_option) { - if (size_t(MR::App::option[first_option].opt - &MR::App::__standard_options[0]) >= - MR::App::__standard_options.size()) - break; + const auto last_arg = std::find( + MR::App::raw_arguments_list.rbegin(), MR::App::raw_arguments_list.rend(), MR::App::argument.back().c_str()); + + if (last_arg == MR::App::raw_arguments_list.rend()) { + throw Exception("FIXME: error determining position of last argument!"); } - if (MR::App::option.size() > first_option) { - first_option = MR::App::option[first_option].args - MR::App::argv; - if (first_option < last_arg_pos) - throw Exception("options must appear after the last argument - see help page for details"); + + const auto last_arg_pos = std::distance(last_arg, MR::App::raw_arguments_list.rend()) - 1; + + const auto is_non_standard_option = [](const MR::App::ParsedOption &option) { + return std::none_of(MR::App::__standard_options.begin(), + MR::App::__standard_options.end(), + [&option](const auto &standard_option) { return option.opt == &standard_option; }); + }; + + const auto first_non_standard_option = + std::find_if(MR::App::option.begin(), MR::App::option.end(), is_non_standard_option); + + if (first_non_standard_option != MR::App::option.end() && first_non_standard_option->index < last_arg_pos) { + throw Exception("options must appear after the last argument - see help page for details"); } }