From 7ebd5f9f540e907de06d8fdc76d95ccacabbbe1f Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 5 Aug 2021 19:36:34 +0300 Subject: Add support for option positions to load_default_options() --- tests/default-options/driver.cxx | 77 +++++++++++++++++++++++++++++++++++----- tests/default-options/testscript | 24 ++++++++++++- 2 files changed, 91 insertions(+), 10 deletions(-) (limited to 'tests') diff --git a/tests/default-options/driver.cxx b/tests/default-options/driver.cxx index 009cddb..17da19c 100644 --- a/tests/default-options/driver.cxx +++ b/tests/default-options/driver.cxx @@ -4,9 +4,11 @@ #include #ifndef __cpp_lib_modules_ts +#include #include #include #include +#include #include // invalid_argument #endif @@ -41,21 +43,21 @@ using namespace butl; // print the resulting options to STDOUT one per line. Note that the options // instance is a vector of arbitrary strings. // -// -f +// -f // Default options file name. Can be specified multiple times. // -// -d +// -d // Directory to start the default options files search from. Can be // specified multiple times, in which case a common start (parent) // directory is deduced. // -// -s +// -s // System directory. // -// -h +// -h // Home directory. // -// -x +// -x // Extra directory. // // -a @@ -70,6 +72,12 @@ using namespace butl; // -t // Trace the default options files search to STDERR. // +// -m +// Maximum number of arguments globally (SIZE_MAX/2 by default). +// +// -l +// Maximum number of arguments in the options file (1024 by default). +// int main (int argc, const char* argv[]) { @@ -78,8 +86,8 @@ main (int argc, const char* argv[]) class scanner { public: - scanner (const string& f, const string& option) - : option_ (option) {load (path (f));} + scanner (const string& f, const string& option, size_t pos) + : option_ (option), start_pos_ (pos) {load (path (f));} bool more () @@ -101,6 +109,12 @@ main (int argc, const char* argv[]) return args_[i_++]; } + size_t + position () + { + return start_pos_ + i_; + } + private: void load (const path& f) @@ -133,6 +147,7 @@ main (int argc, const char* argv[]) optional option_; vector args_; size_t i_ = 0; + size_t start_pos_; }; enum class unknow_mode @@ -141,6 +156,15 @@ main (int argc, const char* argv[]) fail }; + class unknown_argument: public std::exception + { + public: + string argument; + + explicit + unknown_argument (string a): argument (move (a)) {} + }; + class options: public vector { public: @@ -157,7 +181,7 @@ main (int argc, const char* argv[]) switch (m) { case unknow_mode::stop: return r; - case unknow_mode::fail: throw invalid_argument (a); + case unknow_mode::fail: throw unknown_argument (move (a)); } } @@ -200,6 +224,23 @@ main (int argc, const char* argv[]) vector cmd_args; bool print_entries (false); bool trace (false); + size_t arg_max (numeric_limits::max () / 2); + size_t arg_max_file (1024); + + auto num = [] (const string& s) -> size_t + { + assert (!s.empty ()); + + char* e (nullptr); + errno = 0; // We must clear it according to POSIX. + uint64_t r (strtoull (s.c_str (), &e, 10)); // Can't throw. + + assert (errno != ERANGE && + e == s.c_str () + s.size () && + r <= numeric_limits::max ()); + + return static_cast (r); + }; for (int i (1); i != argc; ++i) { @@ -242,6 +283,16 @@ main (int argc, const char* argv[]) { trace = true; } + else if (a == "-m") + { + assert (++i != argc); + arg_max = num (argv[i]); + } + else if (a == "-l") + { + assert (++i != argc); + arg_max_file = num (argv[i]); + } else if (a.compare (0, 2, "--") == 0) cmd_ops.push_back (move (a)); else @@ -270,11 +321,19 @@ main (int argc, const char* argv[]) << (remote ? "remote " : "local ") << f << endl; }, "--options-file", + arg_max, + arg_max_file, args); } + catch (const unknown_argument& e) + { + cerr << "error: unexpected argument '" << e.argument << "'" << endl; + return 1; + } catch (const invalid_argument& e) { - cerr << "error: unexpected argument '" << e.what () << "'" << endl; + cerr << "error: unable to load default options files: " << e.what () + << endl; return 1; } diff --git a/tests/default-options/testscript b/tests/default-options/testscript index 09bb2ec..f071701 100644 --- a/tests/default-options/testscript +++ b/tests/default-options/testscript @@ -51,6 +51,7 @@ +mkdir -p $d/local/ +echo '--package-foo' >=$d/foo + +echo '--package-fox' >+$d/foo +echo '--package-bar' >=$d/bar +echo '--package-local-foo' >=$d/local/foo +echo '--package-local-bar' >=$d/local/bar @@ -78,7 +79,7 @@ %\.+/home/work/project/.build2/bar,--project-bar,true% %\.+/home/work/project/.build2/local/foo,--project-local-foo,true% %\.+/home/work/project/.build2/local/bar,--project-local-bar,true% - %\.+/home/work/project/package/.build2/foo,--package-foo,true% + %\.+/home/work/project/package/.build2/foo,--package-foo --package-fox,true% %\.+/home/work/project/package/.build2/bar,--package-bar,true% %\.+/home/work/project/package/.build2/local/foo,--package-local-foo,true% %\.+/home/work/project/package/.build2/local/bar,--package-local-bar,true% @@ -129,6 +130,7 @@ --project-local-foo --project-local-bar --package-foo + --package-fox --package-bar --package-local-foo --package-local-bar @@ -150,6 +152,26 @@ %overwriting remote \.+/home/work/project/package/.build2/local/baz% %overwriting remote \.+/home/work/project/package/.build2/local/foo% EOE + + : positions + : + { + : success + : + $* -f foo -f bar -d $start_dir -m 36 -l 2 >! + + : fail-file + : + $* -f foo -f bar -d $start_dir -m 36 -l 1 2>>/~%EOE% != 0 + %error: unable to load default options files: too many options in file .+/package/\.build2/foo% + EOE + + : fail-globally + : + $* -f foo -f bar -d $start_dir -m 100 -l 10 2>>EOE != 0 + error: unable to load default options files: too many options files + EOE + } } : args -- cgit v1.1