// -*- C++ -*- // // This file was generated by CLI, a command line interface // compiler for C++. // // Begin prologue. // #include // // End prologue. #include #include #include #include #include #include #include #include #include namespace bbot { namespace cli { // unknown_option // unknown_option:: ~unknown_option () noexcept { } void unknown_option:: print (::std::ostream& os) const { os << "unknown option '" << option ().c_str () << "'"; } const char* unknown_option:: what () const noexcept { return "unknown option"; } // unknown_argument // unknown_argument:: ~unknown_argument () noexcept { } void unknown_argument:: print (::std::ostream& os) const { os << "unknown argument '" << argument ().c_str () << "'"; } const char* unknown_argument:: what () const noexcept { return "unknown argument"; } // missing_value // missing_value:: ~missing_value () noexcept { } void missing_value:: print (::std::ostream& os) const { os << "missing value for option '" << option ().c_str () << "'"; } const char* missing_value:: what () const noexcept { return "missing option value"; } // invalid_value // invalid_value:: ~invalid_value () noexcept { } void invalid_value:: print (::std::ostream& os) const { os << "invalid value '" << value ().c_str () << "' for option '" << option ().c_str () << "'"; if (!message ().empty ()) os << ": " << message ().c_str (); } const char* invalid_value:: what () const noexcept { return "invalid option value"; } // eos_reached // void eos_reached:: print (::std::ostream& os) const { os << what (); } const char* eos_reached:: what () const noexcept { return "end of argument stream reached"; } // unexpected_group // unexpected_group:: ~unexpected_group () noexcept { } void unexpected_group:: print (::std::ostream& os) const { os << "unexpected grouped argument '" << group_ << "' " << "for argument '" << argument_ << "'"; } const char* unexpected_group:: what () const noexcept { return "unexpected grouped argument"; } // group_separator // group_separator:: ~group_separator () noexcept { } void group_separator:: print (::std::ostream& os) const { bool ex (!expected_.empty ()); bool en (!encountered_.empty ()); if (ex) { os << "expected group separator '" << expected_ << "'"; if (en) os << " instead of '" << encountered_ << "'"; } else os << "unexpected group separator '" << encountered_ << "'"; if (en) os << ", use '\\" << encountered_ << "' to escape"; } const char* group_separator:: what () const noexcept { bool ex (!expected_.empty ()); bool en (!encountered_.empty ()); return en ? ex ? "wrong group separator" : "unexpected group separator" : ex ? "expected group separator" : ""; } // scanner // scanner:: ~scanner () { } // argv_scanner // bool argv_scanner:: more () { return i_ < argc_; } const char* argv_scanner:: peek () { if (i_ < argc_) return argv_[i_]; else throw eos_reached (); } const char* argv_scanner:: next () { if (i_ < argc_) { const char* r (argv_[i_]); if (erase_) { for (int i (i_ + 1); i < argc_; ++i) argv_[i - 1] = argv_[i]; --argc_; argv_[argc_] = 0; } else ++i_; ++start_position_; return r; } else throw eos_reached (); } void argv_scanner:: skip () { if (i_ < argc_) { ++i_; ++start_position_; } else throw eos_reached (); } std::size_t argv_scanner:: position () { return start_position_; } // vector_scanner // bool vector_scanner:: more () { return i_ < v_.size (); } const char* vector_scanner:: peek () { if (i_ < v_.size ()) return v_[i_].c_str (); else throw eos_reached (); } const char* vector_scanner:: next () { if (i_ < v_.size ()) return v_[i_++].c_str (); else throw eos_reached (); } void vector_scanner:: skip () { if (i_ < v_.size ()) ++i_; else throw eos_reached (); } std::size_t vector_scanner:: position () { return start_position_ + i_; } // group_scanner // bool group_scanner:: more () { // We don't want to call scan_group() here since that // would invalidate references to previous arguments. // But we do need to check that the previous group was // handled. // if (state_ == scanned) { if (group_scan_.end () != group_.size ()) throw unexpected_group (arg_[i_][j_], group_scan_.next ()); } return j_ != 0 || scan_.more (); } const char* group_scanner:: peek () { if (state_ != peeked) { scan_group (); state_ = peeked; } // Return unescaped. return arg_[i_][j_ - 1].c_str (); } const char* group_scanner:: next () { if (state_ != peeked) scan_group (); state_ = scanned; // Return unescaped. return arg_[i_][--j_].c_str (); } void group_scanner:: skip () { if (state_ != peeked) scan_group (); state_ = skipped; --j_; } std::size_t group_scanner:: position () { return j_ == 0 ? scan_.position () : pos_ + (arg_[i_].size () - j_); } void group_scanner:: scan_group () { // If the previous argument has been scanned, then make // sure the group has been scanned (handled) as well. // if (state_ == scanned) { if (group_scan_.end () != group_.size ()) throw unexpected_group (arg_[i_][j_], group_scan_.next ()); } // If we still have arguments in the pack, rewind the group. // if (j_ != 0) { group_scan_.reset (); return; } i_ += (i_ == 0 ? 1 : -1); group_.clear (); group_scan_.reset (); pos_ = scan_.position (); // Note: using group_ won't cover empty groups and using // j_ won't cover single-argument packs. // bool group (false), pack (false); do { const char* a (scan_.next ()); size_t i (*a == '\\' ? 1 : 0); separator s (sense (a + i)); if (s == none || i != 0) { if (arg_[i_].size () != 1) arg_[i_].resize (1); arg_[i_][0] = a + (s != none ? i : 0); j_ = 1; break; } // Start of a leading group for the next argument or // argument pack. We will only know which once we see // the closing separator. // if (s != open) throw group_separator (a, ""); size_t n (group_.size ()); // Scan the group until the closing separator. // s = none; while (s == none && scan_.more ()) { a = scan_.next (); i = (*a == '\\' ? 1 : 0); s = sense (a + i); if (s == none || i != 0) { group_.push_back (a + (s != none ? i : 0)); s = none; } } if (s == close) { size_t m (group_.size ()); j_ = m - n; if (j_ == 0) throw group_separator ("{", ""); if (arg_[i_].size () != j_) arg_[i_].resize (j_); // Move from group_ to arg_. Add in reverse for ease // of iteration. // for (size_t j (0); j != j_; ++j) arg_[i_][j] = group_[m - j - 1]; group_.resize (n); pack = true; break; } else if (s == close_plus) group = true; else throw group_separator ((s != none ? a : ""), "}+"); } while (scan_.more ()); // Handle the case where we have seen the leading group // but there are no more arguments. // if (group && j_ == 0) throw group_separator ("{", ""); // Handle trailing groups, if any. // while (scan_.more ()) { const char* a (scan_.peek ()); size_t i (*a == '\\' ? 1 : 0); separator s (sense (a + i)); // Next argument, argument pack, or leading group. // if (s == none || s == open || i != 0) break; if (s != open_plus) throw group_separator (a, ""); group = true; // Scan the group until the closing separator. // scan_.next (); s = none; while (s == none && scan_.more ()) { a = scan_.next (); i = (*a == '\\' ? 1 : 0); s = sense (a + i); if (s == none || i != 0) { group_.push_back (a + (s != none ? i : 0)); s = none; } } if (s != close) throw group_separator ((s != none ? a : ""), "}"); } // Handle the case where we have seen the argument pack // without leading or trailing group. // if (pack && !group) throw group_separator ("{", ""); } template struct parser { static void parse (X& x, bool& xs, scanner& s) { using namespace std; const char* o (s.next ()); if (s.more ()) { string v (s.next ()); istringstream is (v); if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) throw invalid_value (o, v); } else throw missing_value (o); xs = true; } }; template <> struct parser { static void parse (bool& x, bool& xs, scanner& s) { const char* o (s.next ()); if (s.more ()) { const char* v (s.next ()); if (std::strcmp (v, "1") == 0 || std::strcmp (v, "true") == 0 || std::strcmp (v, "TRUE") == 0 || std::strcmp (v, "True") == 0) x = true; else if (std::strcmp (v, "0") == 0 || std::strcmp (v, "false") == 0 || std::strcmp (v, "FALSE") == 0 || std::strcmp (v, "False") == 0) x = false; else throw invalid_value (o, v); } else throw missing_value (o); xs = true; } }; template <> struct parser { static void parse (std::string& x, bool& xs, scanner& s) { const char* o (s.next ()); if (s.more ()) x = s.next (); else throw missing_value (o); xs = true; } }; template struct parser > { static void parse (std::pair& x, bool& xs, scanner& s) { x.second = s.position (); parser::parse (x.first, xs, s); } }; template struct parser > { static void parse (std::vector& c, bool& xs, scanner& s) { X x; bool dummy; parser::parse (x, dummy, s); c.push_back (x); xs = true; } }; template struct parser > { static void parse (std::set& c, bool& xs, scanner& s) { X x; bool dummy; parser::parse (x, dummy, s); c.insert (x); xs = true; } }; template struct parser > { static void parse (std::map& m, bool& xs, scanner& s) { const char* o (s.next ()); if (s.more ()) { std::size_t pos (s.position ()); std::string ov (s.next ()); std::string::size_type p = ov.find ('='); K k = K (); V v = V (); std::string kstr (ov, 0, p); std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); int ac (2); char* av[] = { const_cast (o), 0 }; bool dummy; if (!kstr.empty ()) { av[1] = const_cast (kstr.c_str ()); argv_scanner s (0, ac, av, false, pos); parser::parse (k, dummy, s); } if (!vstr.empty ()) { av[1] = const_cast (vstr.c_str ()); argv_scanner s (0, ac, av, false, pos); parser::parse (v, dummy, s); } m[k] = v; } else throw missing_value (o); xs = true; } }; template struct parser > { static void parse (std::multimap& m, bool& xs, scanner& s) { const char* o (s.next ()); if (s.more ()) { std::size_t pos (s.position ()); std::string ov (s.next ()); std::string::size_type p = ov.find ('='); K k = K (); V v = V (); std::string kstr (ov, 0, p); std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); int ac (2); char* av[] = { const_cast (o), 0 }; bool dummy; if (!kstr.empty ()) { av[1] = const_cast (kstr.c_str ()); argv_scanner s (0, ac, av, false, pos); parser::parse (k, dummy, s); } if (!vstr.empty ()) { av[1] = const_cast (vstr.c_str ()); argv_scanner s (0, ac, av, false, pos); parser::parse (v, dummy, s); } m.insert (typename std::multimap::value_type (k, v)); } else throw missing_value (o); xs = true; } }; template void thunk (X& x, scanner& s) { parser::parse (x.*M, s); } template void thunk (X& x, scanner& s) { s.next (); x.*M = true; } template void thunk (X& x, scanner& s) { parser::parse (x.*M, x.*S, s); } } } #include namespace bbot { } // Begin epilogue. // // // End epilogue.