aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/test
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-07-22 22:37:40 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-07-24 21:37:58 +0300
commit72945d9c8eee18aed1550c3f42dc41e6a8a0f029 (patch)
tree9fdfe1c3bf48d0e303dc435c40116dacf48286b3 /libbuild2/test
parent83bb02cada0b894d9134cc5489999e0f0fe8bd7c (diff)
Use CLI-generated classes to parse testscript builtin options
Diffstat (limited to 'libbuild2/test')
-rw-r--r--libbuild2/test/script/builtin-options.cxx3759
-rw-r--r--libbuild2/test/script/builtin-options.hxx1025
-rw-r--r--libbuild2/test/script/builtin-options.ixx326
-rw-r--r--libbuild2/test/script/builtin.cli103
-rw-r--r--libbuild2/test/script/builtin.cxx601
-rw-r--r--libbuild2/test/script/runner.cxx57
6 files changed, 5505 insertions, 366 deletions
diff --git a/libbuild2/test/script/builtin-options.cxx b/libbuild2/test/script/builtin-options.cxx
new file mode 100644
index 0000000..95cd051
--- /dev/null
+++ b/libbuild2/test/script/builtin-options.cxx
@@ -0,0 +1,3759 @@
+// -*- C++ -*-
+//
+// This file was generated by CLI, a command line interface
+// compiler for C++.
+//
+
+// Begin prologue.
+//
+//
+// End prologue.
+
+#include <libbuild2/test/script/builtin-options.hxx>
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <ostream>
+#include <sstream>
+
+namespace build2
+{
+ namespace test
+ {
+ namespace script
+ {
+ namespace cli
+ {
+ // unknown_option
+ //
+ unknown_option::
+ ~unknown_option () throw ()
+ {
+ }
+
+ void unknown_option::
+ print (::std::ostream& os) const
+ {
+ os << "unknown option '" << option ().c_str () << "'";
+ }
+
+ const char* unknown_option::
+ what () const throw ()
+ {
+ return "unknown option";
+ }
+
+ // unknown_argument
+ //
+ unknown_argument::
+ ~unknown_argument () throw ()
+ {
+ }
+
+ void unknown_argument::
+ print (::std::ostream& os) const
+ {
+ os << "unknown argument '" << argument ().c_str () << "'";
+ }
+
+ const char* unknown_argument::
+ what () const throw ()
+ {
+ return "unknown argument";
+ }
+
+ // missing_value
+ //
+ missing_value::
+ ~missing_value () throw ()
+ {
+ }
+
+ void missing_value::
+ print (::std::ostream& os) const
+ {
+ os << "missing value for option '" << option ().c_str () << "'";
+ }
+
+ const char* missing_value::
+ what () const throw ()
+ {
+ return "missing option value";
+ }
+
+ // invalid_value
+ //
+ invalid_value::
+ ~invalid_value () throw ()
+ {
+ }
+
+ void invalid_value::
+ print (::std::ostream& os) const
+ {
+ os << "invalid value '" << value ().c_str () << "' for option '"
+ << option ().c_str () << "'";
+
+ if (!message ().empty ())
+ os << ": " << message ().c_str ();
+ }
+
+ const char* invalid_value::
+ what () const throw ()
+ {
+ return "invalid option value";
+ }
+
+ // eos_reached
+ //
+ void eos_reached::
+ print (::std::ostream& os) const
+ {
+ os << what ();
+ }
+
+ const char* eos_reached::
+ what () const throw ()
+ {
+ return "end of argument stream reached";
+ }
+
+ // scanner
+ //
+ scanner::
+ ~scanner ()
+ {
+ }
+
+ // argv_scanner
+ //
+ bool argv_scanner::
+ more ()
+ {
+ return i_ < argc_;
+ }
+
+ const char* argv_scanner::
+ peek ()
+ {
+ if (i_ < argc_)
+ return argv_[i_];
+ else
+ throw eos_reached ();
+ }
+
+ const char* argv_scanner::
+ next ()
+ {
+ if (i_ < argc_)
+ {
+ const char* r (argv_[i_]);
+
+ if (erase_)
+ {
+ for (int i (i_ + 1); i < argc_; ++i)
+ argv_[i - 1] = argv_[i];
+
+ --argc_;
+ argv_[argc_] = 0;
+ }
+ else
+ ++i_;
+
+ return r;
+ }
+ else
+ throw eos_reached ();
+ }
+
+ void argv_scanner::
+ skip ()
+ {
+ if (i_ < argc_)
+ ++i_;
+ else
+ throw eos_reached ();
+ }
+
+ // vector_scanner
+ //
+ bool vector_scanner::
+ more ()
+ {
+ return i_ < v_.size ();
+ }
+
+ const char* vector_scanner::
+ peek ()
+ {
+ if (i_ < v_.size ())
+ return v_[i_].c_str ();
+ else
+ throw eos_reached ();
+ }
+
+ const char* vector_scanner::
+ next ()
+ {
+ if (i_ < v_.size ())
+ return v_[i_++].c_str ();
+ else
+ throw eos_reached ();
+ }
+
+ void vector_scanner::
+ skip ()
+ {
+ if (i_ < v_.size ())
+ ++i_;
+ else
+ throw eos_reached ();
+ }
+
+ template <typename X>
+ struct parser
+ {
+ static void
+ parse (X& x, bool& xs, scanner& s)
+ {
+ using namespace std;
+
+ const char* o (s.next ());
+
+ if (s.more ())
+ {
+ string v (s.next ());
+ istringstream is (v);
+ if (!(is >> x && is.peek () == istringstream::traits_type::eof ()))
+ throw invalid_value (o, v);
+ }
+ else
+ throw missing_value (o);
+
+ xs = true;
+ }
+ };
+
+ template <>
+ struct parser<bool>
+ {
+ static void
+ parse (bool& x, scanner& s)
+ {
+ s.next ();
+ x = true;
+ }
+ };
+
+ template <>
+ struct parser<std::string>
+ {
+ static void
+ parse (std::string& x, bool& xs, scanner& s)
+ {
+ const char* o (s.next ());
+
+ if (s.more ())
+ x = s.next ();
+ else
+ throw missing_value (o);
+
+ xs = true;
+ }
+ };
+
+ template <typename X>
+ struct parser<std::vector<X> >
+ {
+ static void
+ parse (std::vector<X>& c, bool& xs, scanner& s)
+ {
+ X x;
+ bool dummy;
+ parser<X>::parse (x, dummy, s);
+ c.push_back (x);
+ xs = true;
+ }
+ };
+
+ template <typename X>
+ struct parser<std::set<X> >
+ {
+ static void
+ parse (std::set<X>& c, bool& xs, scanner& s)
+ {
+ X x;
+ bool dummy;
+ parser<X>::parse (x, dummy, s);
+ c.insert (x);
+ xs = true;
+ }
+ };
+
+ template <typename K, typename V>
+ struct parser<std::map<K, V> >
+ {
+ static void
+ parse (std::map<K, V>& m, bool& xs, scanner& s)
+ {
+ const char* o (s.next ());
+
+ if (s.more ())
+ {
+ std::string ov (s.next ());
+ std::string::size_type p = ov.find ('=');
+
+ K k = K ();
+ V v = V ();
+ std::string kstr (ov, 0, p);
+ std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ()));
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (o), 0
+ };
+
+ bool dummy;
+ if (!kstr.empty ())
+ {
+ av[1] = const_cast<char*> (kstr.c_str ());
+ argv_scanner s (0, ac, av);
+ parser<K>::parse (k, dummy, s);
+ }
+
+ if (!vstr.empty ())
+ {
+ av[1] = const_cast<char*> (vstr.c_str ());
+ argv_scanner s (0, ac, av);
+ parser<V>::parse (v, dummy, s);
+ }
+
+ m[k] = v;
+ }
+ else
+ throw missing_value (o);
+
+ xs = true;
+ }
+ };
+
+ template <typename X, typename T, T X::*M>
+ void
+ thunk (X& x, scanner& s)
+ {
+ parser<T>::parse (x.*M, s);
+ }
+
+ template <typename X, typename T, T X::*M, bool X::*S>
+ void
+ thunk (X& x, scanner& s)
+ {
+ parser<T>::parse (x.*M, x.*S, s);
+ }
+ }
+ }
+ }
+}
+
+#include <map>
+#include <cstring>
+
+namespace build2
+{
+ namespace test
+ {
+ namespace script
+ {
+ // cleanup_options
+ //
+
+ cleanup_options::
+ cleanup_options ()
+ : no_cleanup_ ()
+ {
+ }
+
+ typedef
+ std::map<std::string, void (*) (cleanup_options&, ::build2::test::script::cli::scanner&)>
+ _cli_cleanup_options_map;
+
+ static _cli_cleanup_options_map _cli_cleanup_options_map_;
+
+ struct _cli_cleanup_options_map_init
+ {
+ _cli_cleanup_options_map_init ()
+ {
+ _cli_cleanup_options_map_["--no-cleanup"] =
+ &::build2::test::script::cli::thunk< cleanup_options, bool, &cleanup_options::no_cleanup_ >;
+ }
+ };
+
+ static _cli_cleanup_options_map_init _cli_cleanup_options_map_init_;
+
+ bool cleanup_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_cleanup_options_map::const_iterator i (_cli_cleanup_options_map_.find (o));
+
+ if (i != _cli_cleanup_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ return false;
+ }
+
+ // cat_options
+ //
+
+ cat_options::
+ cat_options ()
+ {
+ }
+
+ cat_options::
+ cat_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ cat_options::
+ cat_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ cat_options::
+ cat_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ cat_options::
+ cat_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ cat_options::
+ cat_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (cat_options&, ::build2::test::script::cli::scanner&)>
+ _cli_cat_options_map;
+
+ static _cli_cat_options_map _cli_cat_options_map_;
+
+ struct _cli_cat_options_map_init
+ {
+ _cli_cat_options_map_init ()
+ {
+ }
+ };
+
+ static _cli_cat_options_map_init _cli_cat_options_map_init_;
+
+ bool cat_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_cat_options_map::const_iterator i (_cli_cat_options_map_.find (o));
+
+ if (i != _cli_cat_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool cat_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // cp_options
+ //
+
+ cp_options::
+ cp_options ()
+ : recursive_ (),
+ preserve_ ()
+ {
+ }
+
+ cp_options::
+ cp_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : recursive_ (),
+ preserve_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ cp_options::
+ cp_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : recursive_ (),
+ preserve_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ cp_options::
+ cp_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : recursive_ (),
+ preserve_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ cp_options::
+ cp_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : recursive_ (),
+ preserve_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ cp_options::
+ cp_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : recursive_ (),
+ preserve_ ()
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (cp_options&, ::build2::test::script::cli::scanner&)>
+ _cli_cp_options_map;
+
+ static _cli_cp_options_map _cli_cp_options_map_;
+
+ struct _cli_cp_options_map_init
+ {
+ _cli_cp_options_map_init ()
+ {
+ _cli_cp_options_map_["--recursive"] =
+ &::build2::test::script::cli::thunk< cp_options, bool, &cp_options::recursive_ >;
+ _cli_cp_options_map_["-R"] =
+ &::build2::test::script::cli::thunk< cp_options, bool, &cp_options::recursive_ >;
+ _cli_cp_options_map_["-r"] =
+ &::build2::test::script::cli::thunk< cp_options, bool, &cp_options::recursive_ >;
+ _cli_cp_options_map_["--preserve"] =
+ &::build2::test::script::cli::thunk< cp_options, bool, &cp_options::preserve_ >;
+ _cli_cp_options_map_["-p"] =
+ &::build2::test::script::cli::thunk< cp_options, bool, &cp_options::preserve_ >;
+ }
+ };
+
+ static _cli_cp_options_map_init _cli_cp_options_map_init_;
+
+ bool cp_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_cp_options_map::const_iterator i (_cli_cp_options_map_.find (o));
+
+ if (i != _cli_cp_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ // cleanup_options base
+ //
+ if (::build2::test::script::cleanup_options::_parse (o, s))
+ return true;
+
+ return false;
+ }
+
+ bool cp_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // ln_options
+ //
+
+ ln_options::
+ ln_options ()
+ : symbolic_ ()
+ {
+ }
+
+ ln_options::
+ ln_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : symbolic_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ ln_options::
+ ln_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : symbolic_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ ln_options::
+ ln_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : symbolic_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ ln_options::
+ ln_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : symbolic_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ ln_options::
+ ln_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : symbolic_ ()
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (ln_options&, ::build2::test::script::cli::scanner&)>
+ _cli_ln_options_map;
+
+ static _cli_ln_options_map _cli_ln_options_map_;
+
+ struct _cli_ln_options_map_init
+ {
+ _cli_ln_options_map_init ()
+ {
+ _cli_ln_options_map_["--symbolic"] =
+ &::build2::test::script::cli::thunk< ln_options, bool, &ln_options::symbolic_ >;
+ _cli_ln_options_map_["-s"] =
+ &::build2::test::script::cli::thunk< ln_options, bool, &ln_options::symbolic_ >;
+ }
+ };
+
+ static _cli_ln_options_map_init _cli_ln_options_map_init_;
+
+ bool ln_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_ln_options_map::const_iterator i (_cli_ln_options_map_.find (o));
+
+ if (i != _cli_ln_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ // cleanup_options base
+ //
+ if (::build2::test::script::cleanup_options::_parse (o, s))
+ return true;
+
+ return false;
+ }
+
+ bool ln_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // mkdir_options
+ //
+
+ mkdir_options::
+ mkdir_options ()
+ : parents_ ()
+ {
+ }
+
+ mkdir_options::
+ mkdir_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : parents_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ mkdir_options::
+ mkdir_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : parents_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ mkdir_options::
+ mkdir_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : parents_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ mkdir_options::
+ mkdir_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : parents_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ mkdir_options::
+ mkdir_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : parents_ ()
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (mkdir_options&, ::build2::test::script::cli::scanner&)>
+ _cli_mkdir_options_map;
+
+ static _cli_mkdir_options_map _cli_mkdir_options_map_;
+
+ struct _cli_mkdir_options_map_init
+ {
+ _cli_mkdir_options_map_init ()
+ {
+ _cli_mkdir_options_map_["--parents"] =
+ &::build2::test::script::cli::thunk< mkdir_options, bool, &mkdir_options::parents_ >;
+ _cli_mkdir_options_map_["-p"] =
+ &::build2::test::script::cli::thunk< mkdir_options, bool, &mkdir_options::parents_ >;
+ }
+ };
+
+ static _cli_mkdir_options_map_init _cli_mkdir_options_map_init_;
+
+ bool mkdir_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_mkdir_options_map::const_iterator i (_cli_mkdir_options_map_.find (o));
+
+ if (i != _cli_mkdir_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ // cleanup_options base
+ //
+ if (::build2::test::script::cleanup_options::_parse (o, s))
+ return true;
+
+ return false;
+ }
+
+ bool mkdir_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // mv_options
+ //
+
+ mv_options::
+ mv_options ()
+ : force_ ()
+ {
+ }
+
+ mv_options::
+ mv_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ mv_options::
+ mv_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ mv_options::
+ mv_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ mv_options::
+ mv_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ mv_options::
+ mv_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : force_ ()
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (mv_options&, ::build2::test::script::cli::scanner&)>
+ _cli_mv_options_map;
+
+ static _cli_mv_options_map _cli_mv_options_map_;
+
+ struct _cli_mv_options_map_init
+ {
+ _cli_mv_options_map_init ()
+ {
+ _cli_mv_options_map_["--force"] =
+ &::build2::test::script::cli::thunk< mv_options, bool, &mv_options::force_ >;
+ _cli_mv_options_map_["-f"] =
+ &::build2::test::script::cli::thunk< mv_options, bool, &mv_options::force_ >;
+ }
+ };
+
+ static _cli_mv_options_map_init _cli_mv_options_map_init_;
+
+ bool mv_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_mv_options_map::const_iterator i (_cli_mv_options_map_.find (o));
+
+ if (i != _cli_mv_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ // cleanup_options base
+ //
+ if (::build2::test::script::cleanup_options::_parse (o, s))
+ return true;
+
+ return false;
+ }
+
+ bool mv_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // rm_options
+ //
+
+ rm_options::
+ rm_options ()
+ : recursive_ (),
+ force_ ()
+ {
+ }
+
+ rm_options::
+ rm_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : recursive_ (),
+ force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ rm_options::
+ rm_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : recursive_ (),
+ force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ rm_options::
+ rm_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : recursive_ (),
+ force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ rm_options::
+ rm_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : recursive_ (),
+ force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ rm_options::
+ rm_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : recursive_ (),
+ force_ ()
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (rm_options&, ::build2::test::script::cli::scanner&)>
+ _cli_rm_options_map;
+
+ static _cli_rm_options_map _cli_rm_options_map_;
+
+ struct _cli_rm_options_map_init
+ {
+ _cli_rm_options_map_init ()
+ {
+ _cli_rm_options_map_["--recursive"] =
+ &::build2::test::script::cli::thunk< rm_options, bool, &rm_options::recursive_ >;
+ _cli_rm_options_map_["-r"] =
+ &::build2::test::script::cli::thunk< rm_options, bool, &rm_options::recursive_ >;
+ _cli_rm_options_map_["--force"] =
+ &::build2::test::script::cli::thunk< rm_options, bool, &rm_options::force_ >;
+ _cli_rm_options_map_["-f"] =
+ &::build2::test::script::cli::thunk< rm_options, bool, &rm_options::force_ >;
+ }
+ };
+
+ static _cli_rm_options_map_init _cli_rm_options_map_init_;
+
+ bool rm_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_rm_options_map::const_iterator i (_cli_rm_options_map_.find (o));
+
+ if (i != _cli_rm_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool rm_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // rmdir_options
+ //
+
+ rmdir_options::
+ rmdir_options ()
+ : force_ ()
+ {
+ }
+
+ rmdir_options::
+ rmdir_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ rmdir_options::
+ rmdir_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ rmdir_options::
+ rmdir_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ rmdir_options::
+ rmdir_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : force_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ rmdir_options::
+ rmdir_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : force_ ()
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (rmdir_options&, ::build2::test::script::cli::scanner&)>
+ _cli_rmdir_options_map;
+
+ static _cli_rmdir_options_map _cli_rmdir_options_map_;
+
+ struct _cli_rmdir_options_map_init
+ {
+ _cli_rmdir_options_map_init ()
+ {
+ _cli_rmdir_options_map_["--force"] =
+ &::build2::test::script::cli::thunk< rmdir_options, bool, &rmdir_options::force_ >;
+ _cli_rmdir_options_map_["-f"] =
+ &::build2::test::script::cli::thunk< rmdir_options, bool, &rmdir_options::force_ >;
+ }
+ };
+
+ static _cli_rmdir_options_map_init _cli_rmdir_options_map_init_;
+
+ bool rmdir_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_rmdir_options_map::const_iterator i (_cli_rmdir_options_map_.find (o));
+
+ if (i != _cli_rmdir_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool rmdir_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // sed_options
+ //
+
+ sed_options::
+ sed_options ()
+ : quiet_ (),
+ in_place_ (),
+ expression_ (),
+ expression_specified_ (false)
+ {
+ }
+
+ sed_options::
+ sed_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : quiet_ (),
+ in_place_ (),
+ expression_ (),
+ expression_specified_ (false)
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ sed_options::
+ sed_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : quiet_ (),
+ in_place_ (),
+ expression_ (),
+ expression_specified_ (false)
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ sed_options::
+ sed_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : quiet_ (),
+ in_place_ (),
+ expression_ (),
+ expression_specified_ (false)
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ sed_options::
+ sed_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : quiet_ (),
+ in_place_ (),
+ expression_ (),
+ expression_specified_ (false)
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ sed_options::
+ sed_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : quiet_ (),
+ in_place_ (),
+ expression_ (),
+ expression_specified_ (false)
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (sed_options&, ::build2::test::script::cli::scanner&)>
+ _cli_sed_options_map;
+
+ static _cli_sed_options_map _cli_sed_options_map_;
+
+ struct _cli_sed_options_map_init
+ {
+ _cli_sed_options_map_init ()
+ {
+ _cli_sed_options_map_["--quiet"] =
+ &::build2::test::script::cli::thunk< sed_options, bool, &sed_options::quiet_ >;
+ _cli_sed_options_map_["-n"] =
+ &::build2::test::script::cli::thunk< sed_options, bool, &sed_options::quiet_ >;
+ _cli_sed_options_map_["--in-place"] =
+ &::build2::test::script::cli::thunk< sed_options, bool, &sed_options::in_place_ >;
+ _cli_sed_options_map_["-i"] =
+ &::build2::test::script::cli::thunk< sed_options, bool, &sed_options::in_place_ >;
+ _cli_sed_options_map_["--expression"] =
+ &::build2::test::script::cli::thunk< sed_options, strings, &sed_options::expression_,
+ &sed_options::expression_specified_ >;
+ _cli_sed_options_map_["-e"] =
+ &::build2::test::script::cli::thunk< sed_options, strings, &sed_options::expression_,
+ &sed_options::expression_specified_ >;
+ }
+ };
+
+ static _cli_sed_options_map_init _cli_sed_options_map_init_;
+
+ bool sed_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_sed_options_map::const_iterator i (_cli_sed_options_map_.find (o));
+
+ if (i != _cli_sed_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool sed_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // set_options
+ //
+
+ set_options::
+ set_options ()
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ }
+
+ set_options::
+ set_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ set_options::
+ set_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ set_options::
+ set_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ set_options::
+ set_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ set_options::
+ set_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (set_options&, ::build2::test::script::cli::scanner&)>
+ _cli_set_options_map;
+
+ static _cli_set_options_map _cli_set_options_map_;
+
+ struct _cli_set_options_map_init
+ {
+ _cli_set_options_map_init ()
+ {
+ _cli_set_options_map_["--exact"] =
+ &::build2::test::script::cli::thunk< set_options, bool, &set_options::exact_ >;
+ _cli_set_options_map_["-e"] =
+ &::build2::test::script::cli::thunk< set_options, bool, &set_options::exact_ >;
+ _cli_set_options_map_["--newline"] =
+ &::build2::test::script::cli::thunk< set_options, bool, &set_options::newline_ >;
+ _cli_set_options_map_["-n"] =
+ &::build2::test::script::cli::thunk< set_options, bool, &set_options::newline_ >;
+ _cli_set_options_map_["--whitespace"] =
+ &::build2::test::script::cli::thunk< set_options, bool, &set_options::whitespace_ >;
+ _cli_set_options_map_["-w"] =
+ &::build2::test::script::cli::thunk< set_options, bool, &set_options::whitespace_ >;
+ }
+ };
+
+ static _cli_set_options_map_init _cli_set_options_map_init_;
+
+ bool set_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_set_options_map::const_iterator i (_cli_set_options_map_.find (o));
+
+ if (i != _cli_set_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool set_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // sleep_options
+ //
+
+ sleep_options::
+ sleep_options ()
+ {
+ }
+
+ sleep_options::
+ sleep_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ sleep_options::
+ sleep_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ sleep_options::
+ sleep_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ sleep_options::
+ sleep_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ sleep_options::
+ sleep_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (sleep_options&, ::build2::test::script::cli::scanner&)>
+ _cli_sleep_options_map;
+
+ static _cli_sleep_options_map _cli_sleep_options_map_;
+
+ struct _cli_sleep_options_map_init
+ {
+ _cli_sleep_options_map_init ()
+ {
+ }
+ };
+
+ static _cli_sleep_options_map_init _cli_sleep_options_map_init_;
+
+ bool sleep_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_sleep_options_map::const_iterator i (_cli_sleep_options_map_.find (o));
+
+ if (i != _cli_sleep_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool sleep_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // test_options
+ //
+
+ test_options::
+ test_options ()
+ : file_ (),
+ directory_ ()
+ {
+ }
+
+ test_options::
+ test_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : file_ (),
+ directory_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ test_options::
+ test_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : file_ (),
+ directory_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ test_options::
+ test_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : file_ (),
+ directory_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ test_options::
+ test_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : file_ (),
+ directory_ ()
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ test_options::
+ test_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : file_ (),
+ directory_ ()
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (test_options&, ::build2::test::script::cli::scanner&)>
+ _cli_test_options_map;
+
+ static _cli_test_options_map _cli_test_options_map_;
+
+ struct _cli_test_options_map_init
+ {
+ _cli_test_options_map_init ()
+ {
+ _cli_test_options_map_["--file"] =
+ &::build2::test::script::cli::thunk< test_options, bool, &test_options::file_ >;
+ _cli_test_options_map_["-f"] =
+ &::build2::test::script::cli::thunk< test_options, bool, &test_options::file_ >;
+ _cli_test_options_map_["--directory"] =
+ &::build2::test::script::cli::thunk< test_options, bool, &test_options::directory_ >;
+ _cli_test_options_map_["-d"] =
+ &::build2::test::script::cli::thunk< test_options, bool, &test_options::directory_ >;
+ }
+ };
+
+ static _cli_test_options_map_init _cli_test_options_map_init_;
+
+ bool test_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_test_options_map::const_iterator i (_cli_test_options_map_.find (o));
+
+ if (i != _cli_test_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool test_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+
+ // touch_options
+ //
+
+ touch_options::
+ touch_options ()
+ : after_ (),
+ after_specified_ (false)
+ {
+ }
+
+ touch_options::
+ touch_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : after_ (),
+ after_specified_ (false)
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ touch_options::
+ touch_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : after_ (),
+ after_specified_ (false)
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ touch_options::
+ touch_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : after_ (),
+ after_specified_ (false)
+ {
+ ::build2::test::script::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ touch_options::
+ touch_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : after_ (),
+ after_specified_ (false)
+ {
+ ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ touch_options::
+ touch_options (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt,
+ ::build2::test::script::cli::unknown_mode arg)
+ : after_ (),
+ after_specified_ (false)
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (touch_options&, ::build2::test::script::cli::scanner&)>
+ _cli_touch_options_map;
+
+ static _cli_touch_options_map _cli_touch_options_map_;
+
+ struct _cli_touch_options_map_init
+ {
+ _cli_touch_options_map_init ()
+ {
+ _cli_touch_options_map_["--after"] =
+ &::build2::test::script::cli::thunk< touch_options, string, &touch_options::after_,
+ &touch_options::after_specified_ >;
+ }
+ };
+
+ static _cli_touch_options_map_init _cli_touch_options_map_init_;
+
+ bool touch_options::
+ _parse (const char* o, ::build2::test::script::cli::scanner& s)
+ {
+ _cli_touch_options_map::const_iterator i (_cli_touch_options_map_.find (o));
+
+ if (i != _cli_touch_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ // cleanup_options base
+ //
+ if (::build2::test::script::cleanup_options::_parse (o, s))
+ return true;
+
+ return false;
+ }
+
+ bool touch_options::
+ _parse (::build2::test::script::cli::scanner& s,
+ ::build2::test::script::cli::unknown_mode opt_mode,
+ ::build2::test::script::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::build2::test::script::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ // Handle combined flags.
+ //
+ char cf[3];
+ {
+ const char* p = o + 1;
+ for (; *p != '\0'; ++p)
+ {
+ if (!((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9')))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ for (p = o + 1; *p != '\0'; ++p)
+ {
+ std::strcpy (cf, "-");
+ cf[1] = *p;
+ cf[2] = '\0';
+
+ int ac (1);
+ char* av[] =
+ {
+ cf
+ };
+
+ ::build2::test::script::cli::argv_scanner ns (0, ac, av);
+
+ if (!_parse (cf, ns))
+ break;
+ }
+
+ if (*p == '\0')
+ {
+ // All handled.
+ //
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = cf;
+ }
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::test::script::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::test::script::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::test::script::cli::unknown_mode::fail:
+ {
+ throw ::build2::test::script::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+ }
+ }
+}
+
+// Begin epilogue.
+//
+//
+// End epilogue.
+
diff --git a/libbuild2/test/script/builtin-options.hxx b/libbuild2/test/script/builtin-options.hxx
new file mode 100644
index 0000000..7ff0bac
--- /dev/null
+++ b/libbuild2/test/script/builtin-options.hxx
@@ -0,0 +1,1025 @@
+// -*- C++ -*-
+//
+// This file was generated by CLI, a command line interface
+// compiler for C++.
+//
+
+#ifndef LIBBUILD2_TEST_SCRIPT_BUILTIN_OPTIONS_HXX
+#define LIBBUILD2_TEST_SCRIPT_BUILTIN_OPTIONS_HXX
+
+// Begin prologue.
+//
+//
+// End prologue.
+
+#include <vector>
+#include <iosfwd>
+#include <string>
+#include <cstddef>
+#include <exception>
+
+#ifndef CLI_POTENTIALLY_UNUSED
+# if defined(_MSC_VER) || defined(__xlC__)
+# define CLI_POTENTIALLY_UNUSED(x) (void*)&x
+# else
+# define CLI_POTENTIALLY_UNUSED(x) (void)x
+# endif
+#endif
+
+namespace build2
+{
+ namespace test
+ {
+ namespace script
+ {
+ namespace cli
+ {
+ class unknown_mode
+ {
+ public:
+ enum value
+ {
+ skip,
+ stop,
+ fail
+ };
+
+ unknown_mode (value);
+
+ operator value () const
+ {
+ return v_;
+ }
+
+ private:
+ value v_;
+ };
+
+ // Exceptions.
+ //
+
+ class exception: public std::exception
+ {
+ public:
+ virtual void
+ print (::std::ostream&) const = 0;
+ };
+
+ ::std::ostream&
+ operator<< (::std::ostream&, const exception&);
+
+ class unknown_option: public exception
+ {
+ public:
+ virtual
+ ~unknown_option () throw ();
+
+ unknown_option (const std::string& option);
+
+ const std::string&
+ option () const;
+
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+
+ private:
+ std::string option_;
+ };
+
+ class unknown_argument: public exception
+ {
+ public:
+ virtual
+ ~unknown_argument () throw ();
+
+ unknown_argument (const std::string& argument);
+
+ const std::string&
+ argument () const;
+
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+
+ private:
+ std::string argument_;
+ };
+
+ class missing_value: public exception
+ {
+ public:
+ virtual
+ ~missing_value () throw ();
+
+ missing_value (const std::string& option);
+
+ const std::string&
+ option () const;
+
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+
+ private:
+ std::string option_;
+ };
+
+ class invalid_value: public exception
+ {
+ public:
+ virtual
+ ~invalid_value () throw ();
+
+ invalid_value (const std::string& option,
+ const std::string& value,
+ const std::string& message = std::string ());
+
+ const std::string&
+ option () const;
+
+ const std::string&
+ value () const;
+
+ const std::string&
+ message () const;
+
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+
+ private:
+ std::string option_;
+ std::string value_;
+ std::string message_;
+ };
+
+ class eos_reached: public exception
+ {
+ public:
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+ };
+
+ // 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:
+ virtual
+ ~scanner ();
+
+ virtual bool
+ more () = 0;
+
+ virtual const char*
+ peek () = 0;
+
+ virtual const char*
+ next () = 0;
+
+ virtual void
+ skip () = 0;
+ };
+
+ class argv_scanner: public scanner
+ {
+ public:
+ argv_scanner (int& argc, char** argv, bool erase = false);
+ argv_scanner (int start, int& argc, char** argv, bool erase = false);
+
+ int
+ end () const;
+
+ virtual bool
+ more ();
+
+ virtual const char*
+ peek ();
+
+ virtual const char*
+ next ();
+
+ virtual void
+ skip ();
+
+ private:
+ int i_;
+ int& argc_;
+ char** argv_;
+ bool erase_;
+ };
+
+ class vector_scanner: public scanner
+ {
+ public:
+ vector_scanner (const std::vector<std::string>&, std::size_t start = 0);
+
+ std::size_t
+ end () const;
+
+ void
+ reset (std::size_t start = 0);
+
+ virtual bool
+ more ();
+
+ virtual const char*
+ peek ();
+
+ virtual const char*
+ next ();
+
+ virtual void
+ skip ();
+
+ private:
+ const std::vector<std::string>& v_;
+ std::size_t i_;
+ };
+
+ template <typename X>
+ struct parser;
+ }
+ }
+ }
+}
+
+#include <libbuild2/types.hxx>
+
+namespace build2
+{
+ namespace test
+ {
+ namespace script
+ {
+ class cleanup_options
+ {
+ public:
+ // Option accessors.
+ //
+ const bool&
+ no_cleanup () const;
+
+ // Implementation details.
+ //
+ protected:
+ cleanup_options ();
+
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ public:
+ bool no_cleanup_;
+ };
+
+ class cat_options
+ {
+ public:
+ cat_options ();
+
+ cat_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ cat_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ cat_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ cat_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ cat_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ };
+
+ class cp_options: public ::build2::test::script::cleanup_options
+ {
+ public:
+ cp_options ();
+
+ cp_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ cp_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ cp_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ cp_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ cp_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const bool&
+ recursive () const;
+
+ const bool&
+ preserve () const;
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ bool recursive_;
+ bool preserve_;
+ };
+
+ class ln_options: public ::build2::test::script::cleanup_options
+ {
+ public:
+ ln_options ();
+
+ ln_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ ln_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ ln_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ ln_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ ln_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const bool&
+ symbolic () const;
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ bool symbolic_;
+ };
+
+ class mkdir_options: public ::build2::test::script::cleanup_options
+ {
+ public:
+ mkdir_options ();
+
+ mkdir_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ mkdir_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ mkdir_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ mkdir_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ mkdir_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const bool&
+ parents () const;
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ bool parents_;
+ };
+
+ class mv_options: public ::build2::test::script::cleanup_options
+ {
+ public:
+ mv_options ();
+
+ mv_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ mv_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ mv_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ mv_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ mv_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const bool&
+ force () const;
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ bool force_;
+ };
+
+ class rm_options
+ {
+ public:
+ rm_options ();
+
+ rm_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ rm_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ rm_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ rm_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ rm_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const bool&
+ recursive () const;
+
+ const bool&
+ force () const;
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ bool recursive_;
+ bool force_;
+ };
+
+ class rmdir_options
+ {
+ public:
+ rmdir_options ();
+
+ rmdir_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ rmdir_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ rmdir_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ rmdir_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ rmdir_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const bool&
+ force () const;
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ bool force_;
+ };
+
+ class sed_options
+ {
+ public:
+ sed_options ();
+
+ sed_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ sed_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ sed_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ sed_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ sed_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const bool&
+ quiet () const;
+
+ const bool&
+ in_place () const;
+
+ const strings&
+ expression () const;
+
+ bool
+ expression_specified () const;
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ bool quiet_;
+ bool in_place_;
+ strings expression_;
+ bool expression_specified_;
+ };
+
+ class set_options
+ {
+ public:
+ set_options ();
+
+ set_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ set_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ set_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ set_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ set_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const bool&
+ exact () const;
+
+ const bool&
+ newline () const;
+
+ const bool&
+ whitespace () const;
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ bool exact_;
+ bool newline_;
+ bool whitespace_;
+ };
+
+ class sleep_options
+ {
+ public:
+ sleep_options ();
+
+ sleep_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ sleep_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ sleep_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ sleep_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ sleep_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ };
+
+ class test_options
+ {
+ public:
+ test_options ();
+
+ test_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ test_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ test_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ test_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ test_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const bool&
+ file () const;
+
+ const bool&
+ directory () const;
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ bool file_;
+ bool directory_;
+ };
+
+ class touch_options: public ::build2::test::script::cleanup_options
+ {
+ public:
+ touch_options ();
+
+ touch_options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ touch_options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ touch_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ touch_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ touch_options (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail,
+ ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const string&
+ after () const;
+
+ bool
+ after_specified () const;
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::build2::test::script::cli::scanner&);
+
+ private:
+ bool
+ _parse (::build2::test::script::cli::scanner&,
+ ::build2::test::script::cli::unknown_mode option,
+ ::build2::test::script::cli::unknown_mode argument);
+
+ public:
+ string after_;
+ bool after_specified_;
+ };
+ }
+ }
+}
+
+#include <libbuild2/test/script/builtin-options.ixx>
+
+// Begin epilogue.
+//
+//
+// End epilogue.
+
+#endif // LIBBUILD2_TEST_SCRIPT_BUILTIN_OPTIONS_HXX
diff --git a/libbuild2/test/script/builtin-options.ixx b/libbuild2/test/script/builtin-options.ixx
new file mode 100644
index 0000000..55fd6d2
--- /dev/null
+++ b/libbuild2/test/script/builtin-options.ixx
@@ -0,0 +1,326 @@
+// -*- C++ -*-
+//
+// This file was generated by CLI, a command line interface
+// compiler for C++.
+//
+
+// Begin prologue.
+//
+//
+// End prologue.
+
+#include <cassert>
+
+namespace build2
+{
+ namespace test
+ {
+ namespace script
+ {
+ namespace cli
+ {
+ // unknown_mode
+ //
+ inline unknown_mode::
+ unknown_mode (value v)
+ : v_ (v)
+ {
+ }
+
+ // exception
+ //
+ inline ::std::ostream&
+ operator<< (::std::ostream& os, const exception& e)
+ {
+ e.print (os);
+ return os;
+ }
+
+ // unknown_option
+ //
+ inline unknown_option::
+ unknown_option (const std::string& option)
+ : option_ (option)
+ {
+ }
+
+ inline const std::string& unknown_option::
+ option () const
+ {
+ return option_;
+ }
+
+ // unknown_argument
+ //
+ inline unknown_argument::
+ unknown_argument (const std::string& argument)
+ : argument_ (argument)
+ {
+ }
+
+ inline const std::string& unknown_argument::
+ argument () const
+ {
+ return argument_;
+ }
+
+ // missing_value
+ //
+ inline missing_value::
+ missing_value (const std::string& option)
+ : option_ (option)
+ {
+ }
+
+ inline const std::string& missing_value::
+ option () const
+ {
+ return option_;
+ }
+
+ // invalid_value
+ //
+ inline invalid_value::
+ invalid_value (const std::string& option,
+ const std::string& value,
+ const std::string& message)
+ : option_ (option),
+ value_ (value),
+ message_ (message)
+ {
+ }
+
+ inline const std::string& invalid_value::
+ option () const
+ {
+ return option_;
+ }
+
+ inline const std::string& invalid_value::
+ value () const
+ {
+ return value_;
+ }
+
+ inline const std::string& invalid_value::
+ message () const
+ {
+ return message_;
+ }
+
+ // argv_scanner
+ //
+ inline argv_scanner::
+ argv_scanner (int& argc, char** argv, bool erase)
+ : i_ (1), argc_ (argc), argv_ (argv), erase_ (erase)
+ {
+ }
+
+ inline argv_scanner::
+ argv_scanner (int start, int& argc, char** argv, bool erase)
+ : i_ (start), argc_ (argc), argv_ (argv), erase_ (erase)
+ {
+ }
+
+ inline int argv_scanner::
+ end () const
+ {
+ return i_;
+ }
+
+ // vector_scanner
+ //
+ inline vector_scanner::
+ vector_scanner (const std::vector<std::string>& v, std::size_t i)
+ : v_ (v), i_ (i)
+ {
+ }
+
+ inline std::size_t vector_scanner::
+ end () const
+ {
+ return i_;
+ }
+
+ inline void vector_scanner::
+ reset (std::size_t i)
+ {
+ i_ = i;
+ }
+ }
+ }
+ }
+}
+
+namespace build2
+{
+ namespace test
+ {
+ namespace script
+ {
+ // cleanup_options
+ //
+
+ inline const bool& cleanup_options::
+ no_cleanup () const
+ {
+ return this->no_cleanup_;
+ }
+
+ // cat_options
+ //
+
+ // cp_options
+ //
+
+ inline const bool& cp_options::
+ recursive () const
+ {
+ return this->recursive_;
+ }
+
+ inline const bool& cp_options::
+ preserve () const
+ {
+ return this->preserve_;
+ }
+
+ // ln_options
+ //
+
+ inline const bool& ln_options::
+ symbolic () const
+ {
+ return this->symbolic_;
+ }
+
+ // mkdir_options
+ //
+
+ inline const bool& mkdir_options::
+ parents () const
+ {
+ return this->parents_;
+ }
+
+ // mv_options
+ //
+
+ inline const bool& mv_options::
+ force () const
+ {
+ return this->force_;
+ }
+
+ // rm_options
+ //
+
+ inline const bool& rm_options::
+ recursive () const
+ {
+ return this->recursive_;
+ }
+
+ inline const bool& rm_options::
+ force () const
+ {
+ return this->force_;
+ }
+
+ // rmdir_options
+ //
+
+ inline const bool& rmdir_options::
+ force () const
+ {
+ return this->force_;
+ }
+
+ // sed_options
+ //
+
+ inline const bool& sed_options::
+ quiet () const
+ {
+ return this->quiet_;
+ }
+
+ inline const bool& sed_options::
+ in_place () const
+ {
+ return this->in_place_;
+ }
+
+ inline const strings& sed_options::
+ expression () const
+ {
+ return this->expression_;
+ }
+
+ inline bool sed_options::
+ expression_specified () const
+ {
+ return this->expression_specified_;
+ }
+
+ // set_options
+ //
+
+ inline const bool& set_options::
+ exact () const
+ {
+ return this->exact_;
+ }
+
+ inline const bool& set_options::
+ newline () const
+ {
+ return this->newline_;
+ }
+
+ inline const bool& set_options::
+ whitespace () const
+ {
+ return this->whitespace_;
+ }
+
+ // sleep_options
+ //
+
+ // test_options
+ //
+
+ inline const bool& test_options::
+ file () const
+ {
+ return this->file_;
+ }
+
+ inline const bool& test_options::
+ directory () const
+ {
+ return this->directory_;
+ }
+
+ // touch_options
+ //
+
+ inline const string& touch_options::
+ after () const
+ {
+ return this->after_;
+ }
+
+ inline bool touch_options::
+ after_specified () const
+ {
+ return this->after_specified_;
+ }
+ }
+ }
+}
+
+// Begin epilogue.
+//
+//
+// End epilogue.
diff --git a/libbuild2/test/script/builtin.cli b/libbuild2/test/script/builtin.cli
new file mode 100644
index 0000000..8b8de73
--- /dev/null
+++ b/libbuild2/test/script/builtin.cli
@@ -0,0 +1,103 @@
+// file : libbuild2/test/script/builtin.cli
+// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+include <libbuild2/types.hxx>;
+
+// Note that options in this file are undocumented because we generate neither
+// the usage printing code nor man pages. Instead, they are documented in the
+// Testscript Language Manual's builtin descriptions.
+//
+// Also note that the string type is used for the path options because their
+// parsing depends on the testscript scope working directory (see parse_path()
+// for details) and passing this information to the CLI custom parser would
+// not be easy.
+//
+namespace build2
+{
+ namespace test
+ {
+ namespace script
+ {
+ // Common option base classes.
+ //
+
+ class cleanup_options = 0
+ {
+ bool --no-cleanup;
+ };
+
+ // Builtin options.
+ //
+
+ class cat_options
+ {
+ // No options so far.
+ //
+ };
+
+ class cp_options: cleanup_options
+ {
+ bool --recursive|-R|-r;
+ bool --preserve|-p;
+ };
+
+ class ln_options: cleanup_options
+ {
+ bool --symbolic|-s;
+ };
+
+ class mkdir_options: cleanup_options
+ {
+ bool --parents|-p;
+ };
+
+ class mv_options: cleanup_options
+ {
+ bool --force|-f;
+ };
+
+ class rm_options
+ {
+ bool --recursive|-r;
+ bool --force|-f;
+ };
+
+ class rmdir_options
+ {
+ bool --force|-f;
+ };
+
+ class sed_options
+ {
+ bool --quiet|-n;
+ bool --in-place|-i;
+ strings --expression|-e;
+ };
+
+ class set_options
+ {
+ bool --exact|-e;
+ bool --newline|-n;
+ bool --whitespace|-w;
+ };
+
+ class sleep_options
+ {
+ // No options so far.
+ //
+ };
+
+ class test_options
+ {
+ bool --file|-f;
+ bool --directory|-d;
+ };
+
+ class touch_options: cleanup_options
+ {
+ string --after; // Path (see above).
+ };
+ }
+ }
+}
diff --git a/libbuild2/test/script/builtin.cxx b/libbuild2/test/script/builtin.cxx
index ab57d4f..e572411 100644
--- a/libbuild2/test/script/builtin.cxx
+++ b/libbuild2/test/script/builtin.cxx
@@ -18,6 +18,7 @@
#include <libbuild2/context.hxx> // sched
#include <libbuild2/test/script/script.hxx>
+#include <libbuild2/test/script/builtin-options.hxx>
// Strictly speaking a builtin which reads/writes from/to standard streams
// must be asynchronous so that the caller can communicate with it through
@@ -169,6 +170,13 @@ namespace build2
ifdstream cin (move (in), fdstream_mode::binary);
ofdstream cout (move (out), fdstream_mode::binary);
+ // Parse arguments.
+ //
+ cli::vector_scanner scan (args);
+ cat_options ops (scan); // Makes sure no options passed.
+
+ // Print files.
+ //
// Copy input stream to STDOUT.
//
auto copy = [&cout] (istream& is)
@@ -188,14 +196,16 @@ namespace build2
{
// Print STDIN.
//
- if (args.empty ())
+ if (!scan.more ())
copy (cin);
// Print files.
//
- for (auto i (args.begin ()); i != args.end (); ++i)
+ while (scan.more ())
{
- if (*i == "-")
+ string f (scan.next ());
+
+ if (f == "-")
{
if (!cin.eof ())
{
@@ -206,7 +216,7 @@ namespace build2
continue;
}
- p = parse_path (*i, sp.wd_path);
+ p = parse_path (move (f), sp.wd_path);
ifdstream is (p, ifdstream::binary);
copy (is);
@@ -244,6 +254,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
@@ -281,7 +295,7 @@ namespace build2
cpfile (from, to, f);
if (!exists && cleanup)
- sp.clean ({cleanup_type::always, to}, true);
+ sp.clean ({cleanup_type::always, to}, true /* implicit */);
}
catch (const system_error& e)
{
@@ -308,7 +322,7 @@ namespace build2
throw_generic_error (EEXIST);
if (cleanup)
- sp.clean ({cleanup_type::always, to}, true);
+ sp.clean ({cleanup_type::always, to}, true /* implicit */);
for (const auto& de: dir_iterator (from,
false /* ignore_dangling */))
@@ -343,10 +357,10 @@ namespace build2
}
}
- // cp [-p] [--no-cleanup] <src-file> <dst-file>
- // cp [-p] [--no-cleanup] -R|-r <src-dir> <dst-dir>
- // cp [-p] [--no-cleanup] <src-file>... <dst-dir>/
- // cp [-p] [--no-cleanup] -R|-r <src-path>... <dst-dir>/
+ // cp [-p|--preserve] [--no-cleanup] <src-file> <dst-file>
+ // cp [-p|--preserve] [--no-cleanup] -R|-r|--recursive <src-dir> <dst-dir>
+ // cp [-p|--preserve] [--no-cleanup] <src-file>... <dst-dir>/
+ // cp [-p|--preserve] [--no-cleanup] -R|-r|--recursive <src-path>... <dst-dir>/
//
// Note: can be executed synchronously.
//
@@ -369,49 +383,37 @@ namespace build2
in.close ();
out.close ();
- auto i (args.begin ());
- auto e (args.end ());
-
- // Process options.
+ // Parse arguments.
//
- bool recursive (false);
- bool attrs (false);
- bool cleanup (true);
- for (; i != e; ++i)
- {
- const string& o (*i);
-
- if (o == "-R" || o == "-r")
- recursive = true;
- else if (o == "-p")
- attrs = true;
- else if (o == "--no-cleanup")
- cleanup = false;
- else
- {
- if (o == "--")
- ++i;
-
- break;
- }
- }
+ cli::vector_scanner scan (args);
+ cp_options ops (scan);
// Copy files or directories.
//
- if (i == e)
+ if (!scan.more ())
error () << "missing arguments";
+ // Note that the arguments semantics depends on the last argument,
+ // so we read out and cache them.
+ //
+ small_vector<string, 2> args;
+ while (scan.more ())
+ args.push_back (scan.next ());
+
const dir_path& wd (sp.wd_path);
+ auto i (args.begin ());
auto j (args.rbegin ());
- path dst (parse_path (*j++, wd));
- e = j.base ();
+ path dst (parse_path (move (*j++), wd));
+ auto e (j.base ());
if (i == e)
error () << "missing source path";
auto fail = [&error] () {return error (true);};
+ bool cleanup (!ops.no_cleanup ());
+
// If destination is not a directory path (no trailing separator)
// then make a copy of the filesystem entry at the specified path
// (the only source path is allowed in such a case). Otherwise copy
@@ -419,7 +421,7 @@ namespace build2
//
if (!dst.to_directory ())
{
- path src (parse_path (*i++, wd));
+ path src (parse_path (move (*i++), wd));
// If there are multiple sources but no trailing separator for the
// destination, then, most likelly, it is missing.
@@ -428,14 +430,14 @@ namespace build2
error () << "multiple source paths without trailing separator "
<< "for destination directory";
- if (!recursive)
+ if (!ops.recursive ())
// Synopsis 1: make a file copy at the specified path.
//
cpfile (sp,
src,
dst,
true /* overwrite */,
- attrs,
+ ops.preserve (),
cleanup,
fail);
else
@@ -443,7 +445,7 @@ namespace build2
//
cpdir (sp,
path_cast<dir_path> (src), path_cast<dir_path> (dst),
- attrs,
+ ops.preserve (),
cleanup,
fail);
}
@@ -451,9 +453,9 @@ namespace build2
{
for (; i != e; ++i)
{
- path src (parse_path (*i, wd));
+ path src (parse_path (move (*i), wd));
- if (recursive && dir_exists (src))
+ if (ops.recursive () && dir_exists (src))
// Synopsis 4: copy a filesystem entry into the specified
// directory. Note that we handle only source directories here.
// Source files are handled below.
@@ -461,7 +463,7 @@ namespace build2
cpdir (sp,
path_cast<dir_path> (src),
path_cast<dir_path> (dst / src.leaf ()),
- attrs,
+ ops.preserve (),
cleanup,
fail);
else
@@ -472,7 +474,7 @@ namespace build2
src,
dst / src.leaf (),
true /* overwrite */,
- attrs,
+ ops.preserve (),
cleanup,
fail);
}
@@ -494,6 +496,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
@@ -617,7 +623,7 @@ namespace build2
mksymlink (target, link, dir);
if (cleanup)
- sp.clean ({cleanup_type::always, link}, true);
+ sp.clean ({cleanup_type::always, link}, true /* implicit */);
}
catch (const system_error& e)
{
@@ -636,7 +642,7 @@ namespace build2
mkhardlink (target, link, dir);
if (cleanup)
- sp.clean ({cleanup_type::always, link}, true);
+ sp.clean ({cleanup_type::always, link}, true /* implicit */);
}
catch (const system_error& e)
{
@@ -666,8 +672,8 @@ namespace build2
}
}
- // ln [--no-cleanup] -s <target-path> <link-path>
- // ln [--no-cleanup] -s <target-path>... <link-dir>/
+ // ln [--no-cleanup] -s|--symbolic <target-path> <link-path>
+ // ln [--no-cleanup] -s|--symbolic <target-path>... <link-dir>/
//
// Note: can be executed synchronously.
//
@@ -690,50 +696,40 @@ namespace build2
in.close ();
out.close ();
- auto i (args.begin ());
- auto e (args.end ());
-
- // Process options.
+ // Parse arguments.
//
- bool cleanup (true);
- bool symlink (false);
-
- for (; i != e; ++i)
- {
- const string& o (*i);
-
- if (o == "--no-cleanup")
- cleanup = false;
- else if (o == "-s")
- symlink = true;
- else
- {
- if (o == "--")
- ++i;
+ cli::vector_scanner scan (args);
+ ln_options ops (scan);
- break;
- }
- }
-
- if (!symlink)
- error () << "missing -s option";
+ if (!ops.symbolic ())
+ error () << "missing -s|--symbolic option";
// Create file or directory symlinks.
//
- if (i == e)
+ if (!scan.more ())
error () << "missing arguments";
+ // Note that the arguments semantics depends on the last argument,
+ // so we read out and cache them.
+ //
+ small_vector<string, 2> args;
+ while (scan.more ())
+ args.push_back (scan.next ());
+
const dir_path& wd (sp.wd_path);
+ auto i (args.begin ());
auto j (args.rbegin ());
- path link (parse_path (*j++, wd));
- e = j.base ();
+ path link (parse_path (move (*j++), wd));
+ auto e (j.base ());
if (i == e)
error () << "missing target path";
auto fail = [&error] () {return error (true);};
+ bool cleanup (!ops.no_cleanup ());
+
// If link is not a directory path (no trailing separator), then
// create a symlink to the target path at the specified link path
// (the only target path is allowed in such a case). Otherwise create
@@ -741,7 +737,7 @@ namespace build2
//
if (!link.to_directory ())
{
- path target (parse_path (*i++, wd));
+ path target (parse_path (move (*i++), wd));
// If there are multiple targets but no trailing separator for the
// link, then, most likelly, it is missing.
@@ -757,7 +753,7 @@ namespace build2
{
for (; i != e; ++i)
{
- path target (parse_path (*i, wd));
+ path target (parse_path (move (*i), wd));
// Synopsis 2: create a target path symlink in the specified
// directory.
@@ -782,6 +778,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
@@ -806,11 +806,11 @@ namespace build2
try_mkdir (p); // Returns success or throws.
if (cleanup)
- sp.clean ({cleanup_type::always, p}, true);
+ sp.clean ({cleanup_type::always, p}, true /* implicit */);
}
}
- // mkdir [--no-cleanup] [-p] <dir>...
+ // mkdir [--no-cleanup] [-p|--parents] <dir>...
//
// Note that POSIX doesn't specify if after a directory creation failure
// the command should proceed with the rest of the arguments. The current
@@ -837,47 +837,31 @@ namespace build2
in.close ();
out.close ();
- auto i (args.begin ());
- auto e (args.end ());
-
- // Process options.
+ // Parse arguments.
//
- bool parent (false);
- bool cleanup (true);
- for (; i != e; ++i)
- {
- const string& o (*i);
-
- if (o == "-p")
- parent = true;
- else if (o == "--no-cleanup")
- cleanup = false;
- else
- {
- if (*i == "--")
- ++i;
-
- break;
- }
- }
+ cli::vector_scanner scan (args);
+ mkdir_options ops (scan);
// Create directories.
//
- if (i == e)
+ if (!scan.more ())
error () << "missing directory";
- for (; i != e; ++i)
+ bool cleanup (!ops.no_cleanup ());
+
+ while (scan.more ())
{
- dir_path p (path_cast<dir_path> (parse_path (*i, sp.wd_path)));
+ dir_path p (path_cast<dir_path> (parse_path (scan.next (),
+ sp.wd_path)));
try
{
- if (parent)
+ if (ops.parents ())
mkdir_p (sp, p, cleanup);
else if (try_mkdir (p) == mkdir_status::success)
{
if (cleanup)
- sp.clean ({cleanup_type::always, p}, true);
+ sp.clean ({cleanup_type::always, p}, true /* implicit */);
}
else // == mkdir_status::already_exists
throw_generic_error (EEXIST);
@@ -904,6 +888,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
@@ -913,8 +901,8 @@ namespace build2
return 1;
}
- // mv [--no-cleanup] [-f] <src-path> <dst-path>
- // mv [--no-cleanup] [-f] <src-path>... <dst-dir>/
+ // mv [--no-cleanup] [-f|--force] <src-path> <dst-path>
+ // mv [--no-cleanup] [-f|--force] <src-path>... <dst-dir>/
//
// Note: can be executed synchronously.
//
@@ -937,50 +925,38 @@ namespace build2
in.close ();
out.close ();
- auto i (args.begin ());
- auto e (args.end ());
-
- // Process options.
+ // Parse arguments.
//
- bool no_cleanup (false);
- bool force (false);
- for (; i != e; ++i)
- {
- const string& o (*i);
-
- if (o == "--no-cleanup")
- no_cleanup = true;
- else if (*i == "-f")
- force = true;
- else
- {
- if (o == "--")
- ++i;
-
- break;
- }
- }
+ cli::vector_scanner scan (args);
+ mv_options ops (scan);
// Move filesystem entries.
//
- if (i == e)
+ if (!scan.more ())
error () << "missing arguments";
+ // Note that the arguments semantics depends on the last argument,
+ // so we read out and cache them.
+ //
+ small_vector<string, 2> args;
+ while (scan.more ())
+ args.push_back (scan.next ());
+
const dir_path& wd (sp.wd_path);
+ auto i (args.begin ());
auto j (args.rbegin ());
- path dst (parse_path (*j++, wd));
- e = j.base ();
+ path dst (parse_path (move (*j++), wd));
+ auto e (j.base ());
if (i == e)
error () << "missing source path";
- auto mv = [no_cleanup, force, &wd, &sp, &error] (const path& from,
- const path& to)
+ auto mv = [ops, &wd, &sp, &error] (const path& from, const path& to)
{
const dir_path& rwd (sp.root->wd_path);
- if (!from.sub (rwd) && !force)
+ if (!from.sub (rwd) && !ops.force ())
error () << "'" << from << "' is out of working directory '"
<< rwd << "'";
@@ -1016,7 +992,7 @@ namespace build2
// Unless suppressed, adjust the cleanups that are sub-paths of
// the source path.
//
- if (!no_cleanup)
+ if (!ops.no_cleanup ())
{
// "Move" the matching cleanup if the destination path doesn't
// exist and is a sub-path of the working directory. Otherwise
@@ -1086,7 +1062,7 @@ namespace build2
//
if (!dst.to_directory ())
{
- path src (parse_path (*i++, wd));
+ path src (parse_path (move (*i++), wd));
// If there are multiple sources but no trailing separator for the
// destination, then, most likelly, it is missing.
@@ -1105,7 +1081,7 @@ namespace build2
//
for (; i != e; ++i)
{
- path src (parse_path (*i, wd));
+ path src (parse_path (move (*i), wd));
mv (src, dst / src.leaf ());
}
}
@@ -1126,6 +1102,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
@@ -1135,7 +1115,7 @@ namespace build2
return 1;
}
- // rm [-r] [-f] <path>...
+ // rm [-r|--recursive] [-f|--force] <path>...
//
// The implementation deviates from POSIX in a number of ways. It doesn't
// interact with a user and fails immediatelly if unable to process an
@@ -1165,41 +1145,24 @@ namespace build2
in.close ();
out.close ();
- auto i (args.begin ());
- auto e (args.end ());
-
- // Process options.
+ // Parse arguments.
//
- bool dir (false);
- bool force (false);
- for (; i != e; ++i)
- {
- if (*i == "-r")
- dir = true;
- else if (*i == "-f")
- force = true;
- else
- {
- if (*i == "--")
- ++i;
-
- break;
- }
- }
+ cli::vector_scanner scan (args);
+ rm_options ops (scan);
// Remove entries.
//
- if (i == e && !force)
+ if (!scan.more () && !ops.force ())
error () << "missing file";
const dir_path& wd (sp.wd_path);
const dir_path& rwd (sp.root->wd_path);
- for (; i != e; ++i)
+ while (scan.more ())
{
- path p (parse_path (*i, wd));
+ path p (parse_path (scan.next (), wd));
- if (!p.sub (rwd) && !force)
+ if (!p.sub (rwd) && !ops.force ())
error () << "'" << p << "' is out of working directory '" << rwd
<< "'";
@@ -1209,7 +1172,7 @@ namespace build2
if (dir_exists (d))
{
- if (!dir)
+ if (!ops.recursive ())
error () << "'" << p << "' is a directory";
if (wd.sub (d))
@@ -1221,7 +1184,8 @@ namespace build2
//
try_rmdir_r (d);
}
- else if (try_rmfile (p) == rmfile_status::not_exist && !force)
+ else if (try_rmfile (p) == rmfile_status::not_exist &&
+ !ops.force ())
throw_generic_error (ENOENT);
}
catch (const system_error& e)
@@ -1246,6 +1210,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
@@ -1255,7 +1223,7 @@ namespace build2
return 1;
}
- // rmdir [-f] <path>...
+ // rmdir [-f|--force] <path>...
//
// Note: can be executed synchronously.
//
@@ -1278,42 +1246,28 @@ namespace build2
in.close ();
out.close ();
- auto i (args.begin ());
- auto e (args.end ());
-
- // Process options.
+ // Parse arguments.
//
- bool force (false);
- for (; i != e; ++i)
- {
- if (*i == "-f")
- force = true;
- else
- {
- if (*i == "--")
- ++i;
-
- break;
- }
- }
+ cli::vector_scanner scan (args);
+ rmdir_options ops (scan);
// Remove directories.
//
- if (i == e && !force)
+ if (!scan.more () && !ops.force ())
error () << "missing directory";
const dir_path& wd (sp.wd_path);
const dir_path& rwd (sp.root->wd_path);
- for (; i != e; ++i)
+ while (scan.more ())
{
- dir_path p (path_cast<dir_path> (parse_path (*i, wd)));
+ dir_path p (path_cast<dir_path> (parse_path (scan.next (), wd)));
if (wd.sub (p))
error () << "'" << p << "' contains test working directory '"
<< wd << "'";
- if (!p.sub (rwd) && !force)
+ if (!p.sub (rwd) && !ops.force ())
error () << "'" << p << "' is out of working directory '"
<< rwd << "'";
@@ -1323,7 +1277,7 @@ namespace build2
if (s == rmdir_status::not_empty)
throw_generic_error (ENOTEMPTY);
- else if (s == rmdir_status::not_exist && !force)
+ else if (s == rmdir_status::not_exist && !ops.force ())
throw_generic_error (ENOENT);
}
catch (const system_error& e)
@@ -1348,6 +1302,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
@@ -1357,7 +1315,7 @@ namespace build2
return 1;
}
- // sed [-n] [-i] -e <script> [<file>]
+ // sed [-n|--quiet] [-i|--in-place] -e|--expression <script> [<file>]
//
// Note: must be executed asynchronously.
//
@@ -1388,132 +1346,108 @@ namespace build2
ifdstream cin (move (in), ifdstream::badbit);
ofdstream cout (move (out));
- auto i (args.begin ());
- auto e (args.end ());
+ // Parse arguments.
+ //
+ cli::vector_scanner scan (args);
+ sed_options ops (scan);
+
+ if (ops.expression ().empty ())
+ error () << "missing script";
- // Process options.
+ // Only a single script is supported.
//
- bool auto_prn (true);
- bool in_place (false);
+ if (ops.expression ().size () != 1)
+ error () << "multiple scripts";
- struct substitute
+ struct
{
string regex;
string replacement;
bool icase = false;
bool global = false;
bool print = false;
- };
- optional<substitute> subst;
+ } subst;
- for (; i != e; ++i)
{
- const string& o (*i);
-
- if (o == "-n")
- auto_prn = false;
- else if (o == "-i")
- in_place = true;
- else if (o == "-e")
- {
- // Only a single script is supported.
- //
- if (subst)
- error () << "multiple scripts";
-
- // If option has no value then bail out and report.
- //
- if (++i == e)
- break;
+ const string& v (ops.expression ()[0]);
+ if (v.empty ())
+ error () << "empty script";
- const string& v (*i);
- if (v.empty ())
- error () << "empty script";
+ if (v[0] != 's')
+ error () << "only 's' command supported";
- if (v[0] != 's')
- error () << "only 's' command supported";
-
- // Parse the substitute command.
- //
- if (v.size () < 2)
- error () << "no delimiter for 's' command";
+ // Parse the substitute command.
+ //
+ if (v.size () < 2)
+ error () << "no delimiter for 's' command";
- char delim (v[1]);
- if (delim == '\\' || delim == '\n')
- error () << "invalid delimiter for 's' command";
+ char delim (v[1]);
+ if (delim == '\\' || delim == '\n')
+ error () << "invalid delimiter for 's' command";
- size_t p (v.find (delim, 2));
- if (p == string::npos)
- error () << "unterminated 's' command regex";
+ size_t p (v.find (delim, 2));
+ if (p == string::npos)
+ error () << "unterminated 's' command regex";
- subst = substitute ();
- subst->regex.assign (v, 2, p - 2);
+ subst.regex.assign (v, 2, p - 2);
- // Empty regex matches nothing, so not of much use.
- //
- if (subst->regex.empty ())
- error () << "empty regex in 's' command";
+ // Empty regex matches nothing, so not of much use.
+ //
+ if (subst.regex.empty ())
+ error () << "empty regex in 's' command";
- size_t b (p + 1);
- p = v.find (delim, b);
- if (p == string::npos)
- error () << "unterminated 's' command replacement";
+ size_t b (p + 1);
+ p = v.find (delim, b);
+ if (p == string::npos)
+ error () << "unterminated 's' command replacement";
- subst->replacement.assign (v, b, p - b);
+ subst.replacement.assign (v, b, p - b);
- // Parse the substitute command flags.
- //
- char c;
- for (++p; (c = v[p]) != '\0'; ++p)
+ // Parse the substitute command flags.
+ //
+ char c;
+ for (++p; (c = v[p]) != '\0'; ++p)
+ {
+ switch (c)
{
- switch (c)
+ case 'i': subst.icase = true; break;
+ case 'g': subst.global = true; break;
+ case 'p': subst.print = true; break;
+ default:
{
- case 'i': subst->icase = true; break;
- case 'g': subst->global = true; break;
- case 'p': subst->print = true; break;
- default:
- {
- error () << "invalid 's' command flag '" << c << "'";
- }
+ error () << "invalid 's' command flag '" << c << "'";
}
}
}
- else
- {
- if (o == "--")
- ++i;
-
- break;
- }
}
- if (!subst)
- error () << "missing script";
-
// Path of a file to edit. An empty path represents stdin.
//
path p;
- if (i != e)
+ if (scan.more ())
{
- if (*i != "-")
- p = parse_path (*i, sp.wd_path);
+ string f (scan.next ());
- ++i;
+ if (f != "-")
+ p = parse_path (move (f), sp.wd_path);
}
- if (i != e)
- error () << "unexpected argument '" << *i << "'";
+ if (scan.more ())
+ error () << "unexpected argument '" << scan.next () << "'";
+ // Edit file.
+ //
// If we edit file in place make sure that the file path is specified
// and obtain a temporary file path. We will be writing to the
// temporary file (rather than to stdout) and will move it to the
// original file path afterwards.
//
path tp;
- if (in_place)
+ if (ops.in_place ())
{
if (p.empty ())
- error () << "-i option specified while reading from stdin";
+ error () << "-i|--in-place option specified while reading from "
+ << "stdin";
try
{
@@ -1543,8 +1477,8 @@ namespace build2
// Note that ECMAScript is implied if no grammar flag is specified.
//
- regex re (subst->regex,
- subst->icase ? regex::icase : regex::ECMAScript);
+ regex re (subst.regex,
+ subst.icase ? regex::icase : regex::ECMAScript);
// Edit a file or STDIN.
//
@@ -1566,22 +1500,22 @@ namespace build2
auto r (regex_replace_search (
s,
re,
- subst->replacement,
- subst->global
+ subst.replacement,
+ subst.global
? regex_constants::format_default
: regex_constants::format_first_only));
// Add newline regardless whether the source line is newline-
// terminated or not (in accordance with POSIX).
//
- if (auto_prn || (r.second && subst->print))
+ if (!ops.quiet () || (r.second && subst.print))
cout << r.first << '\n';
}
cin.close ();
cout.close ();
- if (in_place)
+ if (ops.in_place ())
{
mvfile (
tp, p,
@@ -1629,6 +1563,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
@@ -1661,17 +1599,19 @@ namespace build2
in.close ();
out.close ();
- if (args.empty ())
- error () << "missing time interval";
+ // Parse arguments.
+ //
+ cli::vector_scanner scan (args);
+ sleep_options ops (scan); // Makes sure no options passed.
- if (args.size () > 1)
- error () << "unexpected argument '" << args[1] << "'";
+ if (!scan.more ())
+ error () << "missing time interval";
uint64_t n;
for (;;) // Breakout loop.
{
- const string& a (args[0]);
+ string a (scan.next ());
// Note: strtoull() allows these.
//
@@ -1687,6 +1627,11 @@ namespace build2
error () << "invalid time interval '" << a << "'";
}
+ if (scan.more ())
+ error () << "unexpected argument '" << scan.next () << "'";
+
+ // Sleep.
+ //
// If/when required we could probably support the precise sleep mode
// (e.g., via an option).
//
@@ -1704,6 +1649,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
@@ -1713,7 +1662,7 @@ namespace build2
return 1;
}
- // test -f|-d <path>
+ // test (-f|--file)|(-d|--directory) <path>
//
// Note: can be executed synchronously.
//
@@ -1736,22 +1685,28 @@ namespace build2
in.close ();
out.close ();
- if (args.size () < 2)
- error () << "missing path";
+ // Parse arguments.
+ //
+ cli::vector_scanner scan (args);
+ test_options ops (scan); // Makes sure no options passed.
- bool file (args[0] == "-f");
+ if (!ops.file () && !ops.directory ())
+ error () << "either -f|--file or -d|--directory must be specified";
- if (!file && args[0] != "-d")
- error () << "invalid option";
+ if (ops.file () && ops.directory ())
+ error () << "both -f|--file and -d|--directory specified";
- if (args.size () > 2)
- error () << "unexpected argument '" << args[2] << "'";
+ if (!scan.more ())
+ error () << "missing path";
+
+ path p (parse_path (scan.next (), sp.wd_path));
- path p (parse_path (args[1], sp.wd_path));
+ if (scan.more ())
+ error () << "unexpected argument '" << scan.next () << "'";
try
{
- r = (file ? file_exists (p) : dir_exists (p)) ? 0 : 1;
+ r = (ops.file () ? file_exists (p) : dir_exists (p)) ? 0 : 1;
}
catch (const system_error& e)
{
@@ -1772,6 +1727,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
@@ -1811,6 +1770,11 @@ namespace build2
in.close ();
out.close ();
+ // Parse arguments.
+ //
+ cli::vector_scanner scan (args);
+ touch_options ops (scan);
+
auto mtime = [&error] (const path& p) -> timestamp
{
try
@@ -1831,51 +1795,26 @@ namespace build2
return timestamp ();
};
- auto i (args.begin ());
- auto e (args.end ());
-
- // Process options.
- //
- bool cleanup (true);
optional<timestamp> after;
- for (; i != e; ++i)
- {
- const string& o (*i);
-
- if (o == "--no-cleanup")
- cleanup = false;
- else if (o == "--after")
- {
- if (++i == e)
- error () << "missing --after option value";
+ if (ops.after_specified ())
+ after = mtime (parse_path (ops.after (), sp.wd_path));
- after = mtime (parse_path (*i, sp.wd_path));
- }
- else
- {
- if (o == "--")
- ++i;
-
- break;
- }
- }
-
- if (i == e)
+ if (!scan.more ())
error () << "missing file";
// Create files.
//
- for (; i != e; ++i)
+ while (scan.more ())
{
- path p (parse_path (*i, sp.wd_path));
+ path p (parse_path (scan.next (), sp.wd_path));
try
{
// Note that we don't register (implicit) cleanup for an
// existing path.
//
- if (touch_file (p) && cleanup)
- sp.clean ({cleanup_type::always, p}, true);
+ if (touch_file (p) && !ops.no_cleanup ())
+ sp.clean ({cleanup_type::always, p}, true /* implicit */);
if (after)
{
@@ -1905,6 +1844,10 @@ namespace build2
{
// Diagnostics has already been issued.
}
+ catch (const cli::exception& e)
+ {
+ error (false) << e;
+ }
cerr.close ();
return r;
diff --git a/libbuild2/test/script/runner.cxx b/libbuild2/test/script/runner.cxx
index 6c1becd..a1eb9ec 100644
--- a/libbuild2/test/script/runner.cxx
+++ b/libbuild2/test/script/runner.cxx
@@ -19,6 +19,7 @@
#include <libbuild2/test/script/regex.hxx>
#include <libbuild2/test/script/parser.hxx>
#include <libbuild2/test/script/builtin.hxx>
+#include <libbuild2/test/script/builtin-options.hxx>
using namespace std;
using namespace butl;
@@ -1010,45 +1011,23 @@ namespace build2
//
ifdstream cin (move (in), ifdstream::badbit);
- auto i (args.begin ());
- auto e (args.end ());
-
- // Process options.
+ // Parse arguments.
//
- bool exact (false);
- bool newline (false);
- bool whitespace (false);
-
- for (; i != e; ++i)
- {
- const string& o (*i);
-
- if (o == "-e" || o == "--exact")
- exact = true;
- else if (o == "-n" || o == "--newline")
- newline = true;
- else if (o == "-w" || o == "--whitespace")
- whitespace = true;
- else
- {
- if (*i == "--")
- ++i;
+ cli::vector_scanner scan (args);
+ set_options ops (scan);
- break;
- }
- }
+ if (ops.whitespace () && ops.newline ())
+ fail (ll) << "both -n|--newline and -w|--whitespace specified";
- // Process arguments.
- //
- if (i == e)
+ if (!scan.more ())
fail (ll) << "missing variable name";
- const string& a (*i++); // Either attributes or variable name.
- const string* ats (i == e ? nullptr : &a);
- const string& vname (i == e ? a : *i++);
+ string a (scan.next ()); // Either attributes or variable name.
+ const string* ats (!scan.more () ? nullptr : &a);
+ const string& vname (!scan.more () ? a : scan.next ());
- if (i != e)
- fail (ll) << "unexpected argument '" << *i << "'";
+ if (scan.more ())
+ fail (ll) << "unexpected argument '" << scan.next () << "'";
if (ats != nullptr && ats->empty ())
fail (ll) << "empty variable attributes";
@@ -1069,7 +1048,7 @@ namespace build2
// target or as a part of msvcrt junk production (see above).
//
string s;
- if (whitespace)
+ if (ops.whitespace ())
cin >> s;
else
{
@@ -1088,9 +1067,9 @@ namespace build2
//
if (cin.fail ())
{
- if (exact)
+ if (ops.exact ())
{
- if (whitespace || newline)
+ if (ops.whitespace () || ops.newline ())
ns.emplace_back (move (s)); // Reuse empty string.
else if (ns.empty ())
ns.emplace_back ("\n");
@@ -1101,7 +1080,7 @@ namespace build2
break;
}
- if (whitespace || newline || ns.empty ())
+ if (ops.whitespace () || ops.newline () || ns.empty ())
ns.emplace_back (move (s));
else
{
@@ -1157,6 +1136,10 @@ namespace build2
{
fail (ll) << "set: " << e;
}
+ catch (const cli::exception& e)
+ {
+ fail (ll) << "set: " << e;
+ }
}
static bool