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 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 
00084   enum EParseCommandLineReturn {
00085     PARSE_SUCCESSFUL              =  0 
00086     ,PARSE_HELP_PRINTED            =  1 
00087     ,PARSE_UNRECOGNIZED_OPTION     = -1 
00088   };
00089   
00091 
00093 
00094 
00107   CommandLineProcessor(
00108     bool    throwExceptions       = true
00109     ,bool   recogniseAllOptions   = true
00110     ,bool   addOutputSetupOptions = false
00111     );
00112 
00114 
00116 
00117 
00119   void throwExceptions( const bool & throwExceptions );
00120   
00122   bool throwExceptions() const;
00123 
00125   void recogniseAllOptions( const bool & recogniseAllOptions );
00126 
00128   bool recogniseAllOptions() const;
00129 
00131   void addOutputSetupOptions( const bool &addOutputSetupOptions );
00132 
00134   bool addOutputSetupOptions() const;
00135 
00137 
00139 
00140   
00143   void setDocString( const char doc_string[] );
00144 
00157   void setOption(
00158     const char     option_true[]
00159     ,const char    option_false[]
00160     ,bool          *option_val
00161     ,const char    documentation[] = NULL
00162     );
00163 
00174   void setOption(
00175     const char     option_name[]
00176     ,int           *option_val
00177     ,const char    documentation[] = NULL
00178     ,const bool    required        = false
00179     );
00180 
00191   void setOption(
00192     const char     option_name[]
00193     ,double        *option_val
00194     ,const char    documentation[] = NULL
00195     ,const bool    required        = false
00196     );
00197 
00208   void setOption(
00209     const char     option_name[]
00210     ,std::string   *option_val
00211     ,const char    documentation[] = NULL
00212     ,const bool    required        = false
00213     );
00214   
00243   template <class EType>
00244   void setOption(
00245     const char    enum_option_name[]
00246     ,EType        *enum_option_val
00247     ,const int    num_enum_opt_values
00248     ,const EType  enum_opt_values[]
00249     ,const char*  enum_opt_names[]
00250     ,const char   documentation[] = NULL
00251     ,const bool   required        = false
00252     );
00253   
00255 
00257 
00258 
00318   EParseCommandLineReturn  parse(
00319     int             argc
00320     ,char*          argv[]
00321     ,std::ostream   *errout = &std::cerr
00322     ) const;
00323 
00325 
00327 
00328 
00337    void printHelpMessage( const char program_name[], std::ostream &out ) const;
00338 
00340 
00341 public:
00342   //
00343   enum EOptType { OPT_NONE, OPT_BOOL_TRUE, OPT_BOOL_FALSE, OPT_INT, OPT_DOUBLE, OPT_STRING, OPT_ENUM_INT };
00344   // RAB: 2003/10/10: Note: I had to move this out of the private section since
00345   // the sun compiler (version 7) complained (rightly it now appears after looking
00346   // up what the ISO/ANSI C++ standard says) about the declaration for opt_val_val_t
00347   // not being able to access a private member of CommandLineProcessor.
00348 
00349 private:
00350 
00351   // /////////////////////////////////
00352   // Private types
00353 
00354   // ToDo: RAB: 2004/05/25: Clean up these data structures and add
00355   // support for a templated enum type.  This will clean up usage
00356   // quite a bit.
00357 
00358   //
00359   struct opt_val_val_t {
00360     opt_val_val_t()
00361       :opt_type(OPT_NONE)
00362       {}
00363     opt_val_val_t( EOptType opt_type_in, const any& opt_val_in, bool required_in )
00364       :opt_type(opt_type_in),opt_val(opt_val_in),required(required_in),was_read(false)
00365       {}
00366     EOptType     opt_type;
00367     any          opt_val; // Will be bool*, int*, double*, string* or a small int (for OPT_ENUM_INT)
00368     bool         required;
00369     bool         was_read;
00370   };
00371 
00372   //
00373   typedef Teuchos::map<std::string,opt_val_val_t>   options_list_t;
00374 
00375   //
00376   struct opt_doc_t {
00377     opt_doc_t()
00378       :opt_type(OPT_NONE)
00379       {}
00380     opt_doc_t(EOptType opt_type_in, const std::string& opt_name_in, const std::string& opt_name_false_in
00381             ,const std::string &documentation_in, const any &default_val_in )
00382       :opt_type(opt_type_in),opt_name(opt_name_in),opt_name_false(opt_name_false_in)
00383       ,documentation(documentation_in),default_val(default_val_in)
00384       {}
00385     EOptType     opt_type;
00386     std::string  opt_name;
00387     std::string  opt_name_false; // only for bool
00388     std::string  documentation;
00389     any          default_val;
00390   };
00391   
00392   //
00393   typedef std::vector<opt_doc_t>   options_documentation_list_t;
00394 
00395   //
00396   struct enum_opt_data_t {
00397     enum_opt_data_t()
00398       :enum_option_val(NULL), num_enum_opt_values(0)
00399       {}
00400     enum_opt_data_t(
00401       int          *_enum_option_val
00402       ,const int    _num_enum_opt_values
00403       ,const int    _enum_opt_values[]
00404       ,const char*  _enum_opt_names[]
00405       )
00406       :enum_option_val(_enum_option_val)
00407       ,num_enum_opt_values(_num_enum_opt_values)
00408       ,enum_opt_values(_enum_opt_values,_enum_opt_values+_num_enum_opt_values)
00409       {
00410         for( int k = 0; k < num_enum_opt_values; ++k )
00411           enum_opt_names.push_back(std::string(_enum_opt_names[k]));
00412       }
00413     int                  *enum_option_val;
00414     int                  num_enum_opt_values;
00415     std::vector<int>     enum_opt_values;
00416     std::vector<string>  enum_opt_names;
00417   };
00418 
00419   //
00420   typedef std::vector<enum_opt_data_t> enum_opt_data_list_t;
00421 
00422   // /////////////////////////////////
00423   // Private data members
00424 
00425   bool                              throwExceptions_;
00426   bool                             recogniseAllOptions_;
00427   bool                             addOutputSetupOptions_;
00428   std::string                      doc_string_;
00429   mutable options_list_t           options_list_;
00430   options_documentation_list_t     options_documentation_list_;
00431   enum_opt_data_list_t             enum_opt_data_list_;
00432 
00433   bool  output_all_front_matter_;
00434   bool  output_show_line_prefix_;
00435   bool  output_show_tab_count_;
00436   bool  output_show_proc_rank_;
00437   int   output_to_root_rank_only_;
00438 
00439   bool  added_extra_output_setup_options_;
00440   bool  in_add_extra_output_setup_options_;
00441 
00442   static const bool  output_all_front_matter_default_;
00443   static const bool  output_show_line_prefix_default_;
00444   static const bool  output_show_tab_count_default_;
00445   static const bool  output_show_proc_rank_default_;
00446   static const int   output_to_root_rank_only_default_;
00447 
00448   // /////////////////////////////////
00449   // Private member functions
00450 
00451   // Set the extra output setup options
00452   void add_extra_output_setup_options() const;
00453 
00454   // Set an integer enumeration option
00455   void setEnumOption(
00456     const char    enum_option_name[]
00457     ,int          *enum_option_val
00458     ,const int    num_enum_opt_values
00459     ,const int    enum_opt_values[]
00460     ,const char*  enum_opt_names[]
00461     ,const char   documentation[]
00462     ,const bool   required
00463     );
00464 
00465   // Set an enum int option
00466   bool set_enum_value(
00467     int                  argv_i
00468     ,char*               argv[]
00469     ,const std::string   &enum_opt_name
00470     ,const int           enum_id
00471     ,const std::string   &enum_str_val
00472     ,std::ostream        *errout
00473     ) const;
00474 
00475   // Print the valid enum values
00476   void print_enum_opt_names(
00477     const int            enum_id
00478     ,std::ostream        &out
00479     ) const;
00480 
00481   // Return the name of the default value for an enum
00482   std::string enum_opt_default_val_name(
00483     const std::string    &enum_name
00484     ,const int           enum_id
00485     ,std::ostream        *errout
00486     ) const;
00487   
00488   // Return the index given and option value
00489   int find_enum_opt_index(
00490     const std::string           &enum_opt_name
00491     ,const int                  opt_value
00492     ,const enum_opt_data_t      &enum_data
00493     ,std::ostream               *errout
00494     ) const; 
00495 
00496   // Get the option and the value from an entry in argv[].
00497   // Will return false if entry is not formated properly.
00498   bool get_opt_val(
00499     const char     str[]
00500     ,std::string   *opt_name
00501     ,std::string   *opt_val_str // May be empty on return
00502     ) const;
00503 
00504   // String for option type
00505   std::string opt_type_str( EOptType ) const;
00506 
00507   // Print bad option
00508   void print_bad_opt(
00509     int             argv_i
00510     ,char*          argv[]
00511     ,std::ostream   *errout
00512     ) const;
00513 
00514 }; // end class CommandLineProcessor
00515 
00516 // /////////////////////////
00517 // Inline members
00518 
00519 // Behavior modes
00520 
00521 inline
00522 void CommandLineProcessor::throwExceptions( const bool & throwExceptions )
00523 { throwExceptions_ = throwExceptions; }
00524 
00525 inline
00526 bool CommandLineProcessor::throwExceptions() const
00527 { return throwExceptions_; }
00528 
00529 inline
00530 void CommandLineProcessor::recogniseAllOptions( const bool & recogniseAllOptions )
00531 { recogniseAllOptions_ = recogniseAllOptions; }
00532 
00533 inline
00534 bool CommandLineProcessor::recogniseAllOptions() const
00535 { return recogniseAllOptions_; }
00536 
00537 inline
00538 void CommandLineProcessor::addOutputSetupOptions( const bool &addOutputSetupOptions )
00539 { addOutputSetupOptions_ = addOutputSetupOptions; }
00540 
00541 inline
00542 bool CommandLineProcessor::addOutputSetupOptions() const
00543 { return addOutputSetupOptions_; }
00544 
00545 template <class EType>
00546 inline
00547 void CommandLineProcessor::setOption(
00548   const char    enum_option_name[]
00549   ,EType       *enum_option_val
00550   ,const int    num_enum_opt_values
00551   ,const EType  enum_opt_values[]
00552   ,const char*  enum_opt_names[]
00553   ,const char   documentation[]
00554   ,const bool   required
00555   )
00556 {
00557   // RAB: 2004/05/25: Every C++ implementation that I know of just
00558   // represents enumerations as int's and therefore this will compile
00559   // just fine.  However, the ISO/ANSI C++ standard says that
00560   // compilers are allowed to use a smaller storage type for an enum
00561   // but must not require storage any larger than an 'int'.  If the
00562   // below compile-time assertion does not compile then we need to do
00563   // something different but it will be a lot of work!
00564   CompileTimeAssert<sizeof(int)-sizeof(EType)>();
00565   //CompileTimeAssert<sizeof(int)-sizeof(EType)-1>(); // Uncomment to see compilation error
00566   setEnumOption(
00567     enum_option_name
00568     ,reinterpret_cast<int*>(enum_option_val)
00569     ,num_enum_opt_values
00570     ,reinterpret_cast<const int*>(enum_opt_values)
00571     ,enum_opt_names
00572     ,documentation
00573     ,required
00574     );
00575 }
00576 
00577 inline
00578 std::string CommandLineProcessor::opt_type_str( EOptType opt_type ) const
00579 {
00580   std::string str;
00581   switch( opt_type ) {
00582     case OPT_BOOL_TRUE:
00583       str = "bool";
00584       break;
00585     case OPT_INT:
00586       str = "int";
00587       break;
00588     case OPT_DOUBLE:
00589       str = "double";
00590       break;
00591     case OPT_STRING:
00592       str = "string";
00593       break;
00594     case OPT_ENUM_INT:
00595       str = "enum";
00596       break;
00597     default:
00598       assert(0); // Local programming error only
00599   } 
00600   return str;
00601 }
00602 
00603 } // end namespace Teuchos
00604 
00605 #endif // TEUCHOS_COMMAND_LINE_PROCESSOR_HPP

Generated on Thu Sep 18 12:30:29 2008 for Teuchos - Trilinos Tools Package by doxygen 1.3.9.1