// -*- C++ -*- // // This file was generated by CLI, a command line interface // compiler for C++. // #ifndef BDEP_COMMON_OPTIONS_HXX #define BDEP_COMMON_OPTIONS_HXX // Begin prologue. // // // End prologue. #include #include #include #include #include #include #include #include #ifndef CLI_POTENTIALLY_UNUSED # if defined(_MSC_VER) || defined(__xlC__) # define CLI_POTENTIALLY_UNUSED(x) (void*)&x # else # define CLI_POTENTIALLY_UNUSED(x) (void)x # endif #endif namespace bdep { namespace cli { class usage_para { public: enum value { none, text, option }; usage_para (value); operator value () const { return v_; } private: value v_; }; class unknown_mode { public: enum value { skip, stop, fail }; unknown_mode (value); operator value () const { return v_; } private: value v_; }; // Exceptions. // class exception: public std::exception { public: virtual void print (::std::ostream&) const = 0; }; ::std::ostream& operator<< (::std::ostream&, const exception&); class unknown_option: public exception { public: virtual ~unknown_option () noexcept; unknown_option (const std::string& option); const std::string& option () const; virtual void print (::std::ostream&) const; virtual const char* what () const noexcept; private: std::string option_; }; class unknown_argument: public exception { public: virtual ~unknown_argument () noexcept; unknown_argument (const std::string& argument); const std::string& argument () const; virtual void print (::std::ostream&) const; virtual const char* what () const noexcept; private: std::string argument_; }; class missing_value: public exception { public: virtual ~missing_value () noexcept; missing_value (const std::string& option); const std::string& option () const; virtual void print (::std::ostream&) const; virtual const char* what () const noexcept; private: std::string option_; }; class invalid_value: public exception { public: virtual ~invalid_value () noexcept; invalid_value (const std::string& option, const std::string& value, const std::string& message = std::string ()); const std::string& option () const; const std::string& value () const; const std::string& message () const; virtual void print (::std::ostream&) const; virtual const char* what () const noexcept; private: std::string option_; std::string value_; std::string message_; }; class eos_reached: public exception { public: virtual void print (::std::ostream&) const; virtual const char* what () const noexcept; }; class file_io_failure: public exception { public: virtual ~file_io_failure () noexcept; file_io_failure (const std::string& file); const std::string& file () const; virtual void print (::std::ostream&) const; virtual const char* what () const noexcept; private: std::string file_; }; class unmatched_quote: public exception { public: virtual ~unmatched_quote () noexcept; unmatched_quote (const std::string& argument); const std::string& argument () const; virtual void print (::std::ostream&) const; virtual const char* what () const noexcept; private: std::string argument_; }; class unexpected_group: public exception { public: virtual ~unexpected_group () noexcept; unexpected_group (const std::string& argument, const std::string& group); const std::string& argument () const; const std::string& group () const; virtual void print (std::ostream&) const; virtual const char* what () const noexcept; private: std::string argument_; std::string group_; }; class group_separator: public exception { public: virtual ~group_separator () noexcept; // Note: either (but not both) can be empty. // group_separator (const std::string& encountered, const std::string& expected); const std::string& encountered () const; const std::string& expected () const; virtual void print (std::ostream&) const; virtual const char* what () const noexcept; private: std::string encountered_; std::string expected_; }; // Command line argument scanner interface. // // The values returned by next() are guaranteed to be valid // for the two previous arguments up until a call to a third // peek() or next(). // // The position() function returns a monotonically-increasing // number which, if stored, can later be used to determine the // relative position of the argument returned by the following // call to next(). Note that if multiple scanners are used to // extract arguments from multiple sources, then the end // position of the previous scanner should be used as the // start position of the next. // class scanner { public: virtual ~scanner (); virtual bool more () = 0; virtual const char* peek () = 0; virtual const char* next () = 0; virtual void skip () = 0; virtual std::size_t position () = 0; }; class argv_scanner: public scanner { public: argv_scanner (int& argc, char** argv, bool erase = false, std::size_t start_position = 0); argv_scanner (int start, int& argc, char** argv, bool erase = false, std::size_t start_position = 0); int end () const; virtual bool more (); virtual const char* peek (); virtual const char* next (); virtual void skip (); virtual std::size_t position (); protected: std::size_t start_position_; int i_; int& argc_; char** argv_; bool erase_; }; class vector_scanner: public scanner { public: vector_scanner (const std::vector&, std::size_t start = 0, std::size_t start_position = 0); std::size_t end () const; void reset (std::size_t start = 0, std::size_t start_position = 0); virtual bool more (); virtual const char* peek (); virtual const char* next (); virtual void skip (); virtual std::size_t position (); private: std::size_t start_position_; const std::vector& v_; std::size_t i_; }; class argv_file_scanner: public argv_scanner { public: argv_file_scanner (int& argc, char** argv, const std::string& option, bool erase = false, std::size_t start_position = 0); argv_file_scanner (int start, int& argc, char** argv, const std::string& option, bool erase = false, std::size_t start_position = 0); argv_file_scanner (const std::string& file, const std::string& option, std::size_t start_position = 0); struct option_info { // If search_func is not NULL, it is called, with the arg // value as the second argument, to locate the options file. // If it returns an empty string, then the file is ignored. // const char* option; std::string (*search_func) (const char*, void* arg); void* arg; }; argv_file_scanner (int& argc, char** argv, const option_info* options, std::size_t options_count, bool erase = false, std::size_t start_position = 0); argv_file_scanner (int start, int& argc, char** argv, const option_info* options, std::size_t options_count, bool erase = false, std::size_t start_position = 0); argv_file_scanner (const std::string& file, const option_info* options = 0, std::size_t options_count = 0, std::size_t start_position = 0); virtual bool more (); virtual const char* peek (); virtual const char* next (); virtual void skip (); virtual std::size_t position (); // Return the file path if the peeked at argument came from a file and // the empty string otherwise. The reference is guaranteed to be valid // till the end of the scanner lifetime. // const std::string& peek_file (); // Return the 1-based line number if the peeked at argument came from // a file and zero otherwise. // std::size_t peek_line (); private: const option_info* find (const char*) const; void load (const std::string& file); typedef argv_scanner base; const std::string option_; option_info option_info_; const option_info* options_; std::size_t options_count_; struct arg { std::string value; const std::string* file; std::size_t line; }; std::deque args_; std::list files_; // Circular buffer of two arguments. // std::string hold_[2]; std::size_t i_; bool skip_; static int zero_argc_; static std::string empty_string_; }; class group_scanner: public scanner { public: group_scanner (scanner&); virtual bool more (); virtual const char* peek (); virtual const char* next (); virtual void skip (); virtual std::size_t position (); // The group is only available after the call to next() // (and skip() -- in case one needs to make sure the group // was empty, or some such) and is only valid (and must be // handled) until the next call to any of the scanner // functions (including more()). // // Note also that argument positions within each group start // from 0. // scanner& group (); // Escape an argument that is a group separator. Return the // passed string if no escaping is required. // static const char* escape (const char*); private: enum state { peeked, // Argument peeked at with peek(). scanned, // Argument scanned with next(). skipped, // Argument skipped with skip()/initial. }; enum separator { none, open, // { close, // } open_plus, // +{ close_plus // }+ }; static separator sense (const char*); // Scan the leading groups, the next argument/argument pack, // and the trailing groups. // void scan_group (); scanner& scan_; state state_; // Circular buffer of two arguments. // std::vector arg_[2]; std::size_t i_, j_, pos_; std::vector group_; vector_scanner group_scan_; }; typedef std::vector option_names; class option { public: const std::string& name () const; const option_names& aliases () const; bool flag () const; const std::string& default_value () const; public:option (); option (const std::string& name, const option_names& aliases, bool flag, const std::string& default_value); private: std::string name_; option_names aliases_; bool flag_; std::string default_value_; }; class options: public std::vector