aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/script/builtin-options.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2022-10-03 21:23:22 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2022-10-13 13:08:02 +0300
commitf59d82eb8fda3ddcf790556c6c3615e40ae8b15b (patch)
tree74cd2d3415259c6cb3e116a01eef215f6b39861f /libbuild2/script/builtin-options.cxx
parentf0959bca1b44e62c1745027fed42a5973f44cdb4 (diff)
Add support for 'for' loop second (... | for x) and third (for x <...) forms in script
Diffstat (limited to 'libbuild2/script/builtin-options.cxx')
-rw-r--r--libbuild2/script/builtin-options.cxx291
1 files changed, 291 insertions, 0 deletions
diff --git a/libbuild2/script/builtin-options.cxx b/libbuild2/script/builtin-options.cxx
index 8e15ddd..9b4067b 100644
--- a/libbuild2/script/builtin-options.cxx
+++ b/libbuild2/script/builtin-options.cxx
@@ -1076,6 +1076,297 @@ namespace build2
return r;
}
+
+ // for_options
+ //
+
+ for_options::
+ for_options ()
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ }
+
+ for_options::
+ for_options (int& argc,
+ char** argv,
+ bool erase,
+ ::build2::build::cli::unknown_mode opt,
+ ::build2::build::cli::unknown_mode arg)
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ ::build2::build::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ for_options::
+ for_options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::build2::build::cli::unknown_mode opt,
+ ::build2::build::cli::unknown_mode arg)
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ ::build2::build::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ for_options::
+ for_options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::build::cli::unknown_mode opt,
+ ::build2::build::cli::unknown_mode arg)
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ ::build2::build::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ for_options::
+ for_options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::build2::build::cli::unknown_mode opt,
+ ::build2::build::cli::unknown_mode arg)
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ ::build2::build::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ for_options::
+ for_options (::build2::build::cli::scanner& s,
+ ::build2::build::cli::unknown_mode opt,
+ ::build2::build::cli::unknown_mode arg)
+ : exact_ (),
+ newline_ (),
+ whitespace_ ()
+ {
+ _parse (s, opt, arg);
+ }
+
+ typedef
+ std::map<std::string, void (*) (for_options&, ::build2::build::cli::scanner&)>
+ _cli_for_options_map;
+
+ static _cli_for_options_map _cli_for_options_map_;
+
+ struct _cli_for_options_map_init
+ {
+ _cli_for_options_map_init ()
+ {
+ _cli_for_options_map_["--exact"] =
+ &::build2::build::cli::thunk< for_options, &for_options::exact_ >;
+ _cli_for_options_map_["-e"] =
+ &::build2::build::cli::thunk< for_options, &for_options::exact_ >;
+ _cli_for_options_map_["--newline"] =
+ &::build2::build::cli::thunk< for_options, &for_options::newline_ >;
+ _cli_for_options_map_["-n"] =
+ &::build2::build::cli::thunk< for_options, &for_options::newline_ >;
+ _cli_for_options_map_["--whitespace"] =
+ &::build2::build::cli::thunk< for_options, &for_options::whitespace_ >;
+ _cli_for_options_map_["-w"] =
+ &::build2::build::cli::thunk< for_options, &for_options::whitespace_ >;
+ }
+ };
+
+ static _cli_for_options_map_init _cli_for_options_map_init_;
+
+ bool for_options::
+ _parse (const char* o, ::build2::build::cli::scanner& s)
+ {
+ _cli_for_options_map::const_iterator i (_cli_for_options_map_.find (o));
+
+ if (i != _cli_for_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool for_options::
+ _parse (::build2::build::cli::scanner& s,
+ ::build2::build::cli::unknown_mode opt_mode,
+ ::build2::build::cli::unknown_mode arg_mode)
+ {
+ // Can't skip combined flags (--no-combined-flags).
+ //
+ assert (opt_mode != ::build2::build::cli::unknown_mode::skip);
+
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::build2::build::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::build::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::build::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::build::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::build::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::build::cli::unknown_mode::fail:
+ {
+ throw ::build2::build::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::build2::build::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::build2::build::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::build2::build::cli::unknown_mode::fail:
+ {
+ throw ::build2::build::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
}
}