Teuchos - Trilinos Tools Package Version of the Day
Teuchos_CommandLineProcessor.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
00043 #define TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
00044 
00053 #include "Teuchos_map.hpp"
00054 #include "Teuchos_any.hpp"
00055 #include "Teuchos_CompileTimeAssert.hpp"
00056 
00070 namespace Teuchos {
00071 
00072 class TEUCHOS_LIB_DLL_EXPORT CommandLineProcessor {
00073 public:
00074 
00076 
00077 
00079   class ParseError : public std::logic_error
00080   {public: ParseError(const std::string& what_arg) : std::logic_error(what_arg) {}};
00081 
00083   class HelpPrinted : public ParseError
00084   {public: HelpPrinted(const std::string& what_arg) : ParseError(what_arg) {}};
00085 
00087   class UnrecognizedOption : public ParseError
00088   {public: UnrecognizedOption(const std::string& what_arg) : ParseError(what_arg) {}};
00089 
00094   enum EParseCommandLineReturn {
00095     PARSE_SUCCESSFUL              =  0 
00096     ,PARSE_HELP_PRINTED            =  1 
00097     ,PARSE_UNRECOGNIZED_OPTION     =  2 
00098   };
00099   
00101 
00103 
00104 
00117   CommandLineProcessor(
00118     bool    throwExceptions       = true
00119     ,bool   recogniseAllOptions   = true
00120     ,bool   addOutputSetupOptions = false
00121     );
00122 
00124 
00126 
00127 
00129   void throwExceptions( const bool & throwExceptions );
00130   
00132   bool throwExceptions() const;
00133 
00135   void recogniseAllOptions( const bool & recogniseAllOptions );
00136 
00138   bool recogniseAllOptions() const;
00139 
00141   void addOutputSetupOptions( const bool &addOutputSetupOptions );
00142 
00144   bool addOutputSetupOptions() const;
00145 
00147 
00149 
00150   
00153   void setDocString( const char doc_string[] );
00154 
00167   void setOption(
00168     const char     option_true[]
00169     ,const char    option_false[]
00170     ,bool          *option_val
00171     ,const char    documentation[] = NULL
00172     );
00173 
00184   void setOption(
00185     const char     option_name[]
00186     ,int           *option_val
00187     ,const char    documentation[] = NULL
00188     ,const bool    required        = false
00189     );
00190 
00201   void setOption(
00202     const char     option_name[]
00203     ,double        *option_val
00204     ,const char    documentation[] = NULL
00205     ,const bool    required        = false
00206     );
00207 
00218   void setOption(
00219     const char     option_name[]
00220     ,std::string   *option_val
00221     ,const char    documentation[] = NULL
00222     ,const bool    required        = false
00223     );
00224   
00253   template <class EType>
00254   void setOption(
00255     const char    enum_option_name[]
00256     ,EType        *enum_option_val
00257     ,const int    num_enum_opt_values
00258     ,const EType  enum_opt_values[]
00259     ,const char*  enum_opt_names[]
00260     ,const char   documentation[] = NULL
00261     ,const bool   required        = false
00262     );
00263   
00265 
00267 
00268 
00328   EParseCommandLineReturn  parse(
00329     int             argc
00330     ,char*          argv[]
00331     ,std::ostream   *errout = &std::cerr
00332     ) const;
00333 
00335 
00337 
00338 
00347    void printHelpMessage( const char program_name[], std::ostream &out ) const;
00348 
00350 
00351 public:
00352   //
00353   enum EOptType { OPT_NONE, OPT_BOOL_TRUE, OPT_BOOL_FALSE, OPT_INT, OPT_DOUBLE, OPT_STRING, OPT_ENUM_INT };
00354   // RAB: 2003/10/10: Note: I had to move this out of the private section since
00355   // the sun compiler (version 7) complained (rightly it now appears after looking
00356   // up what the ISO/ANSI C++ standard says) about the declaration for opt_val_val_t
00357   // not being able to access a private member of CommandLineProcessor.
00358 
00359 private:
00360 
00361   // /////////////////////////////////
00362   // Private types
00363 
00364   // ToDo: RAB: 2004/05/25: Clean up these data structures and add
00365   // support for a templated enum type.  This will clean up usage
00366   // quite a bit.
00367 
00368   //
00369   struct opt_val_val_t {
00370     opt_val_val_t()
00371       :opt_type(OPT_NONE)
00372       {}
00373     opt_val_val_t( EOptType opt_type_in, const any& opt_val_in, bool required_in )
00374       :opt_type(opt_type_in),opt_val(opt_val_in),required(required_in),was_read(false)
00375       {}
00376     EOptType     opt_type;
00377     any          opt_val; // Will be bool*, int*, double*, std::string* or a small int (for OPT_ENUM_INT)
00378     bool         required;
00379     bool         was_read;
00380   };
00381 
00382   //
00383   typedef Teuchos::map<std::string,opt_val_val_t>   options_list_t;
00384 
00385   //
00386   struct opt_doc_t {
00387     opt_doc_t()
00388       :opt_type(OPT_NONE)
00389       {}
00390     opt_doc_t(EOptType opt_type_in, const std::string& opt_name_in, const std::string& opt_name_false_in
00391             ,const std::string &documentation_in, const any &default_val_in )
00392       :opt_type(opt_type_in),opt_name(opt_name_in),opt_name_false(opt_name_false_in)
00393       ,documentation(documentation_in),default_val(default_val_in)
00394       {}
00395     EOptType     opt_type;
00396     std::string  opt_name;
00397     std::string  opt_name_false; // only for bool
00398     std::string  documentation;
00399     any          default_val;
00400   };
00401   
00402   //
00403   typedef std::vector<opt_doc_t>   options_documentation_list_t;
00404 
00405   //
00406   struct enum_opt_data_t {
00407     enum_opt_data_t()
00408       :enum_option_val(NULL), num_enum_opt_values(0)
00409       {}
00410     enum_opt_data_t(
00411       int          *_enum_option_val
00412       ,const int    _num_enum_opt_values
00413       ,const int    _enum_opt_values[]
00414       ,const char*  _enum_opt_names[]
00415       )
00416       :enum_option_val(_enum_option_val)
00417       ,num_enum_opt_values(_num_enum_opt_values)
00418       ,enum_opt_values(_enum_opt_values,_enum_opt_values+_num_enum_opt_values)
00419       {
00420         for( int k = 0; k < num_enum_opt_values; ++k )
00421           enum_opt_names.push_back(std::string(_enum_opt_names[k]));
00422       }
00423     int                  *enum_option_val;
00424     int                  num_enum_opt_values;
00425     std::vector<int>     enum_opt_values;
00426     std::vector<std::string>  enum_opt_names;
00427   };
00428 
00429   //
00430   typedef std::vector<enum_opt_data_t> enum_opt_data_list_t;
00431 
00432   // /////////////////////////////////
00433   // Private data members
00434 
00435   bool                             throwExceptions_;
00436   bool                             recogniseAllOptions_;
00437   bool                             addOutputSetupOptions_;
00438   std::string                      doc_string_;
00439 
00440   //use pragmas to disable some false positive warnings in windows sharedlib exports
00441 #ifdef _MSC_VER
00442 #pragma warning(push)
00443 #pragma warning(disable:4251)
00444 #endif
00445   mutable options_list_t           options_list_;
00446   options_documentation_list_t     options_documentation_list_;
00447   enum_opt_data_list_t             enum_opt_data_list_;
00448 #ifdef _MSC_VER
00449 #pragma warning(pop)
00450 #endif
00451 
00452   bool  output_all_front_matter_;
00453   bool  output_show_line_prefix_;
00454   bool  output_show_tab_count_;
00455   bool  output_show_proc_rank_;
00456   int   output_to_root_rank_only_;
00457   bool  print_rcpnode_statistics_on_exit_;
00458 
00459   bool  added_extra_output_setup_options_;
00460   bool  in_add_extra_output_setup_options_;
00461 
00462   static const bool  output_all_front_matter_default_;
00463   static const bool  output_show_line_prefix_default_;
00464   static const bool  output_show_tab_count_default_;
00465   static const bool  output_show_proc_rank_default_;
00466   static const int   output_to_root_rank_only_default_;
00467   static const bool  print_rcpnode_statistics_on_exit_default_;
00468 
00469   // /////////////////////////////////
00470   // Private member functions
00471 
00472   // Set the extra output setup options
00473   void add_extra_output_setup_options() const;
00474 
00475   // Set an integer enumeration option
00476   void setEnumOption(
00477     const char    enum_option_name[]
00478     ,int          *enum_option_val
00479     ,const int    num_enum_opt_values
00480     ,const int    enum_opt_values[]
00481     ,const char*  enum_opt_names[]
00482     ,const char   documentation[]
00483     ,const bool   required
00484     );
00485 
00486   // Set an enum int option
00487   bool set_enum_value(
00488     int                  argv_i
00489     ,char*               argv[]
00490     ,const std::string   &enum_opt_name
00491     ,const int           enum_id
00492     ,const std::string   &enum_str_val
00493     ,std::ostream        *errout
00494     ) const;
00495 
00496   // Print the valid enum values
00497   void print_enum_opt_names(
00498     const int            enum_id
00499     ,std::ostream        &out
00500     ) const;
00501 
00502   // Return the name of the default value for an enum
00503   std::string enum_opt_default_val_name(
00504     const std::string    &enum_name
00505     ,const int           enum_id
00506     ,std::ostream        *errout
00507     ) const;
00508   
00509   // Return the index given and option value
00510   int find_enum_opt_index(
00511     const std::string           &enum_opt_name
00512     ,const int                  opt_value
00513     ,const enum_opt_data_t      &enum_data
00514     ,std::ostream               *errout
00515     ) const; 
00516 
00517   // Get the option and the value from an entry in argv[].
00518   // Will return false if entry is not formated properly.
00519   bool get_opt_val(
00520     const char     str[]
00521     ,std::string   *opt_name
00522     ,std::string   *opt_val_str // May be empty on return
00523     ) const;
00524 
00525   // String for option type
00526   std::string opt_type_str( EOptType ) const;
00527 
00528   // Print bad option
00529   void print_bad_opt(
00530     int             argv_i
00531     ,char*          argv[]
00532     ,std::ostream   *errout
00533     ) const;
00534 
00535 }; // end class CommandLineProcessor
00536 
00537 // /////////////////////////
00538 // Inline members
00539 
00540 // Behavior modes
00541 
00542 inline
00543 void CommandLineProcessor::throwExceptions( const bool & throwExceptions_in )
00544 { throwExceptions_ = throwExceptions_in; }
00545 
00546 inline
00547 bool CommandLineProcessor::throwExceptions() const
00548 { return throwExceptions_; }
00549 
00550 inline
00551 void CommandLineProcessor::recogniseAllOptions( const bool & recogniseAllOptions_in )
00552 { recogniseAllOptions_ = recogniseAllOptions_in; }
00553 
00554 inline
00555 bool CommandLineProcessor::recogniseAllOptions() const
00556 { return recogniseAllOptions_; }
00557 
00558 inline
00559 void CommandLineProcessor::addOutputSetupOptions( const bool &addOutputSetupOptions_in )
00560 { addOutputSetupOptions_ = addOutputSetupOptions_in; }
00561 
00562 inline
00563 bool CommandLineProcessor::addOutputSetupOptions() const
00564 { return addOutputSetupOptions_; }
00565 
00566 template <class EType>
00567 inline
00568 void CommandLineProcessor::setOption(
00569   const char    enum_option_name[]
00570   ,EType       *enum_option_val
00571   ,const int    num_enum_opt_values
00572   ,const EType  enum_opt_values[]
00573   ,const char*  enum_opt_names[]
00574   ,const char   documentation[]
00575   ,const bool   required
00576   )
00577 {
00578   // RAB: 2004/05/25: Every C++ implementation that I know of just
00579   // represents enumerations as int's and therefore this will compile
00580   // just fine.  However, the ISO/ANSI C++ standard says that
00581   // compilers are allowed to use a smaller storage type for an enum
00582   // but must not require storage any larger than an 'int'.  If the
00583   // below compile-time assertion does not compile then we need to do
00584   // something different but it will be a lot of work!
00585   CompileTimeAssert<sizeof(int)-sizeof(EType)>();
00586   //CompileTimeAssert<sizeof(int)-sizeof(EType)-1>(); // Uncomment to see compilation error
00587   setEnumOption(
00588     enum_option_name
00589     ,reinterpret_cast<int*>(enum_option_val)
00590     ,num_enum_opt_values
00591     ,reinterpret_cast<const int*>(enum_opt_values)
00592     ,enum_opt_names
00593     ,documentation
00594     ,required
00595     );
00596 }
00597 
00598 inline
00599 std::string CommandLineProcessor::opt_type_str( EOptType opt_type ) const
00600 {
00601   std::string str;
00602   switch( opt_type ) {
00603     case OPT_BOOL_TRUE:
00604       str = "bool";
00605       break;
00606     case OPT_INT:
00607       str = "int";
00608       break;
00609     case OPT_DOUBLE:
00610       str = "double";
00611       break;
00612     case OPT_STRING:
00613       str = "string";
00614       break;
00615     case OPT_ENUM_INT:
00616       str = "enum";
00617       break;
00618     default:
00619       assert(0); // Local programming error only
00620   } 
00621   return str;
00622 }
00623 
00624 } // end namespace Teuchos
00625 
00626 #endif // TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines