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 
238  const char option_name[]
239  ,float *option_val
240  ,const char documentation[]
241  ,const bool required
242  )
243 {
244  add_extra_output_setup_options();
245  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
246  options_list_[std::string(option_name)]
247  = opt_val_val_t(OPT_FLOAT,any(option_val),required);
248  options_documentation_list_.push_back(
249  opt_doc_t(OPT_FLOAT, option_name, "", std::string(documentation?documentation:""),
250  any(option_val))
251  );
252 }
253 
255  const char option_name[]
256  ,std::string *option_val
257  ,const char documentation[]
258  ,const bool required
259  )
260 {
261  add_extra_output_setup_options();
262  TEUCHOS_TEST_FOR_EXCEPT(!(option_val!=NULL));
263  options_list_[std::string(option_name)]
264  = opt_val_val_t(OPT_STRING,any(option_val),required);
265  options_documentation_list_.push_back(
266  opt_doc_t(OPT_STRING, option_name, "", std::string(documentation?documentation:""),
267  any(option_val))
268  );
269 }
270 
271 
272 // Parse command line
273 
274 
277  int argc
278  ,char* argv[]
279  ,std::ostream *errout
280  ) const
281 {
282  add_extra_output_setup_options();
283  std::string opt_name;
284  std::string opt_val_str;
285  const std::string echo_cl_opt = "echo-command-line";
286  const std::string help_opt = "help";
287  const std::string pause_opt = "pause-for-debugging";
288  int procRank = GlobalMPISession::getRank();
289 
290  // check for help options before any others as we modify
291  // the values afterwards
292  for( int i = 1; i < argc; ++i ) {
293  bool gov_return = get_opt_val( argv[i], &opt_name, &opt_val_str );
294  if( gov_return && opt_name == help_opt ) {
295  if(errout) printHelpMessage( argv[0], *errout );
296  return PARSE_HELP_PRINTED;
297  }
298  }
299  // check all other options
300  for( int i = 1; i < argc; ++i ) {
301  bool gov_return = get_opt_val( argv[i], &opt_name, &opt_val_str );
302  if( !gov_return ) {
303  if(procRank == 0)
304  print_bad_opt(i,argv,errout);
305  if( recogniseAllOptions() )
307  else {
308  continue;
309  }
310  }
311  if( opt_name == echo_cl_opt ) {
312  if(errout && procRank == 0) {
313  *errout << "\nEchoing the command-line:\n\n";
314  for( int j = 0; j < argc; ++j )
315  *errout << argv[j] << " ";
316  *errout << "\n\n";
317  }
318  continue;
319  }
320  if( opt_name == pause_opt ) {
321 #ifndef _WIN32
322  Array<int> pids;
324  int rank_pid = getpid();
325  GlobalMPISession::allGather(rank_pid,pids());
326  if(procRank == 0)
327  for (int k=0; k<GlobalMPISession::getNProc(); k++)
328  std::cerr << "Rank " << k << " has PID " << pids[k] << std::endl;
329 #endif
330  if(procRank == 0) {
331  std::cerr << "\nType 0 and press enter to continue : ";
332  int dummy_int = 0;
333  std::cin >> dummy_int;
334  }
336  continue;
337  }
338  // Lookup the option (we had better find it!)
339  options_list_t::iterator itr = options_list_.find(opt_name);
340  if( itr == options_list_.end() ) {
341  if(procRank == 0)
342  print_bad_opt(i,argv,errout);
343  if( recogniseAllOptions() )
345  else
346  continue;
347  }
348  // Changed access to second value of std::map to not use overloaded arrow operator,
349  // otherwise this code will not compile on Janus (HKT, 12/01/2003)
350  opt_val_val_t &opt_val_val = (*itr).second;
351  opt_val_val.was_read = true;
352  switch( opt_val_val.opt_type ) {
353  case OPT_BOOL_TRUE:
354  *(any_cast<bool*>(opt_val_val.opt_val)) = true;
355  break;
356  case OPT_BOOL_FALSE:
357  *(any_cast<bool*>(opt_val_val.opt_val)) = false;
358  break;
359  case OPT_INT:
360  *(any_cast<int*>(opt_val_val.opt_val)) = asSafe<int> (opt_val_str);
361  break;
362  case OPT_LONG_INT:
363  *(any_cast<long int*>(opt_val_val.opt_val)) = asSafe<long int> (opt_val_str);
364  break;
365  case OPT_SIZE_T:
366  *(any_cast<size_t *>(opt_val_val.opt_val)) = asSafe<size_t> (opt_val_str);
367  break;
368  case OPT_LONG_LONG_INT:
369  *(any_cast<long long int*>(opt_val_val.opt_val)) = asSafe<long long int> (opt_val_str);
370  break;
371  case OPT_DOUBLE:
372  *(any_cast<double*>(opt_val_val.opt_val)) = asSafe<double> (opt_val_str);
373  break;
374  case OPT_FLOAT:
375  *(any_cast<float*>(opt_val_val.opt_val)) = asSafe<float> (opt_val_str);
376  break;
377  case OPT_STRING:
378  *(any_cast<std::string*>(opt_val_val.opt_val)) = remove_quotes(opt_val_str);
379  break;
380  case OPT_ENUM_INT:
381  if( !set_enum_value( i, argv, opt_name, any_cast<int>(opt_val_val.opt_val),
382  remove_quotes(opt_val_str), errout ) )
383  {
385  }
386  break;
387  default:
388  TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
389  }
390  }
391  // Look for options that were required but were not set
392  for(
393  options_list_t::const_iterator itr = options_list_.begin();
394  itr != options_list_.end();
395  ++itr
396  )
397  {
398  const opt_val_val_t &opt_val_val = (*itr).second;
399  if( opt_val_val.required && !opt_val_val.was_read ) {
400  const std::string &opt_val_name = (*itr).first;
401 #define CLP_ERR_MSG \
402  "Error, the option --"<<opt_val_name<<" was required but was not set!"
403  if(errout)
404  *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
405  if( throwExceptions() ) {
406  TEUCHOS_TEST_FOR_EXCEPTION( true, ParseError, CLP_ERR_MSG );
407  }
408  return PARSE_ERROR;
409 #undef CLP_ERR_MSG
410  }
411  }
412  // Set the options of a default stream exists and if we are asked to
415  if (defaultOut.get() && addOutputSetupOptions_) {
416  if (output_all_front_matter_ != output_all_front_matter_default_)
417  defaultOut->setShowAllFrontMatter(output_all_front_matter_);
418  if (output_show_line_prefix_ != output_show_line_prefix_default_)
419  defaultOut->setShowLinePrefix(output_show_line_prefix_);
420  if (output_show_tab_count_ != output_show_tab_count_default_)
421  defaultOut->setShowTabCount(output_show_tab_count_);
422  if (output_show_proc_rank_ != output_show_proc_rank_default_)
423  defaultOut->setShowProcRank(output_show_proc_rank_);
424  if (output_to_root_rank_only_ != output_to_root_rank_only_default_)
425  defaultOut->setOutputToRootOnly(output_to_root_rank_only_);
426  RCPNodeTracer::setPrintRCPNodeStatisticsOnExit(print_rcpnode_statistics_on_exit_);
427  }
428  return PARSE_SUCCESSFUL;
429 }
430 
431 
432 void CommandLineProcessor::printHelpMessage( const char program_name[],
433  std::ostream &out ) const
434 {
435  add_extra_output_setup_options();
436  int procRank = GlobalMPISession::getRank();
437  if (procRank == 0) {
438  using std::setw;
439  using std::endl;
440 
441  const int opt_type_w = 14;
442  const char spc_chars[] = " ";
443 
444  // Get the maximum length of an option name
445  int opt_name_w = 19; // For the 'pause-for-debugging' option
446  options_documentation_list_t::const_iterator itr;
447  for (
448  itr = options_documentation_list_.begin();
449  itr != options_documentation_list_.end();
450  ++itr
451  )
452  {
453  opt_name_w = my_max(opt_name_w,static_cast<int>(itr->opt_name.length()));
454  if( itr->opt_type )
455  opt_name_w = my_max(opt_name_w,static_cast<int>(itr->opt_name_false.length()));
456  }
457  opt_name_w += 2;
458 
459  // Some built-in options
460  out
461  << "Usage: " << program_name << " [options]\n"
462  << spc_chars << "options:\n"
463  << spc_chars
464  << "--"
465 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
466  << std::left << setw(opt_name_w) << "help"
467  << std::left << setw(opt_type_w) << " "
468 #else
469  << std::setiosflags(std::ios::left) << setw(opt_name_w) << "help"
470  << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
471 #endif
472  << "Prints this help message"
473  << std::endl
474  << spc_chars
475  << "--"
476 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
477  << std::left << setw(opt_name_w) << "pause-for-debugging"
478  << std::left << setw(opt_type_w) << " "
479 #else
480  << std::setiosflags(std::ios::left) << setw(opt_name_w) << "pause-for-debugging"
481  << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
482 #endif
483  << "Pauses for user input to allow attaching a debugger"
484  << std::endl
485  << spc_chars
486  << "--"
487 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
488  << std::left << setw(opt_name_w) << "echo-command-line"
489  << std::left << setw(opt_type_w) << " "
490 #else
491  << std::setiosflags(std::ios::left) << setw(opt_name_w) << "echo-command-line"
492  << std::setiosflags(std::ios::left) << setw(opt_type_w) << " "
493 #endif
494  << "Echo the command-line but continue as normal"
495  << std::endl;
496  for(
497  itr = options_documentation_list_.begin();
498  itr != options_documentation_list_.end();
499  ++itr )
500  {
501  // print top line with option name, type and short documentation string
502  out
503  << spc_chars
504  << "--"
505 #ifdef HAVE_STD_IOS_BASE_FMTFLAGS
506  << std::left << setw(opt_name_w) << itr->opt_name
507  << std::left << setw(opt_type_w) << opt_type_str(itr->opt_type)
508 #else
509  << std::setiosflags(std::ios::left) << setw(opt_name_w) << itr->opt_name
510  << std::setiosflags(std::ios::left) << setw(opt_type_w) << opt_type_str(itr->opt_type)
511 #endif
512  << ( itr->documentation.length() ? itr->documentation.c_str() : "No documentation" )
513  << std::endl;
514  // If an enumeration option then the next line is the value options
515  if( itr->opt_type == OPT_ENUM_INT ) {
516  out
517  << spc_chars
518  << " "
519  << setw(opt_name_w) << ""
520  << setw(opt_type_w) << "";
521  print_enum_opt_names( any_cast<int>(itr->default_val), out );
522  out
523  << std::endl;
524  }
525  // Now print the line that contains the default values
526  if( itr->opt_type == OPT_BOOL_TRUE ) {
527  out
528  << spc_chars
529  << "--"
530  << setw(opt_name_w) << itr->opt_name_false;
531  }
532  else {
533  out
534  << spc_chars
535  << " "
536  << setw(opt_name_w) << " ";
537  }
538  out
539  << setw(opt_type_w) << " "
540  << "(default: ";
541  switch( itr->opt_type ) {
542  case OPT_BOOL_TRUE:
543  out << "--" << ( (*(any_cast<bool*>(itr->default_val))) ?
544  itr->opt_name : itr->opt_name_false );
545  break;
546  case OPT_INT:
547  case OPT_LONG_INT:
548  case OPT_SIZE_T:
549  case OPT_LONG_LONG_INT:
550  case OPT_DOUBLE:
551  case OPT_FLOAT:
552  case OPT_STRING:
553  case OPT_ENUM_INT:
554  out << "--" << itr->opt_name;
555  break;
556  default:
557  TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
558  }
559  switch( itr->opt_type ) {
560  case OPT_BOOL_TRUE:
561  break;
562  case OPT_INT:
563  out << "=" << (*(any_cast<int*>(itr->default_val)));
564  break;
565  case OPT_LONG_INT:
566  out << "=" << (*(any_cast<long int*>(itr->default_val)));
567  break;
568  case OPT_SIZE_T:
569  out << "=" << (*(any_cast<size_t*>(itr->default_val)));
570  break;
571  case OPT_LONG_LONG_INT:
572  out << "=" << (*(any_cast<long long int*>(itr->default_val)));
573  break;
574  case OPT_DOUBLE:
575  out << "=" << (*(any_cast<double*>(itr->default_val)));
576  break;
577  case OPT_FLOAT:
578  out << "=" << (*(any_cast<float*>(itr->default_val)));
579  break;
580  case OPT_STRING:
581  out << "=" << add_quotes(*(any_cast<std::string*>(itr->default_val)));
582  break;
583  case OPT_ENUM_INT:
584  out << "=" << add_quotes(
585  enum_opt_default_val_name(itr->opt_name,any_cast<int>(itr->default_val),&out));
586  break;
587  default:
588  TEUCHOS_TEST_FOR_EXCEPT(true); // Local programming error only
589  }
590  out << ")\n";
591  }
592  if(doc_string_.length()) {
593  out << "\nDETAILED DOCUMENTATION:\n\n" << doc_string_ << std::endl << std::endl;
594  }
595  if(throwExceptions_)
596  TEUCHOS_TEST_FOR_EXCEPTION( true, HelpPrinted, "Help message was printed" );
597  }
598 }
599 
600 
602  const Ptr<std::ostream> &out_inout
603  )
604 {
605  if (!printed_timer_summary_ && show_timer_summary_on_exit_) {
606  RCP<std::ostream> out;
607  if (nonnull(out_inout)) {
608  out = rcpFromPtr(out_inout);
609  }
610  else {
612  }
613  getTimeMonitorSurrogate()->summarize(*out << "\n");
614  printed_timer_summary_ = true;
615  }
616 }
617 
618 
619 // private
620 
621 
622 void CommandLineProcessor::add_extra_output_setup_options() const
623 {
624  if(
625  // Are we in this function already and calling it recursively?
626  in_add_extra_output_setup_options_
627  ||
628  // Have we already setup these options?
629  added_extra_output_setup_options_
630  ||
631  // Are we not supposed to setup these options?
632  !addOutputSetupOptions_
633  )
634  {
635  return; // If any of the above is true, we need to return right away!
636  }
637  // Set the commandline options for this ...
639  *clp = const_cast<CommandLineProcessor*>(this);
640  clp->in_add_extra_output_setup_options_ = true;
641  clp->setOption(
642  "output-all-front-matter","output-no-front-matter",&clp->output_all_front_matter_
643  ,"Set if all front matter is printed to the default FancyOStream or not"
644  );
645  clp->setOption(
646  "output-show-line-prefix","output-no-show-line-prefix",&clp->output_show_line_prefix_
647  ,"Set if the line prefix matter is printed to the default FancyOStream or not"
648  );
649  clp->setOption(
650  "output-show-tab-count","output-no-show-tab-count",&clp->output_show_tab_count_
651  ,"Set if the tab count is printed to the default FancyOStream or not"
652  );
653  clp->setOption(
654  "output-show-proc-rank","output-no-show-proc-rank",&clp->output_show_proc_rank_
655  ,"Set if the processor rank is printed to the default FancyOStream or not"
656  );
657  clp->setOption(
658  "output-to-root-rank-only",&clp->output_to_root_rank_only_
659  ,"Set which processor (the root) gets the output. If < 0, then all processors get output."
660  );
661  clp->setOption(
662  "print-rcpnode-statistics-on-exit", "no-print-rcpnode-statistics-on-exit",
663  &clp->print_rcpnode_statistics_on_exit_,
664  "Set if the RCPNode usage statistics will be printed on exit or not. Warning,"
665  " this prints to std::cerr or every process so do not turn this on for very large"
666  " parallel runs."
667  );
668  if (nonnull(getTimeMonitorSurrogate())) {
669  clp->setOption(
670  "show-timer-summary", "no-show-timer-sumary", &clp->show_timer_summary_on_exit_,
671  "If true, then Teuchos::TimeMonitor::summarize() is called in"
672  " CommandLineProcessor's destructor (usually at the end of main)."
673  );
674  }
675 
676  clp->added_extra_output_setup_options_ = true;
677  clp->in_add_extra_output_setup_options_ = false;
678 }
679 
680 
681 void CommandLineProcessor::setEnumOption(
682  const char enum_option_name[]
683  ,int *enum_option_val
684  ,const int num_enum_opt_values
685  ,const int enum_opt_values[]
686  ,const char* enum_opt_names[]
687  ,const char documentation[]
688  ,const bool required
689  )
690 {
691  add_extra_output_setup_options();
692 
693  TEUCHOS_TEST_FOR_EXCEPT(enum_option_val==NULL);
694  TEUCHOS_TEST_FOR_EXCEPT(num_enum_opt_values<=0);
695  TEUCHOS_TEST_FOR_EXCEPT(enum_opt_values==NULL);
696  TEUCHOS_TEST_FOR_EXCEPT(enum_opt_names==NULL);
697 
698  enum_opt_data_list_.push_back(
699  enum_opt_data_t(enum_option_val,num_enum_opt_values,enum_opt_values,enum_opt_names)
700  );
701  const int opt_id = static_cast<int>(enum_opt_data_list_.size())-1;
702  options_list_[std::string(enum_option_name)]
703  = opt_val_val_t(OPT_ENUM_INT,any(opt_id),required);
704  options_documentation_list_.push_back(
705  opt_doc_t(OPT_ENUM_INT,enum_option_name, "",
706  std::string(documentation?documentation:""), any(opt_id))
707  );
708 }
709 
710 
711 bool CommandLineProcessor::set_enum_value(
712  int argv_i
713  ,char* argv[]
714  ,const std::string &enum_opt_name
715  ,const int enum_id
716  ,const std::string &enum_str_val
717  ,std::ostream *errout
718  ) const
719 {
720  const enum_opt_data_t
721  &enum_opt_data = enum_opt_data_list_.at(enum_id);
722  std::vector<std::string>::const_iterator
723  itr_begin = enum_opt_data.enum_opt_names.begin(),
724  itr_end = enum_opt_data.enum_opt_names.end(),
725  itr = std::find( itr_begin, itr_end, enum_str_val );
726  if( itr == itr_end ) {
727  const int j = argv_i;
728 #define CLP_ERR_MSG \
729  "Error, the value \"" << enum_str_val << "\" for the " \
730  << j<<(j==1?"st":(j==2?"nd":(j==3?"rd":"th"))) << " option --" \
731  << enum_opt_name << " was not recognized (use --help)!"
732  if(errout)
733  *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
734  if( throwExceptions() ) {
735  TEUCHOS_TEST_FOR_EXCEPTION( true, UnrecognizedOption, CLP_ERR_MSG );
736  }
737  else {
738  return false;
739  }
740 #undef CLP_ERR_MSG
741  }
742  const int enum_opt_val_index = static_cast<int>(itr - itr_begin);
743  *enum_opt_data.enum_option_val = enum_opt_data.enum_opt_values.at(enum_opt_val_index);
744  return true;
745 }
746 
747 
748 void CommandLineProcessor::print_enum_opt_names(
749  const int enum_id
750  ,std::ostream &out
751  ) const
752 {
753  const enum_opt_data_t
754  &enum_opt_data = enum_opt_data_list_.at(enum_id);
755  typedef std::vector<std::string>::const_iterator itr_t;
756  out << "Valid options:";
757  for(
758  itr_t itr = enum_opt_data.enum_opt_names.begin();
759  itr != enum_opt_data.enum_opt_names.end();
760  ++itr
761  )
762  {
763  if( itr != enum_opt_data.enum_opt_names.begin() ) out << ",";
764  out << " " << add_quotes(*itr);
765  }
766 }
767 
768 
769 std::string
770 CommandLineProcessor::enum_opt_default_val_name(
771  const std::string &enum_name
772  ,const int enum_id
773  ,std::ostream *errout
774  ) const
775 {
776  const enum_opt_data_t
777  &enum_opt_data = enum_opt_data_list_.at(enum_id);
778  return enum_opt_data.enum_opt_names.at(
779  find_enum_opt_index(
780  enum_name,*enum_opt_data.enum_option_val,enum_opt_data,errout
781  )
782  );
783 }
784 
785 
786 int CommandLineProcessor::find_enum_opt_index(
787  const std::string &enum_opt_name
788  ,const int opt_value
789  ,const enum_opt_data_t &enum_data
790  ,std::ostream *errout
791  ) const
792 {
793  std::vector<int>::const_iterator
794  itr_begin = enum_data.enum_opt_values.begin(),
795  itr_end = enum_data.enum_opt_values.end(),
796  itr = std::find( itr_begin, itr_end, opt_value );
797  if( itr == itr_end ) {
798 #define CLP_ERR_MSG \
799  ( recogniseAllOptions() ? "Error" : "Warning" ) \
800  << ", option --" << enum_opt_name << " was given an invalid " \
801  "initial option value of " << opt_value << "!"
802  if(errout)
803  *errout << CLP_ERR_MSG << std::endl;
804  if( throwExceptions() )
805  TEUCHOS_TEST_FOR_EXCEPTION( true, std::invalid_argument, CLP_ERR_MSG );
806 #undef CLP_ERR_MSG
807  }
808  return static_cast<int>(itr - itr_begin);
809 }
810 
811 
812 bool CommandLineProcessor::get_opt_val(
813  const char str[]
814  ,std::string *opt_name
815  ,std::string *opt_val_str
816  ) const
817 {
818  const int len = static_cast<int>(std::strlen(str));
819  if( len < 3 )
820  return false; // Can't be an option with '--' followed by at least one char
821  if( str[0] != '-' || str[1] != '-' )
822  return false; // Not a recognised option
823  // Find the '='
824  int equ_i;
825  for( equ_i = 2; equ_i < len && str[equ_i] != '='; ++equ_i );
826  // Set opt_name
827  opt_name->assign( str + 2, equ_i-2 );
828  // Set opt_val_str
829  if( equ_i == len ) {
830  *opt_val_str = "";
831  }
832  else {
833  opt_val_str->assign( str + equ_i + 1, len - equ_i - 1 );
834  }
835  return true;
836 }
837 
838 void CommandLineProcessor::print_bad_opt(
839  int argv_i
840  ,char* argv[]
841  ,std::ostream *errout
842  ) const
843 {
844  const int j = argv_i;
845 #define CLP_ERR_MSG \
846  ( recogniseAllOptions() ? "Error" : "Warning" ) \
847  << ", the " << j<<(j==1?"st":(j==2?"nd":(j==3?"rd":"th"))) \
848  << " option \'" << argv[argv_i] << "\' was not recognized (use --help)!"
849  if(errout)
850  *errout << std::endl << argv[0] << " : " << CLP_ERR_MSG << std::endl;
852  TEUCHOS_TEST_FOR_EXCEPTION( true, UnrecognizedOption, CLP_ERR_MSG );
853 #undef CLP_ERR_MSG
854 }
855 
856 
857 // Hidden stuff
858 
859 
860 void CommandLineProcessor::setTimeMonitorSurrogate(
861  const RCP<CommandLineProcessor::TimeMonitorSurrogate> &timeMonitorSurrogate)
862 {
863  getRawTimeMonitorSurrogate() = timeMonitorSurrogate;
864 }
865 
866 
867 RCP<CommandLineProcessor::TimeMonitorSurrogate>
868 CommandLineProcessor::getTimeMonitorSurrogate()
869 {
870  return getRawTimeMonitorSurrogate();
871 }
872 
873 
874 RCP<CommandLineProcessor::TimeMonitorSurrogate>&
875 CommandLineProcessor::getRawTimeMonitorSurrogate()
876 {
877  static RCP<TimeMonitorSurrogate> timeMonitorSurrogate;
878  return timeMonitorSurrogate;
879 }
880 
881 
882 } // end namespace Teuchos
Templated array class derived from the STL std::vector.
Basic command line parser for input from (argc,argv[])
A MPI utilities class, providing methods for initializing, finalizing, and querying the global MPI se...
Definition of Teuchos::as, for conversions between types.
void resize(size_type new_size, const value_type &x=value_type())
Thrown if –help was specified and throwExceptions==true.
Thrown if a parse std::exception occurs and throwExceptions==true.
bool throwExceptions() const
Returns true if an std::exception is thrown, there is a parse error, or help is printed.
void setOption(const char option_true[], const char option_false[], bool *option_val, const char documentation[]=NULL)
Set a boolean option.
EParseCommandLineReturn
Return value for CommandLineProcessor::parse(). Note: These enums are all given non-negative values s...
EParseCommandLineReturn parse(int argc, char *argv[], std::ostream *errout=&std::cerr) const
Parse a command line.
void printHelpMessage(const char program_name[], std::ostream &out) const
Print the help message.
void printFinalTimerSummary(const Ptr< std::ostream > &out=null)
Call to print timers so that they don't get printed in the destructor.
void setDocString(const char doc_string[])
Set a documentation sting for the entire program printed when –help is specified.
CommandLineProcessor(bool throwExceptions=true, bool recogniseAllOptions=true, bool addOutputSetupOptions=false)
Default Constructor.
bool recogniseAllOptions() const
Returns true if all options must be recognized by the parser.
static void barrier()
Call MPI_Barrier() on MPI_COMM_WORLD.
static int getRank()
The rank of the calling process in MPI_COMM_WORLD.
static int getNProc()
The number of processes in MPI_COMM_WORLD.
static void allGather(int localVal, const ArrayView< int > &allVals)
Global all-to-all of a set of integers across processes.
Simple wrapper class for raw pointers to single objects where no persisting relationship exists.
static void setPrintRCPNodeStatisticsOnExit(bool printRCPNodeStatisticsOnExit)
Set if RCPNode usage statistics will be printed when the program ends or not.
Smart reference counting pointer class for automatic garbage collection.
T * get() const
Get the raw C++ pointer to the underlying object.
static RCP< FancyOStream > getDefaultOStream()
Get the default output stream object.
Modified boost::any class, which is a container for a templated value.
#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.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
bool nonnull(const std::shared_ptr< T > &p)
Returns true if p.get()!=NULL.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...