diff --git a/src/Options.cpp b/src/Options.cpp index c347567..134b1cd 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -44,11 +44,27 @@ void OptionParser::printHelp(bool includeEmail, bool toStdout) { ParseResult OptionParser::parse(int argc, char **argv) const { ParseResult result; - bool scriptConsumed = false; + std::vector operands; + bool endOfOptions = false; for (int i = 1; i < argc; ++i) { std::string arg = argv[i] == nullptr ? "" : argv[i]; + if (endOfOptions) { + operands.push_back(arg); + continue; + } + + if (arg == "--") { + endOfOptions = true; + continue; + } + + if (arg == "-") { + operands.push_back(arg); + continue; + } + // --help and --version are terminal actions: no scripts or files are read. if (arg == "--help") { printHelp(true, true); @@ -63,7 +79,7 @@ ParseResult OptionParser::parse(int argc, char **argv) const { return result; } - if (!scriptConsumed && !arg.empty() && arg[0] == '-') { + if (!arg.empty() && arg[0] == '-') { // Long options either toggle state or add a script source while preserving // the original source order in scriptSpecs. if (arg == "--quiet" || arg == "--silent") { @@ -190,15 +206,21 @@ ParseResult OptionParser::parse(int argc, char **argv) const { continue; } - if (result.options.scripts.empty() && result.options.scriptFiles.empty() && - !scriptConsumed) { - // With no -e/-f, the first non-option argument is the script; the rest are - // input files. - result.options.scripts.push_back(arg); - result.options.scriptSpecs.push_back({false, arg}); - scriptConsumed = true; - } else { - result.options.inputFiles.push_back(arg); + operands.push_back(arg); + } + + if (result.options.scripts.empty() && result.options.scriptFiles.empty() && + !operands.empty()) { + // GNU-style option permutation means later -e/-f options still prevent the + // first operand from becoming an implicit script. Decide only after every + // argv entry has been scanned. + result.options.scripts.push_back(operands.front()); + result.options.scriptSpecs.push_back({false, operands.front()}); + result.options.inputFiles.insert(result.options.inputFiles.end(), + operands.begin() + 1, operands.end()); + } else { + for (const std::string &operand : operands) { + result.options.inputFiles.push_back(operand); } }