From dbed808c7d534069f76e63a1a68a85f30d2be81c Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 10 Sep 2019 23:23:43 +0300 Subject: Move testscript builtins to libbutl --- libbuild2/test/script/builtin-options.cxx | 3197 +--------------------------- libbuild2/test/script/builtin-options.hxx | 680 ------ libbuild2/test/script/builtin-options.ixx | 138 -- libbuild2/test/script/builtin.cli | 79 +- libbuild2/test/script/builtin.cxx | 1924 ----------------- libbuild2/test/script/builtin.hxx | 74 - libbuild2/test/script/runner.cxx | 250 ++- tests/test/script/builtin/buildfile | 2 +- tests/test/script/builtin/cat.testscript | 90 - tests/test/script/builtin/cp-dir/cp-file | 0 tests/test/script/builtin/cp.testscript | 367 +--- tests/test/script/builtin/echo.testscript | 27 - tests/test/script/builtin/ln.testscript | 180 +- tests/test/script/builtin/mkdir.testscript | 95 +- tests/test/script/builtin/mv.testscript | 231 +- tests/test/script/builtin/rm.testscript | 93 +- tests/test/script/builtin/rmdir.testscript | 82 +- tests/test/script/builtin/sed.testscript | 355 --- tests/test/script/builtin/sleep.testscript | 28 - tests/test/script/builtin/test.testscript | 85 - tests/test/script/builtin/touch.testscript | 97 +- 21 files changed, 496 insertions(+), 7578 deletions(-) delete mode 100644 libbuild2/test/script/builtin.cxx delete mode 100644 libbuild2/test/script/builtin.hxx delete mode 100644 tests/test/script/builtin/cat.testscript delete mode 100644 tests/test/script/builtin/cp-dir/cp-file delete mode 100644 tests/test/script/builtin/echo.testscript delete mode 100644 tests/test/script/builtin/sed.testscript delete mode 100644 tests/test/script/builtin/test.testscript diff --git a/libbuild2/test/script/builtin-options.cxx b/libbuild2/test/script/builtin-options.cxx index 9a7968e..6b6afe0 100644 --- a/libbuild2/test/script/builtin-options.cxx +++ b/libbuild2/test/script/builtin-options.cxx @@ -366,133 +366,123 @@ namespace build2 { namespace script { - // cleanup_options - // - - cleanup_options:: - cleanup_options () - : no_cleanup_ () - { - } - - typedef - std::map - _cli_cleanup_options_map; - - static _cli_cleanup_options_map _cli_cleanup_options_map_; - - struct _cli_cleanup_options_map_init - { - _cli_cleanup_options_map_init () - { - _cli_cleanup_options_map_["--no-cleanup"] = - &::build2::test::script::cli::thunk< cleanup_options, bool, &cleanup_options::no_cleanup_ >; - } - }; - - static _cli_cleanup_options_map_init _cli_cleanup_options_map_init_; - - bool cleanup_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_cleanup_options_map::const_iterator i (_cli_cleanup_options_map_.find (o)); - - if (i != _cli_cleanup_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - return false; - } - - // cat_options + // set_options // - cat_options:: - cat_options () + set_options:: + set_options () + : exact_ (), + newline_ (), + whitespace_ () { } - cat_options:: - cat_options (int& argc, + set_options:: + set_options (int& argc, char** argv, bool erase, ::build2::test::script::cli::unknown_mode opt, ::build2::test::script::cli::unknown_mode arg) + : exact_ (), + newline_ (), + whitespace_ () { ::build2::test::script::cli::argv_scanner s (argc, argv, erase); _parse (s, opt, arg); } - cat_options:: - cat_options (int start, + set_options:: + set_options (int start, int& argc, char** argv, bool erase, ::build2::test::script::cli::unknown_mode opt, ::build2::test::script::cli::unknown_mode arg) + : exact_ (), + newline_ (), + whitespace_ () { ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); _parse (s, opt, arg); } - cat_options:: - cat_options (int& argc, + set_options:: + set_options (int& argc, char** argv, int& end, bool erase, ::build2::test::script::cli::unknown_mode opt, ::build2::test::script::cli::unknown_mode arg) + : exact_ (), + newline_ (), + whitespace_ () { ::build2::test::script::cli::argv_scanner s (argc, argv, erase); _parse (s, opt, arg); end = s.end (); } - cat_options:: - cat_options (int start, + set_options:: + set_options (int start, int& argc, char** argv, int& end, bool erase, ::build2::test::script::cli::unknown_mode opt, ::build2::test::script::cli::unknown_mode arg) + : exact_ (), + newline_ (), + whitespace_ () { ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); _parse (s, opt, arg); end = s.end (); } - cat_options:: - cat_options (::build2::test::script::cli::scanner& s, + set_options:: + set_options (::build2::test::script::cli::scanner& s, ::build2::test::script::cli::unknown_mode opt, ::build2::test::script::cli::unknown_mode arg) + : exact_ (), + newline_ (), + whitespace_ () { _parse (s, opt, arg); } typedef - std::map - _cli_cat_options_map; + std::map + _cli_set_options_map; - static _cli_cat_options_map _cli_cat_options_map_; + static _cli_set_options_map _cli_set_options_map_; - struct _cli_cat_options_map_init + struct _cli_set_options_map_init { - _cli_cat_options_map_init () + _cli_set_options_map_init () { + _cli_set_options_map_["--exact"] = + &::build2::test::script::cli::thunk< set_options, bool, &set_options::exact_ >; + _cli_set_options_map_["-e"] = + &::build2::test::script::cli::thunk< set_options, bool, &set_options::exact_ >; + _cli_set_options_map_["--newline"] = + &::build2::test::script::cli::thunk< set_options, bool, &set_options::newline_ >; + _cli_set_options_map_["-n"] = + &::build2::test::script::cli::thunk< set_options, bool, &set_options::newline_ >; + _cli_set_options_map_["--whitespace"] = + &::build2::test::script::cli::thunk< set_options, bool, &set_options::whitespace_ >; + _cli_set_options_map_["-w"] = + &::build2::test::script::cli::thunk< set_options, bool, &set_options::whitespace_ >; } }; - static _cli_cat_options_map_init _cli_cat_options_map_init_; + static _cli_set_options_map_init _cli_set_options_map_init_; - bool cat_options:: + bool set_options:: _parse (const char* o, ::build2::test::script::cli::scanner& s) { - _cli_cat_options_map::const_iterator i (_cli_cat_options_map_.find (o)); + _cli_set_options_map::const_iterator i (_cli_set_options_map_.find (o)); - if (i != _cli_cat_options_map_.end ()) + if (i != _cli_set_options_map_.end ()) { (*(i->second)) (*this, s); return true; @@ -501,3088 +491,7 @@ namespace build2 return false; } - bool cat_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // cp_options - // - - cp_options:: - cp_options () - : recursive_ (), - preserve_ () - { - } - - cp_options:: - cp_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : recursive_ (), - preserve_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - cp_options:: - cp_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : recursive_ (), - preserve_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - cp_options:: - cp_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : recursive_ (), - preserve_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - cp_options:: - cp_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : recursive_ (), - preserve_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - cp_options:: - cp_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : recursive_ (), - preserve_ () - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_cp_options_map; - - static _cli_cp_options_map _cli_cp_options_map_; - - struct _cli_cp_options_map_init - { - _cli_cp_options_map_init () - { - _cli_cp_options_map_["--recursive"] = - &::build2::test::script::cli::thunk< cp_options, bool, &cp_options::recursive_ >; - _cli_cp_options_map_["-R"] = - &::build2::test::script::cli::thunk< cp_options, bool, &cp_options::recursive_ >; - _cli_cp_options_map_["-r"] = - &::build2::test::script::cli::thunk< cp_options, bool, &cp_options::recursive_ >; - _cli_cp_options_map_["--preserve"] = - &::build2::test::script::cli::thunk< cp_options, bool, &cp_options::preserve_ >; - _cli_cp_options_map_["-p"] = - &::build2::test::script::cli::thunk< cp_options, bool, &cp_options::preserve_ >; - } - }; - - static _cli_cp_options_map_init _cli_cp_options_map_init_; - - bool cp_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_cp_options_map::const_iterator i (_cli_cp_options_map_.find (o)); - - if (i != _cli_cp_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - // cleanup_options base - // - if (::build2::test::script::cleanup_options::_parse (o, s)) - return true; - - return false; - } - - bool cp_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // ln_options - // - - ln_options:: - ln_options () - : symbolic_ () - { - } - - ln_options:: - ln_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : symbolic_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - ln_options:: - ln_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : symbolic_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - ln_options:: - ln_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : symbolic_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - ln_options:: - ln_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : symbolic_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - ln_options:: - ln_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : symbolic_ () - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_ln_options_map; - - static _cli_ln_options_map _cli_ln_options_map_; - - struct _cli_ln_options_map_init - { - _cli_ln_options_map_init () - { - _cli_ln_options_map_["--symbolic"] = - &::build2::test::script::cli::thunk< ln_options, bool, &ln_options::symbolic_ >; - _cli_ln_options_map_["-s"] = - &::build2::test::script::cli::thunk< ln_options, bool, &ln_options::symbolic_ >; - } - }; - - static _cli_ln_options_map_init _cli_ln_options_map_init_; - - bool ln_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_ln_options_map::const_iterator i (_cli_ln_options_map_.find (o)); - - if (i != _cli_ln_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - // cleanup_options base - // - if (::build2::test::script::cleanup_options::_parse (o, s)) - return true; - - return false; - } - - bool ln_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // mkdir_options - // - - mkdir_options:: - mkdir_options () - : parents_ () - { - } - - mkdir_options:: - mkdir_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : parents_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - mkdir_options:: - mkdir_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : parents_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - mkdir_options:: - mkdir_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : parents_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - mkdir_options:: - mkdir_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : parents_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - mkdir_options:: - mkdir_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : parents_ () - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_mkdir_options_map; - - static _cli_mkdir_options_map _cli_mkdir_options_map_; - - struct _cli_mkdir_options_map_init - { - _cli_mkdir_options_map_init () - { - _cli_mkdir_options_map_["--parents"] = - &::build2::test::script::cli::thunk< mkdir_options, bool, &mkdir_options::parents_ >; - _cli_mkdir_options_map_["-p"] = - &::build2::test::script::cli::thunk< mkdir_options, bool, &mkdir_options::parents_ >; - } - }; - - static _cli_mkdir_options_map_init _cli_mkdir_options_map_init_; - - bool mkdir_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_mkdir_options_map::const_iterator i (_cli_mkdir_options_map_.find (o)); - - if (i != _cli_mkdir_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - // cleanup_options base - // - if (::build2::test::script::cleanup_options::_parse (o, s)) - return true; - - return false; - } - - bool mkdir_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // mv_options - // - - mv_options:: - mv_options () - : force_ () - { - } - - mv_options:: - mv_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : force_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - mv_options:: - mv_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : force_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - mv_options:: - mv_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : force_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - mv_options:: - mv_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : force_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - mv_options:: - mv_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : force_ () - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_mv_options_map; - - static _cli_mv_options_map _cli_mv_options_map_; - - struct _cli_mv_options_map_init - { - _cli_mv_options_map_init () - { - _cli_mv_options_map_["--force"] = - &::build2::test::script::cli::thunk< mv_options, bool, &mv_options::force_ >; - _cli_mv_options_map_["-f"] = - &::build2::test::script::cli::thunk< mv_options, bool, &mv_options::force_ >; - } - }; - - static _cli_mv_options_map_init _cli_mv_options_map_init_; - - bool mv_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_mv_options_map::const_iterator i (_cli_mv_options_map_.find (o)); - - if (i != _cli_mv_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - // cleanup_options base - // - if (::build2::test::script::cleanup_options::_parse (o, s)) - return true; - - return false; - } - - bool mv_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // rm_options - // - - rm_options:: - rm_options () - : recursive_ (), - force_ () - { - } - - rm_options:: - rm_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : recursive_ (), - force_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - rm_options:: - rm_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : recursive_ (), - force_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - rm_options:: - rm_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : recursive_ (), - force_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - rm_options:: - rm_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : recursive_ (), - force_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - rm_options:: - rm_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : recursive_ (), - force_ () - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_rm_options_map; - - static _cli_rm_options_map _cli_rm_options_map_; - - struct _cli_rm_options_map_init - { - _cli_rm_options_map_init () - { - _cli_rm_options_map_["--recursive"] = - &::build2::test::script::cli::thunk< rm_options, bool, &rm_options::recursive_ >; - _cli_rm_options_map_["-r"] = - &::build2::test::script::cli::thunk< rm_options, bool, &rm_options::recursive_ >; - _cli_rm_options_map_["--force"] = - &::build2::test::script::cli::thunk< rm_options, bool, &rm_options::force_ >; - _cli_rm_options_map_["-f"] = - &::build2::test::script::cli::thunk< rm_options, bool, &rm_options::force_ >; - } - }; - - static _cli_rm_options_map_init _cli_rm_options_map_init_; - - bool rm_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_rm_options_map::const_iterator i (_cli_rm_options_map_.find (o)); - - if (i != _cli_rm_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - return false; - } - - bool rm_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // rmdir_options - // - - rmdir_options:: - rmdir_options () - : force_ () - { - } - - rmdir_options:: - rmdir_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : force_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - rmdir_options:: - rmdir_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : force_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - rmdir_options:: - rmdir_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : force_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - rmdir_options:: - rmdir_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : force_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - rmdir_options:: - rmdir_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : force_ () - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_rmdir_options_map; - - static _cli_rmdir_options_map _cli_rmdir_options_map_; - - struct _cli_rmdir_options_map_init - { - _cli_rmdir_options_map_init () - { - _cli_rmdir_options_map_["--force"] = - &::build2::test::script::cli::thunk< rmdir_options, bool, &rmdir_options::force_ >; - _cli_rmdir_options_map_["-f"] = - &::build2::test::script::cli::thunk< rmdir_options, bool, &rmdir_options::force_ >; - } - }; - - static _cli_rmdir_options_map_init _cli_rmdir_options_map_init_; - - bool rmdir_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_rmdir_options_map::const_iterator i (_cli_rmdir_options_map_.find (o)); - - if (i != _cli_rmdir_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - return false; - } - - bool rmdir_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // sed_options - // - - sed_options:: - sed_options () - : quiet_ (), - in_place_ (), - expression_ (), - expression_specified_ (false) - { - } - - sed_options:: - sed_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : quiet_ (), - in_place_ (), - expression_ (), - expression_specified_ (false) - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - sed_options:: - sed_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : quiet_ (), - in_place_ (), - expression_ (), - expression_specified_ (false) - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - sed_options:: - sed_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : quiet_ (), - in_place_ (), - expression_ (), - expression_specified_ (false) - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - sed_options:: - sed_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : quiet_ (), - in_place_ (), - expression_ (), - expression_specified_ (false) - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - sed_options:: - sed_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : quiet_ (), - in_place_ (), - expression_ (), - expression_specified_ (false) - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_sed_options_map; - - static _cli_sed_options_map _cli_sed_options_map_; - - struct _cli_sed_options_map_init - { - _cli_sed_options_map_init () - { - _cli_sed_options_map_["--quiet"] = - &::build2::test::script::cli::thunk< sed_options, bool, &sed_options::quiet_ >; - _cli_sed_options_map_["-n"] = - &::build2::test::script::cli::thunk< sed_options, bool, &sed_options::quiet_ >; - _cli_sed_options_map_["--in-place"] = - &::build2::test::script::cli::thunk< sed_options, bool, &sed_options::in_place_ >; - _cli_sed_options_map_["-i"] = - &::build2::test::script::cli::thunk< sed_options, bool, &sed_options::in_place_ >; - _cli_sed_options_map_["--expression"] = - &::build2::test::script::cli::thunk< sed_options, strings, &sed_options::expression_, - &sed_options::expression_specified_ >; - _cli_sed_options_map_["-e"] = - &::build2::test::script::cli::thunk< sed_options, strings, &sed_options::expression_, - &sed_options::expression_specified_ >; - } - }; - - static _cli_sed_options_map_init _cli_sed_options_map_init_; - - bool sed_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_sed_options_map::const_iterator i (_cli_sed_options_map_.find (o)); - - if (i != _cli_sed_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - return false; - } - - bool sed_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // set_options - // - - set_options:: - set_options () - : exact_ (), - newline_ (), - whitespace_ () - { - } - - set_options:: - set_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : exact_ (), - newline_ (), - whitespace_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - set_options:: - set_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : exact_ (), - newline_ (), - whitespace_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - set_options:: - set_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : exact_ (), - newline_ (), - whitespace_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - set_options:: - set_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : exact_ (), - newline_ (), - whitespace_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - set_options:: - set_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : exact_ (), - newline_ (), - whitespace_ () - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_set_options_map; - - static _cli_set_options_map _cli_set_options_map_; - - struct _cli_set_options_map_init - { - _cli_set_options_map_init () - { - _cli_set_options_map_["--exact"] = - &::build2::test::script::cli::thunk< set_options, bool, &set_options::exact_ >; - _cli_set_options_map_["-e"] = - &::build2::test::script::cli::thunk< set_options, bool, &set_options::exact_ >; - _cli_set_options_map_["--newline"] = - &::build2::test::script::cli::thunk< set_options, bool, &set_options::newline_ >; - _cli_set_options_map_["-n"] = - &::build2::test::script::cli::thunk< set_options, bool, &set_options::newline_ >; - _cli_set_options_map_["--whitespace"] = - &::build2::test::script::cli::thunk< set_options, bool, &set_options::whitespace_ >; - _cli_set_options_map_["-w"] = - &::build2::test::script::cli::thunk< set_options, bool, &set_options::whitespace_ >; - } - }; - - static _cli_set_options_map_init _cli_set_options_map_init_; - - bool set_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_set_options_map::const_iterator i (_cli_set_options_map_.find (o)); - - if (i != _cli_set_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - return false; - } - - bool set_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // sleep_options - // - - sleep_options:: - sleep_options () - { - } - - sleep_options:: - sleep_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - sleep_options:: - sleep_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - sleep_options:: - sleep_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - sleep_options:: - sleep_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - sleep_options:: - sleep_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_sleep_options_map; - - static _cli_sleep_options_map _cli_sleep_options_map_; - - struct _cli_sleep_options_map_init - { - _cli_sleep_options_map_init () - { - } - }; - - static _cli_sleep_options_map_init _cli_sleep_options_map_init_; - - bool sleep_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_sleep_options_map::const_iterator i (_cli_sleep_options_map_.find (o)); - - if (i != _cli_sleep_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - return false; - } - - bool sleep_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // test_options - // - - test_options:: - test_options () - : file_ (), - directory_ () - { - } - - test_options:: - test_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : file_ (), - directory_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - test_options:: - test_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : file_ (), - directory_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - test_options:: - test_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : file_ (), - directory_ () - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - test_options:: - test_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : file_ (), - directory_ () - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - test_options:: - test_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : file_ (), - directory_ () - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_test_options_map; - - static _cli_test_options_map _cli_test_options_map_; - - struct _cli_test_options_map_init - { - _cli_test_options_map_init () - { - _cli_test_options_map_["--file"] = - &::build2::test::script::cli::thunk< test_options, bool, &test_options::file_ >; - _cli_test_options_map_["-f"] = - &::build2::test::script::cli::thunk< test_options, bool, &test_options::file_ >; - _cli_test_options_map_["--directory"] = - &::build2::test::script::cli::thunk< test_options, bool, &test_options::directory_ >; - _cli_test_options_map_["-d"] = - &::build2::test::script::cli::thunk< test_options, bool, &test_options::directory_ >; - } - }; - - static _cli_test_options_map_init _cli_test_options_map_init_; - - bool test_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_test_options_map::const_iterator i (_cli_test_options_map_.find (o)); - - if (i != _cli_test_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - return false; - } - - bool test_options:: - _parse (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt_mode, - ::build2::test::script::cli::unknown_mode arg_mode) - { - // Can't skip combined flags (--no-combined-flags). - // - assert (opt_mode != ::build2::test::script::cli::unknown_mode::skip); - - bool r = false; - bool opt = true; - - while (s.more ()) - { - const char* o = s.peek (); - - if (std::strcmp (o, "--") == 0) - { - opt = false; - s.skip (); - r = true; - continue; - } - - if (opt) - { - if (_parse (o, s)) - { - r = true; - continue; - } - - if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') - { - // Handle combined option values. - // - std::string co; - if (const char* v = std::strchr (o, '=')) - { - co.assign (o, 0, v - o); - ++v; - - int ac (2); - char* av[] = - { - const_cast (co.c_str ()), - const_cast (v) - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (_parse (co.c_str (), ns)) - { - // Parsed the option but not its value? - // - if (ns.end () != 2) - throw ::build2::test::script::cli::invalid_value (co, v); - - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = co.c_str (); - } - } - - // Handle combined flags. - // - char cf[3]; - { - const char* p = o + 1; - for (; *p != '\0'; ++p) - { - if (!((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9'))) - break; - } - - if (*p == '\0') - { - for (p = o + 1; *p != '\0'; ++p) - { - std::strcpy (cf, "-"); - cf[1] = *p; - cf[2] = '\0'; - - int ac (1); - char* av[] = - { - cf - }; - - ::build2::test::script::cli::argv_scanner ns (0, ac, av); - - if (!_parse (cf, ns)) - break; - } - - if (*p == '\0') - { - // All handled. - // - s.next (); - r = true; - continue; - } - else - { - // Set the unknown option and fall through. - // - o = cf; - } - } - } - - switch (opt_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_option (o); - } - } - - break; - } - } - - switch (arg_mode) - { - case ::build2::test::script::cli::unknown_mode::skip: - { - s.skip (); - r = true; - continue; - } - case ::build2::test::script::cli::unknown_mode::stop: - { - break; - } - case ::build2::test::script::cli::unknown_mode::fail: - { - throw ::build2::test::script::cli::unknown_argument (o); - } - } - - break; - } - - return r; - } - - // touch_options - // - - touch_options:: - touch_options () - : after_ (), - after_specified_ (false) - { - } - - touch_options:: - touch_options (int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : after_ (), - after_specified_ (false) - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - } - - touch_options:: - touch_options (int start, - int& argc, - char** argv, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : after_ (), - after_specified_ (false) - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - } - - touch_options:: - touch_options (int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : after_ (), - after_specified_ (false) - { - ::build2::test::script::cli::argv_scanner s (argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - touch_options:: - touch_options (int start, - int& argc, - char** argv, - int& end, - bool erase, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : after_ (), - after_specified_ (false) - { - ::build2::test::script::cli::argv_scanner s (start, argc, argv, erase); - _parse (s, opt, arg); - end = s.end (); - } - - touch_options:: - touch_options (::build2::test::script::cli::scanner& s, - ::build2::test::script::cli::unknown_mode opt, - ::build2::test::script::cli::unknown_mode arg) - : after_ (), - after_specified_ (false) - { - _parse (s, opt, arg); - } - - typedef - std::map - _cli_touch_options_map; - - static _cli_touch_options_map _cli_touch_options_map_; - - struct _cli_touch_options_map_init - { - _cli_touch_options_map_init () - { - _cli_touch_options_map_["--after"] = - &::build2::test::script::cli::thunk< touch_options, string, &touch_options::after_, - &touch_options::after_specified_ >; - } - }; - - static _cli_touch_options_map_init _cli_touch_options_map_init_; - - bool touch_options:: - _parse (const char* o, ::build2::test::script::cli::scanner& s) - { - _cli_touch_options_map::const_iterator i (_cli_touch_options_map_.find (o)); - - if (i != _cli_touch_options_map_.end ()) - { - (*(i->second)) (*this, s); - return true; - } - - // cleanup_options base - // - if (::build2::test::script::cleanup_options::_parse (o, s)) - return true; - - return false; - } - - bool touch_options:: + bool set_options:: _parse (::build2::test::script::cli::scanner& s, ::build2::test::script::cli::unknown_mode opt_mode, ::build2::test::script::cli::unknown_mode arg_mode) diff --git a/libbuild2/test/script/builtin-options.hxx b/libbuild2/test/script/builtin-options.hxx index 7ff0bac..44e129a 100644 --- a/libbuild2/test/script/builtin-options.hxx +++ b/libbuild2/test/script/builtin-options.hxx @@ -260,514 +260,12 @@ namespace build2 } } -#include - namespace build2 { namespace test { namespace script { - class cleanup_options - { - public: - // Option accessors. - // - const bool& - no_cleanup () const; - - // Implementation details. - // - protected: - cleanup_options (); - - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - public: - bool no_cleanup_; - }; - - class cat_options - { - public: - cat_options (); - - cat_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - cat_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - cat_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - cat_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - cat_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - }; - - class cp_options: public ::build2::test::script::cleanup_options - { - public: - cp_options (); - - cp_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - cp_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - cp_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - cp_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - cp_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - const bool& - recursive () const; - - const bool& - preserve () const; - - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - bool recursive_; - bool preserve_; - }; - - class ln_options: public ::build2::test::script::cleanup_options - { - public: - ln_options (); - - ln_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - ln_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - ln_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - ln_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - ln_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - const bool& - symbolic () const; - - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - bool symbolic_; - }; - - class mkdir_options: public ::build2::test::script::cleanup_options - { - public: - mkdir_options (); - - mkdir_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - mkdir_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - mkdir_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - mkdir_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - mkdir_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - const bool& - parents () const; - - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - bool parents_; - }; - - class mv_options: public ::build2::test::script::cleanup_options - { - public: - mv_options (); - - mv_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - mv_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - mv_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - mv_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - mv_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - const bool& - force () const; - - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - bool force_; - }; - - class rm_options - { - public: - rm_options (); - - rm_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - rm_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - rm_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - rm_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - rm_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - const bool& - recursive () const; - - const bool& - force () const; - - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - bool recursive_; - bool force_; - }; - - class rmdir_options - { - public: - rmdir_options (); - - rmdir_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - rmdir_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - rmdir_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - rmdir_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - rmdir_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - const bool& - force () const; - - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - bool force_; - }; - - class sed_options - { - public: - sed_options (); - - sed_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - sed_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - sed_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - sed_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - sed_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - const bool& - quiet () const; - - const bool& - in_place () const; - - const strings& - expression () const; - - bool - expression_specified () const; - - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - bool quiet_; - bool in_place_; - strings expression_; - bool expression_specified_; - }; - class set_options { public: @@ -833,184 +331,6 @@ namespace build2 bool newline_; bool whitespace_; }; - - class sleep_options - { - public: - sleep_options (); - - sleep_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - sleep_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - sleep_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - sleep_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - sleep_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - }; - - class test_options - { - public: - test_options (); - - test_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - test_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - test_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - test_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - test_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - const bool& - file () const; - - const bool& - directory () const; - - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - bool file_; - bool directory_; - }; - - class touch_options: public ::build2::test::script::cleanup_options - { - public: - touch_options (); - - touch_options (int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - touch_options (int start, - int& argc, - char** argv, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - touch_options (int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - touch_options (int start, - int& argc, - char** argv, - int& end, - bool erase = false, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - touch_options (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option = ::build2::test::script::cli::unknown_mode::fail, - ::build2::test::script::cli::unknown_mode argument = ::build2::test::script::cli::unknown_mode::stop); - - // Option accessors. - // - const string& - after () const; - - bool - after_specified () const; - - // Implementation details. - // - protected: - bool - _parse (const char*, ::build2::test::script::cli::scanner&); - - private: - bool - _parse (::build2::test::script::cli::scanner&, - ::build2::test::script::cli::unknown_mode option, - ::build2::test::script::cli::unknown_mode argument); - - public: - string after_; - bool after_specified_; - }; } } } diff --git a/libbuild2/test/script/builtin-options.ixx b/libbuild2/test/script/builtin-options.ixx index 55fd6d2..bdb95b4 100644 --- a/libbuild2/test/script/builtin-options.ixx +++ b/libbuild2/test/script/builtin-options.ixx @@ -158,111 +158,6 @@ namespace build2 { namespace script { - // cleanup_options - // - - inline const bool& cleanup_options:: - no_cleanup () const - { - return this->no_cleanup_; - } - - // cat_options - // - - // cp_options - // - - inline const bool& cp_options:: - recursive () const - { - return this->recursive_; - } - - inline const bool& cp_options:: - preserve () const - { - return this->preserve_; - } - - // ln_options - // - - inline const bool& ln_options:: - symbolic () const - { - return this->symbolic_; - } - - // mkdir_options - // - - inline const bool& mkdir_options:: - parents () const - { - return this->parents_; - } - - // mv_options - // - - inline const bool& mv_options:: - force () const - { - return this->force_; - } - - // rm_options - // - - inline const bool& rm_options:: - recursive () const - { - return this->recursive_; - } - - inline const bool& rm_options:: - force () const - { - return this->force_; - } - - // rmdir_options - // - - inline const bool& rmdir_options:: - force () const - { - return this->force_; - } - - // sed_options - // - - inline const bool& sed_options:: - quiet () const - { - return this->quiet_; - } - - inline const bool& sed_options:: - in_place () const - { - return this->in_place_; - } - - inline const strings& sed_options:: - expression () const - { - return this->expression_; - } - - inline bool sed_options:: - expression_specified () const - { - return this->expression_specified_; - } - // set_options // @@ -283,39 +178,6 @@ namespace build2 { return this->whitespace_; } - - // sleep_options - // - - // test_options - // - - inline const bool& test_options:: - file () const - { - return this->file_; - } - - inline const bool& test_options:: - directory () const - { - return this->directory_; - } - - // touch_options - // - - inline const string& touch_options:: - after () const - { - return this->after_; - } - - inline bool touch_options:: - after_specified () const - { - return this->after_specified_; - } } } } diff --git a/libbuild2/test/script/builtin.cli b/libbuild2/test/script/builtin.cli index 8b8de73..790e6f1 100644 --- a/libbuild2/test/script/builtin.cli +++ b/libbuild2/test/script/builtin.cli @@ -2,102 +2,25 @@ // copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -include ; - // Note that options in this file are undocumented because we generate neither // the usage printing code nor man pages. Instead, they are documented in the // Testscript Language Manual's builtin descriptions. // -// Also note that the string type is used for the path options because their -// parsing depends on the testscript scope working directory (see parse_path() -// for details) and passing this information to the CLI custom parser would -// not be easy. -// namespace build2 { namespace test { namespace script { - // Common option base classes. - // - - class cleanup_options = 0 - { - bool --no-cleanup; - }; - - // Builtin options. + // Pseudo-builtin options. // - class cat_options - { - // No options so far. - // - }; - - class cp_options: cleanup_options - { - bool --recursive|-R|-r; - bool --preserve|-p; - }; - - class ln_options: cleanup_options - { - bool --symbolic|-s; - }; - - class mkdir_options: cleanup_options - { - bool --parents|-p; - }; - - class mv_options: cleanup_options - { - bool --force|-f; - }; - - class rm_options - { - bool --recursive|-r; - bool --force|-f; - }; - - class rmdir_options - { - bool --force|-f; - }; - - class sed_options - { - bool --quiet|-n; - bool --in-place|-i; - strings --expression|-e; - }; - class set_options { bool --exact|-e; bool --newline|-n; bool --whitespace|-w; }; - - class sleep_options - { - // No options so far. - // - }; - - class test_options - { - bool --file|-f; - bool --directory|-d; - }; - - class touch_options: cleanup_options - { - string --after; // Path (see above). - }; } } } diff --git a/libbuild2/test/script/builtin.cxx b/libbuild2/test/script/builtin.cxx deleted file mode 100644 index 06b0cec..0000000 --- a/libbuild2/test/script/builtin.cxx +++ /dev/null @@ -1,1924 +0,0 @@ -// file : libbuild2/test/script/builtin.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include -#include -#include -#include -#include // strtoull() - -#include -#include // use default operator<< implementation -#include // fdopen_mode, fdstream_mode -#include - -#include // sched - -#include -#include - -// Strictly speaking a builtin which reads/writes from/to standard streams -// must be asynchronous so that the caller can communicate with it through -// pipes without being blocked on I/O operations. However, as an optimization, -// we allow builtins that only print diagnostics to STDERR to be synchronous -// assuming that their output will always fit the pipe buffer. Synchronous -// builtins must not read from STDIN and write to STDOUT. Later we may relax -// this rule to allow a "short" output for such builtins. -// -using namespace std; -using namespace butl; - -namespace build2 -{ - namespace test - { - namespace script - { - using builtin_impl = uint8_t (scope&, - const strings& args, - auto_fd in, auto_fd out, auto_fd err); - - // Operation failed, diagnostics has already been issued. - // - struct failed {}; - - // Accumulate an error message, print it atomically in dtor to the - // provided stream and throw failed afterwards if requested. Prefixes - // the message with the builtin name. - // - // Move constructible-only, not assignable (based to diag_record). - // - class error_record - { - public: - template - friend const error_record& - operator<< (const error_record& r, const T& x) - { - r.ss_ << x; - return r; - } - - error_record (ostream& o, bool fail, const char* name) - : os_ (o), fail_ (fail), empty_ (false) - { - ss_ << name << ": "; - } - - // Older versions of libstdc++ don't have the ostringstream move - // support. Luckily, GCC doesn't seem to be actually needing move due - // to copy/move elision. - // -#ifdef __GLIBCXX__ - error_record (error_record&&); -#else - error_record (error_record&& r) - : os_ (r.os_), - ss_ (move (r.ss_)), - fail_ (r.fail_), - empty_ (r.empty_) - { - r.empty_ = true; - } -#endif - - ~error_record () noexcept (false) - { - if (!empty_) - { - // The output stream can be in a bad state (for example as a - // result of unsuccessful attempt to report a previous error), so - // we check it. - // - if (os_.good ()) - { - ss_.put ('\n'); - os_ << ss_.str (); - os_.flush (); - } - - if (fail_) - throw failed (); - } - } - - private: - ostream& os_; - mutable ostringstream ss_; - - bool fail_; - bool empty_; - }; - - // Parse and normalize a path. Also, unless it is already absolute, make - // the path absolute using the specified directory. Throw invalid_path - // if the path is empty, and on parsing and normalization failures. - // - static path - parse_path (string s, const dir_path& d) - { - path p (move (s)); - - if (p.empty ()) - throw invalid_path (""); - - if (p.relative ()) - p = d / move (p); - - p.normalize (); - return p; - } - - // Builtin commands functions. - // - - // cat ... - // - // Note that POSIX doesn't specify if after I/O operation failure the - // command should proceed with the rest of the arguments. The current - // implementation exits immediatelly in such a case. - // - // @@ Shouldn't we check that we don't print a nonempty regular file to - // itself, as that would merely exhaust the output device? POSIX - // allows (but not requires) such a check and some implementations do - // this. That would require to fstat() file descriptors and complicate - // the code a bit. Was able to reproduce on a big file (should be - // bigger than the stream buffer size) with the test - // 'cat file >+file'. - // - // Note: must be executed asynchronously. - // - static uint8_t - cat (scope& sp, - const strings& args, - auto_fd in, auto_fd out, auto_fd err) noexcept - try - { - uint8_t r (1); - ofdstream cerr (move (err)); - - auto error = [&cerr] (bool fail = true) - { - return error_record (cerr, fail, "cat"); - }; - - try - { - ifdstream cin (move (in), fdstream_mode::binary); - ofdstream cout (move (out), fdstream_mode::binary); - - // Parse arguments. - // - cli::vector_scanner scan (args); - cat_options ops (scan); // Makes sure no options passed. - - // Print files. - // - // Copy input stream to STDOUT. - // - auto copy = [&cout] (istream& is) - { - if (is.peek () != ifdstream::traits_type::eof ()) - cout << is.rdbuf (); - - is.clear (istream::eofbit); // Sets eofbit. - }; - - // Path of a file being printed to STDOUT. An empty path represents - // STDIN. Used in diagnostics. - // - path p; - - try - { - // Print STDIN. - // - if (!scan.more ()) - copy (cin); - - // Print files. - // - while (scan.more ()) - { - string f (scan.next ()); - - if (f == "-") - { - if (!cin.eof ()) - { - p.clear (); - copy (cin); - } - - continue; - } - - p = parse_path (move (f), sp.wd_path); - - ifdstream is (p, fdopen_mode::binary); - copy (is); - is.close (); - } - } - catch (const io_error& e) - { - error_record d (error ()); - d << "unable to print "; - - if (p.empty ()) - d << "stdin"; - else - d << "'" << p << "'"; - - d << ": " << e; - } - - cin.close (); - cout.close (); - r = 0; - } - catch (const invalid_path& e) - { - error (false) << "invalid path '" << e.path << "'"; - } - // Can be thrown while creating/closing cin, cout or writing to cerr. - // - catch (const io_error& e) - { - error (false) << e; - } - catch (const failed&) - { - // Diagnostics has already been issued. - } - catch (const cli::exception& e) - { - error (false) << e; - } - - cerr.close (); - return r; - } - catch (const std::exception&) - { - return 1; - } - - // Make a copy of a file at the specified path, preserving permissions, - // and registering a cleanup for a newly created file. The file paths - // must be absolute. Fail if an exception is thrown by the underlying - // copy operation. - // - static void - cpfile (scope& sp, - const path& from, const path& to, - bool overwrite, - bool attrs, - bool cleanup, - const function& fail) - { - try - { - bool exists (file_exists (to)); - - cpflags f ( - overwrite - ? cpflags::overwrite_permissions | cpflags::overwrite_content - : cpflags::none); - - if (attrs) - f |= cpflags::overwrite_permissions | cpflags::copy_timestamps; - - cpfile (from, to, f); - - if (!exists && cleanup) - sp.clean ({cleanup_type::always, to}, true /* implicit */); - } - catch (const system_error& e) - { - fail () << "unable to copy file '" << from << "' to '" << to - << "': " << e; - } - } - - // Make a copy of a directory at the specified path, registering a - // cleanup for the created directory. The directory paths must be - // absolute. Fail if the destination directory already exists or - // an exception is thrown by the underlying copy operation. - // - static void - cpdir (scope& sp, - const dir_path& from, const dir_path& to, - bool attrs, - bool cleanup, - const function& fail) - { - try - { - if (try_mkdir (to) == mkdir_status::already_exists) - throw_generic_error (EEXIST); - - if (cleanup) - sp.clean ({cleanup_type::always, to}, true /* implicit */); - - for (const auto& de: dir_iterator (from, - false /* ignore_dangling */)) - { - path f (from / de.path ()); - path t (to / de.path ()); - - if (de.type () == entry_type::directory) - cpdir (sp, - path_cast (move (f)), - path_cast (move (t)), - attrs, - cleanup, - fail); - else - cpfile (sp, f, t, false /* overwrite */, attrs, cleanup, fail); - } - - // Note that it is essential to copy timestamps and permissions after - // the directory content is copied. - // - if (attrs) - { - path_permissions (to, path_permissions (from)); - dir_time (to, dir_time (from)); - } - } - catch (const system_error& e) - { - fail () << "unable to copy directory '" << from << "' to '" << to - << "': " << e; - } - } - - // cp [-p|--preserve] [--no-cleanup] - // cp [-p|--preserve] [--no-cleanup] -R|-r|--recursive - // cp [-p|--preserve] [--no-cleanup] ... / - // cp [-p|--preserve] [--no-cleanup] -R|-r|--recursive ... / - // - // Note: can be executed synchronously. - // - static uint8_t - cp (scope& sp, - const strings& args, - auto_fd in, auto_fd out, auto_fd err) noexcept - try - { - uint8_t r (1); - ofdstream cerr (move (err)); - - auto error = [&cerr] (bool fail = true) - { - return error_record (cerr, fail, "cp"); - }; - - try - { - in.close (); - out.close (); - - // Parse arguments. - // - cli::vector_scanner scan (args); - cp_options ops (scan); - - // Copy files or directories. - // - if (!scan.more ()) - error () << "missing arguments"; - - // Note that the arguments semantics depends on the last argument, - // so we read out and cache them. - // - small_vector args; - while (scan.more ()) - args.push_back (scan.next ()); - - const dir_path& wd (sp.wd_path); - - auto i (args.begin ()); - auto j (args.rbegin ()); - path dst (parse_path (move (*j++), wd)); - auto e (j.base ()); - - if (i == e) - error () << "missing source path"; - - auto fail = [&error] () {return error (true);}; - - bool cleanup (!ops.no_cleanup ()); - - // If destination is not a directory path (no trailing separator) - // then make a copy of the filesystem entry at the specified path - // (the only source path is allowed in such a case). Otherwise copy - // the source filesystem entries into the destination directory. - // - if (!dst.to_directory ()) - { - path src (parse_path (move (*i++), wd)); - - // If there are multiple sources but no trailing separator for the - // destination, then, most likelly, it is missing. - // - if (i != e) - error () << "multiple source paths without trailing separator " - << "for destination directory"; - - if (!ops.recursive ()) - // Synopsis 1: make a file copy at the specified path. - // - cpfile (sp, - src, - dst, - true /* overwrite */, - ops.preserve (), - cleanup, - fail); - else - // Synopsis 2: make a directory copy at the specified path. - // - cpdir (sp, - path_cast (src), path_cast (dst), - ops.preserve (), - cleanup, - fail); - } - else - { - for (; i != e; ++i) - { - path src (parse_path (move (*i), wd)); - - if (ops.recursive () && dir_exists (src)) - // Synopsis 4: copy a filesystem entry into the specified - // directory. Note that we handle only source directories here. - // Source files are handled below. - // - cpdir (sp, - path_cast (src), - path_cast (dst / src.leaf ()), - ops.preserve (), - cleanup, - fail); - else - // Synopsis 3: copy a file into the specified directory. Also, - // here we cover synopsis 4 for the source path being a file. - // - cpfile (sp, - src, - dst / src.leaf (), - true /* overwrite */, - ops.preserve (), - cleanup, - fail); - } - } - - r = 0; - } - catch (const invalid_path& e) - { - error (false) << "invalid path '" << e.path << "'"; - } - // Can be thrown while closing in, out or writing to cerr. - // - catch (const io_error& e) - { - error (false) << e; - } - catch (const failed&) - { - // Diagnostics has already been issued. - } - catch (const cli::exception& e) - { - error (false) << e; - } - - cerr.close (); - return r; - } - catch (const std::exception&) - { - return 1; - } - - // echo ... - // - // Note: must be executed asynchronously. - // - static uint8_t - echo (scope&, - const strings& args, - auto_fd in, auto_fd out, auto_fd err) noexcept - try - { - uint8_t r (1); - ofdstream cerr (move (err)); - - try - { - in.close (); - ofdstream cout (move (out)); - - for (auto b (args.begin ()), i (b), e (args.end ()); i != e; ++i) - cout << (i != b ? " " : "") << *i; - - cout << '\n'; - cout.close (); - r = 0; - } - catch (const std::exception& e) - { - cerr << "echo: " << e << endl; - } - - cerr.close (); - return r; - } - catch (const std::exception&) - { - return 1; - } - - // false - // - // Failure to close the file descriptors is silently ignored. - // - // Note: can be executed synchronously. - // - static builtin - false_ (scope&, uint8_t& r, const strings&, auto_fd, auto_fd, auto_fd) - { - return builtin (r = 1); - } - - // true - // - // Failure to close the file descriptors is silently ignored. - // - // Note: can be executed synchronously. - // - static builtin - true_ (scope&, uint8_t& r, const strings&, auto_fd, auto_fd, auto_fd) - { - return builtin (r = 0); - } - - // Create a symlink to a file or directory at the specified path. The - // paths must be absolute. Fall back to creating a hardlink, if symlink - // creation is not supported for the link path. If hardlink creation is - // not supported either, then fall back to copies. If requested, created - // filesystem entries are registered for cleanup. Fail if the target - // filesystem entry doesn't exist or an exception is thrown by the - // underlying filesystem operation (specifically for an already existing - // filesystem entry at the link path). - // - // Note that supporting optional removal of an existing filesystem entry - // at the link path (the -f option) tends to get hairy. As soon as an - // existing and the resulting filesystem entries could be of different - // types, we would end up with canceling an old cleanup and registering - // the new one. Also removing non-empty directories doesn't look very - // natural, but would be required if we want the behavior on POSIX and - // Windows to be consistent. - // - static void - mksymlink (scope& sp, - const path& target, const path& link, - bool cleanup, - const function& fail) - { - // Determine the target type, fail if the target doesn't exist. - // - bool dir (false); - - try - { - pair pe (path_entry (target)); - - if (!pe.first) - fail () << "unable to create symlink to '" << target << "': " - << "no such file or directory"; - - dir = pe.second.type == entry_type::directory; - } - catch (const system_error& e) - { - fail () << "unable to stat '" << target << "': " << e; - } - - // First we try to create a symlink. If that fails (e.g., "Windows - // happens"), then we resort to hard links. If that doesn't work out - // either (e.g., not on the same filesystem), then we fall back to - // copies. So things are going to get a bit nested. - // - // Note: similar to mkanylink() but with support for directories. - // - try - { - mksymlink (target, link, dir); - - if (cleanup) - sp.clean ({cleanup_type::always, link}, true /* implicit */); - } - catch (const system_error& e) - { - // Note that we are not guaranteed (here and below) that the - // system_error exception is of the generic category. - // - int c (e.code ().value ()); - if (!(e.code ().category () == generic_category () && - (c == ENOSYS || // Not implemented. - c == EPERM))) // Not supported by the filesystem(s). - fail () << "unable to create symlink '" << link << "' to '" - << target << "': " << e; - - try - { - mkhardlink (target, link, dir); - - if (cleanup) - sp.clean ({cleanup_type::always, link}, true /* implicit */); - } - catch (const system_error& e) - { - c = e.code ().value (); - if (!(e.code ().category () == generic_category () && - (c == ENOSYS || // Not implemented. - c == EPERM || // Not supported by the filesystem(s). - c == EXDEV))) // On different filesystems. - fail () << "unable to create hardlink '" << link << "' to '" - << target << "': " << e; - - if (dir) - cpdir (sp, - path_cast (target), path_cast (link), - false, - cleanup, - fail); - else - cpfile (sp, - target, - link, - false /* overwrite */, - true /* attrs */, - cleanup, - fail); - } - } - } - - // ln [--no-cleanup] -s|--symbolic - // ln [--no-cleanup] -s|--symbolic ... / - // - // Note: can be executed synchronously. - // - static uint8_t - ln (scope& sp, - const strings& args, - auto_fd in, auto_fd out, auto_fd err) noexcept - try - { - uint8_t r (1); - ofdstream cerr (move (err)); - - auto error = [&cerr] (bool fail = true) - { - return error_record (cerr, fail, "ln"); - }; - - try - { - in.close (); - out.close (); - - // Parse arguments. - // - cli::vector_scanner scan (args); - ln_options ops (scan); - - if (!ops.symbolic ()) - error () << "missing -s|--symbolic option"; - - // Create file or directory symlinks. - // - if (!scan.more ()) - error () << "missing arguments"; - - // Note that the arguments semantics depends on the last argument, - // so we read out and cache them. - // - small_vector args; - while (scan.more ()) - args.push_back (scan.next ()); - - const dir_path& wd (sp.wd_path); - - auto i (args.begin ()); - auto j (args.rbegin ()); - path link (parse_path (move (*j++), wd)); - auto e (j.base ()); - - if (i == e) - error () << "missing target path"; - - auto fail = [&error] () {return error (true);}; - - bool cleanup (!ops.no_cleanup ()); - - // If link is not a directory path (no trailing separator), then - // create a symlink to the target path at the specified link path - // (the only target path is allowed in such a case). Otherwise create - // links to the target paths inside the specified directory. - // - if (!link.to_directory ()) - { - path target (parse_path (move (*i++), wd)); - - // If there are multiple targets but no trailing separator for the - // link, then, most likelly, it is missing. - // - if (i != e) - error () << "multiple target paths with non-directory link path"; - - // Synopsis 1: create a target path symlink at the specified path. - // - mksymlink (sp, target, link, cleanup, fail); - } - else - { - for (; i != e; ++i) - { - path target (parse_path (move (*i), wd)); - - // Synopsis 2: create a target path symlink in the specified - // directory. - // - mksymlink (sp, target, link / target.leaf (), cleanup, fail); - } - } - - r = 0; - } - catch (const invalid_path& e) - { - error (false) << "invalid path '" << e.path << "'"; - } - // Can be thrown while closing in, out or writing to cerr. - // - catch (const io_error& e) - { - error (false) << e; - } - catch (const failed&) - { - // Diagnostics has already been issued. - } - catch (const cli::exception& e) - { - error (false) << e; - } - - cerr.close (); - return r; - } - catch (const std::exception&) - { - return 1; - } - - // Create a directory if not exist and its parent directories if - // necessary. Throw system_error on failure. Register created - // directories for cleanup. The directory path must be absolute. - // - static void - mkdir_p (scope& sp, const dir_path& p, bool cleanup) - { - if (!dir_exists (p)) - { - if (!p.root ()) - mkdir_p (sp, p.directory (), cleanup); - - try_mkdir (p); // Returns success or throws. - - if (cleanup) - sp.clean ({cleanup_type::always, p}, true /* implicit */); - } - } - - // mkdir [--no-cleanup] [-p|--parents] ... - // - // Note that POSIX doesn't specify if after a directory creation failure - // the command should proceed with the rest of the arguments. The current - // implementation exits immediatelly in such a case. - // - // Note: can be executed synchronously. - // - static uint8_t - mkdir (scope& sp, - const strings& args, - auto_fd in, auto_fd out, auto_fd err) noexcept - try - { - uint8_t r (1); - ofdstream cerr (move (err)); - - auto error = [&cerr] (bool fail = true) - { - return error_record (cerr, fail, "mkdir"); - }; - - try - { - in.close (); - out.close (); - - // Parse arguments. - // - cli::vector_scanner scan (args); - mkdir_options ops (scan); - - // Create directories. - // - if (!scan.more ()) - error () << "missing directory"; - - bool cleanup (!ops.no_cleanup ()); - - while (scan.more ()) - { - dir_path p (path_cast (parse_path (scan.next (), - sp.wd_path))); - - try - { - if (ops.parents ()) - mkdir_p (sp, p, cleanup); - else if (try_mkdir (p) == mkdir_status::success) - { - if (cleanup) - sp.clean ({cleanup_type::always, p}, true /* implicit */); - } - else // == mkdir_status::already_exists - throw_generic_error (EEXIST); - } - catch (const system_error& e) - { - error () << "unable to create directory '" << p << "': " << e; - } - } - - r = 0; - } - catch (const invalid_path& e) - { - error (false) << "invalid path '" << e.path << "'"; - } - // Can be thrown while closing in, out or writing to cerr. - // - catch (const io_error& e) - { - error (false) << e; - } - catch (const failed&) - { - // Diagnostics has already been issued. - } - catch (const cli::exception& e) - { - error (false) << e; - } - - cerr.close (); - return r; - } - catch (const std::exception&) - { - return 1; - } - - // mv [--no-cleanup] [-f|--force] - // mv [--no-cleanup] [-f|--force] ... / - // - // Note: can be executed synchronously. - // - static uint8_t - mv (scope& sp, - const strings& args, - auto_fd in, auto_fd out, auto_fd err) noexcept - try - { - uint8_t r (1); - ofdstream cerr (move (err)); - - auto error = [&cerr] (bool fail = true) - { - return error_record (cerr, fail, "mv"); - }; - - try - { - in.close (); - out.close (); - - // Parse arguments. - // - cli::vector_scanner scan (args); - mv_options ops (scan); - - // Move filesystem entries. - // - if (!scan.more ()) - error () << "missing arguments"; - - // Note that the arguments semantics depends on the last argument, - // so we read out and cache them. - // - small_vector args; - while (scan.more ()) - args.push_back (scan.next ()); - - const dir_path& wd (sp.wd_path); - - auto i (args.begin ()); - auto j (args.rbegin ()); - path dst (parse_path (move (*j++), wd)); - auto e (j.base ()); - - if (i == e) - error () << "missing source path"; - - auto mv = [ops, &wd, &sp, &error] (const path& from, const path& to) - { - const dir_path& rwd (sp.root.wd_path); - - if (!from.sub (rwd) && !ops.force ()) - error () << "'" << from << "' is out of working directory '" - << rwd << "'"; - - try - { - auto check_wd = [&wd, &error] (const path& p) - { - if (wd.sub (path_cast (p))) - error () << "'" << p << "' contains test working directory '" - << wd << "'"; - }; - - check_wd (from); - check_wd (to); - - bool exists (butl::entry_exists (to)); - - // Fail if the source and destination paths are the same. - // - // Note that for mventry() function (that is based on the POSIX - // rename() function) this is a noop. - // - if (exists && to == from) - error () << "unable to move entity '" << from << "' to itself"; - - // Rename/move the filesystem entry, replacing an existing one. - // - mventry (from, - to, - cpflags::overwrite_permissions | - cpflags::overwrite_content); - - // Unless suppressed, adjust the cleanups that are sub-paths of - // the source path. - // - if (!ops.no_cleanup ()) - { - // "Move" the matching cleanup if the destination path doesn't - // exist and is a sub-path of the working directory. Otherwise - // just remove it. - // - // Note that it's not enough to just change the cleanup paths. - // We also need to make sure that these cleanups happen before - // the destination directory (or any of its parents) cleanup, - // that is potentially registered. To achieve that we can just - // relocate these cleanup entries to the end of the list, - // preserving their mutual order. Remember that cleanups in - // the list are executed in the reversed order. - // - bool mv_cleanups (!exists && to.sub (rwd)); - cleanups cs; - - // Remove the source path sub-path cleanups from the list, - // adjusting/caching them if required (see above). - // - for (auto i (sp.cleanups.begin ()); i != sp.cleanups.end (); ) - { - cleanup& c (*i); - path& p (c.path); - - if (p.sub (from)) - { - if (mv_cleanups) - { - // Note that we need to preserve the cleanup path - // trailing separator which indicates the removal - // method. Also note that leaf(), in particular, does - // that. - // - p = p != from - ? to / p.leaf (path_cast (from)) - : p.to_directory () - ? path_cast (to) - : to; - - cs.push_back (move (c)); - } - - i = sp.cleanups.erase (i); - } - else - ++i; - } - - // Re-insert the adjusted cleanups at the end of the list. - // - sp.cleanups.insert (sp.cleanups.end (), - make_move_iterator (cs.begin ()), - make_move_iterator (cs.end ())); - } - } - catch (const system_error& e) - { - error () << "unable to move entity '" << from << "' to '" << to - << "': " << e; - } - }; - - // If destination is not a directory path (no trailing separator) - // then move the filesystem entry to the specified path (the only - // source path is allowed in such a case). Otherwise move the source - // filesystem entries into the destination directory. - // - if (!dst.to_directory ()) - { - path src (parse_path (move (*i++), wd)); - - // If there are multiple sources but no trailing separator for the - // destination, then, most likelly, it is missing. - // - if (i != e) - error () << "multiple source paths without trailing separator " - << "for destination directory"; - - // Synopsis 1: move an entity to the specified path. - // - mv (src, dst); - } - else - { - // Synopsis 2: move entities into the specified directory. - // - for (; i != e; ++i) - { - path src (parse_path (move (*i), wd)); - mv (src, dst / src.leaf ()); - } - } - - r = 0; - } - catch (const invalid_path& e) - { - error (false) << "invalid path '" << e.path << "'"; - } - // Can be thrown while closing in, out or writing to cerr. - // - catch (const io_error& e) - { - error (false) << e; - } - catch (const failed&) - { - // Diagnostics has already been issued. - } - catch (const cli::exception& e) - { - error (false) << e; - } - - cerr.close (); - return r; - } - catch (const std::exception&) - { - return 1; - } - - // rm [-r|--recursive] [-f|--force] ... - // - // The implementation deviates from POSIX in a number of ways. It doesn't - // interact with a user and fails immediatelly if unable to process an - // argument. It doesn't check for dots containment in the path, and - // doesn't consider files and directory permissions in any way just - // trying to remove a filesystem entry. Always fails if empty path is - // specified. - // - // Note: can be executed synchronously. - // - static uint8_t - rm (scope& sp, - const strings& args, - auto_fd in, auto_fd out, auto_fd err) noexcept - try - { - uint8_t r (1); - ofdstream cerr (move (err)); - - auto error = [&cerr] (bool fail = true) - { - return error_record (cerr, fail, "rm"); - }; - - try - { - in.close (); - out.close (); - - // Parse arguments. - // - cli::vector_scanner scan (args); - rm_options ops (scan); - - // Remove entries. - // - if (!scan.more () && !ops.force ()) - error () << "missing file"; - - const dir_path& wd (sp.wd_path); - const dir_path& rwd (sp.root.wd_path); - - while (scan.more ()) - { - path p (parse_path (scan.next (), wd)); - - if (!p.sub (rwd) && !ops.force ()) - error () << "'" << p << "' is out of working directory '" << rwd - << "'"; - - try - { - dir_path d (path_cast (p)); - - if (dir_exists (d)) - { - if (!ops.recursive ()) - error () << "'" << p << "' is a directory"; - - if (wd.sub (d)) - error () << "'" << p << "' contains test working directory '" - << wd << "'"; - - // The call can result in rmdir_status::not_exist. That's not - // very likelly but there is also nothing bad about it. - // - try_rmdir_r (d); - } - else if (try_rmfile (p) == rmfile_status::not_exist && - !ops.force ()) - throw_generic_error (ENOENT); - } - catch (const system_error& e) - { - error () << "unable to remove '" << p << "': " << e; - } - } - - r = 0; - } - catch (const invalid_path& e) - { - error (false) << "invalid path '" << e.path << "'"; - } - // Can be thrown while closing in, out or writing to cerr. - // - catch (const io_error& e) - { - error (false) << e; - } - catch (const failed&) - { - // Diagnostics has already been issued. - } - catch (const cli::exception& e) - { - error (false) << e; - } - - cerr.close (); - return r; - } - catch (const std::exception&) - { - return 1; - } - - // rmdir [-f|--force] ... - // - // Note: can be executed synchronously. - // - static uint8_t - rmdir (scope& sp, - const strings& args, - auto_fd in, auto_fd out, auto_fd err) noexcept - try - { - uint8_t r (1); - ofdstream cerr (move (err)); - - auto error = [&cerr] (bool fail = true) - { - return error_record (cerr, fail, "rmdir"); - }; - - try - { - in.close (); - out.close (); - - // Parse arguments. - // - cli::vector_scanner scan (args); - rmdir_options ops (scan); - - // Remove directories. - // - if (!scan.more () && !ops.force ()) - error () << "missing directory"; - - const dir_path& wd (sp.wd_path); - const dir_path& rwd (sp.root.wd_path); - - while (scan.more ()) - { - dir_path p (path_cast (parse_path (scan.next (), wd))); - - if (wd.sub (p)) - error () << "'" << p << "' contains test working directory '" - << wd << "'"; - - if (!p.sub (rwd) && !ops.force ()) - error () << "'" << p << "' is out of working directory '" - << rwd << "'"; - - try - { - rmdir_status s (try_rmdir (p)); - - if (s == rmdir_status::not_empty) - throw_generic_error (ENOTEMPTY); - else if (s == rmdir_status::not_exist && !ops.force ()) - throw_generic_error (ENOENT); - } - catch (const system_error& e) - { - error () << "unable to remove '" << p << "': " << e; - } - } - - r = 0; - } - catch (const invalid_path& e) - { - error (false) << "invalid path '" << e.path << "'"; - } - // Can be thrown while closing in, out or writing to cerr. - // - catch (const io_error& e) - { - error (false) << e; - } - catch (const failed&) - { - // Diagnostics has already been issued. - } - catch (const cli::exception& e) - { - error (false) << e; - } - - cerr.close (); - return r; - } - catch (const std::exception&) - { - return 1; - } - - // sed [-n|--quiet] [-i|--in-place] -e|--expression