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 #ifndef _WIN32
53 #include "Teuchos_Array.hpp"
54 #include "unistd.h"
55 #endif
56 
57 namespace {
58 
59 
60 inline int my_max( int a, int b ) { return a > b ? a : b; }
61 
62 
63 std::string remove_quotes( const std::string& str )
64 {
65  if(str[0] != '\"')
66  return str;
67  return str.substr(1,str.size()-2);
68 }
69 
70 
71 std::string add_quotes( const std::string& str )
72 {
73  if(str[0] == '\"')
74  return str;
75  return "\"" + str + "\"";
76 }
77 
78 
79 } // end namespace
80 
81 
82 namespace Teuchos {
83 
84 
85 const bool CommandLineProcessor::output_all_front_matter_default_(false);
86 const bool CommandLineProcessor::output_show_line_prefix_default_(false);
87 const bool CommandLineProcessor::output_show_tab_count_default_(false);
88 const bool CommandLineProcessor::output_show_proc_rank_default_(false);
89 const int CommandLineProcessor::output_to_root_rank_only_default_(0);
90 const bool CommandLineProcessor::print_rcpnode_statistics_on_exit_default_(false);
91 const bool CommandLineProcessor::show_timer_summary_on_exit_default_(false);
92 
93 
95  bool throwExceptions_in
96  ,bool recogniseAllOptions_in
97  ,bool addOutputSetupOptions_in
98  )
99  :throwExceptions_(throwExceptions_in)
100  ,recogniseAllOptions_(recogniseAllOptions_in)
101  ,addOutputSetupOptions_(addOutputSetupOptions_in)
102  ,output_all_front_matter_(output_all_front_matter_default_)
103  ,output_show_line_prefix_(output_show_line_prefix_default_)
104  ,output_show_tab_count_(output_show_tab_count_default_)
105  ,output_show_proc_rank_(output_show_proc_rank_default_)
106  ,output_to_root_rank_only_(output_to_root_rank_only_default_)
107  ,print_rcpnode_statistics_on_exit_(print_rcpnode_statistics_on_exit_default_)
108  ,show_timer_summary_on_exit_(show_timer_summary_on_exit_default_)
109  ,printed_timer_summary_(false)
110  ,added_extra_output_setup_options_(false)
111  ,in_add_extra_output_setup_options_(false)
112 {}
113 
114 
116 {
118 }
119 
120 
121 // Set up options
122 
123 
124 void CommandLineProcessor::setDocString( const char doc_string[] )
125 {
126  doc_string_ = doc_string;
127 }
128 
129 
131  const char option_true[]
132  ,const char option_false[]
133  ,bool *option_val
134  ,const char documentation[]
135  )
136 {
137  add_extra_output_setup_options();
138  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
139  options_list_[std::string(option_true)]
140  = opt_val_val_t(OPT_BOOL_TRUE,any(option_val),false);
141  options_list_[std::string(option_false)]
142  = opt_val_val_t(OPT_BOOL_FALSE,any(option_val),false);
143  options_documentation_list_.push_back(
144  opt_doc_t(OPT_BOOL_TRUE, option_true, option_false,
145  std::string(documentation?documentation:""), any(option_val))
146  );
147 }
148 
149 
151  const char option_name[]
152  ,int *option_val
153  ,const char documentation[]
154  ,const bool required
155  )
156 {
157  add_extra_output_setup_options();
158  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
159  options_list_[std::string(option_name)]
160  = opt_val_val_t(OPT_INT,any(option_val),required);
161  options_documentation_list_.push_back(
162  opt_doc_t(OPT_INT, option_name, "", std::string(documentation?documentation:""),
163  any(option_val))
164  );
165 }
166 
167 
169  const char option_name[]
170  ,long int *option_val
171  ,const char documentation[]
172  ,const bool required
173  )
174 {
175  add_extra_output_setup_options();
176  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
177  options_list_[std::string(option_name)]
178  = opt_val_val_t(OPT_LONG_INT,any(option_val),required);
179  options_documentation_list_.push_back(
180  opt_doc_t(OPT_LONG_INT, option_name, "", std::string(documentation?documentation:""),
181  any(option_val))
182  );
183 }
184 
185 
187  const char option_name[]
188  ,size_t *option_val
189  ,const char documentation[]
190  ,const bool required
191  )
192 {
193  add_extra_output_setup_options();
194  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
195  options_list_[std::string(option_name)]
196  = opt_val_val_t(OPT_SIZE_T,any(option_val),required);
197  options_documentation_list_.push_back(
198  opt_doc_t(OPT_SIZE_T, option_name, "", std::string(documentation?documentation:""),
199  any(option_val))
200  );
201 }
202 
204  const char option_name[]
205  ,long long int *option_val
206  ,const char documentation[]
207  ,const bool required
208  )
209 {
210  add_extra_output_setup_options();
211  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
212  options_list_[std::string(option_name)]
213  = opt_val_val_t(OPT_LONG_LONG_INT,any(option_val),required);
214  options_documentation_list_.push_back(
215  opt_doc_t(OPT_LONG_LONG_INT, option_name, "", std::string(documentation?documentation:""),
216  any(option_val))
217  );
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 #ifndef _WIN32
306  Array<int> pids;
308  int rank_pid = getpid();
309  GlobalMPISession::allGather(rank_pid,pids());
310  if(procRank == 0)
311  for (int k=0; k<GlobalMPISession::getNProc(); k++)
312  std::cerr << "Rank " << k << " has PID " << pids[k] << std::endl;
313 #endif
314  if(procRank == 0) {
315  std::cerr << "\nType 0 and press enter to continue : ";
316  int dummy_int = 0;
317  std::cin >> dummy_int;
318  }
320  continue;
321  }
322  // Lookup the option (we had better find it!)
323  options_list_t::iterator itr = options_list_.find(opt_name);
324  if( itr == options_list_.end() ) {
325  if(procRank == 0)
326  print_bad_opt(i,argv,errout);
327  if( recogniseAllOptions() )
329  else
330  continue;
331  }
332  // Changed access to second value of std::map to not use overloaded arrow operator,
333  // otherwise this code will not compile on Janus (HKT, 12/01/2003)
334  opt_val_val_t &opt_val_val = (*itr).second;
335  opt_val_val.was_read = true;
336  switch( opt_val_val.opt_type ) {
337  case OPT_BOOL_TRUE:
338  *(any_cast<bool*>(opt_val_val.opt_val)) = true;
339  break;
340  case OPT_BOOL_FALSE:
341  *(any_cast<bool*>(opt_val_val.opt_val)) = false;
342  break;
343  case OPT_INT:
344  *(any_cast<int*>(opt_val_val.opt_val)) = asSafe<int> (opt_val_str);
345  break;
346  case OPT_LONG_INT:
347  *(any_cast<long int*>(opt_val_val.opt_val)) = asSafe<long int> (opt_val_str);
348  break;
349  case OPT_SIZE_T:
350  *(any_cast<size_t *>(opt_val_val.opt_val)) = asSafe<size_t> (opt_val_str);
351  break;
352  case OPT_LONG_LONG_INT:
353  *(any_cast<long long int*>(opt_val_val.opt_val)) = asSafe<long long int> (opt_val_str);
354  break;
355  case OPT_DOUBLE:
356  *(any_cast<double*>(opt_val_val.opt_val)) = asSafe<double> (opt_val_str);
357  break;
358  case OPT_STRING:
359  *(any_cast<std::string*>(opt_val_val.opt_val)) = remove_quotes(opt_val_str);
360  break;
361  case OPT_ENUM_INT:
362  if( !set_enum_value( i, argv, opt_name, any_cast<int>(opt_val_val.opt_val),
363  remove_quotes(opt_val_str), errout ) )
364  {
366  }
367  break;
368  default:
369  TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
370  }
371  }
372  // Look for options that were required but were not set
373  for(
374  options_list_t::const_iterator itr = options_list_.begin();
375  itr != options_list_.end();
376  ++itr
377  )
378  {
379  const opt_val_val_t &opt_val_val = (*itr).second;
380  if( opt_val_val.required && !opt_val_val.was_read ) {
381  const std::string &opt_val_name = (*itr).first;
382 #define CLP_ERR_MSG \
383  "Error, the option --"<<opt_val_name<<" was required but was not set!"
384  if(errout)
385  *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
386  if( throwExceptions() ) {
387  TEUCHOS_TEST_FOR_EXCEPTION( true, ParseError, CLP_ERR_MSG );
388  }
389  return PARSE_ERROR;
390 #undef CLP_ERR_MSG
391  }
392  }
393  // Set the options of a default stream exists and if we are asked to
396  if (defaultOut.get() && addOutputSetupOptions_) {
397  if (output_all_front_matter_ != output_all_front_matter_default_)
398  defaultOut->setShowAllFrontMatter(output_all_front_matter_);
399  if (output_show_line_prefix_ != output_show_line_prefix_default_)
400  defaultOut->setShowLinePrefix(output_show_line_prefix_);
401  if (output_show_tab_count_ != output_show_tab_count_default_)
402  defaultOut->setShowTabCount(output_show_tab_count_);
403  if (output_show_proc_rank_ != output_show_proc_rank_default_)
404  defaultOut->setShowProcRank(output_show_proc_rank_);
405  if (output_to_root_rank_only_ != output_to_root_rank_only_default_)
406  defaultOut->setOutputToRootOnly(output_to_root_rank_only_);
407  RCPNodeTracer::setPrintRCPNodeStatisticsOnExit(print_rcpnode_statistics_on_exit_);
408  }
409  return PARSE_SUCCESSFUL;
410 }
411 
412 
413 void CommandLineProcessor::printHelpMessage( const char program_name[],
414  std::ostream &out ) const
415 {
416  add_extra_output_setup_options();
417  int procRank = GlobalMPISession::getRank();
418  if (procRank == 0) {
419  using std::setw;
420  using std::endl;
421 
422  const int opt_type_w = 14;
423  const char spc_chars[] = " ";
424 
425  // Get the maximum length of an option name
426  int opt_name_w = 19; // For the 'pause-for-debugging' option
427  options_documentation_list_t::const_iterator itr;
428  for (
429  itr = options_documentation_list_.begin();
430  itr != options_documentation_list_.end();
431  ++itr
432  )
433  {
434  opt_name_w = my_max(opt_name_w,static_cast<int>(itr->opt_name.length()));
435  if( itr->opt_type )
436  opt_name_w = my_max(opt_name_w,static_cast<int>(itr->opt_name_false.length()));
437  }
438  opt_name_w += 2;
439 
440  // Some built-in options
441  out
442  << "Usage: " << program_name << " [options]\n"
443  << spc_chars << "options:\n"
444  << spc_chars
445  << "--"
446 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
447  << std::left << setw(opt_name_w) << "help"
448  << std::left << setw(opt_type_w) << " "
449 #else
450  << std::setiosflags(std::ios::left) << setw(opt_name_w) << "help"
451  << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
452 #endif
453  << "Prints this help message"
454  << std::endl
455  << spc_chars
456  << "--"
457 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
458  << std::left << setw(opt_name_w) << "pause-for-debugging"
459  << std::left << setw(opt_type_w) << " "
460 #else
461  << std::setiosflags(std::ios::left) << setw(opt_name_w) << "pause-for-debugging"
462  << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
463 #endif
464  << "Pauses for user input to allow attaching a debugger"
465  << std::endl
466  << spc_chars
467  << "--"
468 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
469  << std::left << setw(opt_name_w) << "echo-command-line"
470  << std::left << setw(opt_type_w) << " "
471 #else
472  << std::setiosflags(std::ios::left) << setw(opt_name_w) << "echo-command-line"
473  << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
474 #endif
475  << "Echo the command-line but continue as normal"
476  << std::endl;
477  for(
478  itr = options_documentation_list_.begin();
479  itr != options_documentation_list_.end();
480  ++itr )
481  {
482  // print top line with option name, type and short documentation string
483  out
484  << spc_chars
485  << "--"
486 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
487  << std::left << setw(opt_name_w) << itr->opt_name
488  << std::left << setw(opt_type_w) << opt_type_str(itr->opt_type)
489 #else
490  << std::setiosflags(std::ios::left) << setw(opt_name_w) << itr->opt_name
491  << std::setiosflags(std::ios::left) << setw(opt_type_w) << opt_type_str(itr->opt_type)
492 #endif
493  << ( itr->documentation.length() ? itr->documentation.c_str() : "No documentation" )
494  << std::endl;
495  // If an enumeration option then the next line is the value options
496  if( itr->opt_type == OPT_ENUM_INT ) {
497  out
498  << spc_chars
499  << " "
500  << setw(opt_name_w) << ""
501  << setw(opt_type_w) << "";
502  print_enum_opt_names( any_cast<int>(itr->default_val), out );
503  out
504  << std::endl;
505  }
506  // Now print the line that contains the default values
507  if( itr->opt_type == OPT_BOOL_TRUE ) {
508  out
509  << spc_chars
510  << "--"
511  << setw(opt_name_w) << itr->opt_name_false;
512  }
513  else {
514  out
515  << spc_chars
516  << " "
517  << setw(opt_name_w) << " ";
518  }
519  out
520  << setw(opt_type_w) << " "
521  << "(default: ";
522  switch( itr->opt_type ) {
523  case OPT_BOOL_TRUE:
524  out << "--" << ( (*(any_cast<bool*>(itr->default_val))) ?
525  itr->opt_name : itr->opt_name_false );
526  break;
527  case OPT_INT:
528  case OPT_LONG_INT:
529  case OPT_SIZE_T:
530  case OPT_LONG_LONG_INT:
531  case OPT_DOUBLE:
532  case OPT_STRING:
533  case OPT_ENUM_INT:
534  out << "--" << itr->opt_name;
535  break;
536  default:
537  TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
538  }
539  switch( itr->opt_type ) {
540  case OPT_BOOL_TRUE:
541  break;
542  case OPT_INT:
543  out << "=" << (*(any_cast<int*>(itr->default_val)));
544  break;
545  case OPT_LONG_INT:
546  out << "=" << (*(any_cast<long int*>(itr->default_val)));
547  break;
548  case OPT_SIZE_T:
549  out << "=" << (*(any_cast<size_t*>(itr->default_val)));
550  break;
551  case OPT_LONG_LONG_INT:
552  out << "=" << (*(any_cast<long long int*>(itr->default_val)));
553  break;
554  case OPT_DOUBLE:
555  out << "=" << (*(any_cast<double*>(itr->default_val)));
556  break;
557  case OPT_STRING:
558  out << "=" << add_quotes(*(any_cast<std::string*>(itr->default_val)));
559  break;
560  case OPT_ENUM_INT:
561  out << "=" << add_quotes(
562  enum_opt_default_val_name(itr->opt_name,any_cast<int>(itr->default_val),&out));
563  break;
564  default:
565  TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
566  }
567  out << ")\n";
568  }
569  if(doc_string_.length()) {
570  out << "\nDETAILED DOCUMENTATION:\n\n" << doc_string_ << std::endl << std::endl;
571  }
572  if(throwExceptions_)
573  TEUCHOS_TEST_FOR_EXCEPTION( true, HelpPrinted, "Help message was printed" );
574  }
575 }
576 
577 
579  const Ptr<std::ostream> &out_inout
580  )
581 {
582  if (!printed_timer_summary_ && show_timer_summary_on_exit_) {
583  RCP<std::ostream> out;
584  if (nonnull(out_inout)) {
585  out = rcpFromPtr(out_inout);
586  }
587  else {
589  }
590  getTimeMonitorSurrogate()->summarize(*out << "\n");
591  printed_timer_summary_ = true;
592  }
593 }
594 
595 
596 // private
597 
598 
599 void CommandLineProcessor::add_extra_output_setup_options() const
600 {
601  if(
602  // Are we in this function already and calling it recursively?
603  in_add_extra_output_setup_options_
604  ||
605  // Have we already setup these options?
606  added_extra_output_setup_options_
607  ||
608  // Are we not supposed to setup these options?
609  !addOutputSetupOptions_
610  )
611  {
612  return; // If any of the above is true, we need to return right away!
613  }
614  // Set the commandline options for this ...
616  *clp = const_cast<CommandLineProcessor*>(this);
617  clp->in_add_extra_output_setup_options_ = true;
618  clp->setOption(
619  "output-all-front-matter","output-no-front-matter",&clp->output_all_front_matter_
620  ,"Set if all front matter is printed to the default FancyOStream or not"
621  );
622  clp->setOption(
623  "output-show-line-prefix","output-no-show-line-prefix",&clp->output_show_line_prefix_
624  ,"Set if the line prefix matter is printed to the default FancyOStream or not"
625  );
626  clp->setOption(
627  "output-show-tab-count","output-no-show-tab-count",&clp->output_show_tab_count_
628  ,"Set if the tab count is printed to the default FancyOStream or not"
629  );
630  clp->setOption(
631  "output-show-proc-rank","output-no-show-proc-rank",&clp->output_show_proc_rank_
632  ,"Set if the processor rank is printed to the default FancyOStream or not"
633  );
634  clp->setOption(
635  "output-to-root-rank-only",&clp->output_to_root_rank_only_
636  ,"Set which processor (the root) gets the output. If < 0, then all processors get output."
637  );
638  clp->setOption(
639  "print-rcpnode-statistics-on-exit", "no-print-rcpnode-statistics-on-exit",
640  &clp->print_rcpnode_statistics_on_exit_,
641  "Set if the RCPNode usage statistics will be printed on exit or not. Warning,"
642  " this prints to std::cerr or every process so do not turn this on for very large"
643  " parallel runs."
644  );
645  if (nonnull(getTimeMonitorSurrogate())) {
646  clp->setOption(
647  "show-timer-summary", "no-show-timer-sumary", &clp->show_timer_summary_on_exit_,
648  "If true, then Teuchos::TimeMonitor::summarize() is called in"
649  " CommandLineProcessor's destructor (usually at the end of main)."
650  );
651  }
652 
653  clp->added_extra_output_setup_options_ = true;
654  clp->in_add_extra_output_setup_options_ = false;
655 }
656 
657 
658 void CommandLineProcessor::setEnumOption(
659  const char enum_option_name[]
660  ,int *enum_option_val
661  ,const int num_enum_opt_values
662  ,const int enum_opt_values[]
663  ,const char* enum_opt_names[]
664  ,const char documentation[]
665  ,const bool required
666  )
667 {
668  add_extra_output_setup_options();
669 
670  TEUCHOS_TEST_FOR_EXCEPT(enum_option_val==NULL);
671  TEUCHOS_TEST_FOR_EXCEPT(num_enum_opt_values<=0);
672  TEUCHOS_TEST_FOR_EXCEPT(enum_opt_values==NULL);
673  TEUCHOS_TEST_FOR_EXCEPT(enum_opt_names==NULL);
674 
675  enum_opt_data_list_.push_back(
676  enum_opt_data_t(enum_option_val,num_enum_opt_values,enum_opt_values,enum_opt_names)
677  );
678  const int opt_id = static_cast<int>(enum_opt_data_list_.size())-1;
679  options_list_[std::string(enum_option_name)]
680  = opt_val_val_t(OPT_ENUM_INT,any(opt_id),required);
681  options_documentation_list_.push_back(
682  opt_doc_t(OPT_ENUM_INT,enum_option_name, "",
683  std::string(documentation?documentation:""), any(opt_id))
684  );
685 }
686 
687 
688 bool CommandLineProcessor::set_enum_value(
689  int argv_i
690  ,char* argv[]
691  ,const std::string &enum_opt_name
692  ,const int enum_id
693  ,const std::string &enum_str_val
694  ,std::ostream *errout
695  ) const
696 {
697  const enum_opt_data_t
698  &enum_opt_data = enum_opt_data_list_.at(enum_id);
699  std::vector<std::string>::const_iterator
700  itr_begin = enum_opt_data.enum_opt_names.begin(),
701  itr_end = enum_opt_data.enum_opt_names.end(),
702  itr = std::find( itr_begin, itr_end, enum_str_val );
703  if( itr == itr_end ) {
704  const int j = argv_i;
705 #define CLP_ERR_MSG \
706  "Error, the value \"" << enum_str_val << "\" for the " \
707  << j<<(j==1?"st":(j==2?"nd":(j==3?"rd":"th"))) << " option --" \
708  << enum_opt_name << " was not recognized (use --help)!"
709  if(errout)
710  *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
711  if( throwExceptions() ) {
712  TEUCHOS_TEST_FOR_EXCEPTION( true, UnrecognizedOption, CLP_ERR_MSG );
713  }
714  else {
715  return false;
716  }
717 #undef CLP_ERR_MSG
718  }
719  const int enum_opt_val_index = static_cast<int>(itr - itr_begin);
720  *enum_opt_data.enum_option_val = enum_opt_data.enum_opt_values.at(enum_opt_val_index);
721  return true;
722 }
723 
724 
725 void CommandLineProcessor::print_enum_opt_names(
726  const int enum_id
727  ,std::ostream &out
728  ) const
729 {
730  const enum_opt_data_t
731  &enum_opt_data = enum_opt_data_list_.at(enum_id);
732  typedef std::vector<std::string>::const_iterator itr_t;
733  out << "Valid options:";
734  for(
735  itr_t itr = enum_opt_data.enum_opt_names.begin();
736  itr != enum_opt_data.enum_opt_names.end();
737  ++itr
738  )
739  {
740  if( itr != enum_opt_data.enum_opt_names.begin() ) out << ",";
741  out << " " << add_quotes(*itr);
742  }
743 }
744 
745 
746 std::string
747 CommandLineProcessor::enum_opt_default_val_name(
748  const std::string &enum_name
749  ,const int enum_id
750  ,std::ostream *errout
751  ) const
752 {
753  const enum_opt_data_t
754  &enum_opt_data = enum_opt_data_list_.at(enum_id);
755  return enum_opt_data.enum_opt_names.at(
756  find_enum_opt_index(
757  enum_name,*enum_opt_data.enum_option_val,enum_opt_data,errout
758  )
759  );
760 }
761 
762 
763 int CommandLineProcessor::find_enum_opt_index(
764  const std::string &enum_opt_name
765  ,const int opt_value
766  ,const enum_opt_data_t &enum_data
767  ,std::ostream *errout
768  ) const
769 {
770  std::vector<int>::const_iterator
771  itr_begin = enum_data.enum_opt_values.begin(),
772  itr_end = enum_data.enum_opt_values.end(),
773  itr = std::find( itr_begin, itr_end, opt_value );
774  if( itr == itr_end ) {
775 #define CLP_ERR_MSG \
776  ( recogniseAllOptions() ? "Error" : "Warning" ) \
777  << ", option --" << enum_opt_name << " was given an invalid " \
778  "initial option value of " << opt_value << "!"
779  if(errout)
780  *errout << CLP_ERR_MSG << std::endl;
781  if( throwExceptions() )
782  TEUCHOS_TEST_FOR_EXCEPTION( true, std::invalid_argument, CLP_ERR_MSG );
783 #undef CLP_ERR_MSG
784  }
785  return static_cast<int>(itr - itr_begin);
786 }
787 
788 
789 bool CommandLineProcessor::get_opt_val(
790  const char str[]
791  ,std::string *opt_name
792  ,std::string *opt_val_str
793  ) const
794 {
795  const int len = static_cast<int>(std::strlen(str));
796  if( len < 3 )
797  return false; // Can't be an option with '--' followed by at least one char
798  if( str[0] != '-' || str[1] != '-' )
799  return false; // Not a recognised option
800  // Find the '='
801  int equ_i;
802  for( equ_i = 2; equ_i < len && str[equ_i] != '='; ++equ_i );
803  // Set opt_name
804  opt_name->assign( str + 2, equ_i-2 );
805  // Set opt_val_str
806  if( equ_i == len ) {
807  *opt_val_str = "";
808  }
809  else {
810  opt_val_str->assign( str + equ_i + 1, len - equ_i - 1 );
811  }
812  return true;
813 }
814 
815 void CommandLineProcessor::print_bad_opt(
816  int argv_i
817  ,char* argv[]
818  ,std::ostream *errout
819  ) const
820 {
821  const int j = argv_i;
822 #define CLP_ERR_MSG \
823  ( recogniseAllOptions() ? "Error" : "Warning" ) \
824  << ", the " << j<<(j==1?"st":(j==2?"nd":(j==3?"rd":"th"))) \
825  << " option \'" << argv[argv_i] << "\' was not recognized (use --help)!"
826  if(errout)
827  *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
829  TEUCHOS_TEST_FOR_EXCEPTION( true, UnrecognizedOption, CLP_ERR_MSG );
830 #undef CLP_ERR_MSG
831 }
832 
833 
834 // Hidden stuff
835 
836 
837 void CommandLineProcessor::setTimeMonitorSurrogate(
838  const RCP<CommandLineProcessor::TimeMonitorSurrogate> &timeMonitorSurrogate)
839 {
840  getRawTimeMonitorSurrogate() = timeMonitorSurrogate;
841 }
842 
843 
844 RCP<CommandLineProcessor::TimeMonitorSurrogate>
845 CommandLineProcessor::getTimeMonitorSurrogate()
846 {
847  return getRawTimeMonitorSurrogate();
848 }
849 
850 
851 RCP<CommandLineProcessor::TimeMonitorSurrogate>&
852 CommandLineProcessor::getRawTimeMonitorSurrogate()
853 {
854  static RCP<TimeMonitorSurrogate> timeMonitorSurrogate;
855  return timeMonitorSurrogate;
856 }
857 
858 
859 } // end namespace Teuchos
static int getRank()
The rank of the calling process in MPI_COMM_WORLD.
Thrown if –help was specified and throwExceptions==true.
static int getNProc()
The number of processes in MPI_COMM_WORLD.
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.
T * get() const
Get the raw C++ pointer to the underlying object.
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.
void resize(size_type new_size, const value_type &x=value_type())
EParseCommandLineReturn
Return value for CommandLineProcessor::parse(). Note: These enums are all given non-negative values s...
Templated array class derived from the STL std::vector.
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.
static void allGather(int localVal, const ArrayView< int > &allVals)
Global all-to-all of a set of integers across processes.
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.
#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...