diff --git a/src/core/util/CommandLine.cc b/src/core/util/CommandLine.cc index 33f6c333..6116beb0 100644 --- a/src/core/util/CommandLine.cc +++ b/src/core/util/CommandLine.cc @@ -43,8 +43,13 @@ bool CommandLine::parse() { option::Descriptor desc = {0, 0, 0, 0, 0, 0}; this->options.push_back(desc); - // Generate the options stats - option::Stats stats(this->options.data(), argv.size(), argv.data()); + // Copy argv to preserve original argument order + // (for proper re-parsing after adding more options) + argv_reordered = argv; + + // Generate the options stats (GNU mode) + option::Stats stats(true, this->options.data(), + argv_reordered.size(), argv_reordered.data()); if (parsed_options) delete[] parsed_options; @@ -56,9 +61,9 @@ bool CommandLine::parse() { parsed_options = new option::Option[stats.options_max]; parsed_buffer = new option::Option[stats.buffer_max]; - m_parser = new option::Parser(this->options.data(), argv.size(), argv.data(), - parsed_options, parsed_buffer); - + m_parser = new option::Parser(true, this->options.data(), + argv_reordered.size(), argv_reordered.data(), + parsed_options, parsed_buffer); // Pop the terminating entry this->options.pop_back(); diff --git a/src/core/util/CommandLine.hpp b/src/core/util/CommandLine.hpp index 21dfd2a3..a89ad9c8 100644 --- a/src/core/util/CommandLine.hpp +++ b/src/core/util/CommandLine.hpp @@ -30,7 +30,7 @@ public: private: static CommandLine m_instance; - std::vector argv; + std::vector argv, argv_reordered; std::vector options; option::Option *parsed_options, *parsed_buffer; option::Parser *m_parser; diff --git a/tools/compute-hops/main.cc b/tools/compute-hops/main.cc index 2f3979de..0c1134a7 100644 --- a/tools/compute-hops/main.cc +++ b/tools/compute-hops/main.cc @@ -40,7 +40,7 @@ int main(int argc, char *argv[]) // Manually fill the command line option parser CommandLine &cmd = CommandLine::Inst(); - cmd.addOption("", "", Arg::None, "USAGE: compute-hops [options]"); + CommandLine::option_handle UNKNOWN = cmd.addOption("", "", Arg::None, "USAGE: compute-hops [options]"); CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h,--help \tPrint usage and exit"); CommandLine::option_handle ALGORITHM = @@ -99,7 +99,13 @@ int main(int argc, char *argv[]) return 1; } - if (cmd[HELP]) { + if (cmd[HELP] || cmd[UNKNOWN] || cmd.parser()->nonOptionsCount() > 0) { + for (option::Option* opt = cmd[UNKNOWN]; opt; opt = opt->next()) { + std::cerr << "Unknown option: " << opt->name << "\n"; + } + for (int i = 0; i < cmd.parser()->nonOptionsCount(); ++i) { + std::cerr << "Unknown non-option: " << cmd.parser()->nonOption(i) << "\n"; + } cmd.printUsage(); if (cmd[HELP]) { exit(0); diff --git a/tools/convert-trace/main.cc b/tools/convert-trace/main.cc index 359d3806..45330ba4 100644 --- a/tools/convert-trace/main.cc +++ b/tools/convert-trace/main.cc @@ -17,7 +17,8 @@ static Logger LOG("convert-trace", true); int main(int argc, char *argv[]) { CommandLine &cmd = CommandLine::Inst(); - cmd.addOption("", "", Arg::None, "usage: convert-trace -f dump|gem5 -t tracefile.tc"); + CommandLine::option_handle UNKNOWN = + cmd.addOption("", "", Arg::None, "usage: convert-trace -f dump|gem5 -t tracefile.tc"); CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h/--help \tPrint usage and exit"); CommandLine::option_handle FORMAT = @@ -28,11 +29,17 @@ int main(int argc, char *argv[]) { cmd.add_args(argv[i]); } if (!cmd.parse()) { - LOG << "Error parsing arguments." << endl; + std::cerr << "Error parsing arguments." << endl; return 1; } - if (cmd[HELP] || !cmd[OUTFILE] || !cmd[FORMAT] || cmd.parser()->nonOptionsCount() != 0) { + if (cmd[HELP] || !cmd[OUTFILE] || !cmd[FORMAT] || cmd[UNKNOWN] || cmd.parser()->nonOptionsCount() != 0) { + for (option::Option* opt = cmd[UNKNOWN]; opt; opt = opt->next()) { + std::cerr << "Unknown option: " << opt->name << "\n"; + } + for (int i = 0; i < cmd.parser()->nonOptionsCount(); ++i) { + std::cerr << "Unknown non-option: " << cmd.parser()->nonOption(i) << "\n"; + } cmd.printUsage(); if (cmd[HELP]) { exit(0); diff --git a/tools/dump-hops/DumpHops.cc b/tools/dump-hops/DumpHops.cc index dd3c88c0..e64695bc 100644 --- a/tools/dump-hops/DumpHops.cc +++ b/tools/dump-hops/DumpHops.cc @@ -49,7 +49,8 @@ int main(int argc, char *argv[]) InjectionPointMessage ev; CommandLine &cmd = CommandLine::Inst(); - cmd.addOption("", "", Arg::None, "usage: dump-hops [options] hopfile.hp"); + CommandLine::option_handle UNKNOWN = + cmd.addOption("", "", Arg::None, "usage: dump-hops [options] hopfile.hp"); CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h/--help \tPrint usage and exit"); // CommandLine::option_handle STATS = @@ -64,7 +65,13 @@ int main(int argc, char *argv[]) return 1; } - if (cmd[HELP] || cmd.parser()->nonOptionsCount() != 1) { + if (cmd[HELP] || cmd[UNKNOWN] || cmd.parser()->nonOptionsCount() != 1) { + for (option::Option* opt = cmd[UNKNOWN]; opt; opt = opt->next()) { + std::cerr << "Unknown option: " << opt->name << "\n"; + } + for (int i = 1; i < cmd.parser()->nonOptionsCount(); ++i) { + std::cerr << "Unknown non-option: " << cmd.parser()->nonOption(i) << "\n"; + } cmd.printUsage(); if (cmd[HELP]) { exit(0); diff --git a/tools/dump-trace/DumpTrace.cc b/tools/dump-trace/DumpTrace.cc index 0015cec2..d86ee5e9 100644 --- a/tools/dump-trace/DumpTrace.cc +++ b/tools/dump-trace/DumpTrace.cc @@ -49,7 +49,8 @@ int main(int argc, char *argv[]) Trace_Event ev; CommandLine &cmd = CommandLine::Inst(); - cmd.addOption("", "", Arg::None, "usage: dump-trace [options] tracefile.tc"); + CommandLine::option_handle UNKNOWN = + cmd.addOption("", "", Arg::None, "usage: dump-trace [options] tracefile.tc"); CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h/--help \tPrint usage and exit"); CommandLine::option_handle STATS = @@ -67,7 +68,13 @@ int main(int argc, char *argv[]) return 1; } - if (cmd[HELP] || cmd.parser()->nonOptionsCount() != 1) { + if (cmd[HELP] || cmd[UNKNOWN] || cmd.parser()->nonOptionsCount() != 1) { + for (option::Option* opt = cmd[UNKNOWN]; opt; opt = opt->next()) { + std::cerr << "Unknown option: " << opt->name << "\n"; + } + for (int i = 1; i < cmd.parser()->nonOptionsCount(); ++i) { + std::cerr << "Unknown non-option: " << cmd.parser()->nonOption(i) << "\n"; + } cmd.printUsage(); if (cmd[HELP]) { exit(0); diff --git a/tools/import-trace/main.cc b/tools/import-trace/main.cc index 9259b612..d039b870 100644 --- a/tools/import-trace/main.cc +++ b/tools/import-trace/main.cc @@ -85,7 +85,8 @@ int main(int argc, char *argv[]) { for (int i = 1; i < argc; ++i) cmd.add_args(argv[i]); - cmd.addOption("", "", Arg::None, "USAGE: import-trace [options]"); + CommandLine::option_handle UNKNOWN = + cmd.addOption("", "", Arg::None, "USAGE: import-trace [options]"); CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h/--help \tPrint usage and exit"); CommandLine::option_handle TRACE_FILE = @@ -176,9 +177,15 @@ int main(int argc, char *argv[]) { // reparse all arguments. cmd.parse(); - if (cmd[HELP]) { + if (cmd[HELP] || cmd[UNKNOWN] || cmd.parser()->nonOptionsCount() > 0) { + for (option::Option* opt = cmd[UNKNOWN]; opt; opt = opt->next()) { + std::cerr << "Unknown option: " << opt->name << "\n"; + } + for (int i = 0; i < cmd.parser()->nonOptionsCount(); ++i) { + std::cerr << "Unknown non-option: " << cmd.parser()->nonOption(i) << "\n"; + } cmd.printUsage(); - exit(0); + exit(!cmd[HELP]); } if (cmd[TRACE_FILE]) { diff --git a/tools/prune-trace/main.cc b/tools/prune-trace/main.cc index 03a5ac6a..295d5c9f 100644 --- a/tools/prune-trace/main.cc +++ b/tools/prune-trace/main.cc @@ -35,7 +35,8 @@ int main(int argc, char *argv[]) { cmd.add_args(argv[i]); } - cmd.addOption("", "", Arg::None, "USAGE: prune-trace [options]"); + CommandLine::option_handle UNKNOWN = + cmd.addOption("", "", Arg::None, "USAGE: prune-trace [options]"); CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h,--help \tPrint usage and exit"); Database::cmdline_setup(); @@ -92,9 +93,15 @@ int main(int argc, char *argv[]) { // reparse all arguments. cmd.parse(); - if (cmd[HELP]) { + if (cmd[HELP] || cmd[UNKNOWN] || cmd.parser()->nonOptionsCount() > 0) { + for (option::Option* opt = cmd[UNKNOWN]; opt; opt = opt->next()) { + std::cerr << "Unknown option: " << opt->name << "\n"; + } + for (int i = 0; i < cmd.parser()->nonOptionsCount(); ++i) { + std::cerr << "Unknown non-option: " << cmd.parser()->nonOption(i) << "\n"; + } cmd.printUsage(); - exit(0); + exit(!cmd[HELP]); } Database *db = Database::cmdline_connect();