aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-03-24 13:37:32 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-03-24 13:37:32 +0200
commit9c3d872426871024d9b601f65698bf5d30466d20 (patch)
tree9845a7ed78b4eeef10bc408e76f6978b16cdbd2a
parent903eeb2c681f2008602bf48265ec628e4fdc9225 (diff)
Fix bug in '--' handling
-rw-r--r--build2/b-options.cxx43
-rw-r--r--build2/b-options.hxx27
-rw-r--r--build2/b-options.ixx6
-rw-r--r--build2/b.cxx6
-rw-r--r--build2/buildfile6
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.
#