00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "Teuchos_CommandLineProcessor.hpp"
00033 #include "Teuchos_TestForException.hpp"
00034
00035 #ifdef HAVE_MPI
00036 #include "mpi.h"
00037 #endif
00038
00039 namespace {
00040
00041 inline int my_max( int a, int b ) { return a > b ? a : b; }
00042
00043 std::string remove_quotes( const std::string& str )
00044 {
00045 if(str[0] != '\"')
00046 return str;
00047 return str.substr(1,str.size()-2);
00048 }
00049
00050 std::string add_quotes( const std::string& str )
00051 {
00052 if(str[0] == '\"')
00053 return str;
00054 return "\"" + str + "\"";
00055 }
00056
00057 }
00058
00059 namespace Teuchos {
00060
00061 CommandLineProcessor::CommandLineProcessor(
00062 bool throwExceptions
00063 ,bool recogniseAllOptions
00064 )
00065 :throwExceptions_(throwExceptions)
00066 ,recogniseAllOptions_(recogniseAllOptions)
00067 {}
00068
00069
00070
00071 void CommandLineProcessor::setOption(
00072 const char option_true[]
00073 ,const char option_false[]
00074 ,bool *option_val
00075 ,const char documentation[]
00076 )
00077 {
00078 assert(option_val!=NULL);
00079 options_list_[std::string(option_true)]
00080 = opt_val_val_t(OPT_BOOL_TRUE,option_val);
00081 options_list_[std::string(option_false)]
00082 = opt_val_val_t(OPT_BOOL_FALSE,option_val);
00083 options_documentation_list_.push_back(
00084 opt_doc_t(OPT_BOOL_TRUE,option_true,option_false,std::string(documentation?documentation:""),option_val) );
00085 }
00086
00087 void CommandLineProcessor::setOption(
00088 const char option_name[]
00089 ,int *option_val
00090 ,const char documentation[]
00091 )
00092 {
00093 assert(option_val!=NULL);
00094 options_list_[std::string(option_name)]
00095 = opt_val_val_t(OPT_INT,option_val);
00096 options_documentation_list_.push_back(
00097 opt_doc_t(OPT_INT,option_name,"",std::string(documentation?documentation:""),option_val) );
00098 }
00099
00100 void CommandLineProcessor::setOption(
00101 const char option_name[]
00102 ,double *option_val
00103 ,const char documentation[]
00104 )
00105 {
00106 assert(option_val!=NULL);
00107 options_list_[std::string(option_name)]
00108 = opt_val_val_t(OPT_DOUBLE,option_val);
00109 options_documentation_list_.push_back(
00110 opt_doc_t(OPT_DOUBLE,option_name,"",std::string(documentation?documentation:""),option_val) );
00111 }
00112
00113 void CommandLineProcessor::setOption(
00114 const char option_name[]
00115 ,std::string *option_val
00116 ,const char documentation[]
00117 )
00118 {
00119 assert(option_val!=NULL);
00120 options_list_[std::string(option_name)]
00121 = opt_val_val_t(OPT_STRING,option_val);
00122 options_documentation_list_.push_back(
00123 opt_doc_t(OPT_STRING,option_name,"",std::string(documentation?documentation:""),option_val) );
00124 }
00125
00126
00127
00128 CommandLineProcessor::EParseCommandLineReturn
00129 CommandLineProcessor::parse(
00130 int argc
00131 ,char* argv[]
00132 ,std::ostream *errout
00133 ) const
00134 {
00135 std::string opt_name;
00136 std::string opt_val_str;
00137 const std::string help_opt = "help";
00138 const std::string pause_opt = "pause-for-debugging";
00139 #ifdef HAVE_MPI
00140 int procRank = -1;
00141 MPI_Comm_rank( MPI_COMM_WORLD, &procRank );
00142 #endif
00143 for( int i = 1; i < argc; ++i ) {
00144 bool gov_return = get_opt_val( argv[i], &opt_name, &opt_val_str );
00145 if( !gov_return && recogniseAllOptions() ) {
00146 #ifdef HAVE_MPI
00147 if (procRank == 0)
00148 #endif
00149 print_bad_opt(i,argv,errout);
00150 return PARSE_UNRECOGNIZED_OPTION;
00151 }
00152 if( opt_name == help_opt ) {
00153 #ifdef HAVE_MPI
00154 if (procRank == 0)
00155 #endif
00156 print_help_msg( argc, argv, errout );
00157 return PARSE_HELP_PRINTED;
00158 }
00159 if( opt_name == pause_opt ) {
00160 #ifdef HAVE_MPI
00161 if(procRank == 0) {
00162 #endif
00163 std::cerr << "\nType 0 and press enter to continue : ";
00164 int dummy_int = 0;
00165 std::cin >> dummy_int;
00166 #ifdef HAVE_MPI
00167 }
00168 MPI_Barrier(MPI_COMM_WORLD);
00169 #endif
00170 continue;
00171 }
00172
00173 options_list_t::const_iterator itr = options_list_.find(opt_name);
00174 if( itr == options_list_.end() && recogniseAllOptions() ) {
00175 #ifdef HAVE_MPI
00176 if(procRank == 0)
00177 #endif
00178 print_bad_opt(i,argv,errout);
00179 return PARSE_UNRECOGNIZED_OPTION;
00180 }
00181
00182
00183 const opt_val_val_t &opt_val_val = (*itr).second;
00184 switch( opt_val_val.opt_type ) {
00185 case OPT_BOOL_TRUE:
00186 *((bool*)opt_val_val.opt_val) = true;
00187 break;
00188 case OPT_BOOL_FALSE:
00189 *((bool*)opt_val_val.opt_val) = false;
00190 break;
00191 case OPT_INT:
00192 *((int*)opt_val_val.opt_val) = ::atoi(opt_val_str.c_str());
00193 break;
00194 case OPT_DOUBLE:
00195 *((double*)opt_val_val.opt_val) = ::atof(opt_val_str.c_str());
00196 break;
00197 case OPT_STRING:
00198 *((std::string*)opt_val_val.opt_val) = remove_quotes(opt_val_str);
00199 break;
00200 default:
00201 assert(0);
00202 }
00203 }
00204 return PARSE_SUCCESSFUL;
00205 }
00206
00207
00208
00209 bool CommandLineProcessor::get_opt_val(
00210 const char str[]
00211 ,std::string *opt_name
00212 ,std::string *opt_val_str
00213 ) const
00214 {
00215 const int len = strlen(str);
00216 if( len < 3 )
00217 return false;
00218 if( str[0] != '-' || str[1] != '-' )
00219 return false;
00220
00221 int equ_i;
00222 for( equ_i = 2; equ_i < len && str[equ_i] != '='; ++equ_i );
00223
00224 opt_name->assign( str + 2, equ_i-2 );
00225
00226 if( equ_i == len ) {
00227 *opt_val_str = "";
00228 }
00229 else {
00230 opt_val_str->assign( str + equ_i + 1, len - equ_i - 1 );
00231 }
00232 return true;
00233 }
00234
00235 void CommandLineProcessor::print_help_msg(
00236 int argc
00237 ,char* argv[]
00238 ,std::ostream *errout
00239 ) const
00240 {
00241 using std::setw;
00242 using std::endl;
00243
00244 if( !errout )
00245 return;
00246
00247 const int opt_type_w = 8;
00248 const char spc_chars[] = " ";
00249
00250
00251 int opt_name_w = 19;
00252 options_documentation_list_t::const_iterator itr;
00253 for( itr = options_documentation_list_.begin(); itr != options_documentation_list_.end(); ++itr ) {
00254 opt_name_w = my_max(opt_name_w,itr->opt_name.length());
00255 if( itr->opt_type )
00256 opt_name_w = my_max(opt_name_w,itr->opt_name_false.length());
00257 }
00258 opt_name_w += 2;
00259
00260
00261 *errout
00262 << "Usage: " << argv[0] << " [options]\n"
00263 << spc_chars << "options:\n"
00264 << spc_chars
00265 << "--"
00266 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
00267 << std::left << setw(opt_name_w) << "help"
00268 << std::left << setw(opt_type_w) << " "
00269 #else
00270 << std::setiosflags(std::ios::left) << setw(opt_name_w) << "help"
00271 << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
00272 #endif
00273 << "Prints this help message"
00274 << endl
00275 << spc_chars
00276 << "--"
00277 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
00278 << std::left << setw(opt_name_w) << "pause-for-debugging"
00279 << std::left << setw(opt_type_w) << " "
00280 #else
00281 << std::setiosflags(std::ios::left) << setw(opt_name_w) << "pause-for-debugging"
00282 << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
00283 #endif
00284 << "Pauses for user input to allow attaching a debugger"
00285 << endl;
00286 for( itr = options_documentation_list_.begin(); itr != options_documentation_list_.end(); ++itr ) {
00287 *errout
00288 << spc_chars
00289 << "--"
00290 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
00291 << std::left << setw(opt_name_w) << itr->opt_name
00292 << std::left << setw(opt_type_w) << opt_type_str(itr->opt_type)
00293 #else
00294 << std::setiosflags(std::ios::left) << setw(opt_name_w) << itr->opt_name
00295 << std::setiosflags(std::ios::left) << setw(opt_type_w) << opt_type_str(itr->opt_type)
00296 #endif
00297 << ( itr->documentation.length() ? itr->documentation.c_str() : "No documentation" )
00298 << endl;
00299 if( itr->opt_type == OPT_BOOL_TRUE ) {
00300 *errout
00301 << spc_chars
00302 << "--"
00303 << setw(opt_name_w) << itr->opt_name_false;
00304 }
00305 else {
00306 *errout
00307 << spc_chars
00308 << " "
00309 << setw(opt_name_w) << " ";
00310 }
00311 *errout
00312 << setw(opt_type_w) << " "
00313 << "(default: ";
00314 switch( itr->opt_type ) {
00315 case OPT_BOOL_TRUE:
00316 *errout << "--" << ( (*((bool*)itr->default_val)) ? itr->opt_name : itr->opt_name_false );
00317 break;
00318 case OPT_INT:
00319 case OPT_DOUBLE:
00320 case OPT_STRING:
00321 *errout << "--" << itr->opt_name;
00322 break;
00323 default:
00324 assert(0);
00325 }
00326 switch( itr->opt_type ) {
00327 case OPT_BOOL_TRUE:
00328 break;
00329 case OPT_INT:
00330 *errout << "=" << (*((int*)itr->default_val));
00331 break;
00332 case OPT_DOUBLE:
00333 *errout << "=" << (*((double*)itr->default_val));
00334 break;
00335 case OPT_STRING:
00336 *errout << "=" << add_quotes(*((std::string*)itr->default_val));
00337 break;
00338 default:
00339 assert(0);
00340 }
00341 *errout << ")\n";
00342 }
00343 if(throwExceptions_)
00344 TEST_FOR_EXCEPTION( true, HelpPrinted, "Help message was printed" );
00345 }
00346
00347 void CommandLineProcessor::print_bad_opt(
00348 int argv_i
00349 ,char* argv[]
00350 ,std::ostream *errout
00351 ) const
00352 {
00353 # define CLP_ERR_MSG "Error, option " << argv_i-1 << " \'" << argv[argv_i] << "\' is not recognized (use --help)!"
00354 if(errout)
00355 *errout << argv[0] << " : " << CLP_ERR_MSG << std::endl;
00356 if(throwExceptions_)
00357 TEST_FOR_EXCEPTION( true, UnrecognizedOption, CLP_ERR_MSG );
00358 # undef CLP_ERR_MSG
00359 }
00360
00361 }
00362
00363