From 9c3d872426871024d9b601f65698bf5d30466d20 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 24 Mar 2018 13:37:32 +0200 Subject: Fix bug in '--' handling --- build2/b-options.cxx | 43 ++++++++++++++++++++++++++----------------- build2/b-options.hxx | 27 ++++++++++++++++++++------- build2/b-options.ixx | 6 ++++++ build2/b.cxx | 6 ++---- build2/buildfile | 6 +++--- 5 files changed, 57 insertions(+), 31 deletions(-) diff --git a/build2/b-options.cxx b/build2/b-options.cxx index 03cbe2c..14ee628 100644 --- a/build2/b-options.cxx +++ b/build2/b-options.cxx @@ -277,9 +277,9 @@ namespace build2 return base::next (); else { - hold_.swap (args_.front ()); + hold_[i_ == 0 ? ++i_ : --i_].swap (args_.front ()); args_.pop_front (); - return hold_.c_str (); + return hold_[i_].c_str (); } } @@ -423,7 +423,7 @@ namespace build2 { using namespace std; - string o (s.next ()); + const char* o (s.next ()); if (s.more ()) { @@ -604,7 +604,7 @@ namespace build2 { } - void options:: + bool options:: parse (int& argc, char** argv, bool erase, @@ -612,10 +612,11 @@ namespace build2 ::build2::cl::unknown_mode arg) { ::build2::cl::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); + bool r = _parse (s, opt, arg); + return r; } - void options:: + bool options:: parse (int start, int& argc, char** argv, @@ -624,10 +625,11 @@ namespace build2 ::build2::cl::unknown_mode arg) { ::build2::cl::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); + bool r = _parse (s, opt, arg); + return r; } - void options:: + bool options:: parse (int& argc, char** argv, int& end, @@ -636,11 +638,12 @@ namespace build2 ::build2::cl::unknown_mode arg) { ::build2::cl::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); + bool r = _parse (s, opt, arg); end = s.end (); + return r; } - void options:: + bool options:: parse (int start, int& argc, char** argv, @@ -650,16 +653,18 @@ namespace build2 ::build2::cl::unknown_mode arg) { ::build2::cl::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); + bool r = _parse (s, opt, arg); end = s.end (); + return r; } - void options:: + bool options:: parse (::build2::cl::scanner& s, ::build2::cl::unknown_mode opt, ::build2::cl::unknown_mode arg) { - _parse (s, opt, arg); + bool r = _parse (s, opt, arg); + return r; } ::build2::cl::usage_para options:: @@ -928,11 +933,12 @@ namespace build2 return false; } - void options:: + bool options:: _parse (::build2::cl::scanner& s, ::build2::cl::unknown_mode opt_mode, ::build2::cl::unknown_mode arg_mode) { + bool r = false; bool opt = true; while (s.more ()) @@ -941,12 +947,11 @@ namespace build2 if (std::strcmp (o, "--") == 0) { - s.skip (); opt = false; - continue; } - if (opt && _parse (o, s)); + if (opt && _parse (o, s)) + r = true; else if (opt && std::strncmp (o, "-", 1) == 0 && o[1] != '\0') { switch (opt_mode) @@ -954,6 +959,7 @@ namespace build2 case ::build2::cl::unknown_mode::skip: { s.skip (); + r = true; continue; } case ::build2::cl::unknown_mode::stop: @@ -975,6 +981,7 @@ namespace build2 case ::build2::cl::unknown_mode::skip: { s.skip (); + r = true; continue; } case ::build2::cl::unknown_mode::stop: @@ -990,6 +997,8 @@ namespace build2 break; } } + + return r; } } diff --git a/build2/b-options.hxx b/build2/b-options.hxx index 12a029c..cab4951 100644 --- a/build2/b-options.hxx +++ b/build2/b-options.hxx @@ -226,6 +226,12 @@ namespace build2 std::string argument_; }; + // Command line argument scanner interface. + // + // The values returned by next() are guaranteed to be valid + // for the two previous arguments up until a call to a third + // peek() or next(). + // class scanner { public: @@ -337,8 +343,13 @@ namespace build2 const option_info* options_; std::size_t options_count_; - std::string hold_; std::deque args_; + + // Circular buffer of two arguments. + // + std::string hold_[2]; + std::size_t i_; + bool skip_; }; @@ -356,14 +367,16 @@ namespace build2 public: options (); - void + // Return true if anything has been parsed. + // + bool parse (int& argc, char** argv, bool erase = false, ::build2::cl::unknown_mode option = ::build2::cl::unknown_mode::fail, ::build2::cl::unknown_mode argument = ::build2::cl::unknown_mode::stop); - void + bool parse (int start, int& argc, char** argv, @@ -371,7 +384,7 @@ namespace build2 ::build2::cl::unknown_mode option = ::build2::cl::unknown_mode::fail, ::build2::cl::unknown_mode argument = ::build2::cl::unknown_mode::stop); - void + bool parse (int& argc, char** argv, int& end, @@ -379,7 +392,7 @@ namespace build2 ::build2::cl::unknown_mode option = ::build2::cl::unknown_mode::fail, ::build2::cl::unknown_mode argument = ::build2::cl::unknown_mode::stop); - void + bool parse (int start, int& argc, char** argv, @@ -388,7 +401,7 @@ namespace build2 ::build2::cl::unknown_mode option = ::build2::cl::unknown_mode::fail, ::build2::cl::unknown_mode argument = ::build2::cl::unknown_mode::stop); - void + bool parse (::build2::cl::scanner&, ::build2::cl::unknown_mode option = ::build2::cl::unknown_mode::fail, ::build2::cl::unknown_mode argument = ::build2::cl::unknown_mode::stop); @@ -504,7 +517,7 @@ namespace build2 _parse (const char*, ::build2::cl::scanner&); private: - void + bool _parse (::build2::cl::scanner&, ::build2::cl::unknown_mode option, ::build2::cl::unknown_mode argument); diff --git a/build2/b-options.ixx b/build2/b-options.ixx index 7a6f33e..33cb18a 100644 --- a/build2/b-options.ixx +++ b/build2/b-options.ixx @@ -9,6 +9,8 @@ // // End prologue. +#include + namespace build2 { namespace cl @@ -160,6 +162,7 @@ namespace build2 option_ (option), options_ (&option_info_), options_count_ (1), + i_ (1), skip_ (false) { option_info_.option = option_.c_str (); @@ -176,6 +179,7 @@ namespace build2 option_ (option), options_ (&option_info_), options_count_ (1), + i_ (1), skip_ (false) { option_info_.option = option_.c_str (); @@ -191,6 +195,7 @@ namespace build2 : argv_scanner (argc, argv, erase), options_ (options), options_count_ (options_count), + i_ (1), skip_ (false) { } @@ -205,6 +210,7 @@ namespace build2 : argv_scanner (start, argc, argv, erase), options_ (options), options_count_ (options_count), + i_ (1), skip_ (false) { } diff --git a/build2/b.cxx b/build2/b.cxx index ad54922..e78eebd 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -218,10 +218,8 @@ main (int argc, char* argv[]) // Parse the next chunk of options until we reach an argument (or // eos). // - ops.parse (scan); - - if (!scan.more ()) - break; + if (ops.parse (scan)) + continue; // Fall through. } diff --git a/build2/buildfile b/build2/buildfile index 9294738..e31008f 100644 --- a/build2/buildfile +++ b/build2/buildfile @@ -41,9 +41,9 @@ if $cli.configured cli.cxx{b-options}: cli{b} cli.options += -I $src_root --include-with-brackets --include-prefix build2 \ ---guard-prefix BUILD2 --cxx-prologue "#include " \ ---cli-namespace build2::cl --generate-file-scanner --generate-parse \ ---generate-specifier +--guard-prefix BUILD2 --cxx-prologue "#include " \ +--cli-namespace build2::cl --generate-file-scanner --keep-separator \ +--generate-parse --generate-specifier # Usage options. # -- cgit v1.1