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 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
00030 #define TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
00031 
00040 #include "Teuchos_map.hpp"
00041 #include "Teuchos_any.hpp"
00042 #include "Teuchos_CompileTimeAssert.hpp"
00043 
00044 namespace Teuchos {
00045 
00046 /* ToDo: RAB: 2003/10/02: Add support for required options as per KRL's suggestion
00047  *
00048  * ToDo:  Finish documentation.
00049  */
00050 
00063 class TEUCHOS_LIB_DLL_EXPORT CommandLineProcessor {
00064 public:
00065 
00067 
00068 
00070   class ParseError : public std::logic_error
00071   {public: ParseError(const std::string& what_arg) : std::logic_error(what_arg) {}};
00072 
00074   class HelpPrinted : public ParseError
00075   {public: HelpPrinted(const std::string& what_arg) : ParseError(what_arg) {}};
00076 
00078   class UnrecognizedOption : public ParseError
00079   {public: UnrecognizedOption(const std::string& what_arg) : ParseError(what_arg) {}};
00080 
00085   enum EParseCommandLineReturn {
00086     PARSE_SUCCESSFUL              =  0 
00087     ,PARSE_HELP_PRINTED            =  1 
00088     ,PARSE_UNRECOGNIZED_OPTION     =  2 
00089   };
00090   
00092 
00094 
00095 
00108   CommandLineProcessor(
00109     bool    throwExceptions       = true
00110     ,bool   recogniseAllOptions   = true
00111     ,bool   addOutputSetupOptions = false
00112     );
00113 
00115 
00117 
00118 
00120   void throwExceptions( const bool & throwExceptions );
00121   
00123   bool throwExceptions() const;
00124 
00126   void recogniseAllOptions( const bool & recogniseAllOptions );
00127 
00129   bool recogniseAllOptions() const;
00130 
00132   void addOutputSetupOptions( const bool &addOutputSetupOptions );
00133 
00135   bool addOutputSetupOptions() const;
00136 
00138 
00140 
00141   
00144   void setDocString( const char doc_string[] );
00145 
00158   void setOption(
00159     const char     option_true[]
00160     ,const char    option_false[]
00161     ,bool          *option_val
00162     ,const char    documentation[] = NULL
00163     );
00164 
00175   void setOption(
00176     const char     option_name[]
00177     ,int           *option_val
00178     ,const char    documentation[] = NULL
00179     ,const bool    required        = false
00180     );
00181 
00192   void setOption(
00193     const char     option_name[]
00194     ,double        *option_val
00195     ,const char    documentation[] = NULL
00196     ,const bool    required        = false
00197     );
00198 
00209   void setOption(
00210     const char     option_name[]
00211     ,std::string   *option_val
00212     ,const char    documentation[] = NULL
00213     ,const bool    required        = false
00214     );
00215   
00244   template <class EType>
00245   void setOption(
00246     const char    enum_option_name[]
00247     ,EType        *enum_option_val
00248     ,const int    num_enum_opt_values
00249     ,const EType  enum_opt_values[]
00250     ,const char*  enum_opt_names[]
00251     ,const char   documentation[] = NULL
00252     ,const bool   required        = false
00253     );
00254   
00256 
00258 
00259 
00319   EParseCommandLineReturn  parse(
00320     int             argc
00321     ,char*          argv[]
00322     ,std::ostream   *errout = &std::cerr
00323     ) const;
00324 
00326 
00328 
00329 
00338    void printHelpMessage( const char program_name[], std::ostream &out ) const;
00339 
00341 
00342 public:
00343   //
00344   enum EOptType { OPT_NONE, OPT_BOOL_TRUE, OPT_BOOL_FALSE, OPT_INT, OPT_DOUBLE, OPT_STRING, OPT_ENUM_INT };
00345   // RAB: 2003/10/10: Note: I had to move this out of the private section since
00346   // the sun compiler (version 7) complained (rightly it now appears after looking
00347   // up what the ISO/ANSI C++ standard says) about the declaration for opt_val_val_t
00348   // not being able to access a private member of CommandLineProcessor.
00349 
00350 private:
00351 
00352   // /////////////////////////////////
00353   // Private types
00354 
00355   // ToDo: RAB: 2004/05/25: Clean up these data structures and add
00356   // support for a templated enum type.  This will clean up usage
00357   // quite a bit.
00358 
00359   //
00360   struct opt_val_val_t {
00361     opt_val_val_t()
00362       :opt_type(OPT_NONE)
00363       {}
00364     opt_val_val_t( EOptType opt_type_in, const any& opt_val_in, bool required_in )
00365       :opt_type(opt_type_in),opt_val(opt_val_in),required(required_in),was_read(false)
00366       {}
00367     EOptType     opt_type;
00368     any          opt_val; // Will be bool*, int*, double*, std::string* or a small int (for OPT_ENUM_INT)
00369     bool         required;
00370     bool         was_read;
00371   };
00372 
00373   //
00374   typedef Teuchos::map<std::string,opt_val_val_t>   options_list_t;
00375 
00376   //
00377   struct opt_doc_t {
00378     opt_doc_t()
00379       :opt_type(OPT_NONE)
00380       {}
00381     opt_doc_t(EOptType opt_type_in, const std::string& opt_name_in, const std::string& opt_name_false_in
00382             ,const std::string &documentation_in, const any &default_val_in )
00383       :opt_type(opt_type_in),opt_name(opt_name_in),opt_name_false(opt_name_false_in)
00384       ,documentation(documentation_in),default_val(default_val_in)
00385       {}
00386     EOptType     opt_type;
00387     std::string  opt_name;
00388     std::string  opt_name_false; // only for bool
00389     std::string  documentation;
00390     any          default_val;
00391   };
00392   
00393   //
00394   typedef std::vector<opt_doc_t>   options_documentation_list_t;
00395 
00396   //
00397   struct enum_opt_data_t {
00398     enum_opt_data_t()
00399       :enum_option_val(NULL), num_enum_opt_values(0)
00400       {}
00401     enum_opt_data_t(
00402       int          *_enum_option_val
00403       ,const int    _num_enum_opt_values
00404       ,const int    _enum_opt_values[]
00405       ,const char*  _enum_opt_names[]
00406       )
00407       :enum_option_val(_enum_option_val)
00408       ,num_enum_opt_values(_num_enum_opt_values)
00409       ,enum_opt_values(_enum_opt_values,_enum_opt_values+_num_enum_opt_values)
00410       {
00411         for( int k = 0; k < num_enum_opt_values; ++k )
00412           enum_opt_names.push_back(std::string(_enum_opt_names[k]));
00413       }
00414     int                  *enum_option_val;
00415     int                  num_enum_opt_values;
00416     std::vector<int>     enum_opt_values;
00417     std::vector<std::string>  enum_opt_names;
00418   };
00419 
00420   //
00421   typedef std::vector<enum_opt_data_t> enum_opt_data_list_t;
00422 
00423   // /////////////////////////////////
00424   // Private data members
00425 
00426   bool                             throwExceptions_;
00427   bool                             recogniseAllOptions_;
00428   bool                             addOutputSetupOptions_;
00429   std::string                      doc_string_;
00430 
00431   //use pragmas to disable some false positive warnings in windows sharedlib exports
00432 #ifdef _MSC_VER
00433 #pragma warning(push)
00434 #pragma warning(disable:4251)
00435 #endif
00436   mutable options_list_t           options_list_;
00437   options_documentation_list_t     options_documentation_list_;
00438   enum_opt_data_list_t             enum_opt_data_list_;
00439 #ifdef _MSC_VER
00440 #pragma warning(pop)
00441 #endif
00442 
00443   bool  output_all_front_matter_;
00444   bool  output_show_line_prefix_;
00445   bool  output_show_tab_count_;
00446   bool  output_show_proc_rank_;
00447   int   output_to_root_rank_only_;
00448   bool  print_rcpnode_statistics_on_exit_;
00449 
00450   bool  added_extra_output_setup_options_;
00451   bool  in_add_extra_output_setup_options_;
00452 
00453   static const bool  output_all_front_matter_default_;
00454   static const bool  output_show_line_prefix_default_;
00455   static const bool  output_show_tab_count_default_;
00456   static const bool  output_show_proc_rank_default_;
00457   static const int   output_to_root_rank_only_default_;
00458   static const bool  print_rcpnode_statistics_on_exit_default_;
00459 
00460   // /////////////////////////////////
00461   // Private member functions
00462 
00463   // Set the extra output setup options
00464   void add_extra_output_setup_options() const;
00465 
00466   // Set an integer enumeration option
00467   void setEnumOption(
00468     const char    enum_option_name[]
00469     ,int          *enum_option_val
00470     ,const int    num_enum_opt_values
00471     ,const int    enum_opt_values[]
00472     ,const char*  enum_opt_names[]
00473     ,const char   documentation[]
00474     ,const bool   required
00475     );
00476 
00477   // Set an enum int option
00478   bool set_enum_value(
00479     int                  argv_i
00480     ,char*               argv[]
00481     ,const std::string   &enum_opt_name
00482     ,const int           enum_id
00483     ,const std::string   &enum_str_val
00484     ,std::ostream        *errout
00485     ) const;
00486 
00487   // Print the valid enum values
00488   void print_enum_opt_names(
00489     const int            enum_id
00490     ,std::ostream        &out
00491     ) const;
00492 
00493   // Return the name of the default value for an enum
00494   std::string enum_opt_default_val_name(
00495     const std::string    &enum_name
00496     ,const int           enum_id
00497     ,std::ostream        *errout
00498     ) const;
00499   
00500   // Return the index given and option value
00501   int find_enum_opt_index(
00502     const std::string           &enum_opt_name
00503     ,const int                  opt_value
00504     ,const enum_opt_data_t      &enum_data
00505     ,std::ostream               *errout
00506     ) const; 
00507 
00508   // Get the option and the value from an entry in argv[].
00509   // Will return false if entry is not formated properly.
00510   bool get_opt_val(
00511     const char     str[]
00512     ,std::string   *opt_name
00513     ,std::string   *opt_val_str // May be empty on return
00514     ) const;
00515 
00516   // String for option type
00517   std::string opt_type_str( EOptType ) const;
00518 
00519   // Print bad option
00520   void print_bad_opt(
00521     int             argv_i
00522     ,char*          argv[]
00523     ,std::ostream   *errout
00524     ) const;
00525 
00526 }; // end class CommandLineProcessor
00527 
00528 // /////////////////////////
00529 // Inline members
00530 
00531 // Behavior modes
00532 
00533 inline
00534 void CommandLineProcessor::throwExceptions( const bool & throwExceptions_in )
00535 { throwExceptions_ = throwExceptions_in; }
00536 
00537 inline
00538 bool CommandLineProcessor::throwExceptions() const
00539 { return throwExceptions_; }
00540 
00541 inline
00542 void CommandLineProcessor::recogniseAllOptions( const bool & recogniseAllOptions_in )
00543 { recogniseAllOptions_ = recogniseAllOptions_in; }
00544 
00545 inline
00546 bool CommandLineProcessor::recogniseAllOptions() const
00547 { return recogniseAllOptions_; }
00548 
00549 inline
00550 void CommandLineProcessor::addOutputSetupOptions( const bool &addOutputSetupOptions_in )
00551 { addOutputSetupOptions_ = addOutputSetupOptions_in; }
00552 
00553 inline
00554 bool CommandLineProcessor::addOutputSetupOptions() const
00555 { return addOutputSetupOptions_; }
00556 
00557 template <class EType>
00558 inline
00559 void CommandLineProcessor::setOption(
00560   const char    enum_option_name[]
00561   ,EType       *enum_option_val
00562   ,const int    num_enum_opt_values
00563   ,const EType  enum_opt_values[]
00564   ,const char*  enum_opt_names[]
00565   ,const char   documentation[]
00566   ,const bool   required
00567   )
00568 {
00569   // RAB: 2004/05/25: Every C++ implementation that I know of just
00570   // represents enumerations as int's and therefore this will compile
00571   // just fine.  However, the ISO/ANSI C++ standard says that
00572   // compilers are allowed to use a smaller storage type for an enum
00573   // but must not require storage any larger than an 'int'.  If the
00574   // below compile-time assertion does not compile then we need to do
00575   // something different but it will be a lot of work!
00576   CompileTimeAssert<sizeof(int)-sizeof(EType)>();
00577   //CompileTimeAssert<sizeof(int)-sizeof(EType)-1>(); // Uncomment to see compilation error
00578   setEnumOption(
00579     enum_option_name
00580     ,reinterpret_cast<int*>(enum_option_val)
00581     ,num_enum_opt_values
00582     ,reinterpret_cast<const int*>(enum_opt_values)
00583     ,enum_opt_names
00584     ,documentation
00585     ,required
00586     );
00587 }
00588 
00589 inline
00590 std::string CommandLineProcessor::opt_type_str( EOptType opt_type ) const
00591 {
00592   std::string str;
00593   switch( opt_type ) {
00594     case OPT_BOOL_TRUE:
00595       str = "bool";
00596       break;
00597     case OPT_INT:
00598       str = "int";
00599       break;
00600     case OPT_DOUBLE:
00601       str = "double";
00602       break;
00603     case OPT_STRING:
00604       str = "string";
00605       break;
00606     case OPT_ENUM_INT:
00607       str = "enum";
00608       break;
00609     default:
00610       assert(0); // Local programming error only
00611   } 
00612   return str;
00613 }
00614 
00615 } // end namespace Teuchos
00616 
00617 #endif // TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Wed Apr 13 09:57:29 2011 for Teuchos Package Browser (Single Doxygen Collection) by  doxygen 1.6.3