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 +++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 9 deletions(-) (limited to 'tests/default-options/driver.cxx') 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; } -- cgit v1.1