Teuchos - Trilinos Tools Package  Version of the Day
Teuchos_CommandLineProcessor.cpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Teuchos: Common Tools Package
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 // //////////////////////////////////////////////////
43 // Teuchos_CommandLineProcessor.cpp
44 
45 
48 #include "Teuchos_VerboseObject.hpp"
49 //#include "Teuchos_TimeMonitor.hpp"
50 #include "Teuchos_Assert.hpp"
51 #include "Teuchos_as.hpp"
52 
53 
54 namespace {
55 
56 
57 inline int my_max( int a, int b ) { return a > b ? a : b; }
58 
59 
60 std::string remove_quotes( const std::string& str )
61 {
62  if(str[0] != '\"')
63  return str;
64  return str.substr(1,str.size()-2);
65 }
66 
67 
68 std::string add_quotes( const std::string& str )
69 {
70  if(str[0] == '\"')
71  return str;
72  return "\"" + str + "\"";
73 }
74 
75 
76 } // end namespace
77 
78 
79 namespace Teuchos {
80 
81 
82 const bool CommandLineProcessor::output_all_front_matter_default_(false);
83 const bool CommandLineProcessor::output_show_line_prefix_default_(false);
84 const bool CommandLineProcessor::output_show_tab_count_default_(false);
85 const bool CommandLineProcessor::output_show_proc_rank_default_(false);
86 const int CommandLineProcessor::output_to_root_rank_only_default_(0);
87 const bool CommandLineProcessor::print_rcpnode_statistics_on_exit_default_(false);
88 const bool CommandLineProcessor::show_timer_summary_on_exit_default_(false);
89 
90 
92  bool throwExceptions_in
93  ,bool recogniseAllOptions_in
94  ,bool addOutputSetupOptions_in
95  )
96  :throwExceptions_(throwExceptions_in)
97  ,recogniseAllOptions_(recogniseAllOptions_in)
98  ,addOutputSetupOptions_(addOutputSetupOptions_in)
99  ,output_all_front_matter_(output_all_front_matter_default_)
100  ,output_show_line_prefix_(output_show_line_prefix_default_)
101  ,output_show_tab_count_(output_show_tab_count_default_)
102  ,output_show_proc_rank_(output_show_proc_rank_default_)
103  ,output_to_root_rank_only_(output_to_root_rank_only_default_)
104  ,print_rcpnode_statistics_on_exit_(print_rcpnode_statistics_on_exit_default_)
105  ,show_timer_summary_on_exit_(show_timer_summary_on_exit_default_)
106  ,printed_timer_summary_(false)
107  ,added_extra_output_setup_options_(false)
108  ,in_add_extra_output_setup_options_(false)
109 {}
110 
111 
113 {
115 }
116 
117 
118 // Set up options
119 
120 
121 void CommandLineProcessor::setDocString( const char doc_string[] )
122 {
123  doc_string_ = doc_string;
124 }
125 
126 
128  const char option_true[]
129  ,const char option_false[]
130  ,bool *option_val
131  ,const char documentation[]
132  )
133 {
134  add_extra_output_setup_options();
135  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
136  options_list_[std::string(option_true)]
137  = opt_val_val_t(OPT_BOOL_TRUE,any(option_val),false);
138  options_list_[std::string(option_false)]
139  = opt_val_val_t(OPT_BOOL_FALSE,any(option_val),false);
140  options_documentation_list_.push_back(
141  opt_doc_t(OPT_BOOL_TRUE, option_true, option_false,
142  std::string(documentation?documentation:""), any(option_val))
143  );
144 }
145 
146 
148  const char option_name[]
149  ,int *option_val
150  ,const char documentation[]
151  ,const bool required
152  )
153 {
154  add_extra_output_setup_options();
155  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
156  options_list_[std::string(option_name)]
157  = opt_val_val_t(OPT_INT,any(option_val),required);
158  options_documentation_list_.push_back(
159  opt_doc_t(OPT_INT, option_name, "", std::string(documentation?documentation:""),
160  any(option_val))
161  );
162 }
163 
164 
166  const char option_name[]
167  ,long int *option_val
168  ,const char documentation[]
169  ,const bool required
170  )
171 {
172  add_extra_output_setup_options();
173  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
174  options_list_[std::string(option_name)]
175  = opt_val_val_t(OPT_LONG_INT,any(option_val),required);
176  options_documentation_list_.push_back(
177  opt_doc_t(OPT_LONG_INT, option_name, "", std::string(documentation?documentation:""),
178  any(option_val))
179  );
180 }
181 
182 
184  const char option_name[]
185  ,size_t *option_val
186  ,const char documentation[]
187  ,const bool required
188  )
189 {
190  add_extra_output_setup_options();
191  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
192  options_list_[std::string(option_name)]
193  = opt_val_val_t(OPT_SIZE_T,any(option_val),required);
194  options_documentation_list_.push_back(
195  opt_doc_t(OPT_SIZE_T, option_name, "", std::string(documentation?documentation:""),
196  any(option_val))
197  );
198 }
199 
200 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
202  const char option_name[]
203  ,long long int *option_val
204  ,const char documentation[]
205  ,const bool required
206  )
207 {
208  add_extra_output_setup_options();
209  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
210  options_list_[std::string(option_name)]
211  = opt_val_val_t(OPT_LONG_LONG_INT,any(option_val),required);
212  options_documentation_list_.push_back(
213  opt_doc_t(OPT_LONG_LONG_INT, option_name, "", std::string(documentation?documentation:""),
214  any(option_val))
215  );
216 }
217 #endif
218 
219 
221  const char option_name[]
222  ,double *option_val
223  ,const char documentation[]
224  ,const bool required
225  )
226 {
227  add_extra_output_setup_options();
228  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
229  options_list_[std::string(option_name)]
230  = opt_val_val_t(OPT_DOUBLE,any(option_val),required);
231  options_documentation_list_.push_back(
232  opt_doc_t(OPT_DOUBLE, option_name, "", std::string(documentation?documentation:""),
233  any(option_val))
234  );
235 }
236 
237 
239  const char option_name[]
240  ,std::string *option_val
241  ,const char documentation[]
242  ,const bool required
243  )
244 {
245  add_extra_output_setup_options();
246  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
247  options_list_[std::string(option_name)]
248  = opt_val_val_t(OPT_STRING,any(option_val),required);
249  options_documentation_list_.push_back(
250  opt_doc_t(OPT_STRING, option_name, "", std::string(documentation?documentation:""),
251  any(option_val))
252  );
253 }
254 
255 
256 // Parse command line
257 
258 
261  int argc
262  ,char* argv[]
263  ,std::ostream *errout
264  ) const
265 {
266  add_extra_output_setup_options();
267  std::string opt_name;
268  std::string opt_val_str;
269  const std::string echo_cl_opt = "echo-command-line";
270  const std::string help_opt = "help";
271  const std::string pause_opt = "pause-for-debugging";
272  int procRank = GlobalMPISession::getRank();
273 
274  // check for help options before any others as we modify
275  // the values afterwards
276  for( int i = 1; i < argc; ++i ) {
277  bool gov_return = get_opt_val( argv[i], &opt_name, &opt_val_str );
278  if( gov_return && opt_name == help_opt ) {
279  if(errout) printHelpMessage( argv[0], *errout );
280  return PARSE_HELP_PRINTED;
281  }
282  }
283  // check all other options
284  for( int i = 1; i < argc; ++i ) {
285  bool gov_return = get_opt_val( argv[i], &opt_name, &opt_val_str );
286  if( !gov_return ) {
287  if(procRank == 0)
288  print_bad_opt(i,argv,errout);
289  if( recogniseAllOptions() )
291  else {
292  continue;
293  }
294  }
295  if( opt_name == echo_cl_opt ) {
296  if(errout && procRank == 0) {
297  *errout << "\nEchoing the command-line:\n\n";
298  for( int j = 0; j < argc; ++j )
299  *errout << argv[j] << " ";
300  *errout << "\n\n";
301  }
302  continue;
303  }
304  if( opt_name == pause_opt ) {
305  if(procRank == 0) {
306  std::cerr << "\nType 0 and press enter to continue : ";
307  int dummy_int = 0;
308  std::cin >> dummy_int;
309  }
311  continue;
312  }
313  // Lookup the option (we had better find it!)
314  options_list_t::iterator itr = options_list_.find(opt_name);
315  if( itr == options_list_.end() ) {
316  if(procRank == 0)
317  print_bad_opt(i,argv,errout);
318  if( recogniseAllOptions() )
320  else
321  continue;
322  }
323  // Changed access to second value of std::map to not use overloaded arrow operator,
324  // otherwise this code will not compile on Janus (HKT, 12/01/2003)
325  opt_val_val_t &opt_val_val = (*itr).second;
326  opt_val_val.was_read = true;
327  switch( opt_val_val.opt_type ) {
328  case OPT_BOOL_TRUE:
329  *(any_cast<bool*>(opt_val_val.opt_val)) = true;
330  break;
331  case OPT_BOOL_FALSE:
332  *(any_cast<bool*>(opt_val_val.opt_val)) = false;
333  break;
334  case OPT_INT:
335  *(any_cast<int*>(opt_val_val.opt_val)) = asSafe<int> (opt_val_str);
336  break;
337  case OPT_LONG_INT:
338  *(any_cast<long int*>(opt_val_val.opt_val)) = asSafe<long int> (opt_val_str);
339  break;
340  case OPT_SIZE_T:
341  *(any_cast<size_t *>(opt_val_val.opt_val)) = asSafe<size_t> (opt_val_str);
342  break;
343 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
344  case OPT_LONG_LONG_INT:
345  *(any_cast<long long int*>(opt_val_val.opt_val)) = asSafe<long long int> (opt_val_str);
346  break;
347 #endif
348  case OPT_DOUBLE:
349  *(any_cast<double*>(opt_val_val.opt_val)) = asSafe<double> (opt_val_str);
350  break;
351  case OPT_STRING:
352  *(any_cast<std::string*>(opt_val_val.opt_val)) = remove_quotes(opt_val_str);
353  break;
354  case OPT_ENUM_INT:
355  if( !set_enum_value( i, argv, opt_name, any_cast<int>(opt_val_val.opt_val),
356  remove_quotes(opt_val_str), errout ) )
357  {
359  }
360  break;
361  default:
362  TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
363  }
364  }
365  // Look for options that were required but were not set
366  for(
367  options_list_t::const_iterator itr = options_list_.begin();
368  itr != options_list_.end();
369  ++itr
370  )
371  {
372  const opt_val_val_t &opt_val_val = (*itr).second;
373  if( opt_val_val.required && !opt_val_val.was_read ) {
374  const std::string &opt_val_name = (*itr).first;
375 #define CLP_ERR_MSG \
376  "Error, the option --"<<opt_val_name<<" was required but was not set!"
377  if(errout)
378  *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
379  if( throwExceptions() ) {
380  TEUCHOS_TEST_FOR_EXCEPTION( true, ParseError, CLP_ERR_MSG );
381  }
382  return PARSE_ERROR;
383 #undef CLP_ERR_MSG
384  }
385  }
386  // Set the options of a default stream exists and if we are asked to
389  if (defaultOut.get() && addOutputSetupOptions_) {
390  if (output_all_front_matter_ != output_all_front_matter_default_)
391  defaultOut->setShowAllFrontMatter(output_all_front_matter_);
392  if (output_show_line_prefix_ != output_show_line_prefix_default_)
393  defaultOut->setShowLinePrefix(output_show_line_prefix_);
394  if (output_show_tab_count_ != output_show_tab_count_default_)
395  defaultOut->setShowTabCount(output_show_tab_count_);
396  if (output_show_proc_rank_ != output_show_proc_rank_default_)
397  defaultOut->setShowProcRank(output_show_proc_rank_);
398  if (output_to_root_rank_only_ != output_to_root_rank_only_default_)
399  defaultOut->setOutputToRootOnly(output_to_root_rank_only_);
400  RCPNodeTracer::setPrintRCPNodeStatisticsOnExit(print_rcpnode_statistics_on_exit_);
401  }
402  return PARSE_SUCCESSFUL;
403 }
404 
405 
406 void CommandLineProcessor::printHelpMessage( const char program_name[],
407  std::ostream &out ) const
408 {
409  add_extra_output_setup_options();
410  int procRank = GlobalMPISession::getRank();
411  if (procRank == 0) {
412  using std::setw;
413  using std::endl;
414 
415  const int opt_type_w = 14;
416  const char spc_chars[] = " ";
417 
418  // Get the maximum length of an option name
419  int opt_name_w = 19; // For the 'pause-for-debugging' option
420  options_documentation_list_t::const_iterator itr;
421  for (
422  itr = options_documentation_list_.begin();
423  itr != options_documentation_list_.end();
424  ++itr
425  )
426  {
427  opt_name_w = my_max(opt_name_w,itr->opt_name.length());
428  if( itr->opt_type )
429  opt_name_w = my_max(opt_name_w,itr->opt_name_false.length());
430  }
431  opt_name_w += 2;
432 
433  // Some built-in options
434  out
435  << "Usage: " << program_name << " [options]\n"
436  << spc_chars << "options:\n"
437  << spc_chars
438  << "--"
439 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
440  << std::left << setw(opt_name_w) << "help"
441  << std::left << setw(opt_type_w) << " "
442 #else
443  << std::setiosflags(std::ios::left) << setw(opt_name_w) << "help"
444  << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
445 #endif
446  << "Prints this help message"
447  << std::endl
448  << spc_chars
449  << "--"
450 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
451  << std::left << setw(opt_name_w) << "pause-for-debugging"
452  << std::left << setw(opt_type_w) << " "
453 #else
454  << std::setiosflags(std::ios::left) << setw(opt_name_w) << "pause-for-debugging"
455  << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
456 #endif
457  << "Pauses for user input to allow attaching a debugger"
458  << std::endl
459  << spc_chars
460  << "--"
461 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
462  << std::left << setw(opt_name_w) << "echo-command-line"
463  << std::left << setw(opt_type_w) << " "
464 #else
465  << std::setiosflags(std::ios::left) << setw(opt_name_w) << "echo-command-line"
466  << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
467 #endif
468  << "Echo the command-line but continue as normal"
469  << std::endl;
470  for(
471  itr = options_documentation_list_.begin();
472  itr != options_documentation_list_.end();
473  ++itr )
474  {
475  // print top line with option name, type and short documentation string
476  out
477  << spc_chars
478  << "--"
479 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
480  << std::left << setw(opt_name_w) << itr->opt_name
481  << std::left << setw(opt_type_w) << opt_type_str(itr->opt_type)
482 #else
483  << std::setiosflags(std::ios::left) << setw(opt_name_w) << itr->opt_name
484  << std::setiosflags(std::ios::left) << setw(opt_type_w) << opt_type_str(itr->opt_type)
485 #endif
486  << ( itr->documentation.length() ? itr->documentation.c_str() : "No documentation" )
487  << std::endl;
488  // If an enumeration option then the next line is the value options
489  if( itr->opt_type == OPT_ENUM_INT ) {
490  out
491  << spc_chars
492  << " "
493  << setw(opt_name_w) << ""
494  << setw(opt_type_w) << "";
495  print_enum_opt_names( any_cast<int>(itr->default_val), out );
496  out
497  << std::endl;
498  }
499  // Now print the line that contains the default values
500  if( itr->opt_type == OPT_BOOL_TRUE ) {
501  out
502  << spc_chars
503  << "--"
504  << setw(opt_name_w) << itr->opt_name_false;
505  }
506  else {
507  out
508  << spc_chars
509  << " "
510  << setw(opt_name_w) << " ";
511  }
512  out
513  << setw(opt_type_w) << " "
514  << "(default: ";
515  switch( itr->opt_type ) {
516  case OPT_BOOL_TRUE:
517  out << "--" << ( (*(any_cast<bool*>(itr->default_val))) ?
518  itr->opt_name : itr->opt_name_false );
519  break;
520  case OPT_INT:
521  case OPT_LONG_INT:
522  case OPT_SIZE_T:
523 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
524  case OPT_LONG_LONG_INT:
525 #endif
526  case OPT_DOUBLE:
527  case OPT_STRING:
528  case OPT_ENUM_INT:
529  out << "--" << itr->opt_name;
530  break;
531  default:
532  TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
533  }
534  switch( itr->opt_type ) {
535  case OPT_BOOL_TRUE:
536  break;
537  case OPT_INT:
538  out << "=" << (*(any_cast<int*>(itr->default_val)));
539  break;
540  case OPT_LONG_INT:
541  out << "=" << (*(any_cast<long int*>(itr->default_val)));
542  break;
543  case OPT_SIZE_T:
544  out << "=" << (*(any_cast<size_t*>(itr->default_val)));
545  break;
546 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
547  case OPT_LONG_LONG_INT:
548  out << "=" << (*(any_cast<long long int*>(itr->default_val)));
549  break;
550 #endif
551  case OPT_DOUBLE:
552  out << "=" << (*(any_cast<double*>(itr->default_val)));
553  break;
554  case OPT_STRING:
555  out << "=" << add_quotes(*(any_cast<std::string*>(itr->default_val)));
556  break;
557  case OPT_ENUM_INT:
558  out << "=" << add_quotes(
559  enum_opt_default_val_name(itr->opt_name,any_cast<int>(itr->default_val),&out));
560  break;
561  default:
562  TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
563  }
564  out << ")\n";
565  }
566  if(doc_string_.length()) {
567  out << "\nDETAILED DOCUMENTATION:\n\n" << doc_string_ << std::endl << std::endl;
568  }
569  if(throwExceptions_)
570  TEUCHOS_TEST_FOR_EXCEPTION( true, HelpPrinted, "Help message was printed" );
571  }
572 }
573 
574 
576  const Ptr<std::ostream> &out_inout
577  )
578 {
579  if (!printed_timer_summary_ && show_timer_summary_on_exit_) {
580  RCP<std::ostream> out;
581  if (nonnull(out_inout)) {
582  out = rcpFromPtr(out_inout);
583  }
584  else {
586  }
587  getTimeMonitorSurrogate()->summarize(*out << "\n");
588  printed_timer_summary_ = true;
589  }
590 }
591 
592 
593 // private
594 
595 
596 void CommandLineProcessor::add_extra_output_setup_options() const
597 {
598  if(
599  // Are we in this function already and calling it recursively?
600  in_add_extra_output_setup_options_
601  ||
602  // Have we already setup these options?
603  added_extra_output_setup_options_
604  ||
605  // Are we not supposed to setup these options?
606  !addOutputSetupOptions_
607  )
608  {
609  return; // If any of the above is true, we need to return right away!
610  }
611  // Set the commandline options for this ...
613  *clp = const_cast<CommandLineProcessor*>(this);
614  clp->in_add_extra_output_setup_options_ = true;
615  clp->setOption(
616  "output-all-front-matter","output-no-front-matter",&clp->output_all_front_matter_
617  ,"Set if all front matter is printed to the default FancyOStream or not"
618  );
619  clp->setOption(
620  "output-show-line-prefix","output-no-show-line-prefix",&clp->output_show_line_prefix_
621  ,"Set if the line prefix matter is printed to the default FancyOStream or not"
622  );
623  clp->setOption(
624  "output-show-tab-count","output-no-show-tab-count",&clp->output_show_tab_count_
625  ,"Set if the tab count is printed to the default FancyOStream or not"
626  );
627  clp->setOption(
628  "output-show-proc-rank","output-no-show-proc-rank",&clp->output_show_proc_rank_
629  ,"Set if the processor rank is printed to the default FancyOStream or not"
630  );
631  clp->setOption(
632  "output-to-root-rank-only",&clp->output_to_root_rank_only_
633  ,"Set which processor (the root) gets the output. If < 0, then all processors get output."
634  );
635  clp->setOption(
636  "print-rcpnode-statistics-on-exit", "no-print-rcpnode-statistics-on-exit",
637  &clp->print_rcpnode_statistics_on_exit_,
638  "Set if the RCPNode usage statistics will be printed on exit or not. Warning,"
639  " this prints to std::cerr or every process so do not turn this on for very large"
640  " parallel runs."
641  );
642  if (nonnull(getTimeMonitorSurrogate())) {
643  clp->setOption(
644  "show-timer-summary", "no-show-timer-sumary", &clp->show_timer_summary_on_exit_,
645  "If true, then Teuchos::TimeMonitor::summarize() is called in"
646  " CommandLineProcessor's destructor (usually at the end of main)."
647  );
648  }
649 
650  clp->added_extra_output_setup_options_ = true;
651  clp->in_add_extra_output_setup_options_ = false;
652 }
653 
654 
655 void CommandLineProcessor::setEnumOption(
656  const char enum_option_name[]
657  ,int *enum_option_val
658  ,const int num_enum_opt_values
659  ,const int enum_opt_values[]
660  ,const char* enum_opt_names[]
661  ,const char documentation[]
662  ,const bool required
663  )
664 {
665  add_extra_output_setup_options();
666 
667  TEUCHOS_TEST_FOR_EXCEPT(enum_option_val==NULL);
668  TEUCHOS_TEST_FOR_EXCEPT(num_enum_opt_values<=0);
669  TEUCHOS_TEST_FOR_EXCEPT(enum_opt_values==NULL);
670  TEUCHOS_TEST_FOR_EXCEPT(enum_opt_names==NULL);
671 
672  enum_opt_data_list_.push_back(
673  enum_opt_data_t(enum_option_val,num_enum_opt_values,enum_opt_values,enum_opt_names)
674  );
675  const int opt_id = enum_opt_data_list_.size()-1;
676  options_list_[std::string(enum_option_name)]
677  = opt_val_val_t(OPT_ENUM_INT,any(opt_id),required);
678  options_documentation_list_.push_back(
679  opt_doc_t(OPT_ENUM_INT,enum_option_name, "",
680  std::string(documentation?documentation:""), any(opt_id))
681  );
682 }
683 
684 
685 bool CommandLineProcessor::set_enum_value(
686  int argv_i
687  ,char* argv[]
688  ,const std::string &enum_opt_name
689  ,const int enum_id
690  ,const std::string &enum_str_val
691  ,std::ostream *errout
692  ) const
693 {
694  const enum_opt_data_t
695  &enum_opt_data = enum_opt_data_list_.at(enum_id);
696  std::vector<std::string>::const_iterator
697  itr_begin = enum_opt_data.enum_opt_names.begin(),
698  itr_end = enum_opt_data.enum_opt_names.end(),
699  itr = std::find( itr_begin, itr_end, enum_str_val );
700  if( itr == itr_end ) {
701  const int j = argv_i;
702 #define CLP_ERR_MSG \
703  "Error, the value \"" << enum_str_val << "\" for the " \
704  << j<<(j==1?"st":(j==2?"nd":(j==3?"rd":"th"))) << " option --" \
705  << enum_opt_name << " was not recognized (use --help)!"
706  if(errout)
707  *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
708  if( throwExceptions() ) {
709  TEUCHOS_TEST_FOR_EXCEPTION( true, UnrecognizedOption, CLP_ERR_MSG );
710  }
711  else {
712  return false;
713  }
714 #undef CLP_ERR_MSG
715  }
716  const int enum_opt_val_index = itr - itr_begin;
717  *enum_opt_data.enum_option_val = enum_opt_data.enum_opt_values.at(enum_opt_val_index);
718  return true;
719 }
720 
721 
722 void CommandLineProcessor::print_enum_opt_names(
723  const int enum_id
724  ,std::ostream &out
725  ) const
726 {
727  const enum_opt_data_t
728  &enum_opt_data = enum_opt_data_list_.at(enum_id);
729  typedef std::vector<std::string>::const_iterator itr_t;
730  out << "Valid options:";
731  for(
732  itr_t itr = enum_opt_data.enum_opt_names.begin();
733  itr != enum_opt_data.enum_opt_names.end();
734  ++itr
735  )
736  {
737  if( itr != enum_opt_data.enum_opt_names.begin() ) out << ",";
738  out << " " << add_quotes(*itr);
739  }
740 }
741 
742 
743 std::string
744 CommandLineProcessor::enum_opt_default_val_name(
745  const std::string &enum_name
746  ,const int enum_id
747  ,std::ostream *errout
748  ) const
749 {
750  const enum_opt_data_t
751  &enum_opt_data = enum_opt_data_list_.at(enum_id);
752  return enum_opt_data.enum_opt_names.at(
753  find_enum_opt_index(
754  enum_name,*enum_opt_data.enum_option_val,enum_opt_data,errout
755  )
756  );
757 }
758 
759 
760 int CommandLineProcessor::find_enum_opt_index(
761  const std::string &enum_opt_name
762  ,const int opt_value
763  ,const enum_opt_data_t &enum_data
764  ,std::ostream *errout
765  ) const
766 {
767  std::vector<int>::const_iterator
768  itr_begin = enum_data.enum_opt_values.begin(),
769  itr_end = enum_data.enum_opt_values.end(),
770  itr = std::find( itr_begin, itr_end, opt_value );
771  if( itr == itr_end ) {
772 #define CLP_ERR_MSG \
773  ( recogniseAllOptions() ? "Error" : "Warning" ) \
774  << ", option --" << enum_opt_name << " was given an invalid " \
775  "initial option value of " << opt_value << "!"
776  if(errout)
777  *errout << CLP_ERR_MSG << std::endl;
778  if( throwExceptions() )
779  TEUCHOS_TEST_FOR_EXCEPTION( true, std::invalid_argument, CLP_ERR_MSG );
780 #undef CLP_ERR_MSG
781  }
782  return itr - itr_begin;
783 }
784 
785 
786 bool CommandLineProcessor::get_opt_val(
787  const char str[]
788  ,std::string *opt_name
789  ,std::string *opt_val_str
790  ) const
791 {
792  const int len = std::strlen(str);
793  if( len < 3 )
794  return false; // Can't be an option with '--' followed by at least one char
795  if( str[0] != '-' || str[1] != '-' )
796  return false; // Not a recognised option
797  // Find the '='
798  int equ_i;
799  for( equ_i = 2; equ_i < len && str[equ_i] != '='; ++equ_i );
800  // Set opt_name
801  opt_name->assign( str + 2, equ_i-2 );
802  // Set opt_val_str
803  if( equ_i == len ) {
804  *opt_val_str = "";
805  }
806  else {
807  opt_val_str->assign( str + equ_i + 1, len - equ_i - 1 );
808  }
809  return true;
810 }
811 
812 void CommandLineProcessor::print_bad_opt(
813  int argv_i
814  ,char* argv[]
815  ,std::ostream *errout
816  ) const
817 {
818  const int j = argv_i;
819 #define CLP_ERR_MSG \
820  ( recogniseAllOptions() ? "Error" : "Warning" ) \
821  << ", the " << j<<(j==1?"st":(j==2?"nd":(j==3?"rd":"th"))) \
822  << " option \'" << argv[argv_i] << "\' was not recognized (use --help)!"
823  if(errout)
824  *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
826  TEUCHOS_TEST_FOR_EXCEPTION( true, UnrecognizedOption, CLP_ERR_MSG );
827 #undef CLP_ERR_MSG
828 }
829 
830 
831 // Hidden stuff
832 
833 
834 void CommandLineProcessor::setTimeMonitorSurrogate(
835  const RCP<CommandLineProcessor::TimeMonitorSurrogate> &timeMonitorSurrogate)
836 {
837  getRawTimeMonitorSurrogate() = timeMonitorSurrogate;
838 }
839 
840 
842 CommandLineProcessor::getTimeMonitorSurrogate()
843 {
844  return getRawTimeMonitorSurrogate();
845 }
846 
847 
849 CommandLineProcessor::getRawTimeMonitorSurrogate()
850 {
851  static RCP<TimeMonitorSurrogate> timeMonitorSurrogate;
852  return timeMonitorSurrogate;
853 }
854 
855 
856 } // end namespace Teuchos
static int getRank()
The rank of the calling process in MPI_COMM_WORLD.
Thrown if –help was specified and throwExceptions==true.
bool nonnull(const std::shared_ptr< T > &p)
Returns true if p.get()!=NULL.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
bool recogniseAllOptions() const
Returns true if all options must be recognized by the parser.
static void setPrintRCPNodeStatisticsOnExit(bool printRCPNodeStatisticsOnExit)
Set if RCPNode usage statistics will be printed when the program ends or not.
CommandLineProcessor(bool throwExceptions=true, bool recogniseAllOptions=true, bool addOutputSetupOptions=false)
Default Constructor.
Modified boost::any class, which is a container for a templated value.
Definition: Teuchos_any.hpp:86
T * get() const
Get the raw C++ pointer to the underlying object.
Thrown if an unrecognized option was found and throwExceptions==true.
void setOption(const char option_true[], const char option_false[], bool *option_val, const char documentation[]=NULL)
Set a boolean option.
EParseCommandLineReturn parse(int argc, char *argv[], std::ostream *errout=&std::cerr) const
Parse a command line.
static RCP< FancyOStream > getDefaultOStream()
Get the default output stream object.
EParseCommandLineReturn
Return value for CommandLineProcessor::parse(). Note: These enums are all given non-negative values s...
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos, as well as a number of utility routines.
A MPI utilities class, providing methods for initializing, finalizing, and querying the global MPI se...
Basic command line parser for input from (argc,argv[])
void setDocString(const char doc_string[])
Set a documentation sting for the entire program printed when –help is specified.
bool throwExceptions() const
Returns true if an std::exception is thrown, there is a parse error, or help is printed.
void printHelpMessage(const char program_name[], std::ostream &out) const
Print the help message.
static void barrier()
Call MPI_Barrier() on MPI_COMM_WORLD.
Smart reference counting pointer class for automatic garbage collection.
void printFinalTimerSummary(const Ptr< std::ostream > &out=null)
Call to print timers so that they don&#39;t get printed in the destructor.
Definition of Teuchos::as, for conversions between types.
Thrown if a parse std::exception occurs and throwExceptions==true.
Class that helps parse command line input arguments from (argc,argv[]) and set options.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
This macro is designed to be a short version of TEUCHOS_TEST_FOR_EXCEPTION() that is easier to call...
Simple wrapper class for raw pointers to single objects where no persisting relationship exists...