Teuchos - Trilinos Tools Package Version of the Day
Teuchos_CommandLineProcessor.cpp
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 // //////////////////////////////////////////////////
00043 // Teuchos_CommandLineProcessor.cpp
00044 
00045 
00046 #include "Teuchos_CommandLineProcessor.hpp"
00047 #include "Teuchos_GlobalMPISession.hpp"
00048 #include "Teuchos_VerboseObject.hpp"
00049 //#include "Teuchos_TimeMonitor.hpp"
00050 #include "Teuchos_Assert.hpp"
00051 #include "Teuchos_as.hpp"
00052 
00053 #ifdef HAVE_MPI
00054 #  include "mpi.h"
00055 #endif
00056 
00057 
00058 namespace {
00059 
00060 
00061 inline int my_max( int a, int b ) { return a > b ? a : b; }
00062 
00063 
00064 std::string remove_quotes( const std::string& str )
00065 {
00066   if(str[0] != '\"')
00067     return str;
00068   return str.substr(1,str.size()-2);
00069 }
00070 
00071 
00072 std::string add_quotes( const std::string& str )
00073 {
00074   if(str[0] == '\"')
00075     return str;
00076   return "\"" + str + "\"";
00077 }
00078 
00079 
00080 } // end namespace
00081 
00082 
00083 namespace Teuchos {
00084 
00085 
00086 const bool  CommandLineProcessor::output_all_front_matter_default_(false);
00087 const bool  CommandLineProcessor::output_show_line_prefix_default_(false);
00088 const bool  CommandLineProcessor::output_show_tab_count_default_(false);
00089 const bool  CommandLineProcessor::output_show_proc_rank_default_(false);
00090 const int   CommandLineProcessor::output_to_root_rank_only_default_(0);
00091 const bool  CommandLineProcessor::print_rcpnode_statistics_on_exit_default_(false);
00092 const bool  CommandLineProcessor::show_timer_summary_on_exit_default_(false);
00093 
00094 
00095 CommandLineProcessor::CommandLineProcessor(
00096   bool   throwExceptions_in
00097   ,bool  recogniseAllOptions_in
00098   ,bool  addOutputSetupOptions_in
00099   )
00100   :throwExceptions_(throwExceptions_in)
00101   ,recogniseAllOptions_(recogniseAllOptions_in)
00102   ,addOutputSetupOptions_(addOutputSetupOptions_in)
00103   ,output_all_front_matter_(output_all_front_matter_default_)
00104   ,output_show_line_prefix_(output_show_line_prefix_default_)
00105   ,output_show_tab_count_(output_show_tab_count_default_)
00106   ,output_show_proc_rank_(output_show_proc_rank_default_)
00107   ,output_to_root_rank_only_(output_to_root_rank_only_default_)
00108   ,print_rcpnode_statistics_on_exit_(print_rcpnode_statistics_on_exit_default_)
00109   ,show_timer_summary_on_exit_(show_timer_summary_on_exit_default_)
00110   ,printed_timer_summary_(false)
00111   ,added_extra_output_setup_options_(false)
00112   ,in_add_extra_output_setup_options_(false)
00113 {}
00114 
00115 
00116 CommandLineProcessor::~CommandLineProcessor()
00117 {
00118   printFinalTimerSummary();
00119 }
00120 
00121 
00122 // Set up options
00123 
00124 
00125 void CommandLineProcessor::setDocString( const char doc_string[] )
00126 {
00127   doc_string_ = doc_string;
00128 }
00129 
00130 
00131 void CommandLineProcessor::setOption(
00132   const char     option_true[]
00133   ,const char    option_false[]
00134   ,bool          *option_val
00135   ,const char    documentation[]
00136   )
00137 {
00138   add_extra_output_setup_options();
00139   TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
00140   options_list_[std::string(option_true)]
00141     = opt_val_val_t(OPT_BOOL_TRUE,any(option_val),false);
00142   options_list_[std::string(option_false)]
00143     = opt_val_val_t(OPT_BOOL_FALSE,any(option_val),false);
00144   options_documentation_list_.push_back(
00145     opt_doc_t(OPT_BOOL_TRUE, option_true, option_false,
00146       std::string(documentation?documentation:""), any(option_val)) 
00147     );
00148 }
00149 
00150 
00151 void CommandLineProcessor::setOption(
00152   const char     option_name[]
00153   ,int           *option_val
00154   ,const char    documentation[]
00155   ,const bool    required
00156   )
00157 {
00158   add_extra_output_setup_options();
00159   TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
00160   options_list_[std::string(option_name)]
00161     = opt_val_val_t(OPT_INT,any(option_val),required);
00162   options_documentation_list_.push_back(
00163     opt_doc_t(OPT_INT, option_name, "", std::string(documentation?documentation:""),
00164       any(option_val))
00165     );
00166 }
00167 
00168 
00169 void CommandLineProcessor::setOption(
00170   const char     option_name[]
00171   ,long int      *option_val
00172   ,const char    documentation[]
00173   ,const bool    required
00174   )
00175 {
00176   add_extra_output_setup_options();
00177   TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
00178   options_list_[std::string(option_name)]
00179     = opt_val_val_t(OPT_LONG_INT,any(option_val),required);
00180   options_documentation_list_.push_back(
00181     opt_doc_t(OPT_LONG_INT, option_name, "", std::string(documentation?documentation:""),
00182       any(option_val))
00183     );
00184 }
00185 
00186 
00187 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
00188 void CommandLineProcessor::setOption(
00189   const char     option_name[]
00190   ,long long int *option_val
00191   ,const char    documentation[]
00192   ,const bool    required
00193   )
00194 {
00195   add_extra_output_setup_options();
00196   TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
00197   options_list_[std::string(option_name)]
00198     = opt_val_val_t(OPT_LONG_LONG_INT,any(option_val),required);
00199   options_documentation_list_.push_back(
00200     opt_doc_t(OPT_LONG_LONG_INT, option_name, "", std::string(documentation?documentation:""),
00201       any(option_val))
00202     );
00203 }
00204 #endif
00205 
00206 
00207 void CommandLineProcessor::setOption(
00208   const char     option_name[]
00209   ,double        *option_val
00210   ,const char    documentation[]
00211   ,const bool    required
00212   )
00213 {
00214   add_extra_output_setup_options();
00215   TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
00216   options_list_[std::string(option_name)]
00217     = opt_val_val_t(OPT_DOUBLE,any(option_val),required);
00218   options_documentation_list_.push_back(
00219     opt_doc_t(OPT_DOUBLE, option_name, "", std::string(documentation?documentation:""),
00220       any(option_val))
00221     );
00222 }
00223 
00224 
00225 void CommandLineProcessor::setOption(
00226   const char     option_name[]
00227   ,std::string   *option_val
00228   ,const char    documentation[]
00229   ,const bool    required
00230   )
00231 {
00232   add_extra_output_setup_options();
00233   TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
00234   options_list_[std::string(option_name)]
00235     = opt_val_val_t(OPT_STRING,any(option_val),required);
00236   options_documentation_list_.push_back(
00237     opt_doc_t(OPT_STRING, option_name, "", std::string(documentation?documentation:""),
00238       any(option_val))
00239     );
00240 }
00241 
00242 
00243 // Parse command line
00244 
00245 
00246 CommandLineProcessor::EParseCommandLineReturn
00247 CommandLineProcessor::parse(
00248   int             argc
00249   ,char*          argv[]
00250   ,std::ostream   *errout
00251   ) const
00252 {
00253   add_extra_output_setup_options();
00254   std::string        opt_name;
00255   std::string        opt_val_str;
00256   const std::string  echo_cl_opt = "echo-command-line";
00257   const std::string  help_opt = "help";
00258   const std::string  pause_opt = "pause-for-debugging";
00259   int procRank = GlobalMPISession::getRank();
00260   for( int i = 1; i < argc; ++i ) {
00261     bool gov_return = get_opt_val( argv[i], &opt_name, &opt_val_str );
00262     if( !gov_return ) {
00263       if(procRank == 0) 
00264         print_bad_opt(i,argv,errout);
00265       if( recogniseAllOptions() ) 
00266         return PARSE_UNRECOGNIZED_OPTION;
00267       else {
00268         continue;
00269       }
00270     }
00271     if( opt_name == echo_cl_opt ) {
00272       if(errout && procRank == 0) {
00273         *errout << "\nEchoing the command-line:\n\n";
00274         for( int j = 0; j < argc; ++j )
00275           *errout << argv[j] << " ";
00276         *errout << "\n\n";
00277       }
00278       continue;
00279     }
00280     if( opt_name == help_opt ) {
00281       if(errout) printHelpMessage( argv[0], *errout );
00282       return PARSE_HELP_PRINTED;
00283     }
00284     if( opt_name == pause_opt ) {
00285       if(procRank == 0) {
00286         std::cerr << "\nType 0 and press enter to continue : ";
00287         int dummy_int = 0;
00288         std::cin >> dummy_int;
00289       }
00290 #ifdef HAVE_MPI
00291       MPI_Barrier(MPI_COMM_WORLD);
00292 #endif
00293       continue;
00294     }
00295     // Lookup the option (we had better find it!)
00296     options_list_t::iterator  itr = options_list_.find(opt_name);
00297     if( itr == options_list_.end() ) {
00298       if(procRank == 0)
00299         print_bad_opt(i,argv,errout);
00300       if( recogniseAllOptions() ) 
00301         return PARSE_UNRECOGNIZED_OPTION;
00302       else
00303         continue;
00304     }
00305     // Changed access to second value of std::map to not use overloaded arrow operator, 
00306     // otherwise this code will not compile on Janus (HKT, 12/01/2003) 
00307     opt_val_val_t &opt_val_val = (*itr).second;
00308     opt_val_val.was_read = true;
00309     switch( opt_val_val.opt_type ) {
00310       case OPT_BOOL_TRUE:
00311         *(any_cast<bool*>(opt_val_val.opt_val)) = true;
00312         break;
00313       case OPT_BOOL_FALSE:
00314         *(any_cast<bool*>(opt_val_val.opt_val)) = false;
00315         break;
00316       case OPT_INT:
00317         *(any_cast<int*>(opt_val_val.opt_val)) = asSafe<int> (opt_val_str);
00318         break;
00319       case OPT_LONG_INT:
00320         *(any_cast<long int*>(opt_val_val.opt_val)) = asSafe<long int> (opt_val_str);
00321         break;
00322 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
00323       case OPT_LONG_LONG_INT:
00324         *(any_cast<long long int*>(opt_val_val.opt_val)) = asSafe<long long int> (opt_val_str);
00325         break;
00326 #endif
00327       case OPT_DOUBLE:
00328         *(any_cast<double*>(opt_val_val.opt_val)) = asSafe<double> (opt_val_str);
00329         break;
00330       case OPT_STRING:
00331         *(any_cast<std::string*>(opt_val_val.opt_val)) = remove_quotes(opt_val_str);
00332         break;
00333       case OPT_ENUM_INT:
00334         if( !set_enum_value( i, argv, opt_name, any_cast<int>(opt_val_val.opt_val),
00335             remove_quotes(opt_val_str), errout ) )
00336         {
00337           return PARSE_UNRECOGNIZED_OPTION;
00338         }
00339         break;
00340       default:
00341         TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
00342     }
00343   }
00344   // Look for options that were required but were not set
00345   for(
00346     options_list_t::const_iterator itr = options_list_.begin();
00347     itr != options_list_.end();
00348     ++itr
00349     )
00350   {
00351     const opt_val_val_t   &opt_val_val  = (*itr).second;
00352     if( opt_val_val.required && !opt_val_val.was_read ) {
00353       const std::string     &opt_val_name = (*itr).first;
00354 #define CLP_ERR_MSG \
00355       "Error, the option --"<<opt_val_name<<" was required but was not set!"
00356       if(errout)
00357         *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
00358       if( throwExceptions() ) {
00359         TEUCHOS_TEST_FOR_EXCEPTION( true, ParseError, CLP_ERR_MSG );
00360       }
00361       return PARSE_ERROR;
00362 #undef CLP_ERR_MSG
00363     }
00364   }
00365   // Set the options of a default stream exists and if we are asked to
00366   RCP<FancyOStream>
00367     defaultOut = VerboseObjectBase::getDefaultOStream();
00368   if (defaultOut.get() && addOutputSetupOptions_) {
00369     if (output_all_front_matter_ != output_all_front_matter_default_)
00370       defaultOut->setShowAllFrontMatter(output_all_front_matter_);
00371     if (output_show_line_prefix_ != output_show_line_prefix_default_)
00372       defaultOut->setShowLinePrefix(output_show_line_prefix_);
00373     if (output_show_tab_count_ != output_show_tab_count_default_)
00374       defaultOut->setShowTabCount(output_show_tab_count_);
00375     if (output_show_proc_rank_ != output_show_proc_rank_default_)
00376       defaultOut->setShowProcRank(output_show_proc_rank_);
00377     if (output_to_root_rank_only_ != output_to_root_rank_only_default_)
00378       defaultOut->setOutputToRootOnly(output_to_root_rank_only_);
00379     RCPNodeTracer::setPrintRCPNodeStatisticsOnExit(print_rcpnode_statistics_on_exit_);
00380   }
00381   return PARSE_SUCCESSFUL;
00382 }
00383 
00384 
00385 void CommandLineProcessor::printHelpMessage( const char program_name[],
00386   std::ostream &out ) const
00387 {
00388   add_extra_output_setup_options();
00389   int procRank = GlobalMPISession::getRank();
00390   if (procRank == 0) {
00391     using std::setw;
00392     using std::endl;
00393     
00394     const int opt_type_w = 14;
00395     const char spc_chars[] = "  ";
00396     
00397     // Get the maximum length of an option name
00398     int opt_name_w = 19; // For the 'pause-for-debugging' option
00399     options_documentation_list_t::const_iterator itr;
00400     for (
00401       itr = options_documentation_list_.begin();
00402       itr != options_documentation_list_.end();
00403       ++itr
00404       )
00405     {
00406       opt_name_w = my_max(opt_name_w,itr->opt_name.length());
00407       if( itr->opt_type )
00408         opt_name_w = my_max(opt_name_w,itr->opt_name_false.length());
00409     }
00410     opt_name_w += 2;
00411     
00412     // Some built-in options
00413     out
00414       << "Usage: " << program_name << " [options]\n"
00415       << spc_chars << "options:\n"
00416       << spc_chars
00417       << "--"
00418 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
00419       << std::left << setw(opt_name_w) << "help"
00420       << std::left << setw(opt_type_w) << " "
00421 #else
00422       << std::setiosflags(std::ios::left) << setw(opt_name_w) << "help"
00423       << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
00424 #endif
00425       << "Prints this help message"
00426       << std::endl
00427       << spc_chars
00428       << "--"
00429 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
00430       << std::left << setw(opt_name_w) << "pause-for-debugging"
00431       << std::left << setw(opt_type_w) << " "
00432 #else
00433       << std::setiosflags(std::ios::left) << setw(opt_name_w) << "pause-for-debugging"
00434       << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
00435 #endif
00436       << "Pauses for user input to allow attaching a debugger"
00437       << std::endl
00438       << spc_chars
00439       << "--"
00440 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
00441       << std::left << setw(opt_name_w) << "echo-command-line"
00442       << std::left << setw(opt_type_w) << " "
00443 #else
00444       << std::setiosflags(std::ios::left) << setw(opt_name_w) << "echo-command-line"
00445       << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
00446 #endif
00447       << "Echo the command-line but continue as normal"
00448       << std::endl;
00449     for(
00450       itr = options_documentation_list_.begin();
00451       itr != options_documentation_list_.end();
00452       ++itr )
00453     {
00454       // print top line with option name, type and short documentation string
00455       out
00456         << spc_chars
00457         << "--"
00458 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
00459         << std::left << setw(opt_name_w) << itr->opt_name
00460         << std::left << setw(opt_type_w) << opt_type_str(itr->opt_type)
00461 #else
00462         << std::setiosflags(std::ios::left) << setw(opt_name_w) << itr->opt_name
00463         << std::setiosflags(std::ios::left) << setw(opt_type_w) << opt_type_str(itr->opt_type)
00464 #endif
00465         << ( itr->documentation.length() ? itr->documentation.c_str() : "No documentation" )
00466         << std::endl;
00467       // If an enumeration option then the next line is the value options
00468       if( itr->opt_type == OPT_ENUM_INT ) {
00469         out
00470           << spc_chars
00471           << "  "
00472           << setw(opt_name_w) << ""
00473           << setw(opt_type_w) << "";
00474         print_enum_opt_names( any_cast<int>(itr->default_val), out );
00475         out
00476           << std::endl;
00477       }
00478       // Now print the line that contains the default values
00479       if( itr->opt_type == OPT_BOOL_TRUE ) {
00480         out
00481           << spc_chars
00482           << "--"
00483           << setw(opt_name_w) << itr->opt_name_false;
00484       }
00485       else {
00486         out
00487           << spc_chars
00488           << "  "
00489           << setw(opt_name_w) << " ";
00490       }
00491       out
00492         << setw(opt_type_w) << " "
00493         << "(default: ";
00494       switch( itr->opt_type ) {
00495         case OPT_BOOL_TRUE:
00496           out << "--" << ( (*(any_cast<bool*>(itr->default_val))) ?
00497             itr->opt_name : itr->opt_name_false );
00498           break;
00499         case OPT_INT:
00500         case OPT_LONG_INT:
00501 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
00502         case OPT_LONG_LONG_INT:
00503 #endif
00504         case OPT_DOUBLE:
00505         case OPT_STRING:
00506         case OPT_ENUM_INT:
00507           out << "--" << itr->opt_name;
00508           break;
00509         default:
00510           TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
00511       }
00512       switch( itr->opt_type ) {
00513         case OPT_BOOL_TRUE:
00514           break;
00515         case OPT_INT:
00516           out << "=" << (*(any_cast<int*>(itr->default_val)));
00517           break;
00518         case OPT_LONG_INT:
00519           out << "=" << (*(any_cast<long int*>(itr->default_val)));
00520           break;
00521 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
00522         case OPT_LONG_LONG_INT:
00523           out << "=" << (*(any_cast<long long int*>(itr->default_val)));
00524           break;
00525 #endif
00526         case OPT_DOUBLE:
00527           out <<  "=" << (*(any_cast<double*>(itr->default_val)));
00528           break;
00529         case OPT_STRING:
00530           out <<  "=" << add_quotes(*(any_cast<std::string*>(itr->default_val)));
00531           break;
00532         case OPT_ENUM_INT:
00533           out <<  "=" << add_quotes(
00534             enum_opt_default_val_name(itr->opt_name,any_cast<int>(itr->default_val),&out));
00535           break;
00536         default:
00537           TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
00538       }
00539       out << ")\n";
00540     }
00541     if(doc_string_.length()) {
00542       out << "\nDETAILED DOCUMENTATION:\n\n" << doc_string_ << std::endl << std::endl;
00543     }
00544     if(throwExceptions_)
00545       TEUCHOS_TEST_FOR_EXCEPTION( true, HelpPrinted, "Help message was printed" );
00546   }
00547 }
00548 
00549 
00550 void CommandLineProcessor::printFinalTimerSummary(
00551   const Ptr<std::ostream> &out_inout
00552   )
00553 {
00554   if (!printed_timer_summary_ && show_timer_summary_on_exit_) {
00555     RCP<std::ostream> out;
00556     if (nonnull(out_inout)) {
00557       out = rcpFromPtr(out_inout);
00558     }
00559     else {
00560       out = VerboseObjectBase::getDefaultOStream();
00561     }
00562     getTimeMonitorSurrogate()->summarize(*out << "\n");
00563     printed_timer_summary_ = true;
00564   }
00565 }
00566 
00567 
00568 // private
00569 
00570 
00571 void CommandLineProcessor::add_extra_output_setup_options() const
00572 {
00573   if(
00574     // Are we in this function already and calling it recursively?
00575     in_add_extra_output_setup_options_
00576     ||
00577     // Have we already setup these options?
00578     added_extra_output_setup_options_
00579     ||
00580     // Are we not supposed to setup these options?
00581     !addOutputSetupOptions_
00582     )
00583   {
00584     return; // If any of the above is true, we need to return right away!
00585   }
00586   // Set the commandline options for this ...
00587   CommandLineProcessor
00588     *clp = const_cast<CommandLineProcessor*>(this);
00589   clp->in_add_extra_output_setup_options_ = true;
00590   clp->setOption(
00591     "output-all-front-matter","output-no-front-matter",&clp->output_all_front_matter_
00592     ,"Set if all front matter is printed to the default FancyOStream or not"
00593     );
00594   clp->setOption(
00595     "output-show-line-prefix","output-no-show-line-prefix",&clp->output_show_line_prefix_
00596     ,"Set if the line prefix matter is printed to the default FancyOStream or not"
00597     );
00598   clp->setOption(
00599     "output-show-tab-count","output-no-show-tab-count",&clp->output_show_tab_count_
00600     ,"Set if the tab count is printed to the default FancyOStream or not"
00601     );
00602   clp->setOption(
00603     "output-show-proc-rank","output-no-show-proc-rank",&clp->output_show_proc_rank_
00604     ,"Set if the processor rank is printed to the default FancyOStream or not"
00605     );
00606   clp->setOption(
00607     "output-to-root-rank-only",&clp->output_to_root_rank_only_
00608     ,"Set which processor (the root) gets the output.  If < 0, then all processors get output."
00609     );
00610   clp->setOption(
00611     "print-rcpnode-statistics-on-exit", "no-print-rcpnode-statistics-on-exit",
00612     &clp->print_rcpnode_statistics_on_exit_,
00613     "Set if the RCPNode usage statistics will be printed on exit or not.  Warning,"
00614     " this prints to std::cerr or every process so do not turn this on for very large"
00615     " parallel runs."
00616     );
00617   if (nonnull(getTimeMonitorSurrogate())) {
00618     clp->setOption(
00619       "show-timer-summary", "no-show-timer-sumary", &clp->show_timer_summary_on_exit_,
00620       "If true, then Teuchos::TimeMonitor::summarize() is called in"
00621       " CommandLineProcessor's destructor (usually at the end of main)."
00622       );
00623   }
00624 
00625   clp->added_extra_output_setup_options_ = true;
00626   clp->in_add_extra_output_setup_options_ = false;
00627 }
00628 
00629 
00630 void CommandLineProcessor::setEnumOption(
00631   const char    enum_option_name[]
00632   ,int          *enum_option_val
00633   ,const int    num_enum_opt_values
00634   ,const int    enum_opt_values[]
00635   ,const char*  enum_opt_names[]
00636   ,const char   documentation[]
00637   ,const bool   required
00638   )
00639 {
00640   add_extra_output_setup_options();
00641 
00642   TEUCHOS_TEST_FOR_EXCEPT(enum_option_val==NULL);
00643   TEUCHOS_TEST_FOR_EXCEPT(num_enum_opt_values<=0);
00644   TEUCHOS_TEST_FOR_EXCEPT(enum_opt_values==NULL);
00645   TEUCHOS_TEST_FOR_EXCEPT(enum_opt_names==NULL);
00646 
00647   enum_opt_data_list_.push_back(
00648     enum_opt_data_t(enum_option_val,num_enum_opt_values,enum_opt_values,enum_opt_names)
00649     );
00650   const int opt_id = enum_opt_data_list_.size()-1;
00651   options_list_[std::string(enum_option_name)]
00652     = opt_val_val_t(OPT_ENUM_INT,any(opt_id),required);
00653   options_documentation_list_.push_back(
00654     opt_doc_t(OPT_ENUM_INT,enum_option_name, "",
00655       std::string(documentation?documentation:""), any(opt_id))
00656     );
00657 }
00658 
00659 
00660 bool CommandLineProcessor::set_enum_value(
00661   int                  argv_i
00662   ,char*               argv[]
00663   ,const std::string   &enum_opt_name
00664   ,const int           enum_id
00665   ,const std::string   &enum_str_val
00666   ,std::ostream        *errout
00667   ) const
00668 {
00669   const enum_opt_data_t
00670     &enum_opt_data = enum_opt_data_list_.at(enum_id);
00671   std::vector<std::string>::const_iterator
00672     itr_begin = enum_opt_data.enum_opt_names.begin(),
00673     itr_end   = enum_opt_data.enum_opt_names.end(),
00674     itr       =  std::find( itr_begin, itr_end, enum_str_val );
00675   if( itr == itr_end ) {
00676     const int j = argv_i;
00677 #define CLP_ERR_MSG \
00678       "Error, the value \"" << enum_str_val << "\" for the " \
00679       << j<<(j==1?"st":(j==2?"nd":(j==3?"rd":"th"))) << " option --" \
00680       << enum_opt_name << " was not recognized (use --help)!"
00681     if(errout)
00682       *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
00683     if( throwExceptions() ) {
00684       TEUCHOS_TEST_FOR_EXCEPTION( true, UnrecognizedOption, CLP_ERR_MSG );
00685     }
00686     else {
00687       return false;
00688     }
00689 #undef CLP_ERR_MSG
00690   }
00691   const int enum_opt_val_index = itr - itr_begin;
00692   *enum_opt_data.enum_option_val = enum_opt_data.enum_opt_values.at(enum_opt_val_index);
00693   return true;
00694 }
00695 
00696 
00697 void CommandLineProcessor::print_enum_opt_names(
00698   const int            enum_id
00699   ,std::ostream        &out
00700   ) const
00701 {
00702   const enum_opt_data_t
00703     &enum_opt_data = enum_opt_data_list_.at(enum_id);
00704   typedef std::vector<std::string>::const_iterator itr_t;
00705   out << "Valid options:";
00706   for(
00707     itr_t itr = enum_opt_data.enum_opt_names.begin();
00708     itr != enum_opt_data.enum_opt_names.end();
00709     ++itr
00710     )
00711   {
00712     if( itr != enum_opt_data.enum_opt_names.begin() ) out << ",";
00713     out << " " << add_quotes(*itr);
00714   }
00715 }
00716 
00717 
00718 std::string
00719 CommandLineProcessor::enum_opt_default_val_name(
00720   const std::string    &enum_name
00721   ,const int           enum_id
00722   ,std::ostream        *errout
00723   ) const
00724 {
00725   const enum_opt_data_t
00726     &enum_opt_data = enum_opt_data_list_.at(enum_id);
00727   return enum_opt_data.enum_opt_names.at(
00728     find_enum_opt_index(
00729       enum_name,*enum_opt_data.enum_option_val,enum_opt_data,errout
00730       )
00731     );
00732 }
00733 
00734 
00735 int CommandLineProcessor::find_enum_opt_index(
00736   const std::string           &enum_opt_name
00737   ,const int                  opt_value
00738   ,const enum_opt_data_t      &enum_data
00739   ,std::ostream               *errout
00740   ) const
00741 {
00742   std::vector<int>::const_iterator
00743     itr_begin = enum_data.enum_opt_values.begin(),
00744     itr_end   = enum_data.enum_opt_values.end(),
00745     itr       =  std::find( itr_begin, itr_end, opt_value );
00746   if( itr == itr_end ) {
00747 #define CLP_ERR_MSG \
00748       ( recogniseAllOptions() ? "Error" : "Warning" ) \
00749       << ", option --" << enum_opt_name << " was given an invalid " \
00750       "initial option value of " << opt_value << "!"
00751     if(errout)
00752       *errout << CLP_ERR_MSG << std::endl;
00753     if( throwExceptions() )
00754       TEUCHOS_TEST_FOR_EXCEPTION( true, std::invalid_argument, CLP_ERR_MSG );
00755 #undef CLP_ERR_MSG
00756   }
00757   return itr - itr_begin;
00758 }
00759 
00760 
00761 bool CommandLineProcessor::get_opt_val(
00762   const char     str[]
00763   ,std::string   *opt_name
00764   ,std::string   *opt_val_str
00765   ) const
00766 {
00767   const int len = std::strlen(str);
00768   if( len < 3 )
00769     return false; // Can't be an option with '--' followed by at least one char
00770   if( str[0] != '-' || str[1] != '-' )
00771     return false; // Not a recognised option
00772   // Find the '='
00773   int equ_i;
00774   for( equ_i = 2; equ_i < len && str[equ_i] != '='; ++equ_i );
00775   // Set opt_name
00776   opt_name->assign( str + 2, equ_i-2 );
00777   // Set opt_val_str
00778   if( equ_i == len ) {
00779     *opt_val_str = "";
00780   }
00781   else {
00782     opt_val_str->assign( str + equ_i + 1, len - equ_i - 1 );
00783   }
00784   return true;
00785 }
00786 
00787 void CommandLineProcessor::print_bad_opt(
00788   int             argv_i
00789   ,char*          argv[]
00790   ,std::ostream   *errout
00791   ) const
00792 {
00793   const int j = argv_i;
00794 #define CLP_ERR_MSG \
00795     ( recogniseAllOptions() ? "Error" : "Warning" ) \
00796     << ", the " << j<<(j==1?"st":(j==2?"nd":(j==3?"rd":"th"))) \
00797     << " option \'" << argv[argv_i] << "\' was not recognized (use --help)!"
00798   if(errout)
00799     *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
00800   if( recogniseAllOptions() && throwExceptions() )
00801     TEUCHOS_TEST_FOR_EXCEPTION( true, UnrecognizedOption, CLP_ERR_MSG );
00802 #undef CLP_ERR_MSG
00803 }
00804 
00805 
00806 // Hidden stuff
00807 
00808 
00809 void CommandLineProcessor::setTimeMonitorSurrogate(
00810   const RCP<CommandLineProcessor::TimeMonitorSurrogate> &timeMonitorSurrogate)
00811 {
00812   getRawTimeMonitorSurrogate() = timeMonitorSurrogate;
00813 }
00814 
00815 
00816 RCP<CommandLineProcessor::TimeMonitorSurrogate>
00817 CommandLineProcessor::getTimeMonitorSurrogate()
00818 {
00819   return getRawTimeMonitorSurrogate();
00820 }
00821 
00822 
00823 RCP<CommandLineProcessor::TimeMonitorSurrogate>&
00824 CommandLineProcessor::getRawTimeMonitorSurrogate()
00825 {
00826   static RCP<TimeMonitorSurrogate> timeMonitorSurrogate;
00827   return timeMonitorSurrogate;
00828 } 
00829 
00830 
00831 } // end namespace Teuchos
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines