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 #include "Teuchos_Ptr.hpp"
00057 
00071 namespace Teuchos {
00072 
00073 class TEUCHOS_LIB_DLL_EXPORT CommandLineProcessor {
00074 public:
00075 
00077 
00078 
00080   class ParseError : public std::logic_error
00081   {public: ParseError(const std::string& what_arg) : std::logic_error(what_arg) {}};
00082 
00084   class HelpPrinted : public ParseError
00085   {public: HelpPrinted(const std::string& what_arg) : ParseError(what_arg) {}};
00086 
00088   class UnrecognizedOption : public ParseError
00089   {public: UnrecognizedOption(const std::string& what_arg) : ParseError(what_arg) {}};
00090 
00095   enum EParseCommandLineReturn {
00096     PARSE_SUCCESSFUL              =  0 
00097     ,PARSE_HELP_PRINTED            =  1 
00098     ,PARSE_UNRECOGNIZED_OPTION     =  2 
00099     ,PARSE_ERROR                   =  3 
00100   };
00101   
00103 
00105 
00106 
00122   CommandLineProcessor(
00123     bool    throwExceptions       = true
00124     ,bool   recogniseAllOptions   = true
00125     ,bool   addOutputSetupOptions = false
00126     );
00127 
00130   ~CommandLineProcessor();
00131 
00133 
00135 
00136 
00138   void throwExceptions( const bool & throwExceptions );
00139   
00141   bool throwExceptions() const;
00142 
00144   void recogniseAllOptions( const bool & recogniseAllOptions );
00145 
00147   bool recogniseAllOptions() const;
00148 
00150   void addOutputSetupOptions( const bool &addOutputSetupOptions );
00151 
00153   bool addOutputSetupOptions() const;
00154 
00156 
00158 
00159   
00162   void setDocString( const char doc_string[] );
00163 
00176   void setOption(
00177     const char     option_true[]
00178     ,const char    option_false[]
00179     ,bool          *option_val
00180     ,const char    documentation[] = NULL
00181     );
00182 
00193   void setOption(
00194     const char     option_name[]
00195     ,int           *option_val
00196     ,const char    documentation[] = NULL
00197     ,const bool    required        = false
00198     );
00199 
00210   void setOption(
00211     const char     option_name[]
00212     ,double        *option_val
00213     ,const char    documentation[] = NULL
00214     ,const bool    required        = false
00215     );
00216 
00227   void setOption(
00228     const char     option_name[]
00229     ,std::string   *option_val
00230     ,const char    documentation[] = NULL
00231     ,const bool    required        = false
00232     );
00233   
00262   template <class EType>
00263   void setOption(
00264     const char    enum_option_name[]
00265     ,EType        *enum_option_val
00266     ,const int    num_enum_opt_values
00267     ,const EType  enum_opt_values[]
00268     ,const char*  enum_opt_names[]
00269     ,const char   documentation[] = NULL
00270     ,const bool   required        = false
00271     );
00272   
00274 
00276 
00277 
00337   EParseCommandLineReturn  parse(
00338     int             argc
00339     ,char*          argv[]
00340     ,std::ostream   *errout = &std::cerr
00341     ) const;
00342 
00344 
00346 
00347 
00356    void printHelpMessage( const char program_name[], std::ostream &out ) const;
00357 
00363   void printFinalTimerSummary(const Ptr<std::ostream> &out = null);
00364 
00366 
00367 public:
00368   //
00369   enum EOptType { OPT_NONE, OPT_BOOL_TRUE, OPT_BOOL_FALSE, OPT_INT, OPT_DOUBLE, OPT_STRING, OPT_ENUM_INT };
00370   // RAB: 2003/10/10: Note: I had to move this out of the private section since
00371   // the sun compiler (version 7) complained (rightly it now appears after looking
00372   // up what the ISO/ANSI C++ standard says) about the declaration for opt_val_val_t
00373   // not being able to access a private member of CommandLineProcessor.
00374 
00375 private:
00376 
00377   // /////////////////////////////////
00378   // Private types
00379 
00380   // ToDo: RAB: 2004/05/25: Clean up these data structures and add
00381   // support for a templated enum type.  This will clean up usage
00382   // quite a bit.
00383 
00384   //
00385   struct opt_val_val_t {
00386     opt_val_val_t()
00387       :opt_type(OPT_NONE)
00388       {}
00389     opt_val_val_t( EOptType opt_type_in, const any& opt_val_in, bool required_in )
00390       :opt_type(opt_type_in),opt_val(opt_val_in),required(required_in),was_read(false)
00391       {}
00392     EOptType     opt_type;
00393     any          opt_val; // Will be bool*, int*, double*, std::string* or a small int (for OPT_ENUM_INT)
00394     bool         required;
00395     bool         was_read;
00396   };
00397 
00398   //
00399   typedef Teuchos::map<std::string,opt_val_val_t>   options_list_t;
00400 
00401   //
00402   struct opt_doc_t {
00403     opt_doc_t()
00404       :opt_type(OPT_NONE)
00405       {}
00406     opt_doc_t(EOptType opt_type_in, const std::string& opt_name_in, const std::string& opt_name_false_in
00407             ,const std::string &documentation_in, const any &default_val_in )
00408       :opt_type(opt_type_in),opt_name(opt_name_in),opt_name_false(opt_name_false_in)
00409       ,documentation(documentation_in),default_val(default_val_in)
00410       {}
00411     EOptType     opt_type;
00412     std::string  opt_name;
00413     std::string  opt_name_false; // only for bool
00414     std::string  documentation;
00415     any          default_val;
00416   };
00417   
00418   //
00419   typedef std::vector<opt_doc_t>   options_documentation_list_t;
00420 
00421   //
00422   struct enum_opt_data_t {
00423     enum_opt_data_t()
00424       :enum_option_val(NULL), num_enum_opt_values(0)
00425       {}
00426     enum_opt_data_t(
00427       int          *_enum_option_val
00428       ,const int    _num_enum_opt_values
00429       ,const int    _enum_opt_values[]
00430       ,const char*  _enum_opt_names[]
00431       )
00432       :enum_option_val(_enum_option_val)
00433       ,num_enum_opt_values(_num_enum_opt_values)
00434       ,enum_opt_values(_enum_opt_values,_enum_opt_values+_num_enum_opt_values)
00435       {
00436         for( int k = 0; k < num_enum_opt_values; ++k )
00437           enum_opt_names.push_back(std::string(_enum_opt_names[k]));
00438       }
00439     int                  *enum_option_val;
00440     int                  num_enum_opt_values;
00441     std::vector<int>     enum_opt_values;
00442     std::vector<std::string>  enum_opt_names;
00443   };
00444 
00445   //
00446   typedef std::vector<enum_opt_data_t> enum_opt_data_list_t;
00447 
00448   // /////////////////////////////////
00449   // Private data members
00450 
00451   bool                             throwExceptions_;
00452   bool                             recogniseAllOptions_;
00453   bool                             addOutputSetupOptions_;
00454   std::string                      doc_string_;
00455 
00456   //use pragmas to disable some false positive warnings in windows sharedlib exports
00457 #ifdef _MSC_VER
00458 #pragma warning(push)
00459 #pragma warning(disable:4251)
00460 #endif
00461   mutable options_list_t           options_list_;
00462   options_documentation_list_t     options_documentation_list_;
00463   enum_opt_data_list_t             enum_opt_data_list_;
00464 #ifdef _MSC_VER
00465 #pragma warning(pop)
00466 #endif
00467 
00468   bool  output_all_front_matter_;
00469   bool  output_show_line_prefix_;
00470   bool  output_show_tab_count_;
00471   bool  output_show_proc_rank_;
00472   int   output_to_root_rank_only_;
00473   bool  print_rcpnode_statistics_on_exit_;
00474   bool  show_timer_summary_on_exit_;
00475 
00476   bool printed_timer_summary_;
00477 
00478   bool  added_extra_output_setup_options_;
00479   bool  in_add_extra_output_setup_options_;
00480 
00481   static const bool  output_all_front_matter_default_;
00482   static const bool  output_show_line_prefix_default_;
00483   static const bool  output_show_tab_count_default_;
00484   static const bool  output_show_proc_rank_default_;
00485   static const int   output_to_root_rank_only_default_;
00486   static const bool  print_rcpnode_statistics_on_exit_default_;
00487   static const bool  show_timer_summary_on_exit_default_;
00488 
00489   // /////////////////////////////////
00490   // Private member functions
00491 
00492   // Set the extra output setup options
00493   void add_extra_output_setup_options() const;
00494 
00495   // Set an integer enumeration option
00496   void setEnumOption(
00497     const char    enum_option_name[]
00498     ,int          *enum_option_val
00499     ,const int    num_enum_opt_values
00500     ,const int    enum_opt_values[]
00501     ,const char*  enum_opt_names[]
00502     ,const char   documentation[]
00503     ,const bool   required
00504     );
00505 
00506   // Set an enum int option
00507   bool set_enum_value(
00508     int                  argv_i
00509     ,char*               argv[]
00510     ,const std::string   &enum_opt_name
00511     ,const int           enum_id
00512     ,const std::string   &enum_str_val
00513     ,std::ostream        *errout
00514     ) const;
00515 
00516   // Print the valid enum values
00517   void print_enum_opt_names(
00518     const int            enum_id
00519     ,std::ostream        &out
00520     ) const;
00521 
00522   // Return the name of the default value for an enum
00523   std::string enum_opt_default_val_name(
00524     const std::string    &enum_name
00525     ,const int           enum_id
00526     ,std::ostream        *errout
00527     ) const;
00528   
00529   // Return the index given and option value
00530   int find_enum_opt_index(
00531     const std::string           &enum_opt_name
00532     ,const int                  opt_value
00533     ,const enum_opt_data_t      &enum_data
00534     ,std::ostream               *errout
00535     ) const; 
00536 
00537   // Get the option and the value from an entry in argv[].
00538   // Will return false if entry is not formated properly.
00539   bool get_opt_val(
00540     const char     str[]
00541     ,std::string   *opt_name
00542     ,std::string   *opt_val_str // May be empty on return
00543     ) const;
00544 
00545   // String for option type
00546   std::string opt_type_str( EOptType ) const;
00547 
00548   // Print bad option
00549   void print_bad_opt(
00550     int             argv_i
00551     ,char*          argv[]
00552     ,std::ostream   *errout
00553     ) const;
00554 
00555 }; // end class CommandLineProcessor
00556 
00557 // /////////////////////////
00558 // Inline members
00559 
00560 // Behavior modes
00561 
00562 inline
00563 void CommandLineProcessor::throwExceptions( const bool & throwExceptions_in )
00564 { throwExceptions_ = throwExceptions_in; }
00565 
00566 inline
00567 bool CommandLineProcessor::throwExceptions() const
00568 { return throwExceptions_; }
00569 
00570 inline
00571 void CommandLineProcessor::recogniseAllOptions( const bool & recogniseAllOptions_in )
00572 { recogniseAllOptions_ = recogniseAllOptions_in; }
00573 
00574 inline
00575 bool CommandLineProcessor::recogniseAllOptions() const
00576 { return recogniseAllOptions_; }
00577 
00578 inline
00579 void CommandLineProcessor::addOutputSetupOptions( const bool &addOutputSetupOptions_in )
00580 { addOutputSetupOptions_ = addOutputSetupOptions_in; }
00581 
00582 inline
00583 bool CommandLineProcessor::addOutputSetupOptions() const
00584 { return addOutputSetupOptions_; }
00585 
00586 template <class EType>
00587 inline
00588 void CommandLineProcessor::setOption(
00589   const char    enum_option_name[]
00590   ,EType       *enum_option_val
00591   ,const int    num_enum_opt_values
00592   ,const EType  enum_opt_values[]
00593   ,const char*  enum_opt_names[]
00594   ,const char   documentation[]
00595   ,const bool   required
00596   )
00597 {
00598   // RAB: 2004/05/25: Every C++ implementation that I know of just
00599   // represents enumerations as int's and therefore this will compile
00600   // just fine.  However, the ISO/ANSI C++ standard says that
00601   // compilers are allowed to use a smaller storage type for an enum
00602   // but must not require storage any larger than an 'int'.  If the
00603   // below compile-time assertion does not compile then we need to do
00604   // something different but it will be a lot of work!
00605   CompileTimeAssert<sizeof(int)-sizeof(EType)>();
00606   //CompileTimeAssert<sizeof(int)-sizeof(EType)-1>(); // Uncomment to see compilation error
00607   setEnumOption(
00608     enum_option_name
00609     ,reinterpret_cast<int*>(enum_option_val)
00610     ,num_enum_opt_values
00611     ,reinterpret_cast<const int*>(enum_opt_values)
00612     ,enum_opt_names
00613     ,documentation
00614     ,required
00615     );
00616 }
00617 
00618 inline
00619 std::string CommandLineProcessor::opt_type_str( EOptType opt_type ) const
00620 {
00621   std::string str;
00622   switch( opt_type ) {
00623     case OPT_BOOL_TRUE:
00624       str = "bool";
00625       break;
00626     case OPT_INT:
00627       str = "int";
00628       break;
00629     case OPT_DOUBLE:
00630       str = "double";
00631       break;
00632     case OPT_STRING:
00633       str = "string";
00634       break;
00635     case OPT_ENUM_INT:
00636       str = "enum";
00637       break;
00638     default:
00639       assert(0); // Local programming error only
00640   } 
00641   return str;
00642 }
00643 
00644 } // end namespace Teuchos
00645 
00646 #endif // TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines