From cce2cd1db97c4f7b28ca5a27541bad14fc073cdc Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 9 Sep 2024 20:53:30 +0300 Subject: Make changes required for CI --- bdep/argument-grouping.cxx | 84 + bdep/argument-grouping.hxx | 31 + bdep/bdep-options.cxx | 1711 +++++++++++++ bdep/bdep-options.hxx | 485 ++++ bdep/bdep-options.ixx | 387 +++ bdep/ci-options.cxx | 1231 +++++++++ bdep/ci-options.hxx | 345 +++ bdep/ci-options.ixx | 417 ++++ bdep/clean-options.cxx | 758 ++++++ bdep/clean-options.hxx | 139 ++ bdep/clean-options.ixx | 57 + bdep/common-options.cxx | 2034 +++++++++++++++ bdep/common-options.hxx | 1012 ++++++++ bdep/common-options.ixx | 989 ++++++++ bdep/config-options.cxx | 1336 ++++++++++ bdep/config-options.hxx | 293 +++ bdep/config-options.ixx | 186 ++ bdep/database-views-odb.cxx | 233 ++ bdep/database-views-odb.hxx | 148 ++ bdep/database-views-odb.ixx | 27 + bdep/default-options-files.cxx | 91 + bdep/default-options-files.hxx | 31 + bdep/deinit-options.cxx | 749 ++++++ bdep/deinit-options.hxx | 139 ++ bdep/deinit-options.ixx | 57 + bdep/fetch-options.cxx | 730 ++++++ bdep/fetch-options.hxx | 129 + bdep/fetch-options.ixx | 39 + bdep/help-options.cxx | 680 +++++ bdep/help-options.hxx | 119 + bdep/help-options.ixx | 21 + bdep/init-options.cxx | 1109 +++++++++ bdep/init-options.hxx | 261 ++ bdep/init-options.ixx | 273 ++ bdep/new-options.cxx | 5392 ++++++++++++++++++++++++++++++++++++++++ bdep/new-options.hxx | 1696 +++++++++++++ bdep/new-options.ixx | 1665 +++++++++++++ bdep/project-odb.cxx | 1676 +++++++++++++ bdep/project-odb.hxx | 636 +++++ bdep/project-odb.ixx | 94 + bdep/project-options.cxx | 1619 ++++++++++++ bdep/project-options.hxx | 460 ++++ bdep/project-options.ixx | 339 +++ bdep/projects-configs.cxx | 103 + bdep/projects-configs.hxx | 31 + bdep/publish-options.cxx | 986 ++++++++ bdep/publish-options.hxx | 260 ++ bdep/publish-options.ixx | 267 ++ bdep/release-options.cxx | 1318 ++++++++++ bdep/release-options.hxx | 408 +++ bdep/release-options.ixx | 531 ++++ bdep/status-options.cxx | 904 +++++++ bdep/status-options.hxx | 169 ++ bdep/status-options.ixx | 111 + bdep/sync-options.cxx | 1631 ++++++++++++ bdep/sync-options.hxx | 447 ++++ bdep/sync-options.ixx | 462 ++++ bdep/test-options.cxx | 758 ++++++ bdep/test-options.hxx | 139 ++ bdep/test-options.ixx | 57 + bdep/update-options.cxx | 758 ++++++ bdep/update-options.hxx | 139 ++ bdep/update-options.ixx | 57 + buildfile | 2 +- repositories.manifest | 6 +- 65 files changed, 39447 insertions(+), 5 deletions(-) create mode 100644 bdep/argument-grouping.cxx create mode 100644 bdep/argument-grouping.hxx create mode 100644 bdep/bdep-options.cxx create mode 100644 bdep/bdep-options.hxx create mode 100644 bdep/bdep-options.ixx create mode 100644 bdep/ci-options.cxx create mode 100644 bdep/ci-options.hxx create mode 100644 bdep/ci-options.ixx create mode 100644 bdep/clean-options.cxx create mode 100644 bdep/clean-options.hxx create mode 100644 bdep/clean-options.ixx create mode 100644 bdep/common-options.cxx create mode 100644 bdep/common-options.hxx create mode 100644 bdep/common-options.ixx create mode 100644 bdep/config-options.cxx create mode 100644 bdep/config-options.hxx create mode 100644 bdep/config-options.ixx create mode 100644 bdep/database-views-odb.cxx create mode 100644 bdep/database-views-odb.hxx create mode 100644 bdep/database-views-odb.ixx create mode 100644 bdep/default-options-files.cxx create mode 100644 bdep/default-options-files.hxx create mode 100644 bdep/deinit-options.cxx create mode 100644 bdep/deinit-options.hxx create mode 100644 bdep/deinit-options.ixx create mode 100644 bdep/fetch-options.cxx create mode 100644 bdep/fetch-options.hxx create mode 100644 bdep/fetch-options.ixx create mode 100644 bdep/help-options.cxx create mode 100644 bdep/help-options.hxx create mode 100644 bdep/help-options.ixx create mode 100644 bdep/init-options.cxx create mode 100644 bdep/init-options.hxx create mode 100644 bdep/init-options.ixx create mode 100644 bdep/new-options.cxx create mode 100644 bdep/new-options.hxx create mode 100644 bdep/new-options.ixx create mode 100644 bdep/project-odb.cxx create mode 100644 bdep/project-odb.hxx create mode 100644 bdep/project-odb.ixx create mode 100644 bdep/project-options.cxx create mode 100644 bdep/project-options.hxx create mode 100644 bdep/project-options.ixx create mode 100644 bdep/projects-configs.cxx create mode 100644 bdep/projects-configs.hxx create mode 100644 bdep/publish-options.cxx create mode 100644 bdep/publish-options.hxx create mode 100644 bdep/publish-options.ixx create mode 100644 bdep/release-options.cxx create mode 100644 bdep/release-options.hxx create mode 100644 bdep/release-options.ixx create mode 100644 bdep/status-options.cxx create mode 100644 bdep/status-options.hxx create mode 100644 bdep/status-options.ixx create mode 100644 bdep/sync-options.cxx create mode 100644 bdep/sync-options.hxx create mode 100644 bdep/sync-options.ixx create mode 100644 bdep/test-options.cxx create mode 100644 bdep/test-options.hxx create mode 100644 bdep/test-options.ixx create mode 100644 bdep/update-options.cxx create mode 100644 bdep/update-options.hxx create mode 100644 bdep/update-options.ixx diff --git a/bdep/argument-grouping.cxx b/bdep/argument-grouping.cxx new file mode 100644 index 0000000..b5796c0 --- /dev/null +++ b/bdep/argument-grouping.cxx @@ -0,0 +1,84 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include +// +// End prologue. + +#include + +#include + +namespace bdep +{ + ::bdep::cli::usage_para + print_bdep_argument_grouping_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbdep\033[0m \033[1m{\033[0m \033[4moptions\033[0m \033[1m}+\033[0m \033[4margument\033[0m \033[1m+{\033[0m \033[4moptions\033[0m \033[1m}\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "For certain commands certain options and command line variables can be grouped" << ::std::endl + << "to only apply to specific arguments. This help topic describes the argument" << ::std::endl + << "grouping facility used for this purpose." << ::std::endl + << ::std::endl + << "Groups can be specified before (leading) and/or after (trailing) the argument" << ::std::endl + << "they apply to. A leading group starts with '\033[1m{\033[0m' and ends with '\033[1m}+\033[0m' while a" << ::std::endl + << "trailing group starts with '\033[1m+{\033[0m' and ends with '\033[1m}\033[0m'. For example:" << ::std::endl + << ::std::endl + << "{ --foo --bar }+ arg # 'arg' with '--foo' '--bar'" << ::std::endl + << "arg +{ fox=1 baz=2 } # 'arg' with 'fox=1' 'baz=2'" << ::std::endl + << ::std::endl + << "Multiple leading and/or trailing groups can be specified for the same argument." << ::std::endl + << "For example:" << ::std::endl + << ::std::endl + << "{ -f }+ { -b }+ arg +{ f=1 } +{ b=2 } # 'arg' with '-f' 'b' 'f=1' 'b=2'" << ::std::endl + << ::std::endl + << "The group applies to a single argument only unless multiple arguments are" << ::std::endl + << "themselves grouped with '\033[1m{\033[0m' and '\033[1m}\033[0m'. For example:" << ::std::endl + << ::std::endl + << "{ --foo }+ arg1 arg2 +{ --bar } # 'arg1' with '--foo'" << ::std::endl + << " # 'arg2' with '--bar'" << ::std::endl + << ::std::endl + << "{ --foo }+ { arg1 arg2 } +{ --bar } # 'arg1' with '--foo' '--bar'" << ::std::endl + << " # 'arg2' with '--foo' '--bar'" << ::std::endl + << ::std::endl + << "The group separators ('\033[1m{\033[0m', '\033[1m}+'\033[0m, etc) must be separate command line arguments." << ::std::endl + << "In particular, they must not be adjacent either to the arguments inside the" << ::std::endl + << "group nor to the argument they apply to. All such cases will be treated as" << ::std::endl + << "ordinary arguments. For example:" << ::std::endl + << ::std::endl + << "{--foo}+ arg # '{--foo}+' ..." << ::std::endl + << "arg+{ --foo } # 'arg+{' ..." << ::std::endl + << ::std::endl + << "If one of the group separators needs to be specified as an argument verbatim," << ::std::endl + << "then it must be escaped with '\033[1m\\\033[0m'. For example:" << ::std::endl + << ::std::endl + << "} # error: unexpected group separator" << ::std::endl + << "}x # '}x'" << ::std::endl + << "\\} # '}'" << ::std::endl + << "{ \\}+ }+ arg # 'arg' with '}+'" << ::std::endl; + + p = ::bdep::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bdep/argument-grouping.hxx b/bdep/argument-grouping.hxx new file mode 100644 index 0000000..a89eb16 --- /dev/null +++ b/bdep/argument-grouping.hxx @@ -0,0 +1,31 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BDEP_ARGUMENT_GROUPING_HXX +#define BDEP_ARGUMENT_GROUPING_HXX + +// Begin prologue. +// +// +// End prologue. + +#include + +// Print page usage information. +// +namespace bdep +{ + ::bdep::cli::usage_para + print_bdep_argument_grouping_usage (::std::ostream&, + ::bdep::cli::usage_para = ::bdep::cli::usage_para::none); +} + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BDEP_ARGUMENT_GROUPING_HXX diff --git a/bdep/bdep-options.cxx b/bdep/bdep-options.cxx new file mode 100644 index 0000000..e6e0a73 --- /dev/null +++ b/bdep/bdep-options.cxx @@ -0,0 +1,1711 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include +// +// End prologue. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace bdep +{ + namespace cli + { + template + 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; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser + { + static void + parse (bool& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser + { + 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; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template + struct parser > + { + static void + parse (std::pair& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser::parse (x.first, xs, s); + } + + static void + merge (std::pair& b, const std::pair& a) + { + b = a; + } + }; + + template + struct parser > + { + static void + parse (std::vector& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector& b, const std::vector& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template + struct parser > + { + static void + parse (std::set& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set& b, const std::set& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template + struct parser > + { + static void + parse (std::map& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + 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 (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map& b, const std::map& a) + { + for (typename std::map::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template + struct parser > + { + static void + parse (std::multimap& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + 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 (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (v, dummy, s); + } + + m.insert (typename std::multimap::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap& b, const std::multimap& a) + { + for (typename std::multimap::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap::value_type (i->first, + i->second)); + } + }; + + template + void + thunk (X& x, scanner& s) + { + parser::parse (x.*M, s); + } + + template + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + template + void + thunk (X& x, scanner& s) + { + parser::parse (x.*M, x.*S, s); + } + } +} + +#include + +namespace bdep +{ + // commands + // + + commands:: + commands () + : help_ (), + new__ (), + init_ (), + sync_ (), + fetch_ (), + status_ (), + ci_ (), + release_ (), + publish_ (), + deinit_ (), + config_ (), + test_ (), + update_ (), + clean_ () + { + } + + bool commands:: + parse (int& argc, + char** argv, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool commands:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool commands:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool commands:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool commands:: + parse (::bdep::cli::scanner& s, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void commands:: + merge (const commands& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.help_) + { + ::bdep::cli::parser< bool>::merge ( + this->help_, a.help_); + } + + if (a.new__) + { + ::bdep::cli::parser< bool>::merge ( + this->new__, a.new__); + } + + if (a.init_) + { + ::bdep::cli::parser< bool>::merge ( + this->init_, a.init_); + } + + if (a.sync_) + { + ::bdep::cli::parser< bool>::merge ( + this->sync_, a.sync_); + } + + if (a.fetch_) + { + ::bdep::cli::parser< bool>::merge ( + this->fetch_, a.fetch_); + } + + if (a.status_) + { + ::bdep::cli::parser< bool>::merge ( + this->status_, a.status_); + } + + if (a.ci_) + { + ::bdep::cli::parser< bool>::merge ( + this->ci_, a.ci_); + } + + if (a.release_) + { + ::bdep::cli::parser< bool>::merge ( + this->release_, a.release_); + } + + if (a.publish_) + { + ::bdep::cli::parser< bool>::merge ( + this->publish_, a.publish_); + } + + if (a.deinit_) + { + ::bdep::cli::parser< bool>::merge ( + this->deinit_, a.deinit_); + } + + if (a.config_) + { + ::bdep::cli::parser< bool>::merge ( + this->config_, a.config_); + } + + if (a.test_) + { + ::bdep::cli::parser< bool>::merge ( + this->test_, a.test_); + } + + if (a.update_) + { + ::bdep::cli::parser< bool>::merge ( + this->update_, a.update_); + } + + if (a.clean_) + { + ::bdep::cli::parser< bool>::merge ( + this->clean_, a.clean_); + } + } + + ::bdep::cli::usage_para commands:: + print_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCOMMANDS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1mhelp\033[0m [\033[4mtopic\033[0m] \033[1mbdep-help(1)\033[0m -- show help for a command or help topic" << ::std::endl; + + os << "\033[1mnew\033[0m \033[1mbdep-new(1)\033[0m -- create and initialize new project" << ::std::endl; + + os << "\033[1minit\033[0m \033[1mbdep-init(1)\033[0m -- initialize project in build" << ::std::endl + << " configurations" << ::std::endl; + + os << "\033[1msync\033[0m \033[1mbdep-sync(1)\033[0m -- synchronize project and build" << ::std::endl + << " configurations" << ::std::endl; + + os << "\033[1mfetch\033[0m \033[1mbdep-fetch(1)\033[0m -- fetch list of available project" << ::std::endl + << " dependencies" << ::std::endl; + + os << "\033[1mstatus\033[0m \033[1mbdep-status(1)\033[0m -- print status of project and/or its" << ::std::endl + << " dependencies" << ::std::endl; + + os << "\033[1mci\033[0m \033[1mbdep-ci(1)\033[0m -- submit project test request to CI" << ::std::endl + << " server" << ::std::endl; + + os << "\033[1mrelease\033[0m \033[1mbdep-release(1)\033[0m -- manage project's version during" << ::std::endl + << " release" << ::std::endl; + + os << "\033[1mpublish\033[0m \033[1mbdep-publish(1)\033[0m -- publish project to archive" << ::std::endl + << " repository" << ::std::endl; + + os << "\033[1mdeinit\033[0m \033[1mbdep-deinit(1)\033[0m -- deinitialize project in build" << ::std::endl + << " configurations" << ::std::endl; + + os << "\033[1mconfig\033[0m \033[1mbdep-config(1)\033[0m -- manage project's build" << ::std::endl + << " configurations" << ::std::endl; + + os << "\033[1mtest\033[0m \033[1mbdep-test(1)\033[0m -- test project in build configurations" << ::std::endl; + + os << "\033[1mupdate\033[0m \033[1mbdep-update(1)\033[0m -- update project in build" << ::std::endl + << " configurations" << ::std::endl; + + os << "\033[1mclean\033[0m \033[1mbdep-clean(1)\033[0m -- clean project in build" << ::std::endl + << " configurations" << ::std::endl; + + p = ::bdep::cli::usage_para::option; + + return p; + } + + struct _cli_commands_desc_type: ::bdep::cli::options + { + _cli_commands_desc_type () + { + ::bdep::commands::fill (*this); + } + }; + + void commands:: + fill (::bdep::cli::options& os) + { + // help + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("help", a, true, dv); + os.push_back (o); + } + + // new + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("new", a, true, dv); + os.push_back (o); + } + + // init + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("init", a, true, dv); + os.push_back (o); + } + + // sync + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("sync", a, true, dv); + os.push_back (o); + } + + // fetch + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("fetch", a, true, dv); + os.push_back (o); + } + + // status + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("status", a, true, dv); + os.push_back (o); + } + + // ci + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("ci", a, true, dv); + os.push_back (o); + } + + // release + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("release", a, true, dv); + os.push_back (o); + } + + // publish + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("publish", a, true, dv); + os.push_back (o); + } + + // deinit + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("deinit", a, true, dv); + os.push_back (o); + } + + // config + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("config", a, true, dv); + os.push_back (o); + } + + // test + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("test", a, true, dv); + os.push_back (o); + } + + // update + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("update", a, true, dv); + os.push_back (o); + } + + // clean + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("clean", a, true, dv); + os.push_back (o); + } + } + + const ::bdep::cli::options& commands:: + description () + { + static _cli_commands_desc_type _cli_commands_desc_; + return _cli_commands_desc_; + } + + typedef + std::map + _cli_commands_map; + + static _cli_commands_map _cli_commands_map_; + + struct _cli_commands_map_init + { + _cli_commands_map_init () + { + _cli_commands_map_["help"] = + &::bdep::cli::thunk< commands, &commands::help_ >; + _cli_commands_map_["new"] = + &::bdep::cli::thunk< commands, &commands::new__ >; + _cli_commands_map_["init"] = + &::bdep::cli::thunk< commands, &commands::init_ >; + _cli_commands_map_["sync"] = + &::bdep::cli::thunk< commands, &commands::sync_ >; + _cli_commands_map_["fetch"] = + &::bdep::cli::thunk< commands, &commands::fetch_ >; + _cli_commands_map_["status"] = + &::bdep::cli::thunk< commands, &commands::status_ >; + _cli_commands_map_["ci"] = + &::bdep::cli::thunk< commands, &commands::ci_ >; + _cli_commands_map_["release"] = + &::bdep::cli::thunk< commands, &commands::release_ >; + _cli_commands_map_["publish"] = + &::bdep::cli::thunk< commands, &commands::publish_ >; + _cli_commands_map_["deinit"] = + &::bdep::cli::thunk< commands, &commands::deinit_ >; + _cli_commands_map_["config"] = + &::bdep::cli::thunk< commands, &commands::config_ >; + _cli_commands_map_["test"] = + &::bdep::cli::thunk< commands, &commands::test_ >; + _cli_commands_map_["update"] = + &::bdep::cli::thunk< commands, &commands::update_ >; + _cli_commands_map_["clean"] = + &::bdep::cli::thunk< commands, &commands::clean_ >; + } + }; + + static _cli_commands_map_init _cli_commands_map_init_; + + bool commands:: + _parse (const char* o, ::bdep::cli::scanner& s) + { + _cli_commands_map::const_iterator i (_cli_commands_map_.find (o)); + + if (i != _cli_commands_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool commands:: + _parse (::bdep::cli::scanner& s, + ::bdep::cli::unknown_mode opt_mode, + ::bdep::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bdep::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; + } + + 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 (co.c_str ()), + const_cast (v) + }; + + ::bdep::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 ::bdep::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 + }; + + ::bdep::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 ::bdep::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bdep::cli::unknown_mode::stop: + { + break; + } + case ::bdep::cli::unknown_mode::fail: + { + throw ::bdep::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bdep::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bdep::cli::unknown_mode::stop: + { + break; + } + case ::bdep::cli::unknown_mode::fail: + { + throw ::bdep::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } + + // topics + // + + topics:: + topics () + : common_options_ (), + projects_configs_ (), + default_options_files_ (), + argument_grouping_ () + { + } + + bool topics:: + parse (int& argc, + char** argv, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool topics:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool topics:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool topics:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool topics:: + parse (::bdep::cli::scanner& s, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void topics:: + merge (const topics& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.common_options_) + { + ::bdep::cli::parser< bool>::merge ( + this->common_options_, a.common_options_); + } + + if (a.projects_configs_) + { + ::bdep::cli::parser< bool>::merge ( + this->projects_configs_, a.projects_configs_); + } + + if (a.default_options_files_) + { + ::bdep::cli::parser< bool>::merge ( + this->default_options_files_, a.default_options_files_); + } + + if (a.argument_grouping_) + { + ::bdep::cli::parser< bool>::merge ( + this->argument_grouping_, a.argument_grouping_); + } + } + + ::bdep::cli::usage_para topics:: + print_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mHELP TOPICS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1mcommon-options\033[0m \033[1mbdep-common-options(1)\033[0m -- details on common options" << ::std::endl; + + os << "\033[1mprojects-configs\033[0m \033[1mbdep-projects-configs(1)\033[0m -- specifying projects and" << ::std::endl + << " configurations" << ::std::endl; + + os << "\033[1mdefault-options-files\033[0m \033[1mbdep-default-options-files(1)\033[0m -- specifying default" << ::std::endl + << " options" << ::std::endl; + + os << "\033[1margument-grouping\033[0m \033[1mbdep-argument-grouping(1)\033[0m -- argument grouping" << ::std::endl + << " facility" << ::std::endl; + + p = ::bdep::cli::usage_para::option; + + return p; + } + + struct _cli_topics_desc_type: ::bdep::cli::options + { + _cli_topics_desc_type () + { + ::bdep::topics::fill (*this); + } + }; + + void topics:: + fill (::bdep::cli::options& os) + { + // common-options + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("common-options", a, true, dv); + os.push_back (o); + } + + // projects-configs + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("projects-configs", a, true, dv); + os.push_back (o); + } + + // default-options-files + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("default-options-files", a, true, dv); + os.push_back (o); + } + + // argument-grouping + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("argument-grouping", a, true, dv); + os.push_back (o); + } + } + + const ::bdep::cli::options& topics:: + description () + { + static _cli_topics_desc_type _cli_topics_desc_; + return _cli_topics_desc_; + } + + typedef + std::map + _cli_topics_map; + + static _cli_topics_map _cli_topics_map_; + + struct _cli_topics_map_init + { + _cli_topics_map_init () + { + _cli_topics_map_["common-options"] = + &::bdep::cli::thunk< topics, &topics::common_options_ >; + _cli_topics_map_["projects-configs"] = + &::bdep::cli::thunk< topics, &topics::projects_configs_ >; + _cli_topics_map_["default-options-files"] = + &::bdep::cli::thunk< topics, &topics::default_options_files_ >; + _cli_topics_map_["argument-grouping"] = + &::bdep::cli::thunk< topics, &topics::argument_grouping_ >; + } + }; + + static _cli_topics_map_init _cli_topics_map_init_; + + bool topics:: + _parse (const char* o, ::bdep::cli::scanner& s) + { + _cli_topics_map::const_iterator i (_cli_topics_map_.find (o)); + + if (i != _cli_topics_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool topics:: + _parse (::bdep::cli::scanner& s, + ::bdep::cli::unknown_mode opt_mode, + ::bdep::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bdep::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; + } + + 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 (co.c_str ()), + const_cast (v) + }; + + ::bdep::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 ::bdep::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 + }; + + ::bdep::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 ::bdep::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bdep::cli::unknown_mode::stop: + { + break; + } + case ::bdep::cli::unknown_mode::fail: + { + throw ::bdep::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bdep::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bdep::cli::unknown_mode::stop: + { + break; + } + case ::bdep::cli::unknown_mode::fail: + { + throw ::bdep::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } + + // options + // + + options:: + options () + : help_ (), + version_ () + { + } + + bool options:: + parse (int& argc, + char** argv, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool options:: + parse (::bdep::cli::scanner& s, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void options:: + merge (const options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // common_options base + // + ::bdep::common_options::merge (a); + + if (a.help_) + { + ::bdep::cli::parser< bool>::merge ( + this->help_, a.help_); + } + + if (a.version_) + { + ::bdep::cli::parser< bool>::merge ( + this->version_, a.version_); + } + } + + ::bdep::cli::usage_para options:: + print_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + // common_options base + // + p = ::bdep::common_options::print_usage (os, p); + + return p; + } + + struct _cli_options_desc_type: ::bdep::cli::options + { + _cli_options_desc_type () + { + ::bdep::options::fill (*this); + } + }; + + void options:: + fill (::bdep::cli::options& os) + { + // common_options base + // + ::bdep::common_options::fill (os); + + // --help + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--help", a, true, dv); + os.push_back (o); + } + + // --version + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--version", a, true, dv); + os.push_back (o); + } + } + + const ::bdep::cli::options& options:: + description () + { + static _cli_options_desc_type _cli_options_desc_; + return _cli_options_desc_; + } + + typedef + std::map + _cli_options_map; + + static _cli_options_map _cli_options_map_; + + struct _cli_options_map_init + { + _cli_options_map_init () + { + _cli_options_map_["--help"] = + &::bdep::cli::thunk< options, &options::help_ >; + _cli_options_map_["--version"] = + &::bdep::cli::thunk< options, &options::version_ >; + } + }; + + static _cli_options_map_init _cli_options_map_init_; + + bool options:: + _parse (const char* o, ::bdep::cli::scanner& s) + { + _cli_options_map::const_iterator i (_cli_options_map_.find (o)); + + if (i != _cli_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // common_options base + // + if (::bdep::common_options::_parse (o, s)) + return true; + + return false; + } + + bool options:: + _parse (::bdep::cli::scanner& s, + ::bdep::cli::unknown_mode opt_mode, + ::bdep::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bdep::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; + } + + 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 (co.c_str ()), + const_cast (v) + }; + + ::bdep::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 ::bdep::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 + }; + + ::bdep::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 ::bdep::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bdep::cli::unknown_mode::stop: + { + break; + } + case ::bdep::cli::unknown_mode::fail: + { + throw ::bdep::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bdep::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bdep::cli::unknown_mode::stop: + { + break; + } + case ::bdep::cli::unknown_mode::fail: + { + throw ::bdep::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bdep +{ + ::bdep::cli::usage_para + print_bdep_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbdep --help\033[0m" << ::std::endl + << "\033[1mbdep --version\033[0m" << ::std::endl + << "\033[1mbdep help\033[0m [\033[4mcommand\033[0m | \033[4mtopic\033[0m]" << ::std::endl + << "\033[1mbdep\033[0m [\033[4mcommon-options\033[0m] \033[4mcommand\033[0m [\033[4mcommand-options\033[0m] \033[4mcommand-args\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mbuild2\033[0m project dependency manager is used to manage the dependencies of a" << ::std::endl + << "project during development." << ::std::endl + << ::std::endl + << "For a detailed description of any command or help topic, use the \033[1mhelp\033[0m command" << ::std::endl + << "or see the corresponding man page (the man pages have the \033[1mbdep-\033[0m prefix, for" << ::std::endl + << "example \033[1mbdep-help(1)\033[0m). Note also that \033[4mcommand-options\033[0m and \033[4mcommand-args\033[0m can be" << ::std::endl + << "specified in any order and \033[4mcommon-options\033[0m can be specified as part of" << ::std::endl + << "\033[4mcommand-options\033[0m." << ::std::endl; + + p = ::bdep::commands::print_usage (os, ::bdep::cli::usage_para::text); + + p = ::bdep::topics::print_usage (os, p); + + p = ::bdep::options::print_usage (os, p); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mEXIT STATUS\033[0m" << ::std::endl + << ::std::endl + << "Non-zero exit status is returned in case of an error." << ::std::endl + << ::std::endl + << "\033[1mENVIRONMENT\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mBDEP_DEF_OPT\033[0m environment variable is used to suppress loading of default" << ::std::endl + << "options files in nested \033[1mbdep\033[0m invocations. Its values are \033[1mfalse\033[0m or \033[1m0\033[0m to suppress" << ::std::endl + << "and \033[1mtrue\033[0m or \033[1m1\033[0m to load." << ::std::endl; + + p = ::bdep::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bdep/bdep-options.hxx b/bdep/bdep-options.hxx new file mode 100644 index 0000000..3d5d92d --- /dev/null +++ b/bdep/bdep-options.hxx @@ -0,0 +1,485 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BDEP_BDEP_OPTIONS_HXX +#define BDEP_BDEP_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include + +namespace bdep +{ + class commands + { + public: + commands (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (::bdep::cli::scanner&, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const commands&); + + // Option accessors and modifiers. + // + const bool& + help () const; + + bool& + help (); + + void + help (const bool&); + + const bool& + new_ () const; + + bool& + new_ (); + + void + new_ (const bool&); + + const bool& + init () const; + + bool& + init (); + + void + init (const bool&); + + const bool& + sync () const; + + bool& + sync (); + + void + sync (const bool&); + + const bool& + fetch () const; + + bool& + fetch (); + + void + fetch (const bool&); + + const bool& + status () const; + + bool& + status (); + + void + status (const bool&); + + const bool& + ci () const; + + bool& + ci (); + + void + ci (const bool&); + + const bool& + release () const; + + bool& + release (); + + void + release (const bool&); + + const bool& + publish () const; + + bool& + publish (); + + void + publish (const bool&); + + const bool& + deinit () const; + + bool& + deinit (); + + void + deinit (const bool&); + + const bool& + config () const; + + bool& + config (); + + void + config (const bool&); + + const bool& + test () const; + + bool& + test (); + + void + test (const bool&); + + const bool& + update () const; + + bool& + update (); + + void + update (const bool&); + + const bool& + clean () const; + + bool& + clean (); + + void + clean (const bool&); + + // Print usage information. + // + static ::bdep::cli::usage_para + print_usage (::std::ostream&, + ::bdep::cli::usage_para = ::bdep::cli::usage_para::none); + + // Option description. + // + static const ::bdep::cli::options& + description (); + + // Implementation details. + // + protected: + friend struct _cli_commands_desc_type; + + static void + fill (::bdep::cli::options&); + + bool + _parse (const char*, ::bdep::cli::scanner&); + + private: + bool + _parse (::bdep::cli::scanner&, + ::bdep::cli::unknown_mode option, + ::bdep::cli::unknown_mode argument); + + public: + bool help_; + bool new__; + bool init_; + bool sync_; + bool fetch_; + bool status_; + bool ci_; + bool release_; + bool publish_; + bool deinit_; + bool config_; + bool test_; + bool update_; + bool clean_; + }; + + class topics + { + public: + topics (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (::bdep::cli::scanner&, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const topics&); + + // Option accessors and modifiers. + // + const bool& + common_options () const; + + bool& + common_options (); + + void + common_options (const bool&); + + const bool& + projects_configs () const; + + bool& + projects_configs (); + + void + projects_configs (const bool&); + + const bool& + default_options_files () const; + + bool& + default_options_files (); + + void + default_options_files (const bool&); + + const bool& + argument_grouping () const; + + bool& + argument_grouping (); + + void + argument_grouping (const bool&); + + // Print usage information. + // + static ::bdep::cli::usage_para + print_usage (::std::ostream&, + ::bdep::cli::usage_para = ::bdep::cli::usage_para::none); + + // Option description. + // + static const ::bdep::cli::options& + description (); + + // Implementation details. + // + protected: + friend struct _cli_topics_desc_type; + + static void + fill (::bdep::cli::options&); + + bool + _parse (const char*, ::bdep::cli::scanner&); + + private: + bool + _parse (::bdep::cli::scanner&, + ::bdep::cli::unknown_mode option, + ::bdep::cli::unknown_mode argument); + + public: + bool common_options_; + bool projects_configs_; + bool default_options_files_; + bool argument_grouping_; + }; + + class options: public ::bdep::common_options + { + public: + options (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (::bdep::cli::scanner&, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const options&); + + // Option accessors and modifiers. + // + const bool& + help () const; + + bool& + help (); + + void + help (const bool&); + + const bool& + version () const; + + bool& + version (); + + void + version (const bool&); + + // Print usage information. + // + static ::bdep::cli::usage_para + print_usage (::std::ostream&, + ::bdep::cli::usage_para = ::bdep::cli::usage_para::none); + + // Option description. + // + static const ::bdep::cli::options& + description (); + + // Implementation details. + // + protected: + friend struct _cli_options_desc_type; + + static void + fill (::bdep::cli::options&); + + bool + _parse (const char*, ::bdep::cli::scanner&); + + private: + bool + _parse (::bdep::cli::scanner&, + ::bdep::cli::unknown_mode option, + ::bdep::cli::unknown_mode argument); + + public: + bool help_; + bool version_; + }; +} + +// Print page usage information. +// +namespace bdep +{ + ::bdep::cli::usage_para + print_bdep_usage (::std::ostream&, + ::bdep::cli::usage_para = ::bdep::cli::usage_para::none); +} + +#include + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BDEP_BDEP_OPTIONS_HXX diff --git a/bdep/bdep-options.ixx b/bdep/bdep-options.ixx new file mode 100644 index 0000000..c046f4a --- /dev/null +++ b/bdep/bdep-options.ixx @@ -0,0 +1,387 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bdep +{ + // commands + // + + inline const bool& commands:: + help () const + { + return this->help_; + } + + inline bool& commands:: + help () + { + return this->help_; + } + + inline void commands:: + help (const bool& x) + { + this->help_ = x; + } + + inline const bool& commands:: + new_ () const + { + return this->new__; + } + + inline bool& commands:: + new_ () + { + return this->new__; + } + + inline void commands:: + new_ (const bool& x) + { + this->new__ = x; + } + + inline const bool& commands:: + init () const + { + return this->init_; + } + + inline bool& commands:: + init () + { + return this->init_; + } + + inline void commands:: + init (const bool& x) + { + this->init_ = x; + } + + inline const bool& commands:: + sync () const + { + return this->sync_; + } + + inline bool& commands:: + sync () + { + return this->sync_; + } + + inline void commands:: + sync (const bool& x) + { + this->sync_ = x; + } + + inline const bool& commands:: + fetch () const + { + return this->fetch_; + } + + inline bool& commands:: + fetch () + { + return this->fetch_; + } + + inline void commands:: + fetch (const bool& x) + { + this->fetch_ = x; + } + + inline const bool& commands:: + status () const + { + return this->status_; + } + + inline bool& commands:: + status () + { + return this->status_; + } + + inline void commands:: + status (const bool& x) + { + this->status_ = x; + } + + inline const bool& commands:: + ci () const + { + return this->ci_; + } + + inline bool& commands:: + ci () + { + return this->ci_; + } + + inline void commands:: + ci (const bool& x) + { + this->ci_ = x; + } + + inline const bool& commands:: + release () const + { + return this->release_; + } + + inline bool& commands:: + release () + { + return this->release_; + } + + inline void commands:: + release (const bool& x) + { + this->release_ = x; + } + + inline const bool& commands:: + publish () const + { + return this->publish_; + } + + inline bool& commands:: + publish () + { + return this->publish_; + } + + inline void commands:: + publish (const bool& x) + { + this->publish_ = x; + } + + inline const bool& commands:: + deinit () const + { + return this->deinit_; + } + + inline bool& commands:: + deinit () + { + return this->deinit_; + } + + inline void commands:: + deinit (const bool& x) + { + this->deinit_ = x; + } + + inline const bool& commands:: + config () const + { + return this->config_; + } + + inline bool& commands:: + config () + { + return this->config_; + } + + inline void commands:: + config (const bool& x) + { + this->config_ = x; + } + + inline const bool& commands:: + test () const + { + return this->test_; + } + + inline bool& commands:: + test () + { + return this->test_; + } + + inline void commands:: + test (const bool& x) + { + this->test_ = x; + } + + inline const bool& commands:: + update () const + { + return this->update_; + } + + inline bool& commands:: + update () + { + return this->update_; + } + + inline void commands:: + update (const bool& x) + { + this->update_ = x; + } + + inline const bool& commands:: + clean () const + { + return this->clean_; + } + + inline bool& commands:: + clean () + { + return this->clean_; + } + + inline void commands:: + clean (const bool& x) + { + this->clean_ = x; + } + + // topics + // + + inline const bool& topics:: + common_options () const + { + return this->common_options_; + } + + inline bool& topics:: + common_options () + { + return this->common_options_; + } + + inline void topics:: + common_options (const bool& x) + { + this->common_options_ = x; + } + + inline const bool& topics:: + projects_configs () const + { + return this->projects_configs_; + } + + inline bool& topics:: + projects_configs () + { + return this->projects_configs_; + } + + inline void topics:: + projects_configs (const bool& x) + { + this->projects_configs_ = x; + } + + inline const bool& topics:: + default_options_files () const + { + return this->default_options_files_; + } + + inline bool& topics:: + default_options_files () + { + return this->default_options_files_; + } + + inline void topics:: + default_options_files (const bool& x) + { + this->default_options_files_ = x; + } + + inline const bool& topics:: + argument_grouping () const + { + return this->argument_grouping_; + } + + inline bool& topics:: + argument_grouping () + { + return this->argument_grouping_; + } + + inline void topics:: + argument_grouping (const bool& x) + { + this->argument_grouping_ = x; + } + + // options + // + + inline const bool& options:: + help () const + { + return this->help_; + } + + inline bool& options:: + help () + { + return this->help_; + } + + inline void options:: + help (const bool& x) + { + this->help_ = x; + } + + inline const bool& options:: + version () const + { + return this->version_; + } + + inline bool& options:: + version () + { + return this->version_; + } + + inline void options:: + version (const bool& x) + { + this->version_ = x; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bdep/ci-options.cxx b/bdep/ci-options.cxx new file mode 100644 index 0000000..582f327 --- /dev/null +++ b/bdep/ci-options.cxx @@ -0,0 +1,1231 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include +#include +// +// End prologue. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace bdep +{ + namespace cli + { + template + 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; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser + { + static void + parse (bool& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser + { + 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; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template + struct parser > + { + static void + parse (std::pair& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser::parse (x.first, xs, s); + } + + static void + merge (std::pair& b, const std::pair& a) + { + b = a; + } + }; + + template + struct parser > + { + static void + parse (std::vector& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector& b, const std::vector& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template + struct parser > + { + static void + parse (std::set& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set& b, const std::set& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template + struct parser > + { + static void + parse (std::map& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + 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 (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map& b, const std::map& a) + { + for (typename std::map::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template + struct parser > + { + static void + parse (std::multimap& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + 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 (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (v, dummy, s); + } + + m.insert (typename std::multimap::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap& b, const std::multimap& a) + { + for (typename std::multimap::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap::value_type (i->first, + i->second)); + } + }; + + template + void + thunk (X& x, scanner& s) + { + parser::parse (x.*M, s); + } + + template + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + template + void + thunk (X& x, scanner& s) + { + parser::parse (x.*M, x.*S, s); + } + } +} + +#include + +namespace bdep +{ + // cmd_ci_options + // + + cmd_ci_options:: + cmd_ci_options () + : yes_ (), + interactive_ (), + interactive_specified_ (false), + server_ (), + server_specified_ (false), + repository_ (), + repository_specified_ (false), + override_ (), + override_specified_ (false), + overrides_file_ (), + overrides_file_specified_ (false), + builds_ (), + builds_specified_ (false), + build_config_ (), + build_config_specified_ (false), + target_config_ (), + target_config_specified_ (false), + package_config_ (), + package_config_specified_ (false), + build_email_ (), + build_email_specified_ (false), + overrides_ (), + overrides_specified_ (false), + simulate_ (), + simulate_specified_ (false), + forward_ () + { + } + + bool cmd_ci_options:: + parse (int& argc, + char** argv, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cmd_ci_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cmd_ci_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cmd_ci_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cmd_ci_options:: + parse (::bdep::cli::scanner& s, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void cmd_ci_options:: + merge (const cmd_ci_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // project_options base + // + ::bdep::project_options::merge (a); + + if (a.yes_) + { + ::bdep::cli::parser< bool>::merge ( + this->yes_, a.yes_); + } + + if (a.interactive_specified_) + { + ::bdep::cli::parser< string>::merge ( + this->interactive_, a.interactive_); + this->interactive_specified_ = true; + } + + if (a.server_specified_) + { + ::bdep::cli::parser< url>::merge ( + this->server_, a.server_); + this->server_specified_ = true; + } + + if (a.repository_specified_) + { + ::bdep::cli::parser< url>::merge ( + this->repository_, a.repository_); + this->repository_specified_ = true; + } + + if (a.override_specified_) + { + ::bdep::cli::parser< strings>::merge ( + this->override_, a.override_); + this->override_specified_ = true; + } + + if (a.overrides_file_specified_) + { + ::bdep::cli::parser< path>::merge ( + this->overrides_file_, a.overrides_file_); + this->overrides_file_specified_ = true; + } + + if (a.builds_specified_) + { + ::bdep::cli::parser< strings>::merge ( + this->builds_, a.builds_); + this->builds_specified_ = true; + } + + if (a.build_config_specified_) + { + ::bdep::cli::parser< strings>::merge ( + this->build_config_, a.build_config_); + this->build_config_specified_ = true; + } + + if (a.target_config_specified_) + { + ::bdep::cli::parser< strings>::merge ( + this->target_config_, a.target_config_); + this->target_config_specified_ = true; + } + + if (a.package_config_specified_) + { + ::bdep::cli::parser< strings>::merge ( + this->package_config_, a.package_config_); + this->package_config_specified_ = true; + } + + if (a.build_email_specified_) + { + ::bdep::cli::parser< string>::merge ( + this->build_email_, a.build_email_); + this->build_email_specified_ = true; + } + + if (a.overrides_specified_) + { + ::bdep::cli::parser< cmd_ci_override>::merge ( + this->overrides_, a.overrides_); + this->overrides_specified_ = true; + } + + if (a.simulate_specified_) + { + ::bdep::cli::parser< string>::merge ( + this->simulate_, a.simulate_); + this->simulate_specified_ = true; + } + + if (a.forward_) + { + ::bdep::cli::parser< bool>::merge ( + this->forward_, a.forward_); + } + } + + ::bdep::cli::usage_para cmd_ci_options:: + print_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCI OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--yes\033[0m|\033[1m-y\033[0m Don't prompt for confirmation before submitting." << ::std::endl; + + os << std::endl + << "\033[1m--interactive\033[0m|\033[1m-i\033[0m \033[4mcf\033[0m[:\033[4mbp\033[0m] Test the package interactively in the specified build" << ::std::endl + << " configuration, pausing the execution at the specified" << ::std::endl + << " breakpoint. The build configuration is a target" << ::std::endl + << " configuration (\033[4mtc\033[0m), optionally for a specific package" << ::std::endl + << " configuration (\033[4mpc\033[0m) and/or for a specific target (\033[4mtg\033[0m):" << ::std::endl + << ::std::endl + << " \033[4mcf\033[0m = [\033[4mpc\033[0m\033[1m/\033[0m]\033[4mtc\033[0m | \033[4mpc\033[0m\033[1m/\033[0m\033[4mtc\033[0m\033[1m/\033[0m\033[4mtg\033[0m\033[0m" << ::std::endl + << ::std::endl + << " Refer to the \033[1m--build-config\033[0m option for details on the" << ::std::endl + << " build configuration component semantics. Note that" << ::std::endl + << " for interactive testing they should identify a single" << ::std::endl + << " build configuration. Failed that, the test request" << ::std::endl + << " will be aborted." << ::std::endl + << ::std::endl + << " Valid breakpoint values are \033[1mnone\033[0m (don't stop), \033[1merror\033[0m" << ::std::endl + << " (stop after first error), \033[1mwarning\033[0m (stop after first" << ::std::endl + << " warning), as well as the CI service-specific step ids" << ::std::endl + << " in which case the execution stops before performing" << ::std::endl + << " the specified step (see \033[1mbbot\033[0m worker step ids" << ::std::endl + << " (bbot#arch-worker)). If no breakpoint is specified," << ::std::endl + << " then \033[1merror\033[0m is assumed." << ::std::endl; + + os << std::endl + << "\033[1m--server\033[0m \033[4murl\033[0m CI server to submit the request to." << ::std::endl; + + os << std::endl + << "\033[1m--repository\033[0m \033[4murl\033[0m Remote repository URL for the project." << ::std::endl; + + os << std::endl + << "\033[1m--override\033[0m \033[4mname\033[0m:\033[4mvalue\033[0m Package manifest value override. Repeat this option" << ::std::endl + << " to override multiple values." << ::std::endl; + + os << std::endl + << "\033[1m--overrides-file\033[0m \033[4mfile\033[0m Read manifest value overrides from the specified" << ::std::endl + << " manifest fragment file. Repeat this option to specify" << ::std::endl + << " multiple override files." << ::std::endl; + + os << std::endl + << "\033[1m--builds\033[0m [\033[4mpc\033[0m/]\033[4mclass-expr\033[0m Shortcut for the following option:" << ::std::endl + << ::std::endl + << " \033[1m--override \033[0m[\033[4mpc\033[0m\033[1m-\033[0m]\033[1mbuilds:\033[0m\033[4mclass-expr\033[0m\033[0m" << ::std::endl + << ::std::endl + << " Repeat this option to specify multiple build target" << ::std::endl + << " configuration classes." << ::std::endl; + + os << std::endl + << "\033[1m--build-config\033[0m \033[4mpc\033[0m/\033[4mtc\033[0m[/\033[4mtg\033[0m] Shortcut for the following options sequence:" << ::std::endl + << ::std::endl + << " [\033[1m--override \033[0m\033[4mpc\033[0m\033[1m-builds:all\033[0m\033[0m]" << ::std::endl + << " \033[1m--override \033[0m\033[4mpc\033[0m\033[1m-build-include:\033[0m\033[4mtc\033[0m[\033[1m/\033[0m\033[4mtg\033[0m]\033[0m" << ::std::endl + << " \033[1m--override \033[0m\033[4mpc\033[0m\033[1m-build-exclude:**\033[0m\033[0m" << ::std::endl + << ::std::endl + << " The first override is omitted from the above sequence" << ::std::endl + << " if the \033[4mpc\033[0m\033[1m-builds\033[0m\033[0m override is specified on the command" << ::std::endl + << " line." << ::std::endl + << ::std::endl + << " Repeat this option to specify multiple build" << ::std::endl + << " configurations." << ::std::endl; + + os << std::endl + << "\033[1m--target-config\033[0m \033[4mtc\033[0m[/\033[4mtg\033[0m] Shortcut for the following options sequence:" << ::std::endl + << ::std::endl + << " [\033[1m--override builds:all\033[0m\033[0m]" << ::std::endl + << " \033[1m--override build-include:\033[0m\033[4mtc\033[0m[\033[1m/\033[0m\033[4mtg\033[0m]\033[0m" << ::std::endl + << " \033[1m--override build-exclude:**\033[0m\033[0m" << ::std::endl + << ::std::endl + << " The first override is omitted from the above sequence" << ::std::endl + << " if the \033[1mbuilds\033[0m override is specified on the command" << ::std::endl + << " line." << ::std::endl + << ::std::endl + << " Repeat this option to specify multiple build target" << ::std::endl + << " configurations." << ::std::endl; + + os << std::endl + << "\033[1m--package-config\033[0m \033[4mpc\033[0m Shortcut for the following options sequence:" << ::std::endl + << ::std::endl + << " \033[1m--override \033[0m\033[4mpc\033[0m\033[1m-builds:\033[0m...\033[0m" << ::std::endl + << " \033[1m--override \033[0m\033[4mpc\033[0m\033[1m-build-include:\033[0m...\033[0m" << ::std::endl + << " \033[1m--override \033[0m\033[4mpc\033[0m\033[1m-build-exclude:\033[0m...\033[0m" << ::std::endl + << ::std::endl + << " Where the override values are the build constraints" << ::std::endl + << " for the specified build package configuration from" << ::std::endl + << " the package manifest." << ::std::endl + << ::std::endl + << " Repeat this option to specify multiple build package" << ::std::endl + << " configurations." << ::std::endl; + + os << std::endl + << "\033[1m--build-email\033[0m \033[4memail\033[0m Shortcut for the following option:" << ::std::endl + << ::std::endl + << " \033[1m--override build-email:\033[0m\033[4memail\033[0m\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--simulate\033[0m \033[4moutcome\033[0m Simulate the specified outcome of the CI process" << ::std::endl + << " without actually performing any externally visible" << ::std::endl + << " actions (such as testing the packages or publishing" << ::std::endl + << " the result). The commonly used outcome value is" << ::std::endl + << " \033[1msuccess\033[0m. For other recognized outcomes refer to the" << ::std::endl + << " CI service documentation." << ::std::endl; + + os << std::endl + << "\033[1m--forward\033[0m Use the forwarded configuration for each package" << ::std::endl + << " instead of the default configuration." << ::std::endl; + + p = ::bdep::cli::usage_para::option; + + // project_options base + // + p = ::bdep::project_options::print_usage (os, p); + + return p; + } + + struct _cli_cmd_ci_options_desc_type: ::bdep::cli::options + { + _cli_cmd_ci_options_desc_type () + { + ::bdep::cmd_ci_options::fill (*this); + } + }; + + void cmd_ci_options:: + fill (::bdep::cli::options& os) + { + // project_options base + // + ::bdep::project_options::fill (os); + + // --yes + // + { + ::bdep::cli::option_names a; + a.push_back ("-y"); + std::string dv; + ::bdep::cli::option o ("--yes", a, true, dv); + os.push_back (o); + } + + // --interactive + // + { + ::bdep::cli::option_names a; + a.push_back ("-i"); + std::string dv; + ::bdep::cli::option o ("--interactive", a, false, dv); + os.push_back (o); + } + + // --server + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--server", a, false, dv); + os.push_back (o); + } + + // --repository + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--repository", a, false, dv); + os.push_back (o); + } + + // --override + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--override", a, false, dv); + os.push_back (o); + } + + // --overrides-file + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--overrides-file", a, false, dv); + os.push_back (o); + } + + // --builds + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--builds", a, false, dv); + os.push_back (o); + } + + // --build-config + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--build-config", a, false, dv); + os.push_back (o); + } + + // --target-config + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--target-config", a, false, dv); + os.push_back (o); + } + + // --package-config + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--package-config", a, false, dv); + os.push_back (o); + } + + // --build-email + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--build-email", a, false, dv); + os.push_back (o); + } + + // --overrides + // + { + ::bdep::cli::option_names a; + a.push_back ("--override"); + a.push_back ("--overrides-file"); + a.push_back ("--builds"); + a.push_back ("--build-email"); + std::string dv; + ::bdep::cli::option o ("--overrides", a, false, dv); + os.push_back (o); + } + + // --simulate + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--simulate", a, false, dv); + os.push_back (o); + } + + // --forward + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--forward", a, true, dv); + os.push_back (o); + } + } + + const ::bdep::cli::options& cmd_ci_options:: + description () + { + static _cli_cmd_ci_options_desc_type _cli_cmd_ci_options_desc_; + return _cli_cmd_ci_options_desc_; + } + + typedef + std::map + _cli_cmd_ci_options_map; + + static _cli_cmd_ci_options_map _cli_cmd_ci_options_map_; + + struct _cli_cmd_ci_options_map_init + { + _cli_cmd_ci_options_map_init () + { + _cli_cmd_ci_options_map_["--yes"] = + &::bdep::cli::thunk< cmd_ci_options, &cmd_ci_options::yes_ >; + _cli_cmd_ci_options_map_["-y"] = + &::bdep::cli::thunk< cmd_ci_options, &cmd_ci_options::yes_ >; + _cli_cmd_ci_options_map_["--interactive"] = + &::bdep::cli::thunk< cmd_ci_options, string, &cmd_ci_options::interactive_, + &cmd_ci_options::interactive_specified_ >; + _cli_cmd_ci_options_map_["-i"] = + &::bdep::cli::thunk< cmd_ci_options, string, &cmd_ci_options::interactive_, + &cmd_ci_options::interactive_specified_ >; + _cli_cmd_ci_options_map_["--server"] = + &::bdep::cli::thunk< cmd_ci_options, url, &cmd_ci_options::server_, + &cmd_ci_options::server_specified_ >; + _cli_cmd_ci_options_map_["--repository"] = + &::bdep::cli::thunk< cmd_ci_options, url, &cmd_ci_options::repository_, + &cmd_ci_options::repository_specified_ >; + _cli_cmd_ci_options_map_["--override"] = + &::bdep::cli::thunk< cmd_ci_options, strings, &cmd_ci_options::override_, + &cmd_ci_options::override_specified_ >; + _cli_cmd_ci_options_map_["--overrides-file"] = + &::bdep::cli::thunk< cmd_ci_options, path, &cmd_ci_options::overrides_file_, + &cmd_ci_options::overrides_file_specified_ >; + _cli_cmd_ci_options_map_["--builds"] = + &::bdep::cli::thunk< cmd_ci_options, strings, &cmd_ci_options::builds_, + &cmd_ci_options::builds_specified_ >; + _cli_cmd_ci_options_map_["--build-config"] = + &::bdep::cli::thunk< cmd_ci_options, strings, &cmd_ci_options::build_config_, + &cmd_ci_options::build_config_specified_ >; + _cli_cmd_ci_options_map_["--target-config"] = + &::bdep::cli::thunk< cmd_ci_options, strings, &cmd_ci_options::target_config_, + &cmd_ci_options::target_config_specified_ >; + _cli_cmd_ci_options_map_["--package-config"] = + &::bdep::cli::thunk< cmd_ci_options, strings, &cmd_ci_options::package_config_, + &cmd_ci_options::package_config_specified_ >; + _cli_cmd_ci_options_map_["--build-email"] = + &::bdep::cli::thunk< cmd_ci_options, string, &cmd_ci_options::build_email_, + &cmd_ci_options::build_email_specified_ >; + _cli_cmd_ci_options_map_["--overrides"] = + &::bdep::cli::thunk< cmd_ci_options, cmd_ci_override, &cmd_ci_options::overrides_, + &cmd_ci_options::overrides_specified_ >; + _cli_cmd_ci_options_map_["--override"] = + &::bdep::cli::thunk< cmd_ci_options, cmd_ci_override, &cmd_ci_options::overrides_, + &cmd_ci_options::overrides_specified_ >; + _cli_cmd_ci_options_map_["--overrides-file"] = + &::bdep::cli::thunk< cmd_ci_options, cmd_ci_override, &cmd_ci_options::overrides_, + &cmd_ci_options::overrides_specified_ >; + _cli_cmd_ci_options_map_["--builds"] = + &::bdep::cli::thunk< cmd_ci_options, cmd_ci_override, &cmd_ci_options::overrides_, + &cmd_ci_options::overrides_specified_ >; + _cli_cmd_ci_options_map_["--build-email"] = + &::bdep::cli::thunk< cmd_ci_options, cmd_ci_override, &cmd_ci_options::overrides_, + &cmd_ci_options::overrides_specified_ >; + _cli_cmd_ci_options_map_["--simulate"] = + &::bdep::cli::thunk< cmd_ci_options, string, &cmd_ci_options::simulate_, + &cmd_ci_options::simulate_specified_ >; + _cli_cmd_ci_options_map_["--forward"] = + &::bdep::cli::thunk< cmd_ci_options, &cmd_ci_options::forward_ >; + } + }; + + static _cli_cmd_ci_options_map_init _cli_cmd_ci_options_map_init_; + + bool cmd_ci_options:: + _parse (const char* o, ::bdep::cli::scanner& s) + { + _cli_cmd_ci_options_map::const_iterator i (_cli_cmd_ci_options_map_.find (o)); + + if (i != _cli_cmd_ci_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // project_options base + // + if (::bdep::project_options::_parse (o, s)) + return true; + + return false; + } + + bool cmd_ci_options:: + _parse (::bdep::cli::scanner& s, + ::bdep::cli::unknown_mode opt_mode, + ::bdep::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bdep::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; + } + + 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 (co.c_str ()), + const_cast (v) + }; + + ::bdep::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 ::bdep::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 + }; + + ::bdep::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 ::bdep::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bdep::cli::unknown_mode::stop: + { + break; + } + case ::bdep::cli::unknown_mode::fail: + { + throw ::bdep::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bdep::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bdep::cli::unknown_mode::stop: + { + break; + } + case ::bdep::cli::unknown_mode::fail: + { + throw ::bdep::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bdep +{ + ::bdep::cli::usage_para + print_bdep_ci_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbdep ci\033[0m [\033[4moptions\033[0m] [\033[4mcfg-spec\033[0m] [\033[4mpkg-spec\033[0m]\033[0m" << ::std::endl + << ::std::endl + << "\033[4mcfg-spec\033[0m = (\033[1m@\033[0m\033[4mcfg-name\033[0m | \033[1m--config\033[0m|\033[1m-c\033[0m \033[4mcfg-dir\033[0m)... | \033[1m--all\033[0m|\033[1m-a\033[0m | \033[1m--forward\033[0m" << ::std::endl + << "\033[4mpkg-spec\033[0m = (\033[4mpkg\033[0m | (\033[1m--directory\033[0m|\033[1m-d\033[0m \033[4mpkg-dir\033[0m))... | \033[4mprj-spec\033[0m" << ::std::endl + << "\033[4mprj-spec\033[0m = \033[1m--directory\033[0m|\033[1m-d\033[0m \033[4mprj-dir\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mci\033[0m command submits the project packages test request to a CI server." << ::std::endl + << ::std::endl + << "If no project or package directory is specified, then the current working" << ::std::endl + << "directory is assumed. If no configuration is specified, then the default" << ::std::endl + << "configurations are used. If the specified directory is a project directory," << ::std::endl + << "then all the packages initialized in the configurations are submitted, unless" << ::std::endl + << "the \033[1m--forward\033[0m option is specified (see below). See \033[1mbdep-projects-configs(1)\033[0m for" << ::std::endl + << "details on specifying projects and configurations." << ::std::endl + << ::std::endl + << "A CI request consists of the specified packages and their versions as well as" << ::std::endl + << "the project's remote version control repository URL corresponding to the" << ::std::endl + << "current (local) state of the project. The CI server should be able to fetch" << ::std::endl + << "these package versions from this repository as well as any dependencies from" << ::std::endl + << "this repository or its prerequisite/complement repositories, according to each" << ::std::endl + << "package's \033[1mrepositories.manifest\033[0m." << ::std::endl + << ::std::endl + << "If the CI server is not explicitly specified with the \033[1m--server\033[0m option, the" << ::std::endl + << "request is submitted to \033[1mci.cppget.org\033[0m by default." << ::std::endl + << ::std::endl + << "Unless the remote repository URL is specified with the \033[1m--repository\033[0m option, it" << ::std::endl + << "will be automatically derived from the version control's \"remote\" URL. In case" << ::std::endl + << "of \033[1mgit(1)\033[0m, it will be based on the \033[1mremote.origin.url\033[0m configuration value unless" << ::std::endl + << "overridden with \033[1mremote.origin.build2Url\033[0m. The repository URL is then adjusted to" << ::std::endl + << "corresponding to the current (local) state of the project. In case of \033[1mgit(1)\033[0m," << ::std::endl + << "the current branch and commit id are added as the repository URL fragment (see" << ::std::endl + << "\033[1mbpkg-repository-types(1)\033[0m for details)." << ::std::endl + << ::std::endl + << "Some package manifest values can be overridden as part of the CI request" << ::std::endl + << "submission using the \033[1m--override\033[0m and \033[1m--overrides-file\033[0m options as well as their" << ::std::endl + << "\033[1m--builds\033[0m, \033[1m--build-config\033[0m, \033[1m--target-config\033[0m, \033[1m--package-config\033[0m, and \033[1m--build-email\033[0m" << ::std::endl + << "shortcuts. This is primarily useful for specifying alternative build" << ::std::endl + << "configurations and/or build notification emails. For example:" << ::std::endl + << ::std::endl + << "$ bdep ci --builds gcc" << ::std::endl + << "$ bdep ci --builds network/gcc" << ::std::endl + << "$ bdep ci --target-config 'linux*-gcc*'" << ::std::endl + << "$ bdep ci --package-config network" << ::std::endl + << "$ bdep ci --build-config 'network/linux*-gcc*'" << ::std::endl + << ::std::endl + << "$ bdep ci --override \\" << ::std::endl + << " 'default-build-config: config.foo.cache=true config.foo.buffer=16'" << ::std::endl + << ::std::endl + << "$ bdep ci --override 'mytest-build-config: config.foo.cache=true' \\" << ::std::endl + << " --package-config mytest" << ::std::endl + << ::std::endl + << "$ bdep ci --override 'build-auxiliary: *-postgresql_16'" << ::std::endl + << ::std::endl + << "Manifest overrides other than [\033[1m*-\033[0m]\033[1mbuild-auxiliary\033[0m[\033[1m-*\033[0m]\033[0m override the entire value" << ::std::endl + << "group that they belong to. The [\033[1m*-\033[0m]\033[1mbuild-auxiliary\033[0m[\033[1m-*\033[0m]\033[0m values only override the" << ::std::endl + << "matching values, which are expected to already be present in the package" << ::std::endl + << "manifest. Currently, the following value groups/values can be overridden. The" << ::std::endl + << "\033[1mbuild-*email\033[0m group is overridden by default as if by specifying an empty build" << ::std::endl + << "email." << ::std::endl + << ::std::endl + << "build-email build-{warning,error}-email" << ::std::endl + << "builds build-{include,exclude}" << ::std::endl + << "build-bot" << ::std::endl + << "*-builds *-build-{include,exclude}" << ::std::endl + << "*-build-bot" << ::std::endl + << "*-build-config" << ::std::endl + << "*-build-email *-build-{warning,error}-email" << ::std::endl + << ::std::endl + << "[*-]build-auxiliary[-*]" << ::std::endl + << ::std::endl + << "For the package configuration-specific build constraint, email, auxiliary, and" << ::std::endl + << "custom bot public key overrides, the corresponding configuration must exist in" << ::std::endl + << "the package manifest. In contrast, the package configuration override" << ::std::endl + << "(\033[1m*-build-config\033[0m) adds a new configuration if it doesn't exist and updates the" << ::std::endl + << "arguments of the existing configuration otherwise. In the former case, all the" << ::std::endl + << "potential build constraint, email, auxiliary, and custom bot public key" << ::std::endl + << "overrides for such a newly added configuration must follow the corresponding" << ::std::endl + << "\033[1m*-build-config\033[0m override." << ::std::endl + << ::std::endl + << "Note that the build constraints group values (both common and build package" << ::std::endl + << "configuration-specific) are overridden hierarchically so that the" << ::std::endl + << "[\033[1m*-\033[0m]\033[1mbuild-\033[0m{\033[1minclude\033[0m,\033[1mexclude\033[0m}\033[0m overrides don't affect the respective [\033[1m*-\033[0m]\033[1mbuilds\033[0m\033[0m" << ::std::endl + << "values." << ::std::endl + << ::std::endl + << "Note also that the common and build package configuration-specific build" << ::std::endl + << "constraints group value overrides are mutually exclusive. If the common build" << ::std::endl + << "constraints are overridden, then all the configuration-specific constraints are" << ::std::endl + << "removed. Otherwise, if any configuration-specific constraints are overridden," << ::std::endl + << "then for the remaining configurations the build constraints are reset to" << ::std::endl + << "\033[1mbuilds: none\033[0m." << ::std::endl + << ::std::endl + << "Similar to the build constraints groups, the common and build package" << ::std::endl + << "configuration-specific custom bot public key value overrides are mutually" << ::std::endl + << "exclusive. If the common build custom bot public keys are overridden, then all" << ::std::endl + << "the configuration-specific custom bot public keys are removed. Otherwise, if" << ::std::endl + << "any configuration-specific custom bot public keys are overridden, then for the" << ::std::endl + << "remaining configurations the custom bot public keys are left unchanged." << ::std::endl + << ::std::endl + << "Similar to the above, the common and build package configuration-specific build" << ::std::endl + << "emails group value overrides are mutually exclusive. If the common build emails" << ::std::endl + << "are overridden, then all the configuration-specific emails are removed." << ::std::endl + << "Otherwise, if any configuration-specific emails are overridden, then for the" << ::std::endl + << "remaining configurations the build emails are reset to the empty values and the" << ::std::endl + << "build warning and error emails are removed (which effectively disables email" << ::std::endl + << "notifications for such configurations)." << ::std::endl + << ::std::endl + << "If supported by the CI service, a package can be tested interactively in a" << ::std::endl + << "specific build configuration using the \033[1m--interactive\033[0m|\033[1m-i\033[0m\033[0m option. In this mode" << ::std::endl + << "the CI service provides the login information for the execution environment and" << ::std::endl + << "pauses the testing at the specified breakpoint." << ::std::endl + << ::std::endl + << "While the exact interpretation of the CI request depends on the specific" << ::std::endl + << "service, normally, the CI server will respond with a reference that can be used" << ::std::endl + << "to query the results. See Package CI (brep#ci) for details on the CI request" << ::std::endl + << "handling." << ::std::endl + << ::std::endl + << "If the \033[1m--forward\033[0m option is specified then the forwarded configurations are used" << ::std::endl + << "instead of the default configurations. In particular, this means that in this" << ::std::endl + << "mode the project doesn't need to be initialized and all that's required is for" << ::std::endl + << "package's source directories to be configured to forward to an out of source" << ::std::endl + << "build configuration (see \033[1mb(1)\033[0m for details on forwarded configurations). This," << ::std::endl + << "for example, can be used to submit packages that don't use the standard" << ::std::endl + << "version." << ::std::endl; + + p = ::bdep::cmd_ci_options::print_usage (os, ::bdep::cli::usage_para::text); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mDEFAULT OPTIONS FILES\033[0m" << ::std::endl + << ::std::endl + << "See \033[1mbdep-default-options-files(1)\033[0m for an overview of the default options files." << ::std::endl + << "For the \033[1mci\033[0m command the search start directory is the project directory. The" << ::std::endl + << "following options files are searched for in each directory and, if found," << ::std::endl + << "loaded in the order listed:" << ::std::endl + << ::std::endl + << "bdep.options" << ::std::endl + << "bdep-ci.options" << ::std::endl + << ::std::endl + << "The following \033[1mci\033[0m command options cannot be specified in the default options" << ::std::endl + << "files:" << ::std::endl + << ::std::endl + << "--directory|-d" << ::std::endl; + + p = ::bdep::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bdep/ci-options.hxx b/bdep/ci-options.hxx new file mode 100644 index 0000000..da7f078 --- /dev/null +++ b/bdep/ci-options.hxx @@ -0,0 +1,345 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BDEP_CI_OPTIONS_HXX +#define BDEP_CI_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include + +#include + +namespace bdep +{ + class cmd_ci_options: public ::bdep::project_options + { + public: + cmd_ci_options (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (::bdep::cli::scanner&, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const cmd_ci_options&); + + // Option accessors and modifiers. + // + const bool& + yes () const; + + bool& + yes (); + + void + yes (const bool&); + + const string& + interactive () const; + + string& + interactive (); + + void + interactive (const string&); + + bool + interactive_specified () const; + + void + interactive_specified (bool); + + const url& + server () const; + + url& + server (); + + void + server (const url&); + + bool + server_specified () const; + + void + server_specified (bool); + + const url& + repository () const; + + url& + repository (); + + void + repository (const url&); + + bool + repository_specified () const; + + void + repository_specified (bool); + + const strings& + override () const; + + strings& + override (); + + void + override (const strings&); + + bool + override_specified () const; + + void + override_specified (bool); + + const path& + overrides_file () const; + + path& + overrides_file (); + + void + overrides_file (const path&); + + bool + overrides_file_specified () const; + + void + overrides_file_specified (bool); + + const strings& + builds () const; + + strings& + builds (); + + void + builds (const strings&); + + bool + builds_specified () const; + + void + builds_specified (bool); + + const strings& + build_config () const; + + strings& + build_config (); + + void + build_config (const strings&); + + bool + build_config_specified () const; + + void + build_config_specified (bool); + + const strings& + target_config () const; + + strings& + target_config (); + + void + target_config (const strings&); + + bool + target_config_specified () const; + + void + target_config_specified (bool); + + const strings& + package_config () const; + + strings& + package_config (); + + void + package_config (const strings&); + + bool + package_config_specified () const; + + void + package_config_specified (bool); + + const string& + build_email () const; + + string& + build_email (); + + void + build_email (const string&); + + bool + build_email_specified () const; + + void + build_email_specified (bool); + + const cmd_ci_override& + overrides () const; + + cmd_ci_override& + overrides (); + + void + overrides (const cmd_ci_override&); + + bool + overrides_specified () const; + + void + overrides_specified (bool); + + const string& + simulate () const; + + string& + simulate (); + + void + simulate (const string&); + + bool + simulate_specified () const; + + void + simulate_specified (bool); + + const bool& + forward () const; + + bool& + forward (); + + void + forward (const bool&); + + // Print usage information. + // + static ::bdep::cli::usage_para + print_usage (::std::ostream&, + ::bdep::cli::usage_para = ::bdep::cli::usage_para::none); + + // Option description. + // + static const ::bdep::cli::options& + description (); + + // Implementation details. + // + protected: + friend struct _cli_cmd_ci_options_desc_type; + + static void + fill (::bdep::cli::options&); + + bool + _parse (const char*, ::bdep::cli::scanner&); + + private: + bool + _parse (::bdep::cli::scanner&, + ::bdep::cli::unknown_mode option, + ::bdep::cli::unknown_mode argument); + + public: + bool yes_; + string interactive_; + bool interactive_specified_; + url server_; + bool server_specified_; + url repository_; + bool repository_specified_; + strings override_; + bool override_specified_; + path overrides_file_; + bool overrides_file_specified_; + strings builds_; + bool builds_specified_; + strings build_config_; + bool build_config_specified_; + strings target_config_; + bool target_config_specified_; + strings package_config_; + bool package_config_specified_; + string build_email_; + bool build_email_specified_; + cmd_ci_override overrides_; + bool overrides_specified_; + string simulate_; + bool simulate_specified_; + bool forward_; + }; +} + +// Print page usage information. +// +namespace bdep +{ + ::bdep::cli::usage_para + print_bdep_ci_usage (::std::ostream&, + ::bdep::cli::usage_para = ::bdep::cli::usage_para::none); +} + +#include + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BDEP_CI_OPTIONS_HXX diff --git a/bdep/ci-options.ixx b/bdep/ci-options.ixx new file mode 100644 index 0000000..2d5d3bd --- /dev/null +++ b/bdep/ci-options.ixx @@ -0,0 +1,417 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bdep +{ + // cmd_ci_options + // + + inline const bool& cmd_ci_options:: + yes () const + { + return this->yes_; + } + + inline bool& cmd_ci_options:: + yes () + { + return this->yes_; + } + + inline void cmd_ci_options:: + yes (const bool& x) + { + this->yes_ = x; + } + + inline const string& cmd_ci_options:: + interactive () const + { + return this->interactive_; + } + + inline string& cmd_ci_options:: + interactive () + { + return this->interactive_; + } + + inline void cmd_ci_options:: + interactive (const string& x) + { + this->interactive_ = x; + } + + inline bool cmd_ci_options:: + interactive_specified () const + { + return this->interactive_specified_; + } + + inline void cmd_ci_options:: + interactive_specified (bool x) + { + this->interactive_specified_ = x; + } + + inline const url& cmd_ci_options:: + server () const + { + return this->server_; + } + + inline url& cmd_ci_options:: + server () + { + return this->server_; + } + + inline void cmd_ci_options:: + server (const url& x) + { + this->server_ = x; + } + + inline bool cmd_ci_options:: + server_specified () const + { + return this->server_specified_; + } + + inline void cmd_ci_options:: + server_specified (bool x) + { + this->server_specified_ = x; + } + + inline const url& cmd_ci_options:: + repository () const + { + return this->repository_; + } + + inline url& cmd_ci_options:: + repository () + { + return this->repository_; + } + + inline void cmd_ci_options:: + repository (const url& x) + { + this->repository_ = x; + } + + inline bool cmd_ci_options:: + repository_specified () const + { + return this->repository_specified_; + } + + inline void cmd_ci_options:: + repository_specified (bool x) + { + this->repository_specified_ = x; + } + + inline const strings& cmd_ci_options:: + override () const + { + return this->override_; + } + + inline strings& cmd_ci_options:: + override () + { + return this->override_; + } + + inline void cmd_ci_options:: + override (const strings& x) + { + this->override_ = x; + } + + inline bool cmd_ci_options:: + override_specified () const + { + return this->override_specified_; + } + + inline void cmd_ci_options:: + override_specified (bool x) + { + this->override_specified_ = x; + } + + inline const path& cmd_ci_options:: + overrides_file () const + { + return this->overrides_file_; + } + + inline path& cmd_ci_options:: + overrides_file () + { + return this->overrides_file_; + } + + inline void cmd_ci_options:: + overrides_file (const path& x) + { + this->overrides_file_ = x; + } + + inline bool cmd_ci_options:: + overrides_file_specified () const + { + return this->overrides_file_specified_; + } + + inline void cmd_ci_options:: + overrides_file_specified (bool x) + { + this->overrides_file_specified_ = x; + } + + inline const strings& cmd_ci_options:: + builds () const + { + return this->builds_; + } + + inline strings& cmd_ci_options:: + builds () + { + return this->builds_; + } + + inline void cmd_ci_options:: + builds (const strings& x) + { + this->builds_ = x; + } + + inline bool cmd_ci_options:: + builds_specified () const + { + return this->builds_specified_; + } + + inline void cmd_ci_options:: + builds_specified (bool x) + { + this->builds_specified_ = x; + } + + inline const strings& cmd_ci_options:: + build_config () const + { + return this->build_config_; + } + + inline strings& cmd_ci_options:: + build_config () + { + return this->build_config_; + } + + inline void cmd_ci_options:: + build_config (const strings& x) + { + this->build_config_ = x; + } + + inline bool cmd_ci_options:: + build_config_specified () const + { + return this->build_config_specified_; + } + + inline void cmd_ci_options:: + build_config_specified (bool x) + { + this->build_config_specified_ = x; + } + + inline const strings& cmd_ci_options:: + target_config () const + { + return this->target_config_; + } + + inline strings& cmd_ci_options:: + target_config () + { + return this->target_config_; + } + + inline void cmd_ci_options:: + target_config (const strings& x) + { + this->target_config_ = x; + } + + inline bool cmd_ci_options:: + target_config_specified () const + { + return this->target_config_specified_; + } + + inline void cmd_ci_options:: + target_config_specified (bool x) + { + this->target_config_specified_ = x; + } + + inline const strings& cmd_ci_options:: + package_config () const + { + return this->package_config_; + } + + inline strings& cmd_ci_options:: + package_config () + { + return this->package_config_; + } + + inline void cmd_ci_options:: + package_config (const strings& x) + { + this->package_config_ = x; + } + + inline bool cmd_ci_options:: + package_config_specified () const + { + return this->package_config_specified_; + } + + inline void cmd_ci_options:: + package_config_specified (bool x) + { + this->package_config_specified_ = x; + } + + inline const string& cmd_ci_options:: + build_email () const + { + return this->build_email_; + } + + inline string& cmd_ci_options:: + build_email () + { + return this->build_email_; + } + + inline void cmd_ci_options:: + build_email (const string& x) + { + this->build_email_ = x; + } + + inline bool cmd_ci_options:: + build_email_specified () const + { + return this->build_email_specified_; + } + + inline void cmd_ci_options:: + build_email_specified (bool x) + { + this->build_email_specified_ = x; + } + + inline const cmd_ci_override& cmd_ci_options:: + overrides () const + { + return this->overrides_; + } + + inline cmd_ci_override& cmd_ci_options:: + overrides () + { + return this->overrides_; + } + + inline void cmd_ci_options:: + overrides (const cmd_ci_override& x) + { + this->overrides_ = x; + } + + inline bool cmd_ci_options:: + overrides_specified () const + { + return this->overrides_specified_; + } + + inline void cmd_ci_options:: + overrides_specified (bool x) + { + this->overrides_specified_ = x; + } + + inline const string& cmd_ci_options:: + simulate () const + { + return this->simulate_; + } + + inline string& cmd_ci_options:: + simulate () + { + return this->simulate_; + } + + inline void cmd_ci_options:: + simulate (const string& x) + { + this->simulate_ = x; + } + + inline bool cmd_ci_options:: + simulate_specified () const + { + return this->simulate_specified_; + } + + inline void cmd_ci_options:: + simulate_specified (bool x) + { + this->simulate_specified_ = x; + } + + inline const bool& cmd_ci_options:: + forward () const + { + return this->forward_; + } + + inline bool& cmd_ci_options:: + forward () + { + return this->forward_; + } + + inline void cmd_ci_options:: + forward (const bool& x) + { + this->forward_ = x; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bdep/clean-options.cxx b/bdep/clean-options.cxx new file mode 100644 index 0000000..8200b72 --- /dev/null +++ b/bdep/clean-options.cxx @@ -0,0 +1,758 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include +// +// End prologue. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace bdep +{ + namespace cli + { + template + 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; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser + { + static void + parse (bool& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser + { + 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; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template + struct parser > + { + static void + parse (std::pair& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser::parse (x.first, xs, s); + } + + static void + merge (std::pair& b, const std::pair& a) + { + b = a; + } + }; + + template + struct parser > + { + static void + parse (std::vector& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector& b, const std::vector& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template + struct parser > + { + static void + parse (std::set& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set& b, const std::set& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template + struct parser > + { + static void + parse (std::map& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + 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 (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map& b, const std::map& a) + { + for (typename std::map::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template + struct parser > + { + static void + parse (std::multimap& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + 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 (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (v, dummy, s); + } + + m.insert (typename std::multimap::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap& b, const std::multimap& a) + { + for (typename std::multimap::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap::value_type (i->first, + i->second)); + } + }; + + template + void + thunk (X& x, scanner& s) + { + parser::parse (x.*M, s); + } + + template + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + template + void + thunk (X& x, scanner& s) + { + parser::parse (x.*M, x.*S, s); + } + } +} + +#include + +namespace bdep +{ + // cmd_clean_options + // + + cmd_clean_options:: + cmd_clean_options () + : immediate_ (), + recursive_ () + { + } + + bool cmd_clean_options:: + parse (int& argc, + char** argv, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cmd_clean_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cmd_clean_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cmd_clean_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + ::bdep::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cmd_clean_options:: + parse (::bdep::cli::scanner& s, + ::bdep::cli::unknown_mode opt, + ::bdep::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void cmd_clean_options:: + merge (const cmd_clean_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // project_options base + // + ::bdep::project_options::merge (a); + + if (a.immediate_) + { + ::bdep::cli::parser< bool>::merge ( + this->immediate_, a.immediate_); + } + + if (a.recursive_) + { + ::bdep::cli::parser< bool>::merge ( + this->recursive_, a.recursive_); + } + } + + ::bdep::cli::usage_para cmd_clean_options:: + print_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCLEAN OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--immediate\033[0m|\033[1m-i\033[0m Also clean immediate dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m|\033[1m-r\033[0m Also clean all dependencies, recursively." << ::std::endl; + + p = ::bdep::cli::usage_para::option; + + // project_options base + // + p = ::bdep::project_options::print_usage (os, p); + + return p; + } + + struct _cli_cmd_clean_options_desc_type: ::bdep::cli::options + { + _cli_cmd_clean_options_desc_type () + { + ::bdep::cmd_clean_options::fill (*this); + } + }; + + void cmd_clean_options:: + fill (::bdep::cli::options& os) + { + // project_options base + // + ::bdep::project_options::fill (os); + + // --immediate + // + { + ::bdep::cli::option_names a; + a.push_back ("-i"); + std::string dv; + ::bdep::cli::option o ("--immediate", a, true, dv); + os.push_back (o); + } + + // --recursive + // + { + ::bdep::cli::option_names a; + a.push_back ("-r"); + std::string dv; + ::bdep::cli::option o ("--recursive", a, true, dv); + os.push_back (o); + } + } + + const ::bdep::cli::options& cmd_clean_options:: + description () + { + static _cli_cmd_clean_options_desc_type _cli_cmd_clean_options_desc_; + return _cli_cmd_clean_options_desc_; + } + + typedef + std::map + _cli_cmd_clean_options_map; + + static _cli_cmd_clean_options_map _cli_cmd_clean_options_map_; + + struct _cli_cmd_clean_options_map_init + { + _cli_cmd_clean_options_map_init () + { + _cli_cmd_clean_options_map_["--immediate"] = + &::bdep::cli::thunk< cmd_clean_options, &cmd_clean_options::immediate_ >; + _cli_cmd_clean_options_map_["-i"] = + &::bdep::cli::thunk< cmd_clean_options, &cmd_clean_options::immediate_ >; + _cli_cmd_clean_options_map_["--recursive"] = + &::bdep::cli::thunk< cmd_clean_options, &cmd_clean_options::recursive_ >; + _cli_cmd_clean_options_map_["-r"] = + &::bdep::cli::thunk< cmd_clean_options, &cmd_clean_options::recursive_ >; + } + }; + + static _cli_cmd_clean_options_map_init _cli_cmd_clean_options_map_init_; + + bool cmd_clean_options:: + _parse (const char* o, ::bdep::cli::scanner& s) + { + _cli_cmd_clean_options_map::const_iterator i (_cli_cmd_clean_options_map_.find (o)); + + if (i != _cli_cmd_clean_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // project_options base + // + if (::bdep::project_options::_parse (o, s)) + return true; + + return false; + } + + bool cmd_clean_options:: + _parse (::bdep::cli::scanner& s, + ::bdep::cli::unknown_mode opt_mode, + ::bdep::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bdep::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; + } + + 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 (co.c_str ()), + const_cast (v) + }; + + ::bdep::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 ::bdep::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 + }; + + ::bdep::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 ::bdep::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bdep::cli::unknown_mode::stop: + { + break; + } + case ::bdep::cli::unknown_mode::fail: + { + throw ::bdep::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bdep::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bdep::cli::unknown_mode::stop: + { + break; + } + case ::bdep::cli::unknown_mode::fail: + { + throw ::bdep::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bdep +{ + ::bdep::cli::usage_para + print_bdep_clean_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbdep clean\033[0m [\033[4moptions\033[0m] [\033[4mpkg-spec\033[0m] [\033[4mcfg-spec\033[0m] [\033[4mcfg-var\033[0m...]\033[0m" << ::std::endl + << ::std::endl + << "\033[4mcfg-spec\033[0m = (\033[1m@\033[0m\033[4mcfg-name\033[0m | \033[1m--config\033[0m|\033[1m-c\033[0m \033[4mcfg-dir\033[0m)... | \033[1m--all\033[0m|\033[1m-a\033[0m" << ::std::endl + << "\033[4mpkg-spec\033[0m = (\033[4mpkg\033[0m | (\033[1m--directory\033[0m|\033[1m-d\033[0m \033[4mpkg-dir\033[0m))... | \033[4mprj-spec\033[0m" << ::std::endl + << "\033[4mprj-spec\033[0m = \033[1m--directory\033[0m|\033[1m-d\033[0m \033[4mprj-dir\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mclean\033[0m command cleans the project packages in one or more build" << ::std::endl + << "configurations. Additionally, immediate or all dependencies of the project" << ::std::endl + << "packages can be cleaned by specifying the \033[1m--immediate\033[0m|\033[1m-i\033[0m\033[0m or \033[1m--recursive\033[0m|\033[1m-r\033[0m\033[0m" << ::std::endl + << "options, respectively." << ::std::endl + << ::std::endl + << "Underneath \033[1mclean\033[0m executes the \033[1mbpkg-pkg-clean(1)\033[0m command which itself is not" << ::std::endl + << "much more than the build system \033[1mclean\033[0m operation (see \033[1mb(1)\033[0m for details). As a" << ::std::endl + << "result, the main utility of this command is the ability to refer to build" << ::std::endl + << "configurations by names and to project packages implicitly via the current" << ::std::endl + << "working directory as well as to clean dependencies." << ::std::endl + << ::std::endl + << "If no project or package directory is specified, then the current working" << ::std::endl + << "directory is assumed. If no configuration is specified, then the default" << ::std::endl + << "configurations are assumed. See \033[1mbdep-projects-configs(1)\033[0m for details on" << ::std::endl + << "specifying projects and configurations. Optional \033[4mcfg-var\033[0m...\033[0m are the additional" << ::std::endl + << "configuration variables to pass to the build system." << ::std::endl; + + p = ::bdep::cmd_clean_options::print_usage (os, ::bdep::cli::usage_para::text); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mDEFAULT OPTIONS FILES\033[0m" << ::std::endl + << ::std::endl + << "See \033[1mbdep-default-options-files(1)\033[0m for an overview of the default options files." << ::std::endl + << "For the \033[1mclean\033[0m command the search start directory is the project directory. The" << ::std::endl + << "following options files are searched for in each directory and, if found," << ::std::endl + << "loaded in the order listed:" << ::std::endl + << ::std::endl + << "bdep.options" << ::std::endl + << "bdep-clean.options" << ::std::endl + << ::std::endl + << "The following \033[1mclean\033[0m command options cannot be specified in the default options" << ::std::endl + << "files:" << ::std::endl + << ::std::endl + << "--directory|-d" << ::std::endl; + + p = ::bdep::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bdep/clean-options.hxx b/bdep/clean-options.hxx new file mode 100644 index 0000000..9f0ad65 --- /dev/null +++ b/bdep/clean-options.hxx @@ -0,0 +1,139 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BDEP_CLEAN_OPTIONS_HXX +#define BDEP_CLEAN_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include + +namespace bdep +{ + class cmd_clean_options: public ::bdep::project_options + { + public: + cmd_clean_options (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + bool + parse (::bdep::cli::scanner&, + ::bdep::cli::unknown_mode option = ::bdep::cli::unknown_mode::fail, + ::bdep::cli::unknown_mode argument = ::bdep::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const cmd_clean_options&); + + // Option accessors and modifiers. + // + const bool& + immediate () const; + + bool& + immediate (); + + void + immediate (const bool&); + + const bool& + recursive () const; + + bool& + recursive (); + + void + recursive (const bool&); + + // Print usage information. + // + static ::bdep::cli::usage_para + print_usage (::std::ostream&, + ::bdep::cli::usage_para = ::bdep::cli::usage_para::none); + + // Option description. + // + static const ::bdep::cli::options& + description (); + + // Implementation details. + // + protected: + friend struct _cli_cmd_clean_options_desc_type; + + static void + fill (::bdep::cli::options&); + + bool + _parse (const char*, ::bdep::cli::scanner&); + + private: + bool + _parse (::bdep::cli::scanner&, + ::bdep::cli::unknown_mode option, + ::bdep::cli::unknown_mode argument); + + public: + bool immediate_; + bool recursive_; + }; +} + +// Print page usage information. +// +namespace bdep +{ + ::bdep::cli::usage_para + print_bdep_clean_usage (::std::ostream&, + ::bdep::cli::usage_para = ::bdep::cli::usage_para::none); +} + +#include + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BDEP_CLEAN_OPTIONS_HXX diff --git a/bdep/clean-options.ixx b/bdep/clean-options.ixx new file mode 100644 index 0000000..e6270a0 --- /dev/null +++ b/bdep/clean-options.ixx @@ -0,0 +1,57 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bdep +{ + // cmd_clean_options + // + + inline const bool& cmd_clean_options:: + immediate () const + { + return this->immediate_; + } + + inline bool& cmd_clean_options:: + immediate () + { + return this->immediate_; + } + + inline void cmd_clean_options:: + immediate (const bool& x) + { + this->immediate_ = x; + } + + inline const bool& cmd_clean_options:: + recursive () const + { + return this->recursive_; + } + + inline bool& cmd_clean_options:: + recursive () + { + return this->recursive_; + } + + inline void cmd_clean_options:: + recursive (const bool& x) + { + this->recursive_ = x; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bdep/common-options.cxx b/bdep/common-options.cxx new file mode 100644 index 0000000..f386c04 --- /dev/null +++ b/bdep/common-options.cxx @@ -0,0 +1,2034 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include +// +// End prologue. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace bdep +{ + namespace cli + { + // unknown_option + // + unknown_option:: + ~unknown_option () noexcept + { + } + + void unknown_option:: + print (::std::ostream& os) const + { + os << "unknown option '" << option ().c_str () << "'"; + } + + const char* unknown_option:: + what () const noexcept + { + return "unknown option"; + } + + // unknown_argument + // + unknown_argument:: + ~unknown_argument () noexcept + { + } + + void unknown_argument:: + print (::std::ostream& os) const + { + os << "unknown argument '" << argument ().c_str () << "'"; + } + + const char* unknown_argument:: + what () const noexcept + { + return "unknown argument"; + } + + // missing_value + // + missing_value:: + ~missing_value () noexcept + { + } + + void missing_value:: + print (::std::ostream& os) const + { + os << "missing value for option '" << option ().c_str () << "'"; + } + + const char* missing_value:: + what () const noexcept + { + return "missing option value"; + } + + // invalid_value + // + invalid_value:: + ~invalid_value () noexcept + { + } + + 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 noexcept + { + return "invalid option value"; + } + + // eos_reached + // + void eos_reached:: + print (::std::ostream& os) const + { + os << what (); + } + + const char* eos_reached:: + what () const noexcept + { + return "end of argument stream reached"; + } + + // file_io_failure + // + file_io_failure:: + ~file_io_failure () noexcept + { + } + + void file_io_failure:: + print (::std::ostream& os) const + { + os << "unable to open file '" << file ().c_str () << "' or read failure"; + } + + const char* file_io_failure:: + what () const noexcept + { + return "unable to open file or read failure"; + } + + // unmatched_quote + // + unmatched_quote:: + ~unmatched_quote () noexcept + { + } + + void unmatched_quote:: + print (::std::ostream& os) const + { + os << "unmatched quote in argument '" << argument ().c_str () << "'"; + } + + const char* unmatched_quote:: + what () const noexcept + { + return "unmatched quote"; + } + + // unexpected_group + // + unexpected_group:: + ~unexpected_group () noexcept + { + } + + void unexpected_group:: + print (::std::ostream& os) const + { + os << "unexpected grouped argument '" << group_ << "' " + << "for argument '" << argument_ << "'"; + } + + const char* unexpected_group:: + what () const noexcept + { + return "unexpected grouped argument"; + } + + // group_separator + // + group_separator:: + ~group_separator () noexcept + { + } + + void group_separator:: + print (::std::ostream& os) const + { + bool ex (!expected_.empty ()); + bool en (!encountered_.empty ()); + + if (ex) + { + os << "expected group separator '" << expected_ << "'"; + if (en) + os << " instead of '" << encountered_ << "'"; + } + else + os << "unexpected group separator '" << encountered_ << "'"; + + if (en) + os << ", use '\\" << encountered_ << "' to escape"; + } + + const char* group_separator:: + what () const noexcept + { + bool ex (!expected_.empty ()); + bool en (!encountered_.empty ()); + + return en + ? ex ? "wrong group separator" : "unexpected group separator" + : ex ? "expected group separator" : ""; + } + + // 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_; + + ++start_position_; + return r; + } + else + throw eos_reached (); + } + + void argv_scanner:: + skip () + { + if (i_ < argc_) + { + ++i_; + ++start_position_; + } + else + throw eos_reached (); + } + + std::size_t argv_scanner:: + position () + { + return start_position_; + } + + // 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 (); + } + + std::size_t vector_scanner:: + position () + { + return start_position_ + i_; + } + + // argv_file_scanner + // + int argv_file_scanner::zero_argc_ = 0; + std::string argv_file_scanner::empty_string_; + + bool argv_file_scanner:: + more () + { + if (!args_.empty ()) + return true; + + while (base::more ()) + { + // See if the next argument is the file option. + // + const char* a (base::peek ()); + const option_info* oi = 0; + const char* ov = 0; + + if (!skip_) + { + if ((oi = find (a)) != 0) + { + base::next (); + + if (!base::more ()) + throw missing_value (a); + + ov = base::next (); + } + else if (std::strncmp (a, "-", 1) == 0) + { + if ((ov = std::strchr (a, '=')) != 0) + { + std::string o (a, 0, ov - a); + if ((oi = find (o.c_str ())) != 0) + { + base::next (); + ++ov; + } + } + } + } + + if (oi != 0) + { + if (oi->search_func != 0) + { + std::string f (oi->search_func (ov, oi->arg)); + + if (!f.empty ()) + load (f); + } + else + load (ov); + + if (!args_.empty ()) + return true; + } + else + { + if (!skip_) + skip_ = (std::strcmp (a, "--") == 0); + + return true; + } + } + + return false; + } + + const char* argv_file_scanner:: + peek () + { + if (!more ()) + throw eos_reached (); + + return args_.empty () ? base::peek () : args_.front ().value.c_str (); + } + + const std::string& argv_file_scanner:: + peek_file () + { + if (!more ()) + throw eos_reached (); + + return args_.empty () ? empty_string_ : *args_.front ().file; + } + + std::size_t argv_file_scanner:: + peek_line () + { + if (!more ()) + throw eos_reached (); + + return args_.empty () ? 0 : args_.front ().line; + } + + const char* argv_file_scanner:: + next () + { + if (!more ()) + throw eos_reached (); + + if (args_.empty ()) + return base::next (); + else + { + hold_[i_ == 0 ? ++i_ : --i_].swap (args_.front ().value); + args_.pop_front (); + ++start_position_; + return hold_[i_].c_str (); + } + } + + void argv_file_scanner:: + skip () + { + if (!more ()) + throw eos_reached (); + + if (args_.empty ()) + return base::skip (); + else + { + args_.pop_front (); + ++start_position_; + } + } + + const argv_file_scanner::option_info* argv_file_scanner:: + find (const char* a) const + { + for (std::size_t i (0); i < options_count_; ++i) + if (std::strcmp (a, options_[i].option) == 0) + return &options_[i]; + + return 0; + } + + std::size_t argv_file_scanner:: + position () + { + return start_position_; + } + + void argv_file_scanner:: + load (const std::string& file) + { + using namespace std; + + ifstream is (file.c_str ()); + + if (!is.is_open ()) + throw file_io_failure (file); + + files_.push_back (file); + + arg a; + a.file = &*files_.rbegin (); + + for (a.line = 1; !is.eof (); ++a.line) + { + string line; + getline (is, line); + + if (is.fail () && !is.eof ()) + throw file_io_failure (file); + + string::size_type n (line.size ()); + + // Trim the line from leading and trailing whitespaces. + // + if (n != 0) + { + const char* f (line.c_str ()); + const char* l (f + n); + + const char* of (f); + while (f < l && (*f == ' ' || *f == '\t' || *f == '\r')) + ++f; + + --l; + + const char* ol (l); + while (l > f && (*l == ' ' || *l == '\t' || *l == '\r')) + --l; + + if (f != of || l != ol) + line = f <= l ? string (f, l - f + 1) : string (); + } + + // Ignore empty lines, those that start with #. + // + if (line.empty () || line[0] == '#') + continue; + + string::size_type p (string::npos); + if (line.compare (0, 1, "-") == 0) + { + p = line.find (' '); + + string::size_type q (line.find ('=')); + if (q != string::npos && q < p) + p = q; + } + + string s1; + if (p != string::npos) + { + s1.assign (line, 0, p); + + // Skip leading whitespaces in the argument. + // + if (line[p] == '=') + ++p; + else + { + n = line.size (); + for (++p; p < n; ++p) + { + char c (line[p]); + if (c != ' ' && c != '\t' && c != '\r') + break; + } + } + } + else if (!skip_) + skip_ = (line == "--"); + + string s2 (line, p != string::npos ? p : 0); + + // If the string (which is an option value or argument) is + // wrapped in quotes, remove them. + // + n = s2.size (); + char cf (s2[0]), cl (s2[n - 1]); + + if (cf == '"' || cf == '\'' || cl == '"' || cl == '\'') + { + if (n == 1 || cf != cl) + throw unmatched_quote (s2); + + s2 = string (s2, 1, n - 2); + } + + if (!s1.empty ()) + { + // See if this is another file option. + // + const option_info* oi; + if (!skip_ && (oi = find (s1.c_str ()))) + { + if (s2.empty ()) + throw missing_value (oi->option); + + if (oi->search_func != 0) + { + string f (oi->search_func (s2.c_str (), oi->arg)); + if (!f.empty ()) + load (f); + } + else + { + // If the path of the file being parsed is not simple and the + // path of the file that needs to be loaded is relative, then + // complete the latter using the former as a base. + // +#ifndef _WIN32 + string::size_type p (file.find_last_of ('/')); + bool c (p != string::npos && s2[0] != '/'); +#else + string::size_type p (file.find_last_of ("/\\")); + bool c (p != string::npos && s2[1] != ':'); +#endif + if (c) + s2.insert (0, file, 0, p + 1); + + load (s2); + } + + continue; + } + + a.value = s1; + args_.push_back (a); + } + + a.value = s2; + args_.push_back (a); + } + } + + // group_scanner + // + bool group_scanner:: + more () + { + // We don't want to call scan_group() here since that + // would invalidate references to previous arguments. + // But we do need to check that the previous group was + // handled. + // + if (state_ == scanned) + { + if (group_scan_.end () != group_.size ()) + throw unexpected_group (arg_[i_][j_], group_scan_.next ()); + } + + return j_ != 0 || scan_.more (); + } + + const char* group_scanner:: + peek () + { + if (state_ != peeked) + { + scan_group (); + state_ = peeked; + } + + // Return unescaped. + return arg_[i_][j_ - 1].c_str (); + } + + const char* group_scanner:: + next () + { + if (state_ != peeked) + scan_group (); + state_ = scanned; + // Return unescaped. + return arg_[i_][--j_].c_str (); + } + + void group_scanner:: + skip () + { + if (state_ != peeked) + scan_group (); + state_ = skipped; + --j_; + } + + std::size_t group_scanner:: + position () + { + return j_ == 0 ? scan_.position () : pos_ + (arg_[i_].size () - j_); + } + + void group_scanner:: + scan_group () + { + // If the previous argument has been scanned, then make + // sure the group has been scanned (handled) as well. + // + if (state_ == scanned) + { + if (group_scan_.end () != group_.size ()) + throw unexpected_group (arg_[i_][j_], group_scan_.next ()); + } + + // If we still have arguments in the pack, rewind the group. + // + if (j_ != 0) + { + group_scan_.reset (); + return; + } + + i_ += (i_ == 0 ? 1 : -1); + group_.clear (); + group_scan_.reset (); + pos_ = scan_.position (); + + // Note: using group_ won't cover empty groups and using + // j_ won't cover single-argument packs. + // + bool group (false), pack (false); + + do + { + const char* a (scan_.next ()); + size_t i (*a == '\\' ? 1 : 0); + separator s (sense (a + i)); + + if (s == none || i != 0) + { + if (arg_[i_].size () != 1) + arg_[i_].resize (1); + + arg_[i_][0] = a + (s != none ? i : 0); + j_ = 1; + break; + } + + // Start of a leading group for the next argument or + // argument pack. We will only know which once we see + // the closing separator. + // + if (s != open) + throw group_separator (a, ""); + + size_t n (group_.size ()); + + // Scan the group until the closing separator. + // + s = none; + while (s == none && scan_.more ()) + { + a = scan_.next (); + i = (*a == '\\' ? 1 : 0); + s = sense (a + i); + + if (s == none || i != 0) + { + group_.push_back (a + (s != none ? i : 0)); + s = none; + } + } + + if (s == close) + { + size_t m (group_.size ()); + + j_ = m - n; + if (j_ == 0) + throw group_separator ("{", ""); + + if (arg_[i_].size () != j_) + arg_[i_].resize (j_); + + // Move from group_ to arg_. Add in reverse for ease + // of iteration. + // + for (size_t j (0); j != j_; ++j) + arg_[i_][j] = group_[m - j - 1]; + group_.resize (n); + + pack = true; + break; + } + else if (s == close_plus) + group = true; + else + throw group_separator ((s != none ? a : ""), "}+"); + } + while (scan_.more ()); + + // Handle the case where we have seen the leading group + // but there are no more arguments. + // + if (group && j_ == 0) + throw group_separator ("{", ""); + + // Handle trailing groups, if any. + // + while (scan_.more ()) + { + const char* a (scan_.peek ()); + size_t i (*a == '\\' ? 1 : 0); + separator s (sense (a + i)); + + // Next argument, argument pack, or leading group. + // + if (s == none || s == open || i != 0) + break; + + if (s != open_plus) + throw group_separator (a, ""); + + group = true; + + // Scan the group until the closing separator. + // + scan_.next (); + s = none; + while (s == none && scan_.more ()) + { + a = scan_.next (); + i = (*a == '\\' ? 1 : 0); + s = sense (a + i); + + if (s == none || i != 0) + { + group_.push_back (a + (s != none ? i : 0)); + s = none; + } + } + + if (s != close) + throw group_separator ((s != none ? a : ""), "}"); + } + + // Handle the case where we have seen the argument pack + // without leading or trailing group. + // + if (pack && !group) + throw group_separator ("{", ""); + } + + void options:: + push_back (const option& o) + { + container_type::size_type n (size ()); + container_type::push_back (o); + map_[o.name ()] = n; + + for (option_names::const_iterator i (o.aliases ().begin ()); + i != o.aliases ().end (); ++i) + map_[*i] = n; + } + + template + 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; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser + { + static void + parse (bool& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser + { + 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; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template + struct parser > + { + static void + parse (std::pair& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser::parse (x.first, xs, s); + } + + static void + merge (std::pair& b, const std::pair& a) + { + b = a; + } + }; + + template + struct parser > + { + static void + parse (std::vector& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector& b, const std::vector& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template + struct parser > + { + static void + parse (std::set& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set& b, const std::set& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template + struct parser > + { + static void + parse (std::map& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + 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 (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map& b, const std::map& a) + { + for (typename std::map::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template + struct parser > + { + static void + parse (std::multimap& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + 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 (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser::parse (v, dummy, s); + } + + m.insert (typename std::multimap::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap& b, const std::multimap& a) + { + for (typename std::multimap::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap::value_type (i->first, + i->second)); + } + }; + + template + void + thunk (X& x, scanner& s) + { + parser::parse (x.*M, s); + } + + template + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + template + void + thunk (X& x, scanner& s) + { + parser::parse (x.*M, x.*S, s); + } + } +} + +#include + +namespace bdep +{ + // common_options + // + + common_options:: + common_options () + : v_ (), + V_ (), + quiet_ (), + verbose_ (1), + verbose_specified_ (false), + stdout_format_ (bdep::stdout_format::lines), + stdout_format_specified_ (false), + jobs_ (), + jobs_specified_ (false), + progress_ (), + no_progress_ (), + diag_color_ (), + no_diag_color_ (), + bpkg_ (), + bpkg_specified_ (false), + bpkg_option_ (), + bpkg_option_specified_ (false), + build_ (), + build_specified_ (false), + build_option_ (), + build_option_specified_ (false), + curl_ ("curl"), + curl_specified_ (false), + curl_option_ (), + curl_option_specified_ (false), + pager_ (), + pager_specified_ (false), + pager_option_ (), + pager_option_specified_ (false), + options_file_ (), + options_file_specified_ (false), + default_options_ (), + default_options_specified_ (false), + no_default_options_ () + { + } + + void common_options:: + merge (const common_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.v_) + { + ::bdep::cli::parser< bool>::merge ( + this->v_, a.v_); + } + + if (a.V_) + { + ::bdep::cli::parser< bool>::merge ( + this->V_, a.V_); + } + + if (a.quiet_) + { + ::bdep::cli::parser< bool>::merge ( + this->quiet_, a.quiet_); + } + + if (a.verbose_specified_) + { + ::bdep::cli::parser< uint16_t>::merge ( + this->verbose_, a.verbose_); + this->verbose_specified_ = true; + } + + if (a.stdout_format_specified_) + { + ::bdep::cli::parser< bdep::stdout_format>::merge ( + this->stdout_format_, a.stdout_format_); + this->stdout_format_specified_ = true; + } + + if (a.jobs_specified_) + { + ::bdep::cli::parser< size_t>::merge ( + this->jobs_, a.jobs_); + this->jobs_specified_ = true; + } + + if (a.progress_) + { + ::bdep::cli::parser< bool>::merge ( + this->progress_, a.progress_); + } + + if (a.no_progress_) + { + ::bdep::cli::parser< bool>::merge ( + this->no_progress_, a.no_progress_); + } + + if (a.diag_color_) + { + ::bdep::cli::parser< bool>::merge ( + this->diag_color_, a.diag_color_); + } + + if (a.no_diag_color_) + { + ::bdep::cli::parser< bool>::merge ( + this->no_diag_color_, a.no_diag_color_); + } + + if (a.bpkg_specified_) + { + ::bdep::cli::parser< path>::merge ( + this->bpkg_, a.bpkg_); + this->bpkg_specified_ = true; + } + + if (a.bpkg_option_specified_) + { + ::bdep::cli::parser< strings>::merge ( + this->bpkg_option_, a.bpkg_option_); + this->bpkg_option_specified_ = true; + } + + if (a.build_specified_) + { + ::bdep::cli::parser< path>::merge ( + this->build_, a.build_); + this->build_specified_ = true; + } + + if (a.build_option_specified_) + { + ::bdep::cli::parser< strings>::merge ( + this->build_option_, a.build_option_); + this->build_option_specified_ = true; + } + + if (a.curl_specified_) + { + ::bdep::cli::parser< path>::merge ( + this->curl_, a.curl_); + this->curl_specified_ = true; + } + + if (a.curl_option_specified_) + { + ::bdep::cli::parser< strings>::merge ( + this->curl_option_, a.curl_option_); + this->curl_option_specified_ = true; + } + + if (a.pager_specified_) + { + ::bdep::cli::parser< string>::merge ( + this->pager_, a.pager_); + this->pager_specified_ = true; + } + + if (a.pager_option_specified_) + { + ::bdep::cli::parser< strings>::merge ( + this->pager_option_, a.pager_option_); + this->pager_option_specified_ = true; + } + + if (a.options_file_specified_) + { + ::bdep::cli::parser< string>::merge ( + this->options_file_, a.options_file_); + this->options_file_specified_ = true; + } + + if (a.default_options_specified_) + { + ::bdep::cli::parser< dir_path>::merge ( + this->default_options_, a.default_options_); + this->default_options_specified_ = true; + } + + if (a.no_default_options_) + { + ::bdep::cli::parser< bool>::merge ( + this->no_default_options_, a.no_default_options_); + } + } + + ::bdep::cli::usage_para common_options:: + print_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCOMMON OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "The common options are summarized below with a more detailed description" << ::std::endl + << "available in \033[1mbdep-common-options(1)\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m-v\033[0m Print essential underlying commands being executed." << ::std::endl; + + os << "\033[1m-V\033[0m Print all underlying commands being executed." << ::std::endl; + + os << "\033[1m--quiet\033[0m|\033[1m-q\033[0m Run quietly, only printing error messages." << ::std::endl; + + os << "\033[1m--verbose\033[0m \033[4mlevel\033[0m Set the diagnostics verbosity to \033[4mlevel\033[0m between 0 and" << ::std::endl + << " 6." << ::std::endl; + + os << "\033[1m--stdout-format\033[0m \033[4mformat\033[0m Representation format to use for printing to \033[1mstdout\033[0m." << ::std::endl; + + os << "\033[1m--jobs\033[0m|\033[1m-j\033[0m \033[4mnum\033[0m Number of jobs to perform in parallel." << ::std::endl; + + os << "\033[1m--progress\033[0m Display progress indicators for long-lasting" << ::std::endl + << " operations, such as network transfers, building, etc." << ::std::endl; + + os << "\033[1m--no-progress\033[0m Suppress progress indicators for long-lasting" << ::std::endl + << " operations, such as network transfers, building, etc." << ::std::endl; + + os << "\033[1m--diag-color\033[0m Use color in diagnostics." << ::std::endl; + + os << "\033[1m--no-diag-color\033[0m Don't use color in diagnostics." << ::std::endl; + + os << "\033[1m--bpkg\033[0m \033[4mpath\033[0m The package manager program to be used for build" << ::std::endl + << " configuration management." << ::std::endl; + + os << "\033[1m--bpkg-option\033[0m \033[4mopt\033[0m Additional option to be passed to the package manager" << ::std::endl + << " program." << ::std::endl; + + os << "\033[1m--build\033[0m \033[4mpath\033[0m The build program to be used to build packages." << ::std::endl; + + os << "\033[1m--build-option\033[0m \033[4mopt\033[0m Additional option to be passed to the build program." << ::std::endl; + + os << "\033[1m--curl\033[0m \033[4mpath\033[0m The curl program to be used for network operations." << ::std::endl; + + os << "\033[1m--curl-option\033[0m \033[4mopt\033[0m Additional option to be passed to the curl program." << ::std::endl; + + os << "\033[1m--pager\033[0m \033[4mpath\033[0m The pager program to be used to show long text." << ::std::endl; + + os << "\033[1m--pager-option\033[0m \033[4mopt\033[0m Additional option to be passed to the pager program." << ::std::endl; + + os << "\033[1m--options-file\033[0m \033[4mfile\033[0m Read additional options from \033[4mfile\033[0m." << ::std::endl; + + os << "\033[1m--default-options\033[0m \033[4mdir\033[0m The directory to load additional default options" << ::std::endl + << " files from." << ::std::endl; + + os << "\033[1m--no-default-options\033[0m Don't load default options files." << ::std::endl; + + p = ::bdep::cli::usage_para::option; + + return p; + } + + ::bdep::cli::usage_para common_options:: + print_long_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCOMMON OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m-v\033[0m Print essential underlying commands being executed." << ::std::endl + << " This is equivalent to \033[1m--verbose 2\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m-V\033[0m Print all underlying commands being executed. This is" << ::std::endl + << " equivalent to \033[1m--verbose 3\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--quiet\033[0m|\033[1m-q\033[0m Run quietly, only printing error messages. This is" << ::std::endl + << " equivalent to \033[1m--verbose 0\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--verbose\033[0m \033[4mlevel\033[0m Set the diagnostics verbosity to \033[4mlevel\033[0m between 0 and" << ::std::endl + << " 6. Level 0 disables any non-error messages while" << ::std::endl + << " level 6 produces lots of information, with level 1" << ::std::endl + << " being the default. The following additional types of" << ::std::endl + << " diagnostics are produced at each level:" << ::std::endl + << ::std::endl + << " 1. High-level information messages." << ::std::endl + << " 2. Essential underlying commands being executed." << ::std::endl + << " 3. All underlying commands being executed." << ::std::endl + << " 4. Information that could be helpful to the user." << ::std::endl + << " 5. Information that could be helpful to the" << ::std::endl + << " developer." << ::std::endl + << " 6. Even more detailed information." << ::std::endl; + + os << std::endl + << "\033[1m--stdout-format\033[0m \033[4mformat\033[0m Representation format to use for printing to \033[1mstdout\033[0m." << ::std::endl + << " Valid values for this option are \033[1mlines\033[0m (default) and" << ::std::endl + << " \033[1mjson\033[0m. See the JSON OUTPUT section below for details" << ::std::endl + << " on the \033[1mjson\033[0m format." << ::std::endl; + + os << std::endl + << "\033[1m--jobs\033[0m|\033[1m-j\033[0m \033[4mnum\033[0m Number of jobs to perform in parallel. If this option" << ::std::endl + << " is not specified or specified with the 0\033[0m value, then" << ::std::endl + << " the number of available hardware threads is used." << ::std::endl + << " This option is also propagated when executing package" << ::std::endl + << " manager commands such as \033[1mbpkg-pkg-update(1)\033[0m," << ::std::endl + << " \033[1mbpkg-pkg-test(1)\033[0m, etc., which in turn propagate it to" << ::std::endl + << " the build system." << ::std::endl; + + os << std::endl + << "\033[1m--progress\033[0m Display progress indicators for long-lasting" << ::std::endl + << " operations, such as network transfers, building, etc." << ::std::endl + << " If printing to a terminal the progress is displayed" << ::std::endl + << " by default for low verbosity levels. Use" << ::std::endl + << " \033[1m--no-progress\033[0m to suppress." << ::std::endl; + + os << std::endl + << "\033[1m--no-progress\033[0m Suppress progress indicators for long-lasting" << ::std::endl + << " operations, such as network transfers, building, etc." << ::std::endl; + + os << std::endl + << "\033[1m--diag-color\033[0m Use color in diagnostics. If printing to a terminal" << ::std::endl + << " the color is used by default provided the terminal is" << ::std::endl + << " not dumb. Use \033[1m--no-diag-color\033[0m to suppress." << ::std::endl; + + os << std::endl + << "\033[1m--no-diag-color\033[0m Don't use color in diagnostics." << ::std::endl; + + os << std::endl + << "\033[1m--bpkg\033[0m \033[4mpath\033[0m The package manager program to be used for build" << ::std::endl + << " configuration management. This should be the path to" << ::std::endl + << " the \033[1mbpkg\033[0m executable. You can also specify additional" << ::std::endl + << " options that should be passed to the package manager" << ::std::endl + << " program with \033[1m--bpkg-option\033[0m." << ::std::endl + << ::std::endl + << " If the package manager program is not explicitly" << ::std::endl + << " specified, then \033[1mbdep\033[0m will by default use \033[1mbpkg\033[0m plus an" << ::std::endl + << " executable suffix if one was specified when building" << ::std::endl + << " \033[1mbdep\033[0m. So, for example, if \033[1mbdep\033[0m name was set to" << ::std::endl + << " \033[1mbdep-1.0\033[0m, then it will look for \033[1mbpkg-1.0\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--bpkg-option\033[0m \033[4mopt\033[0m Additional option to be passed to the package manager" << ::std::endl + << " program. See \033[1m--bpkg\033[0m for more information on the" << ::std::endl + << " package manager program. Repeat this option to" << ::std::endl + << " specify multiple package manager options." << ::std::endl; + + os << std::endl + << "\033[1m--build\033[0m \033[4mpath\033[0m The build program to be used to build packages. This" << ::std::endl + << " should be the path to the build2 \033[1mb\033[0m executable. You" << ::std::endl + << " can also specify additional options that should be" << ::std::endl + << " passed to the build program with \033[1m--build-option\033[0m." << ::std::endl + << ::std::endl + << " If the build program is not explicitly specified," << ::std::endl + << " then \033[1mbdep\033[0m will by default use \033[1mb\033[0m plus an executable" << ::std::endl + << " suffix if one was specified when building \033[1mbdep\033[0m. So," << ::std::endl + << " for example, if \033[1mbdep\033[0m name was set to \033[1mbdep-1.0\033[0m, then" << ::std::endl + << " it will look for \033[1mb-1.0\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--build-option\033[0m \033[4mopt\033[0m Additional option to be passed to the build program." << ::std::endl + << " See \033[1m--build\033[0m for more information on the build" << ::std::endl + << " program. Repeat this option to specify multiple build" << ::std::endl + << " options." << ::std::endl; + + os << std::endl + << "\033[1m--curl\033[0m \033[4mpath\033[0m The curl program to be used for network operations." << ::std::endl + << " You can also specify additional options that should" << ::std::endl + << " be passed to the curl program with \033[1m--curl-option\033[0m." << ::std::endl + << ::std::endl + << " If the curl program is not explicitly specified, then" << ::std::endl + << " \033[1mbdep\033[0m will use \033[1mcurl\033[0m by default. Note that this program" << ::std::endl + << " will also be used by the underlying \033[1mbpkg\033[0m invocations" << ::std::endl + << " unless overridden." << ::std::endl; + + os << std::endl + << "\033[1m--curl-option\033[0m \033[4mopt\033[0m Additional option to be passed to the curl program." << ::std::endl + << " See \033[1m--curl\033[0m for more information on the curl program." << ::std::endl + << " Repeat this option to specify multiple curl options." << ::std::endl + << ::std::endl + << " Note that these options will also be used by the" << ::std::endl + << " underlying \033[1mbpkg\033[0m invocations provided that curl is" << ::std::endl + << " used." << ::std::endl; + + os << std::endl + << "\033[1m--pager\033[0m \033[4mpath\033[0m The pager program to be used to show long text." << ::std::endl + << " Commonly used pager programs are \033[1mless\033[0m and \033[1mmore\033[0m. You" << ::std::endl + << " can also specify additional options that should be" << ::std::endl + << " passed to the pager program with \033[1m--pager-option\033[0m. If" << ::std::endl + << " an empty string is specified as the pager program," << ::std::endl + << " then no pager will be used. If the pager program is" << ::std::endl + << " not explicitly specified, then \033[1mbdep\033[0m will try to use" << ::std::endl + << " \033[1mless\033[0m. If it is not available, then no pager will be" << ::std::endl + << " used." << ::std::endl; + + os << std::endl + << "\033[1m--pager-option\033[0m \033[4mopt\033[0m Additional option to be passed to the pager program." << ::std::endl + << " See \033[1m--pager\033[0m for more information on the pager" << ::std::endl + << " program. Repeat this option to specify multiple pager" << ::std::endl + << " options." << ::std::endl; + + os << std::endl + << "\033[1m--options-file\033[0m \033[4mfile\033[0m Read additional options from \033[4mfile\033[0m. Each option should" << ::std::endl + << " appear on a separate line optionally followed by" << ::std::endl + << " space or equal sign (\033[1m=\033[0m) and an option value. Empty" << ::std::endl + << " lines and lines starting with \033[1m#\033[0m are ignored. Option" << ::std::endl + << " values can be enclosed in double (\033[1m\"\033[0m) or single (\033[1m'\033[0m)" << ::std::endl + << " quotes to preserve leading and trailing whitespaces" << ::std::endl + << " as well as to specify empty values. If the value" << ::std::endl + << " itself contains trailing or leading quotes, enclose" << ::std::endl + << " it with an extra pair of quotes, for example \033[1m'\"x\"'\033[0m." << ::std::endl + << " Non-leading and non-trailing quotes are interpreted" << ::std::endl + << " as being part of the option value." << ::std::endl + << ::std::endl + << " The semantics of providing options in a file is" << ::std::endl + << " equivalent to providing the same set of options in" << ::std::endl + << " the same order on the command line at the point where" << ::std::endl + << " the \033[1m--options-file\033[0m option is specified except that" << ::std::endl + << " the shell escaping and quoting is not required." << ::std::endl + << " Repeat this option to specify more than one options" << ::std::endl + << " file." << ::std::endl; + + os << std::endl + << "\033[1m--default-options\033[0m \033[4mdir\033[0m The directory to load additional default options" << ::std::endl + << " files from." << ::std::endl; + + os << std::endl + << "\033[1m--no-default-options\033[0m Don't load default options files." << ::std::endl; + + p = ::bdep::cli::usage_para::option; + + return p; + } + + struct _cli_common_options_desc_type: ::bdep::cli::options + { + _cli_common_options_desc_type () + { + ::bdep::common_options::fill (*this); + } + }; + + void common_options:: + fill (::bdep::cli::options& os) + { + // -v + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("-v", a, true, dv); + os.push_back (o); + } + + // -V + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("-V", a, true, dv); + os.push_back (o); + } + + // --quiet + // + { + ::bdep::cli::option_names a; + a.push_back ("-q"); + std::string dv; + ::bdep::cli::option o ("--quiet", a, true, dv); + os.push_back (o); + } + + // --verbose + // + { + ::bdep::cli::option_names a; + std::string dv ("1"); + ::bdep::cli::option o ("--verbose", a, false, dv); + os.push_back (o); + } + + // --stdout-format + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--stdout-format", a, false, dv); + os.push_back (o); + } + + // --jobs + // + { + ::bdep::cli::option_names a; + a.push_back ("-j"); + std::string dv; + ::bdep::cli::option o ("--jobs", a, false, dv); + os.push_back (o); + } + + // --progress + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--progress", a, true, dv); + os.push_back (o); + } + + // --no-progress + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--no-progress", a, true, dv); + os.push_back (o); + } + + // --diag-color + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--diag-color", a, true, dv); + os.push_back (o); + } + + // --no-diag-color + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--no-diag-color", a, true, dv); + os.push_back (o); + } + + // --bpkg + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--bpkg", a, false, dv); + os.push_back (o); + } + + // --bpkg-option + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--bpkg-option", a, false, dv); + os.push_back (o); + } + + // --build + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--build", a, false, dv); + os.push_back (o); + } + + // --build-option + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--build-option", a, false, dv); + os.push_back (o); + } + + // --curl + // + { + ::bdep::cli::option_names a; + std::string dv ("curl"); + ::bdep::cli::option o ("--curl", a, false, dv); + os.push_back (o); + } + + // --curl-option + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--curl-option", a, false, dv); + os.push_back (o); + } + + // --pager + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--pager", a, false, dv); + os.push_back (o); + } + + // --pager-option + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--pager-option", a, false, dv); + os.push_back (o); + } + + // --options-file + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--options-file", a, false, dv); + os.push_back (o); + } + + // --default-options + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--default-options", a, false, dv); + os.push_back (o); + } + + // --no-default-options + // + { + ::bdep::cli::option_names a; + std::string dv; + ::bdep::cli::option o ("--no-default-options", a, true, dv); + os.push_back (o); + } + } + + const ::bdep::cli::options& common_options:: + description () + { + static _cli_common_options_desc_type _cli_common_options_desc_; + return _cli_common_options_desc_; + } + + typedef + std::map + _cli_common_options_map; + + static _cli_common_options_map _cli_common_options_map_; + + struct _cli_common_options_map_init + { + _cli_common_options_map_init () + { + _cli_common_options_map_["-v"] = + &::bdep::cli::thunk< common_options, &common_options::v_ >; + _cli_common_options_map_["-V"] = + &::bdep::cli::thunk< common_options, &common_options::V_ >; + _cli_common_options_map_["--quiet"] = + &::bdep::cli::thunk< common_options, &common_options::quiet_ >; + _cli_common_options_map_["-q"] = + &::bdep::cli::thunk< common_options, &common_options::quiet_ >; + _cli_common_options_map_["--verbose"] = + &::bdep::cli::thunk< common_options, uint16_t, &common_options::verbose_, + &common_options::verbose_specified_ >; + _cli_common_options_map_["--stdout-format"] = + &::bdep::cli::thunk< common_options, bdep::stdout_format, &common_options::stdout_format_, + &common_options::stdout_format_specified_ >; + _cli_common_options_map_["--jobs"] = + &::bdep::cli::thunk< common_options, size_t, &common_options::jobs_, + &common_options::jobs_specified_ >; + _cli_common_options_map_["-j"] = + &::bdep::cli::thunk< common_options, size_t, &common_options::jobs_, + &common_options::jobs_specified_ >; + _cli_common_options_map_["--progress"] = + &::bdep::cli::thunk< common_options, &common_options::progress_ >; + _cli_common_options_map_["--no-progress"] = + &::bdep::cli::thunk< common_options, &common_options::no_progress_ >; + _cli_common_options_map_["--diag-color"] = + &::bdep::cli::thunk< common_options, &common_options::diag_color_ >; + _cli_common_options_map_["--no-diag-color"] = + &::bdep::cli::thunk< common_options, &common_options::no_diag_color_ >; + _cli_common_options_map_["--bpkg"] = + &::bdep::cli::thunk< common_options, path, &common_options::bpkg_, + &common_options::bpkg_specified_ >; + _cli_common_options_map_["--bpkg-option"] = + &::bdep::cli::thunk< common_options, strings, &common_options::bpkg_option_, + &common_options::bpkg_option_specified_ >; + _cli_common_options_map_["--build"] = + &::bdep::cli::thunk< common_options, path, &common_options::build_, + &common_options::build_specified_ >; + _cli_common_options_map_["--build-option"] = + &::bdep::cli::thunk< common_options, strings, &common_options::build_option_, + &common_options::build_option_specified_ >; + _cli_common_options_map_["--curl"] = + &::bdep::cli::thunk< common_options, path, &common_options::curl_, + &common_options::curl_specified_ >; + _cli_common_options_map_["--curl-option"] = + &::bdep::cli::thunk< common_options, strings, &common_options::curl_option_, + &common_options::curl_option_specified_ >; + _cli_common_options_map_["--pager"] = + &::bdep::cli::thunk< common_options, string, &common_options::pager_, + &common_options::pager_specified_ >; + _cli_common_options_map_["--pager-option"] = + &::bdep::cli::thunk< common_options, strings, &common_options::pager_option_, + &common_options::pager_option_specified_ >; + _cli_common_options_map_["--options-file"] = + &::bdep::cli::thunk< common_options, string, &common_options::options_file_, + &common_options::options_file_specified_ >; + _cli_common_options_map_["--default-options"] = + &::bdep::cli::thunk< common_options, dir_path, &common_options::default_options_, + &common_options::default_options_specified_ >; + _cli_common_options_map_["--no-default-options"] = + &::bdep::cli::thunk< common_options, &common_options::no_default_options_ >; + } + }; + + static _cli_common_options_map_init _cli_common_options_map_init_; + + bool common_options:: + _parse (const char* o, ::bdep::cli::scanner& s) + { + _cli_common_options_map::const_iterator i (_cli_common_options_map_.find (o)); + + if (i != _cli_common_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } +} + +namespace bdep +{ + ::bdep::cli::usage_para + print_bdep_common_options_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbdep\033[0m [\033[4mcommon-options\033[0m] ...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The common options control behavior that is common to all or most of the \033[1mbdep\033[0m" << ::std::endl + << "commands. They can be specified either before the command or after, together" << ::std::endl + << "with the command-specific options." << ::std::endl; + + p = ::bdep::common_options::print_usage (os, ::bdep::cli::usage_para::text); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mJSON OUTPUT\033[0m" << ::std::endl + << ::std::endl + << "Commands that support the JSON output specify their formats as a serialized" << ::std::endl + << "representation of a C++ \033[1mstruct\033[0m or an array thereof. For example:" << ::std::endl + << ::std::endl + << "struct package" << ::std::endl + << "{" << ::std::endl + << " string name;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct configuration" << ::std::endl + << "{" << ::std::endl + << " uint64_t id;" << ::std::endl + << " string path;" << ::std::endl + << " optional name;" << ::std::endl + << " bool default;" << ::std::endl + << " vector packages;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "An example of the serialized JSON representation of \033[1mstruct\033[0m \033[1mconfiguration\033[0m:" << ::std::endl + << ::std::endl + << "{" << ::std::endl + << " \"id\": 1," << ::std::endl + << " \"path\": \"/tmp/hello-gcc\"," << ::std::endl + << " \"name\": \"gcc\"," << ::std::endl + << " \"default\": true," << ::std::endl + << " \"packages\": [" << ::std::endl + << " {" << ::std::endl + << " \"name\": \"hello\"" << ::std::endl + << " }" << ::std::endl + << " ]" << ::std::endl + << "}" << ::std::endl + << ::std::endl + << "This sections provides details on the overall properties of such formats and" << ::std::endl + << "the semantics of the \033[1mstruct\033[0m serialization." << ::std::endl + << ::std::endl + << "The order of members in a JSON object is fixed as specified in the" << ::std::endl + << "corresponding \033[1mstruct\033[0m. While new members may be added in the future (and should" << ::std::endl + << "be ignored by older consumers), the semantics of the existing members" << ::std::endl + << "(including whether the top-level entry is an object or array) may not change." << ::std::endl + << ::std::endl + << "An object member is required unless its type is \033[1moptional<>\033[0m, \033[1mbool\033[0m, or \033[1mvector<>\033[0m" << ::std::endl + << "(array). For \033[1mbool\033[0m members absent means \033[1mfalse\033[0m. For \033[1mvector<>\033[0m members absent means" << ::std::endl + << "empty. An empty top-level array is always present." << ::std::endl + << ::std::endl + << "For example, the following JSON text is a possible serialization of the above" << ::std::endl + << "\033[1mstruct\033[0m \033[1mconfiguration\033[0m:" << ::std::endl + << ::std::endl + << "{" << ::std::endl + << " \"id\": 1," << ::std::endl + << " \"path\": \"/tmp/hello-gcc\"" << ::std::endl + << "}" << ::std::endl; + + p = ::bdep::cli::usage_para::text; + + return p; + } + + ::bdep::cli::usage_para + print_bdep_common_options_long_usage (::std::ostream& os, ::bdep::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbdep\033[0m [\033[4mcommon-options\033[0m] ...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The common options control behavior that is common to all or most of the \033[1mbdep\033[0m" << ::std::endl + << "commands. They can be specified either before the command or after, together" << ::std::endl + << "with the command-specific options." << ::std::endl; + + p = ::bdep::common_options::print_long_usage (os, ::bdep::cli::usage_para::text); + + if (p != ::bdep::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mJSON OUTPUT\033[0m" << ::std::endl + << ::std::endl + << "Commands that support the JSON output specify their formats as a serialized" << ::std::endl + << "representation of a C++ \033[1mstruct\033[0m or an array thereof. For example:" << ::std::endl + << ::std::endl + << "struct package" << ::std::endl + << "{" << ::std::endl + << " string name;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct configuration" << ::std::endl + << "{" << ::std::endl + << " uint64_t id;" << ::std::endl + << " string path;" << ::std::endl + << " optional name;" << ::std::endl + << " bool default;" << ::std::endl + << " vector packages;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "An example of the serialized JSON representation of \033[1mstruct\033[0m \033[1mconfiguration\033[0m:" << ::std::endl + << ::std::endl + << "{" << ::std::endl + << " \"id\": 1," << ::std::endl + << " \"path\": \"/tmp/hello-gcc\"," << ::std::endl + << " \"name\": \"gcc\"," << ::std::endl + << " \"default\": true," << ::std::endl + << " \"packages\": [" << ::std::endl + << " {" << ::std::endl + << " \"name\": \"hello\"" << ::std::endl + << " }" << ::std::endl + << " ]" << ::std::endl + << "}" << ::std::endl + << ::std::endl + << "This sections provides details on the overall properties of such formats and" << ::std::endl + << "the semantics of the \033[1mstruct\033[0m serialization." << ::std::endl + << ::std::endl + << "The order of members in a JSON object is fixed as specified in the" << ::std::endl + << "corresponding \033[1mstruct\033[0m. While new members may be added in the future (and should" << ::std::endl + << "be ignored by older consumers), the semantics of the existing members" << ::std::endl + << "(including whether the top-level entry is an object or array) may not change." << ::std::endl + << ::std::endl + << "An object member is required unless its type is \033[1moptional<>\033[0m, \033[1mbool\033[0m, or \033[1mvector<>\033[0m" << ::std::endl + << "(array). For \033[1mbool\033[0m members absent means \033[1mfalse\033[0m. For \033[1mvector<>\033[0m members absent means" << ::std::endl + << "empty. An empty top-level array is always present." << ::std::endl + << ::std::endl + << "For example, the following JSON text is a possible serialization of the above" << ::std::endl + << "\033[1mstruct\033[0m \033[1mconfiguration\033[0m:" << ::std::endl + << ::std::endl + << "{" << ::std::endl + << " \"id\": 1," << ::std::endl + << " \"path\": \"/tmp/hello-gcc\"" << ::std::endl + << "}" << ::std::endl; + + p = ::bdep::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bdep/common-options.hxx b/bdep/common-options.hxx new file mode 100644 index 0000000..fb9af76 --- /dev/null +++ b/bdep/common-options.hxx @@ -0,0 +1,1012 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BDEP_COMMON_OPTIONS_HXX +#define BDEP_COMMON_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 bdep +{ + namespace cli + { + class usage_para + { + public: + enum value + { + none, + text, + option + }; + + usage_para (value); + + operator value () const + { + return v_; + } + + private: + value v_; + }; + + 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 () noexcept; + + unknown_option (const std::string& option); + + const std::string& + option () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string option_; + }; + + class unknown_argument: public exception + { + public: + virtual + ~unknown_argument () noexcept; + + unknown_argument (const std::string& argument); + + const std::string& + argument () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string argument_; + }; + + class missing_value: public exception + { + public: + virtual + ~missing_value () noexcept; + + missing_value (const std::string& option); + + const std::string& + option () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string option_; + }; + + class invalid_value: public exception + { + public: + virtual + ~invalid_value () noexcept; + + 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 noexcept; + + 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 noexcept; + }; + + class file_io_failure: public exception + { + public: + virtual + ~file_io_failure () noexcept; + + file_io_failure (const std::string& file); + + const std::string& + file () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string file_; + }; + + class unmatched_quote: public exception + { + public: + virtual + ~unmatched_quote () noexcept; + + unmatched_quote (const std::string& argument); + + const std::string& + argument () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string argument_; + }; + + class unexpected_group: public exception + { + public: + virtual + ~unexpected_group () noexcept; + + unexpected_group (const std::string& argument, + const std::string& group); + + const std::string& + argument () const; + + const std::string& + group () const; + + virtual void + print (std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string argument_; + std::string group_; + }; + + class group_separator: public exception + { + public: + virtual + ~group_separator () noexcept; + + // Note: either (but not both) can be empty. + // + group_separator (const std::string& encountered, + const std::string& expected); + + const std::string& + encountered () const; + + const std::string& + expected () const; + + virtual void + print (std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string encountered_; + std::string expected_; + }; + + // 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(). + // + // The position() function returns a monotonically-increasing + // number which, if stored, can later be used to determine the + // relative position of the argument returned by the following + // call to next(). Note that if multiple scanners are used to + // extract arguments from multiple sources, then the end + // position of the previous scanner should be used as the + // start position of the next. + // + class scanner + { + public: + virtual + ~scanner (); + + virtual bool + more () = 0; + + virtual const char* + peek () = 0; + + virtual const char* + next () = 0; + + virtual void + skip () = 0; + + virtual std::size_t + position () = 0; + }; + + class argv_scanner: public scanner + { + public: + argv_scanner (int& argc, + char** argv, + bool erase = false, + std::size_t start_position = 0); + + argv_scanner (int start, + int& argc, + char** argv, + bool erase = false, + std::size_t start_position = 0); + + int + end () const; + + virtual bool + more (); + + virtual const char* + peek (); + + virtual const char* + next (); + + virtual void + skip (); + + virtual std::size_t + position (); + + protected: + std::size_t start_position_; + int i_; + int& argc_; + char** argv_; + bool erase_; + }; + + class vector_scanner: public scanner + { + public: + vector_scanner (const std::vector&, + std::size_t start = 0, + std::size_t start_position = 0); + + std::size_t + end () const; + + void + reset (std::size_t start = 0, std::size_t start_position = 0); + + virtual bool + more (); + + virtual const char* + peek (); + + virtual const char* + next (); + + virtual void + skip (); + + virtual std::size_t + position (); + + private: + std::size_t start_position_; + const std::vector& v_; + std::size_t i_; + }; + + class argv_file_scanner: public argv_scanner + { + public: + argv_file_scanner (int& argc, + char** argv, + const std::string& option, + bool erase = false, + std::size_t start_position = 0); + + argv_file_scanner (int start, + int& argc, + char** argv, + const std::string& option, + bool erase = false, + std::size_t start_position = 0); + + argv_file_scanner (const std::string& file, + const std::string& option, + std::size_t start_position = 0); + + struct option_info + { + // If search_func is not NULL, it is called, with the arg + // value as the second argument, to locate the options file. + // If it returns an empty string, then the file is ignored. + // + const char* option; + std::string (*search_func) (const char*, void* arg); + void* arg; + }; + + argv_file_scanner (int& argc, + char** argv, + const option_info* options, + std::size_t options_count, + bool erase = false, + std::size_t start_position = 0); + + argv_file_scanner (int start, + int& argc, + char** argv, + const option_info* options, + std::size_t options_count, + bool erase = false, + std::size_t start_position = 0); + + argv_file_scanner (const std::string& file, + const option_info* options = 0, + std::size_t options_count = 0, + std::size_t start_position = 0); + + virtual bool + more (); + + virtual const char* + peek (); + + virtual const char* + next (); + + virtual void + skip (); + + virtual std::size_t + position (); + + // Return the file path if the peeked at argument came from a file and + // the empty string otherwise. The reference is guaranteed to be valid + // till the end of the scanner lifetime. + // + const std::string& + peek_file (); + + // Return the 1-based line number if the peeked at argument came from + // a file and zero otherwise. + // + std::size_t + peek_line (); + + private: + const option_info* + find (const char*) const; + + void + load (const std::string& file); + + typedef argv_scanner base; + + const std::string option_; + option_info option_info_; + const option_info* options_; + std::size_t options_count_; + + struct arg + { + std::string value; + const std::string* file; + std::size_t line; + }; + + std::deque args_; + std::list files_; + + // Circular buffer of two arguments. + // + std::string hold_[2]; + std::size_t i_; + + bool skip_; + + static int zero_argc_; + static std::string empty_string_; + }; + + class group_scanner: public scanner + { + public: + group_scanner (scanner&); + + virtual bool + more (); + + virtual const char* + peek (); + + virtual const char* + next (); + + virtual void + skip (); + + virtual std::size_t + position (); + + // The group is only available after the call to next() + // (and skip() -- in case one needs to make sure the group + // was empty, or some such) and is only valid (and must be + // handled) until the next call to any of the scanner + // functions (including more()). + // + // Note also that argument positions within each group start + // from 0. + // + scanner& + group (); + + // Escape an argument that is a group separator. Return the + // passed string if no escaping is required. + // + static const char* + escape (const char*); + + private: + enum state + { + peeked, // Argument peeked at with peek(). + scanned, // Argument scanned with next(). + skipped, // Argument skipped with skip()/initial. + }; + + enum separator + { + none, + open, // { + close, // } + open_plus, // +{ + close_plus // }+ + }; + + static separator + sense (const char*); + + // Scan the leading groups, the next argument/argument pack, + // and the trailing groups. + // + void + scan_group (); + + scanner& scan_; + state state_; + + // Circular buffer of two arguments. + // + std::vector arg_[2]; + std::size_t i_, j_, pos_; + + std::vector group_; + vector_scanner group_scan_; + }; + + typedef std::vector option_names; + + class option + { + public: + + const std::string& + name () const; + + const option_names& + aliases () const; + + bool + flag () const; + + const std::string& + default_value () const; + + public:option (); + option (const std::string& name, + const option_names& aliases, + bool flag, + const std::string& default_value); + + private: + std::string name_; + option_names aliases_; + bool flag_; + std::string default_value_; + }; + + class options: public std::vector