28 template <
typename T >
52 OptType get_opt_type< std::vector< int > >()
61 std::vector< std::string >
args;
85 ProgOpt(
const std::string& longname_p,
const std::string& shortname_p,
int flags_p,
OptType t =
FLAG )
98 if( !helpstring.empty() )
main_help.push_back( helpstring );
99 addOpt< void >(
"help,h",
"Show full help text",
help_flag );
121 *longname = namestring;
123 size_t idx = namestring.find_first_of(
',' );
124 if( idx != namestring.npos )
126 *longname = namestring.substr( 0, idx );
127 *shortname = namestring.substr( idx + 1, namestring.npos );
136 addOpt< void >(
"version",
"Print version number and exit",
version_flag );
140 template <
typename T >
141 void ProgOptions::addOpt(
const std::string& namestring,
const std::string& helpstring, T* value,
int flags )
144 std::string shortname, longname;
149 if( !shortname.empty() )
error(
"Requested short name with int_flag option" );
150 if( get_opt_type< T >() !=
INT )
error(
"Requested int_flag for non-integer option" );
155 ProgOpt* opt =
new ProgOpt( longname, shortname, flags, get_opt_type< T >() );
156 if( value ) opt->
storage = value;
158 if( longname.length() )
long_names[longname] = opt;
159 if( shortname.length() )
short_names[shortname] = opt;
166 std::string flag =
"no-" + ( longname.length() ? longname : shortname );
168 if( value ) cancel_opt->
storage = value;
172 std::string clear_helpstring =
"Clear previous " + flag.substr( 3, flag.npos ) +
" flag";
173 help = std::make_pair( cancel_opt, clear_helpstring );
178 template <
typename T >
182 OptType type = get_opt_type< T >();
185 if( value ) opt->
storage = value;
191 template <
typename T >
193 const std::string& helpname,
194 const std::string& helpstring,
202 std::map< std::string, ProgOpt* >::iterator iter;
213 addRequiredArg< T >( helpname, helpstring, 0, flags );
231 for( std::vector< std::string >::iterator i =
main_help.begin(); i !=
main_help.end(); ++i )
233 if( ( *i ).length() )
235 out << std::endl << *i << std::endl;
243 const int max_padding = 20;
249 int max_arg_namelen = 0;
253 max_arg_namelen = std::max( max_arg_namelen, (
int)( ( *i ).first->longname.length() ) );
256 max_arg_namelen = std::min( max_arg_namelen + 3, max_padding );
258 out <<
"Arguments: " << std::endl;
262 ProgOpt* option = ( *i ).first;
263 std::string& info = ( *i ).second;
267 out << std::setw( max_arg_namelen ) << std::left << s.str();
268 out <<
": " << info << std::endl;
273 out <<
"Options: " << std::endl;
274 int max_option_prefix_len = 0;
278 ProgOpt* option = ( *i ).first;
279 std::string& info = ( *i ).second;
284 if( max_option_prefix_len == 0 )
288 for( std::vector< help_line >::iterator j = i; j !=
option_help_strings.end() && ( *j ).first; ++j )
291 max_option_prefix_len = std::max( max_option_prefix_len, len );
294 max_option_prefix_len = std::min( max_option_prefix_len, max_padding );
297 out << std::setw( max_option_prefix_len ) << std::left << option_prefix;
303 max_option_prefix_len = 0;
305 out << info << std::endl;
311 bool has_shortname = option.
shortname.length() > 0;
312 bool has_longname = option.
longname.length() > 0;
338 if( has_shortname ) s <<
"[";
340 if( has_shortname ) s <<
"]";
343 if( argstr.length() ) s <<
" <" << argstr <<
">";
350 out <<
"Usage: " <<
progname <<
" --help | [options] ";
370 std::map< std::string, ProgOpt* >::const_iterator it = table.find( arg );
371 if( it != table.end() )
382 std::string longname, shortname;
390 error(
"Invalid option: " + namestring );
398 std::cerr <<
"Error: " << err <<
"\n" << std::endl;
401 std::cerr << std::endl;
402 if( getenv(
"MOAB_PROG_OPT_ABORT" ) ) abort();
403 std::exit( EXIT_FAILURE );
412 char* mystr = strdup(
string );
413 for(
const char* ptr = strtok( mystr,
", \t" ); ptr; ptr = strtok( 0,
", \t" ) )
416 long val = strtol( ptr, &endptr, 0 );
419 std::cerr <<
"Not an integer: \"" << ptr <<
'"' << std::endl;
427 const char* sptr = endptr + 1;
428 val2 = strtol( sptr, &endptr, 0 );
431 std::cerr <<
"Not an integer: \"" << sptr <<
'"' << std::endl;
437 std::cerr <<
"Invalid id range: \"" << ptr <<
'"' << std::endl;
449 for( ; val <= val2; ++val )
450 results.push_back( (
int)val );
461 #ifndef MOAB_HAVE_MPI
465 if( MPI_SUCCESS != MPI_Comm_rank( MPI_COMM_WORLD, &rank ) || MPI_SUCCESS != MPI_Comm_size( MPI_COMM_WORLD, &
size ) )
474 size_t j = s.find(
'%' );
475 if( j == std::string::npos )
return s;
477 std::ostringstream st;
478 st << std::setfill(
'0' );
479 st << s.substr( 0, j );
483 while( ( i = s.find(
'%', j + 1 ) ) != std::string::npos )
485 st << s.substr( j, i - j );
486 st << std::setw( width ) << rank;
489 st << s.substr( j + 1 );
504 unsigned idx = arg_idx ? *arg_idx : opt.
args.size() - 1;
509 error(
"Cannot evaluate a flag" );
513 int* i = target ?
reinterpret_cast< int*
>( target ) : &temp;
514 if( opt.
args.size() < 1 )
516 error(
"Missing argument to " + option +
" option" );
518 const char* arg = opt.
args.at( idx ).c_str();
520 *i = std::strtol( arg, &p, 0 );
523 error(
"Bad integer argument '" + opt.
args.at( idx ) +
"' to " + option +
" option." );
529 double* i = target ?
reinterpret_cast< double*
>( target ) : &temp;
530 if( opt.
args.size() < 1 )
532 error(
"Missing argument to " + option +
" option" );
534 const char* arg = opt.
args.at( idx ).c_str();
536 *i = std::strtod( arg, &p );
539 error(
"Bad real argument '" + opt.
args.at( idx ) +
"' to " + option +
" option." );
546 std::string* i = target ?
reinterpret_cast< std::string*
>( target ) : &temp;
547 if( opt.
args.size() < 1 )
549 error(
"Missing argument to " + option +
" option" );
554 *i = opt.
args.at( idx );
559 std::vector< int > temp;
560 std::vector< int >* i = target ?
reinterpret_cast< std::vector< int >*
>( target ) : &temp;
562 error(
"Bad integer list '" + opt.
args.at( idx ) +
"' to " + option +
" option." );
570 template <
typename T >
576 if( get_opt_type< T >() != opt->
type )
578 error(
"Option '" + namestring +
"' looked up with incompatible type" );
582 if( opt->
args.size() )
591 template <
typename T >
600 for(
unsigned i = 0; i < opt->
args.size(); ++i )
605 if( get_opt_type< T >() != opt->
type )
607 error(
"Option '" + namestring +
"' looked up with incompatible type" );
610 values.resize( opt->
args.size() );
614 for(
unsigned i = 0; i < opt->
args.size(); ++i )
616 evaluate( *opt, &( values[i] ),
"", &i );
622 std::string longname, shortname;
630 error(
"Could not look up option: " + namestring );
633 return opt->
args.size();
636 template <
typename T >
644 error(
"Could not look up required arg: " + namestring );
654 template <
typename T >
661 error(
"Could not look up required arg: " + namestring );
664 if( get_opt_type< T >() != opt->
type )
666 error(
"Option '" + namestring +
"' looked up with incompatible type" );
669 values.resize( opt->
args.size() );
673 for(
unsigned i = 0; i < opt->
args.size(); ++i )
675 evaluate( *opt, &( values[i] ),
"", &i );
687 if( arg ==
"--manpage" )
693 error(
"Unknown option: " + arg );
699 exit( EXIT_SUCCESS );
705 exit( EXIT_SUCCESS );
710 if( !value )
return true;
712 opt->
args.push_back( value );
719 error(
"Unexpected value for flag: " + arg );
731 opt->
args.push_back(
"" );
739 const char* name = strrchr( argv[0],
'/' );
745 std::vector< const char* > args;
746 std::list< ProgOpt* > expected_vals;
747 bool no_more_flags =
false;
750 for(
int i = 1; i < argc; ++i )
752 std::string arg( argv[i] );
753 if( arg.empty() )
continue;
755 if( !expected_vals.empty() )
757 ProgOpt* opt = expected_vals.front();
758 expected_vals.pop_front();
760 opt->
args.push_back( arg );
763 else if( !no_more_flags && arg[0] ==
'-' )
765 if( arg.length() > 2 && arg[1] ==
'-' )
767 size_t eq = arg.find_first_of(
'=' );
768 if( eq != std::string::npos )
779 else if( arg ==
"--" )
781 no_more_flags =
true;
784 for(
size_t f = 1; f < arg.length(); ++f )
789 const char val[] = { arg[f], 0 };
793 expected_vals.push_back( opt );
799 args.push_back( argv[i] );
804 if( !expected_vals.empty() )
806 error(
"Missing value for option: -" + expected_vals.front()->shortname +
",--" +
807 expected_vals.front()->longname );
812 std::vector< const char* >::iterator arg_val_pos = args.begin();
822 max_required_args = std::numeric_limits< int >::max();
826 if( args.size() < min_required_args )
828 size_t missing_pos = args.size();
831 const std::string& missed_arg =
arg_help_strings[missing_pos].first->longname;
832 error(
"Did not find required positional argument: " + missed_arg );
834 else if( args.size() > max_required_args )
836 error(
"Unexpected argument: " + std::string( args[max_required_args] ) );
841 while( arg_help_pos != opt_args_pos )
843 ProgOpt* opt = arg_help_pos->first;
845 opt->
args.push_back( *arg_val_pos );
852 assert( arg_help_pos == opt_args_pos );
853 size_t num_opt_args = args.size() + 1 -
required_args.size();
854 ProgOpt* opt = arg_help_pos->first;
856 while( num_opt_args-- )
858 opt->
args.push_back( *arg_val_pos );
866 assert( arg_val_pos != args.end() );
867 ProgOpt* opt = arg_help_pos->first;
869 opt->
args.push_back( *arg_val_pos );
873 assert( arg_val_pos == args.end() );
879 std::string lprogname;
902 std::vector< help_line >::iterator it;
903 std::set< ProgOpt* > skip_list;
906 s << std::endl <<
".TH " << lprogname <<
" 1" << std::endl;
909 s << std::endl <<
".SH NAME" << std::endl <<
".P " << std::endl << lprogname <<
" \\- ";
914 s << std::endl << std::endl;
917 s << std::endl <<
".SH SYNOPSIS" << std::endl <<
".HP" << std::endl <<
".B \"" << lprogname <<
'"' << std::endl;
920 if( !it->first || skip_list.find( it->first ) != skip_list.end() || it->first->longname ==
"help" )
continue;
922 if( it->first->type ==
FLAG )
926 if( !it->first->shortname.empty() )
928 s <<
' ' << c <<
" \"-" << it->first->shortname <<
'"';
931 if( !it->first->longname.empty() )
933 s <<
' ' << c <<
" \"--" << it->first->longname <<
'"';
935 if( it->first->cancel_opt )
937 skip_list.insert( it->first->cancel_opt );
938 if( !it->first->cancel_opt->shortname.empty() )
939 s <<
" | \"-" << it->first->cancel_opt->shortname <<
'"';
940 if( !it->first->cancel_opt->longname.empty() ) s <<
" | \"--" << it->first->cancel_opt->longname <<
'"';
942 s <<
" ]" << std::endl;
944 else if( it->first->flags &
int_flag )
946 s <<
".RB [ - <n>| \"--" << it->first->longname <<
"\" \"=" << it->first->get_argstring() <<
"]\""
952 if( !it->first->shortname.empty() )
953 s <<
"\"-" << it->first->shortname <<
"\" \"\\ " << it->first->get_argstring();
954 if( !it->first->shortname.empty() && !it->first->longname.empty() ) s <<
"|\" ";
955 if( !it->first->longname.empty() )
956 s <<
"\"--" << it->first->longname <<
"\" \"=" << it->first->get_argstring();
957 s <<
"]\"" << std::endl;
962 if( !it->first )
continue;
965 s << it->first->longname <<
' ';
967 s <<
'[' << it->first->longname <<
"] ";
969 s <<
'[' << it->first->longname <<
" ...] ";
972 s <<
".HP" << std::endl <<
".B \"" << lprogname <<
" -h|--help\"" << std::endl;
975 s << std::endl <<
".SH DESCRIPTION" << std::endl;
977 for(
size_t i = 0; i <
main_help.size(); ++i )
979 const std::string::size_type n =
main_help[i].size();
980 std::string::size_type j = 0, k;
981 s << std::endl <<
".P" << std::endl;
986 s << std::endl <<
".P" << std::endl;
991 if( k == std::string::npos ) k = n;
999 s << std::endl <<
".SH OPTIONS" << std::endl;
1003 s <<
".IP \"" << it->first->longname <<
'"' << std::endl << it->second << std::endl;
1005 s <<
".SS " << it->first->longname << std::endl;
1011 s <<
".SS " << it->second << std::endl;
1016 if( it->first->longname.empty() )
1017 s <<
"-" << it->first->shortname;
1018 else if( it->first->shortname.empty() )
1019 s <<
"--" << it->first->longname;
1021 s <<
"-" << it->first->shortname <<
", --" << it->first->longname;
1022 s <<
'"' << std::endl << it->second << std::endl;
1029 #define DECLARE_OPTION_TYPE( T ) \
1030 template void ProgOptions::addOpt< T >( const std::string&, const std::string&, T*, int ); \
1031 template bool ProgOptions::getOpt< T >( const std::string&, T* );
1033 #define DECLARE_VALUED_OPTION_TYPE( T ) \
1034 DECLARE_OPTION_TYPE( T ) \
1035 template void ProgOptions::getOptAllArgs< T >( const std::string&, std::vector< T >& ); \
1036 template void ProgOptions::addRequiredArg< T >( const std::string&, const std::string&, T*, int ); \
1037 template void ProgOptions::addOptionalArgs< T >( unsigned, const std::string&, const std::string&, int ); \
1038 template T ProgOptions::getReqArg< T >( const std::string& ); \
1039 template void ProgOptions::getArgs< T >( const std::string&, std::vector< T >& );