Teuchos - Trilinos Tools Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
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 
00073 namespace Teuchos {
00074 
00075 class TEUCHOSCORE_LIB_DLL_EXPORT CommandLineProcessor {
00076 public:
00077 
00079 
00080 
00082   class ParseError : public std::logic_error
00083   {public: ParseError(const std::string& what_arg) : std::logic_error(what_arg) {}};
00084 
00086   class HelpPrinted : public ParseError
00087   {public: HelpPrinted(const std::string& what_arg) : ParseError(what_arg) {}};
00088 
00090   class UnrecognizedOption : public ParseError
00091   {public: UnrecognizedOption(const std::string& what_arg) : ParseError(what_arg) {}};
00092 
00097   enum EParseCommandLineReturn {
00098     PARSE_SUCCESSFUL              =  0 
00099     ,PARSE_HELP_PRINTED            =  1 
00100     ,PARSE_UNRECOGNIZED_OPTION     =  2 
00101     ,PARSE_ERROR                   =  3 
00102   };
00103 
00105 
00107 
00108 
00124   CommandLineProcessor(
00125     bool    throwExceptions       = true
00126     ,bool   recogniseAllOptions   = true
00127     ,bool   addOutputSetupOptions = false
00128     );
00129 
00132   ~CommandLineProcessor();
00133 
00135 
00137 
00138 
00140   void throwExceptions( const bool & throwExceptions );
00141 
00143   bool throwExceptions() const;
00144 
00146   void recogniseAllOptions( const bool & recogniseAllOptions );
00147 
00149   bool recogniseAllOptions() const;
00150 
00152   void addOutputSetupOptions( const bool &addOutputSetupOptions );
00153 
00155   bool addOutputSetupOptions() const;
00156 
00158 
00160 
00161 
00164   void setDocString( const char doc_string[] );
00165 
00178   void setOption(
00179     const char     option_true[]
00180     ,const char    option_false[]
00181     ,bool          *option_val
00182     ,const char    documentation[] = NULL
00183     );
00184 
00195   void setOption(
00196     const char     option_name[]
00197     ,int           *option_val
00198     ,const char    documentation[] = NULL
00199     ,const bool    required        = false
00200     );
00201 
00212   void setOption(
00213     const char     option_name[]
00214     ,long int      *option_val
00215     ,const char    documentation[] = NULL
00216     ,const bool    required        = false
00217     );
00218 
00229   void setOption(
00230     const char     option_name[]
00231     ,size_t        *option_val
00232     ,const char    documentation[] = NULL
00233     ,const bool    required        = false
00234     );
00235 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
00236 
00246   void setOption(
00247     const char     option_name[]
00248     ,long long int *option_val
00249     ,const char    documentation[] = NULL
00250     ,const bool    required        = false
00251     );
00252 #endif
00253 
00264   void setOption(
00265     const char     option_name[]
00266     ,double        *option_val
00267     ,const char    documentation[] = NULL
00268     ,const bool    required        = false
00269     );
00270 
00281   void setOption(
00282     const char     option_name[]
00283     ,std::string   *option_val
00284     ,const char    documentation[] = NULL
00285     ,const bool    required        = false
00286     );
00287 
00316   template <class EType>
00317   void setOption(
00318     const char    enum_option_name[]
00319     ,EType        *enum_option_val
00320     ,const int    num_enum_opt_values
00321     ,const EType  enum_opt_values[]
00322     ,const char*  enum_opt_names[]
00323     ,const char   documentation[] = NULL
00324     ,const bool   required        = false
00325     );
00326 
00328 
00330 
00331 
00391   EParseCommandLineReturn  parse(
00392     int             argc
00393     ,char*          argv[]
00394     ,std::ostream   *errout = &std::cerr
00395     ) const;
00396 
00398 
00400 
00401 
00410    void printHelpMessage( const char program_name[], std::ostream &out ) const;
00411 
00417   void printFinalTimerSummary(const Ptr<std::ostream> &out = null);
00418 
00420 
00421 public:
00422   //
00423   enum EOptType { OPT_NONE, OPT_BOOL_TRUE, OPT_BOOL_FALSE, OPT_INT, OPT_LONG_INT, OPT_SIZE_T,
00424 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
00425   OPT_LONG_LONG_INT,
00426 #endif
00427   OPT_DOUBLE, OPT_STRING, OPT_ENUM_INT };
00428 
00429   // RAB: 2003/10/10: Note: I had to move this out of the private section since
00430   // the sun compiler (version 7) complained (rightly it now appears after looking
00431   // up what the ISO/ANSI C++ standard says) about the declaration for opt_val_val_t
00432   // not being able to access a private member of CommandLineProcessor.
00433 
00434 private:
00435 
00436   // /////////////////////////////////
00437   // Private types
00438 
00439   // ToDo: RAB: 2004/05/25: Clean up these data structures and add
00440   // support for a templated enum type.  This will clean up usage
00441   // quite a bit.
00442 
00443   //
00444   struct opt_val_val_t {
00445     opt_val_val_t():
00446       opt_type(OPT_NONE),
00447       required(false),
00448       was_read(false)
00449       {}
00450     opt_val_val_t( EOptType opt_type_in, const any& opt_val_in, bool required_in )
00451       :opt_type(opt_type_in),opt_val(opt_val_in),required(required_in),was_read(false)
00452       {}
00453     EOptType     opt_type;
00454     any          opt_val; // Will be bool*, int*, double*, std::string* or a small int (for OPT_ENUM_INT)
00455     bool         required;
00456     bool         was_read;
00457   };
00458 
00459   //
00460   typedef Teuchos::map<std::string,opt_val_val_t>   options_list_t;
00461 
00462   //
00463   struct opt_doc_t {
00464     opt_doc_t()
00465       :opt_type(OPT_NONE)
00466       {}
00467     opt_doc_t(EOptType opt_type_in, const std::string& opt_name_in, const std::string& opt_name_false_in
00468             ,const std::string &documentation_in, const any &default_val_in )
00469       :opt_type(opt_type_in),opt_name(opt_name_in),opt_name_false(opt_name_false_in)
00470       ,documentation(documentation_in),default_val(default_val_in)
00471       {}
00472     EOptType     opt_type;
00473     std::string  opt_name;
00474     std::string  opt_name_false; // only for bool
00475     std::string  documentation;
00476     any          default_val;
00477   };
00478 
00479   //
00480   typedef std::vector<opt_doc_t>   options_documentation_list_t;
00481 
00482   //
00483   struct enum_opt_data_t {
00484     enum_opt_data_t()
00485       :enum_option_val(NULL), num_enum_opt_values(0)
00486       {}
00487     enum_opt_data_t(
00488       int          *_enum_option_val
00489       ,const int    _num_enum_opt_values
00490       ,const int    _enum_opt_values[]
00491       ,const char*  _enum_opt_names[]
00492       )
00493       :enum_option_val(_enum_option_val)
00494       ,num_enum_opt_values(_num_enum_opt_values)
00495       ,enum_opt_values(_enum_opt_values,_enum_opt_values+_num_enum_opt_values)
00496       {
00497         for( int k = 0; k < num_enum_opt_values; ++k )
00498           enum_opt_names.push_back(std::string(_enum_opt_names[k]));
00499       }
00500     int                  *enum_option_val;
00501     int                  num_enum_opt_values;
00502     std::vector<int>     enum_opt_values;
00503     std::vector<std::string>  enum_opt_names;
00504   };
00505 
00506   //
00507   typedef std::vector<enum_opt_data_t> enum_opt_data_list_t;
00508 
00509   // /////////////////////////////////
00510   // Private data members
00511 
00512   bool                             throwExceptions_;
00513   bool                             recogniseAllOptions_;
00514   bool                             addOutputSetupOptions_;
00515   std::string                      doc_string_;
00516 
00517   //use pragmas to disable some false positive warnings in windows sharedlib exports
00518 #ifdef _MSC_VER
00519 #pragma warning(push)
00520 #pragma warning(disable:4251)
00521 #endif
00522   mutable options_list_t           options_list_;
00523   options_documentation_list_t     options_documentation_list_;
00524   enum_opt_data_list_t             enum_opt_data_list_;
00525 #ifdef _MSC_VER
00526 #pragma warning(pop)
00527 #endif
00528 
00529   bool  output_all_front_matter_;
00530   bool  output_show_line_prefix_;
00531   bool  output_show_tab_count_;
00532   bool  output_show_proc_rank_;
00533   int   output_to_root_rank_only_;
00534   bool  print_rcpnode_statistics_on_exit_;
00535   bool  show_timer_summary_on_exit_;
00536 
00537   bool printed_timer_summary_;
00538 
00539   bool  added_extra_output_setup_options_;
00540   bool  in_add_extra_output_setup_options_;
00541 
00542   static const bool  output_all_front_matter_default_;
00543   static const bool  output_show_line_prefix_default_;
00544   static const bool  output_show_tab_count_default_;
00545   static const bool  output_show_proc_rank_default_;
00546   static const int   output_to_root_rank_only_default_;
00547   static const bool  print_rcpnode_statistics_on_exit_default_;
00548   static const bool  show_timer_summary_on_exit_default_;
00549 
00550   // /////////////////////////////////
00551   // Private member functions
00552 
00553   // Set the extra output setup options
00554   void add_extra_output_setup_options() const;
00555 
00556   // Set an integer enumeration option
00557   void setEnumOption(
00558     const char    enum_option_name[]
00559     ,int          *enum_option_val
00560     ,const int    num_enum_opt_values
00561     ,const int    enum_opt_values[]
00562     ,const char*  enum_opt_names[]
00563     ,const char   documentation[]
00564     ,const bool   required
00565     );
00566 
00567   // Set an enum int option
00568   bool set_enum_value(
00569     int                  argv_i
00570     ,char*               argv[]
00571     ,const std::string   &enum_opt_name
00572     ,const int           enum_id
00573     ,const std::string   &enum_str_val
00574     ,std::ostream        *errout
00575     ) const;
00576 
00577   // Print the valid enum values
00578   void print_enum_opt_names(
00579     const int            enum_id
00580     ,std::ostream        &out
00581     ) const;
00582 
00583   // Return the name of the default value for an enum
00584   std::string enum_opt_default_val_name(
00585     const std::string    &enum_name
00586     ,const int           enum_id
00587     ,std::ostream        *errout
00588     ) const;
00589 
00590   // Return the index given and option value
00591   int find_enum_opt_index(
00592     const std::string           &enum_opt_name
00593     ,const int                  opt_value
00594     ,const enum_opt_data_t      &enum_data
00595     ,std::ostream               *errout
00596     ) const;
00597 
00598   // Get the option and the value from an entry in argv[].
00599   // Will return false if entry is not formated properly.
00600   bool get_opt_val(
00601     const char     str[]
00602     ,std::string   *opt_name
00603     ,std::string   *opt_val_str // May be empty on return
00604     ) const;
00605 
00606   // String for option type
00607   std::string opt_type_str( EOptType ) const;
00608 
00609   // Print bad option
00610   void print_bad_opt(
00611     int             argv_i
00612     ,char*          argv[]
00613     ,std::ostream   *errout
00614     ) const;
00615 
00616 public: // Hidden implementation stuff that clients should never see
00617 
00652   class TimeMonitorSurrogate {
00653   public:
00655     virtual ~TimeMonitorSurrogate() {}
00657     virtual void summarize(std::ostream &out=std::cout) = 0;
00658   };
00659 
00660   static void setTimeMonitorSurrogate(const RCP<TimeMonitorSurrogate> &timeMonitorSurrogate);
00661 
00662   static RCP<TimeMonitorSurrogate> getTimeMonitorSurrogate();
00663 
00664 private:
00665 
00666   static RCP<TimeMonitorSurrogate>& getRawTimeMonitorSurrogate();
00667 
00668 }; // end class CommandLineProcessor
00669 
00670 
00671 // /////////////////////////
00672 // Inline members
00673 
00674 
00675 // Behavior modes
00676 
00677 
00678 inline
00679 void CommandLineProcessor::throwExceptions( const bool & throwExceptions_in )
00680 { throwExceptions_ = throwExceptions_in; }
00681 
00682 
00683 inline
00684 bool CommandLineProcessor::throwExceptions() const
00685 { return throwExceptions_; }
00686 
00687 
00688 inline
00689 void CommandLineProcessor::recogniseAllOptions( const bool & recogniseAllOptions_in )
00690 { recogniseAllOptions_ = recogniseAllOptions_in; }
00691 
00692 
00693 inline
00694 bool CommandLineProcessor::recogniseAllOptions() const
00695 { return recogniseAllOptions_; }
00696 
00697 
00698 inline
00699 void CommandLineProcessor::addOutputSetupOptions( const bool &addOutputSetupOptions_in )
00700 { addOutputSetupOptions_ = addOutputSetupOptions_in; }
00701 
00702 
00703 inline
00704 bool CommandLineProcessor::addOutputSetupOptions() const
00705 { return addOutputSetupOptions_; }
00706 
00707 
00708 template <class EType>
00709 inline
00710 void CommandLineProcessor::setOption(
00711   const char    enum_option_name[]
00712   ,EType       *enum_option_val
00713   ,const int    num_enum_opt_values
00714   ,const EType  enum_opt_values[]
00715   ,const char*  enum_opt_names[]
00716   ,const char   documentation[]
00717   ,const bool   required
00718   )
00719 {
00720   // RAB: 2004/05/25: Every C++ implementation that I know of just
00721   // represents enumerations as int's and therefore this will compile
00722   // just fine.  However, the ISO/ANSI C++ standard says that
00723   // compilers are allowed to use a smaller storage type for an enum
00724   // but must not require storage any larger than an 'int'.  If the
00725   // below compile-time assertion does not compile then we need to do
00726   // something different but it will be a lot of work!
00727   CompileTimeAssert<sizeof(int)-sizeof(EType)>();
00728   //CompileTimeAssert<sizeof(int)-sizeof(EType)-1>(); // Uncomment to see compilation error
00729   setEnumOption(
00730     enum_option_name
00731     ,reinterpret_cast<int*>(enum_option_val)
00732     ,num_enum_opt_values
00733     ,reinterpret_cast<const int*>(enum_opt_values)
00734     ,enum_opt_names
00735     ,documentation
00736     ,required
00737     );
00738 }
00739 
00740 
00741 inline
00742 std::string CommandLineProcessor::opt_type_str( EOptType opt_type ) const
00743 {
00744   std::string str;
00745   switch( opt_type ) {
00746     case OPT_BOOL_TRUE:
00747       str = "bool";
00748       break;
00749     case OPT_INT:
00750       str = "int";
00751       break;
00752     case OPT_LONG_INT:
00753       str = "long int";
00754       break;
00755     case OPT_SIZE_T:
00756       str = "size_t";
00757       break;
00758 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
00759     case OPT_LONG_LONG_INT:
00760       str = "long long int";
00761       break;
00762 #endif
00763     case OPT_DOUBLE:
00764       str = "double";
00765       break;
00766     case OPT_STRING:
00767       str = "string";
00768       break;
00769     case OPT_ENUM_INT:
00770       str = "enum";
00771       break;
00772     default:
00773       assert(0); // Local programming error only
00774   }
00775   return str;
00776 }
00777 
00778 
00779 } // end namespace Teuchos
00780 
00781 
00782 #endif // TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines