diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2018-03-24 13:37:32 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2018-03-24 13:37:32 +0200 |
commit | 9c3d872426871024d9b601f65698bf5d30466d20 (patch) | |
tree | 9845a7ed78b4eeef10bc408e76f6978b16cdbd2a | |
parent | 903eeb2c681f2008602bf48265ec628e4fdc9225 (diff) |
Fix bug in '--' handling
-rw-r--r-- | build2/b-options.cxx | 43 | ||||
-rw-r--r-- | build2/b-options.hxx | 27 | ||||
-rw-r--r-- | build2/b-options.ixx | 6 | ||||
-rw-r--r-- | build2/b.cxx | 6 | ||||
-rw-r--r-- | 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<std::string> 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 <cassert> + 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 <build2/types-parsers.hxx>" \ ---cli-namespace build2::cl --generate-file-scanner --generate-parse \ ---generate-specifier +--guard-prefix BUILD2 --cxx-prologue "#include <build2/types-parsers.hxx>" \ +--cli-namespace build2::cl --generate-file-scanner --keep-separator \ +--generate-parse --generate-specifier # Usage options. # |