MOAB: Mesh Oriented datABase  (version 5.2.1)
ProgOptions Class Reference

#include <ProgOptions.hpp>

+ Collaboration diagram for ProgOptions:

Public Member Functions

 ProgOptions (const std::string &helptext="", const std::string &briefdesc="")
 unimplemented flag for required arguments that may be given multiple times
 ~ProgOptions ()
void setVersion (const std::string &version_string, bool addFlag=true)
template<typename T >
void addOpt (const std::string &namestring, const std::string &helpstring, T *value, int flags=0)
template<typename T >
void addOpt (const std::string &namestring, const std::string &helpstring, int flags=0)
void addOptionHelpHeading (const std::string &)
template<typename T >
void addRequiredArg (const std::string &helpname, const std::string &helpstring, T *value=NULL, int flags=0)
template<typename T >
void addOptionalArgs (unsigned max_count, const std::string &helpname, const std::string &helpstring, int flags=0)
void printHelp (std::ostream &str=std::cout)
void printUsage (std::ostream &str=std::cout)
void printVersion (std::ostream &str=std::cout)
void parseCommandLine (int argc, char *argv[])
template<typename T >
bool getOpt (const std::string &namestring, T *value)
template<typename T >
void getOptAllArgs (const std::string &namestring, std::vector< T > &values)
int numOptSet (const std::string &namestring)
template<typename T >
T getReqArg (const std::string &namestring)
template<typename T >
void getArgs (const std::string &namestring, std::vector< T > &values)
void error (const std::string &message)
void write_man_page (std::ostream &to_this_stream)

Static Public Attributes

static const int help_flag = 1 << 0
static const int add_cancel_opt = 1 << 1
static const int store_false = 1 << 2
static const int int_flag = 1 << 3
static const int rank_subst = 1 << 4
static const int version_flag = 1 << 5
 Set for a flag that, when detected, will call printVersion() and halt the program.

Protected Types

typedef std::pair< ProgOpt
*, std::string > 
help_line

Protected Member Functions

std::string get_option_usage_prefix (const ProgOpt &option)
void get_namestrings (const std::string &input, std::string *l, std::string *s)
ProgOptlookup (const std::map< std::string, ProgOpt * > &, const std::string &)
ProgOptlookup_option (const std::string &)
bool evaluate (const ProgOpt &opt, void *target, const std::string &option, unsigned *arg_idx=NULL)
bool process_option (ProgOpt *opt, std::string arg, const char *value=0)

Protected Attributes

std::map< std::string, ProgOpt * > long_names
std::map< std::string, ProgOpt * > short_names
std::map< std::string, ProgOpt * > required_args
std::vector< help_lineoption_help_strings
std::vector< help_linearg_help_strings
std::vector< std::string > main_help
std::string brief_help
bool expect_optional_args
unsigned optional_args_position
unsigned max_optional_args
std::string progname
std::string progversion
std::string number_option_name

Detailed Description

A simple command-line option parser and help utility

Utility class to specify a program's command-line options arguments, produce a help message explaining how they work, and parse user's command line input (producing useful errors messages if any problems arise). Loosely (okay, very loosely) inspired by boost program_options.

Options are specified by a comma-separated namestring. An option named "foo,f" can be specified three ways on the command line: "-f val", "--foo val", or "--foo=val". The types of options and arguments are specified by function templates. Valid template values for positional argument and options are int, double, and std::string. void may also be used in options, and it indicates a command line option that does not take an argument.

Example usage: ProgOptions po( "Example usage of ProgOptions" ); po.addOpt<void>( "verbose,v", "Turn on verbose messages" ); po.addOpt<std::string> ("foo", "Specify the foo string" ); int x = 0; po.addOpt<int>( ",x", "Specify the x number", &x ); // x will be automatically set when options parsed po.parseCommandLine( argc, argv ); bool verbose = po.numOptSet("verbose") > 0; std::string foo; if( !po.getOpt( "foo", &foo ) ) foo = "default"; ...

See the file dagmc_preproc.cpp in the dagmc directory for a real-world example.

Examples:
addPCdata.cpp, ComputeTriDual.cpp, copyPartition.cpp, CrystalRouterExample.cpp, DeformMeshRemap.cpp, DirectAccessNoHoles.cpp, DirectAccessWithHoles.cpp, GenLargeMesh.cpp, LaplacianSmoother.cpp, and StructuredMeshSimple.cpp.

Definition at line 35 of file ProgOptions.hpp.


Member Typedef Documentation

typedef std::pair< ProgOpt*, std::string > ProgOptions::help_line [protected]

Definition at line 260 of file ProgOptions.hpp.


Constructor & Destructor Documentation

ProgOptions::ProgOptions ( const std::string &  helptext = "",
const std::string &  briefdesc = "" 
)

unimplemented flag for required arguments that may be given multiple times

Parameters:
helptextA brief summary of the program's function, to be printed when the help flag is detected

Definition at line 94 of file ProgOptions.cpp.

References brief_help, help_flag, and main_help.

    : expect_optional_args( false ), optional_args_position( 0 ), max_optional_args( 0 )
{
    brief_help = briefhelp;
    if( !helpstring.empty() ) main_help.push_back( helpstring );
    addOpt< void >( "help,h", "Show full help text", help_flag );
}

Definition at line 102 of file ProgOptions.cpp.

References arg_help_strings, and option_help_strings.

{
    for( std::vector< help_line >::iterator i = option_help_strings.begin(); i != option_help_strings.end(); ++i )
    {
        if( ( *i ).first ) { delete( *i ).first; }
    }

    for( std::vector< help_line >::iterator i = arg_help_strings.begin(); i != arg_help_strings.end(); ++i )
    {
        delete( *i ).first;
    }
}

Member Function Documentation

template<typename T >
void ProgOptions::addOpt ( const std::string &  namestring,
const std::string &  helpstring,
T value,
int  flags = 0 
)

Specify a new command-line option

Instruct the parser to accept a new command-line argument, as well as specifying how the argument should be handled. The template parameter indicates the type of command-line option being specified: acceptable types are void (indicating a flag without an argument), int, double, and std::string.

Parameters:
namestringThe command-line options name(s). Format is longname,shortname. If the comma is omitted, or appears only at the end, this option will have no shortname; if the comma is the first letter of the namestring, the option has no longname.
helpstringThe help information displayed for the option when the program is invoked with --help
valueA pointer to memory in which to store the parsed value for this option. If NULL, then the value of the option must be queried using the getOpt function. If the template parameter is void and value is non-NULL, treat value as a bool* and store 'true' into it when the flag is encountered. (See also store_false, above)
flagsOption behavior flags, which should come from static vars in the ProgOptions class
Examples:
addPCdata.cpp, ComputeTriDual.cpp, copyPartition.cpp, CrystalRouterExample.cpp, DirectAccessNoHoles.cpp, DirectAccessWithHoles.cpp, GenLargeMesh.cpp, LaplacianSmoother.cpp, and StructuredMeshSimple.cpp.

Definition at line 135 of file ProgOptions.cpp.

References add_cancel_opt, ProgOpt::cancel_opt, error(), FLAG, get_namestrings(), help(), INT, int_flag, long_names, number_option_name, option_help_strings, short_names, ProgOpt::storage, store_false, and value().

Referenced by main(), parse_options(), ToolContext::ParseCLOptions(), test_flag_cancel(), test_flag_opt_long(), test_flag_opt_long_short(), test_flag_opt_short(), test_flag_store_false(), test_int_opt(), test_int_vect_opt(), test_real_opt(), test_squashed_short(), test_string_opt(), and test_string_rank_subst().

{

    std::string shortname, longname;
    get_namestrings( namestring, &longname, &shortname );

    if( flags & int_flag )
    {  // short name is implicit for this flag
        if( !shortname.empty() ) error( "Requested short name with int_flag option" );
        if( get_opt_type< T >() != INT ) error( "Requested int_flag for non-integer option" );
        if( !number_option_name.empty() ) error( "Requested int_flag for multiple options" );
        number_option_name = longname;
    }

    ProgOpt* opt = new ProgOpt( longname, shortname, flags, get_opt_type< T >() );
    if( value ) opt->storage = value;

    if( longname.length() ) long_names[longname] = opt;
    if( shortname.length() ) short_names[shortname] = opt;

    help_line help = std::make_pair( opt, helpstring );
    option_help_strings.push_back( help );

    if( flags & add_cancel_opt )
    {
        std::string flag    = "no-" + ( longname.length() ? longname : shortname );
        ProgOpt* cancel_opt = new ProgOpt( flag, "", flags ^ ProgOptions::store_false, FLAG );
        if( value ) cancel_opt->storage = value;

        cancel_opt->cancel_opt       = opt;
        long_names[flag]             = cancel_opt;
        std::string clear_helpstring = "Clear previous " + flag.substr( 3, flag.npos ) + " flag";
        help                         = std::make_pair( cancel_opt, clear_helpstring );
        option_help_strings.push_back( help );
    }
}
template<typename T >
void ProgOptions::addOpt ( const std::string &  namestring,
const std::string &  helpstring,
int  flags = 0 
) [inline]

Specify a new command-line option

This funtion is identical to the 4-arg version, but omits the value parameter, which is assumed to be NULL

Definition at line 122 of file ProgOptions.hpp.

    {
        addOpt< T >( namestring, helpstring, NULL, flags );
    }
template<typename T >
void ProgOptions::addOptionalArgs ( unsigned  max_count,
const std::string &  helpname,
const std::string &  helpstring,
int  flags = 0 
)

Add optional positional arguments

Specify location in ordered argument list at which optional arguments may occur. Optional arguments are allowed at only one location it argument list (this function may not be called more than once.). The template parameter may be int, double, or std::string (but not void)

Parameters:
countThe maximum number of optional arguments. Specify zero for unlimited.
helpnameThe name to give the argument in the help text
helpstringThe help text for the arguments

Definition at line 186 of file ProgOptions.cpp.

References arg_help_strings, expect_optional_args, max_optional_args, optional_args_position, and required_args.

Referenced by test_optional_arg(), and test_optional_args().

{
    // If there was a previous one, we need to remove it
    // because there can be only one.  If we didn't remove
    // the old one then it would be treated as a required arg.
    if( expect_optional_args )
    {
        std::map< std::string, ProgOpt* >::iterator iter;
        iter = required_args.find( arg_help_strings[optional_args_position].second );
        assert( iter != required_args.end() );
        delete iter->second;
        required_args.erase( iter );
        arg_help_strings.erase( arg_help_strings.begin() + optional_args_position );
    }

    expect_optional_args   = true;
    optional_args_position = arg_help_strings.size();
    max_optional_args      = max_count;
    addRequiredArg< T >( helpname, helpstring, 0, flags );
}
void ProgOptions::addOptionHelpHeading ( const std::string &  s)

Add a new line of help text to the option help printout

Add a line of text to the option-related help. Called between calls to addOpt(), this function can be used to divide the option list into groups of related options to make the help text more convenient.

Definition at line 208 of file ProgOptions.cpp.

References option_help_strings.

Referenced by main().

{
    option_help_strings.push_back( std::make_pair( (ProgOpt*)NULL, s ) );
}
template<typename T >
void ProgOptions::addRequiredArg ( const std::string &  helpname,
const std::string &  helpstring,
T value = NULL,
int  flags = 0 
)

Add required positional argument

Add a new required positional argument. The order in which arguments are specified is the order in which they will be expected on the command line. The template parameter may be int, double, or std::string (but not void)

Parameters:
helpnameThe name to give the argument in the help text
helpstringThe help text for the argument
valuePointer to where parsed value from command line should be stored. If NULL, the value must be queried using getReqArg()

Definition at line 173 of file ProgOptions.cpp.

References arg_help_strings, help(), required_args, and value().

Referenced by main(), test_int_arg(), test_int_vect_arg(), test_optional_arg(), test_optional_args(), test_real_arg(), test_string_arg(), and test_string_rank_subst().

{

    OptType type = get_opt_type< T >();

    ProgOpt* opt = new ProgOpt( helpname, "", flags, type );
    if( value ) opt->storage = value;
    help_line help = std::make_pair( opt, helpstring );
    arg_help_strings.push_back( help );
    required_args[helpname] = opt;
}
void ProgOptions::error ( const std::string &  message)

Prints an error message to std::cerr, along with a brief usage message, then halts the program. Used throughout ProgramOptions implementation. Users may call this directly if they detect an incorrect usage of program options that the ProgramOptions wasn't able to detect itself.

Parameters:
messageThe error message to print before program halt.

Definition at line 376 of file ProgOptions.cpp.

References printUsage().

Referenced by addOpt(), evaluate(), getArgs(), getOpt(), getOptAllArgs(), getReqArg(), lookup_option(), main(), numOptSet(), parseCommandLine(), and process_option().

{
    std::cerr << "Error: " << err << "\n" << std::endl;
    ;
    printUsage( std::cerr );
    std::cerr << std::endl;
    if( getenv( "MOAB_PROG_OPT_ABORT" ) ) abort();
    std::exit( EXIT_FAILURE );
}
bool ProgOptions::evaluate ( const ProgOpt opt,
void *  target,
const std::string &  option,
unsigned *  arg_idx = NULL 
) [protected]

Check the input to a given option for correctness, converting it to its expected type (e.g. int) and storing the result to target, if target is non-NULL.

Parameters:
optionUsed only in error messages to state which option could not be successfully converted
arg_idxIf non-NULL, evaluate the (*arg_idx)'th item in opt's args list

Definition at line 481 of file ProgOptions.cpp.

References ProgOpt::args, do_rank_subst(), error(), FLAG, ProgOpt::flags, INT, INT_VECT, parse_int_list(), rank_subst, REAL, STRING, and ProgOpt::type.

Referenced by getArgs(), getOpt(), getOptAllArgs(), getReqArg(), parseCommandLine(), and process_option().

{

    unsigned idx = arg_idx ? *arg_idx : opt.args.size() - 1;

    switch( opt.type )
    {
        case FLAG:
            error( "Cannot evaluate a flag" );
            break;
        case INT: {
            int temp;
            int* i = target ? reinterpret_cast< int* >( target ) : &temp;
            if( opt.args.size() < 1 ) { error( "Missing argument to " + option + " option" ); }
            const char* arg = opt.args.at( idx ).c_str();
            char* p;
            *i = std::strtol( arg, &p, 0 );
            if( *p != '\0' ) { error( "Bad integer argument '" + opt.args.at( idx ) + "' to " + option + " option." ); }
            return true;
        }
        case REAL: {
            double temp;
            double* i = target ? reinterpret_cast< double* >( target ) : &temp;
            if( opt.args.size() < 1 ) { error( "Missing argument to " + option + " option" ); }
            const char* arg = opt.args.at( idx ).c_str();
            char* p;
            *i = std::strtod( arg, &p );
            if( *p != '\0' ) { error( "Bad real argument '" + opt.args.at( idx ) + "' to " + option + " option." ); }
            return true;
        }

        case STRING: {
            std::string temp;
            std::string* i = target ? reinterpret_cast< std::string* >( target ) : &temp;
            if( opt.args.size() < 1 ) { error( "Missing argument to " + option + " option" ); }
            if( opt.flags & rank_subst )
                *i = do_rank_subst( opt.args.at( idx ) );
            else
                *i = opt.args.at( idx );
            return true;
        }

        case INT_VECT: {
            std::vector< int > temp;
            std::vector< int >* i = target ? reinterpret_cast< std::vector< int >* >( target ) : &temp;
            if( !parse_int_list( opt.args.at( idx ).c_str(), *i ) )
                error( "Bad integer list '" + opt.args.at( idx ) + "' to " + option + " option." );
            return true;
        }
    }

    return false;
}
void ProgOptions::get_namestrings ( const std::string &  input,
std::string *  l,
std::string *  s 
) [protected]

Definition at line 115 of file ProgOptions.cpp.

Referenced by addOpt(), lookup_option(), and numOptSet().

{
    *shortname = "";
    *longname  = namestring;

    size_t idx = namestring.find_first_of( ',' );
    if( idx != namestring.npos )
    {
        *longname  = namestring.substr( 0, idx );
        *shortname = namestring.substr( idx + 1, namestring.npos );
    }
}
std::string ProgOptions::get_option_usage_prefix ( const ProgOpt option) [protected]

Definition at line 298 of file ProgOptions.cpp.

References ProgOpt::flags, ProgOpt::get_argstring(), int_flag, ProgOpt::longname, and ProgOpt::shortname.

Referenced by printHelp().

{
    bool has_shortname = option.shortname.length() > 0;
    bool has_longname  = option.longname.length() > 0;
    std::string argstr = option.get_argstring();

    std::stringstream s;
    s << "  ";
    if( has_shortname )
    {

        s << "-" << option.shortname;
        if( has_longname ) { s << " "; }
    }
    else if( option.flags & int_flag )
    {

        s << "-<n>";
        if( has_longname ) { s << " "; }
    }
    if( has_longname )
    {

        if( has_shortname ) s << "[";
        s << "--" << option.longname;
        if( has_shortname ) s << "]";
    }

    if( argstr.length() ) s << " <" << argstr << ">";
    return s.str();
}
template<typename T >
void ProgOptions::getArgs ( const std::string &  namestring,
std::vector< T > &  values 
)

Append the values of any required or optional arguments

Parameters:
namestringThe helpname that was given to addRequiredArg or addOptionalArgs.

Definition at line 608 of file ProgOptions.cpp.

References ProgOpt::args, error(), evaluate(), lookup(), required_args, and ProgOpt::type.

Referenced by test_optional_arg(), and test_optional_args().

{
    ProgOpt* opt = lookup( required_args, namestring );

    if( !opt ) { error( "Could not look up required arg: " + namestring ); }

    if( get_opt_type< T >() != opt->type ) { error( "Option '" + namestring + "' looked up with incompatible type" ); }

    values.resize( opt->args.size() );

    // These calls to evaluate are inefficient, because the arguments were evaluated when they were
    // parsed
    for( unsigned i = 0; i < opt->args.size(); ++i )
    {
        evaluate( *opt, &( values[i] ), "", &i );
    }
}
template<typename T >
bool ProgOptions::getOpt ( const std::string &  namestring,
T value 
)

Get the value of the named option.

Parameters:
namestringThe name string given when the option was created. This need not be idential to the created name; only the longname, or the shortname (with comma prefix), will also work.
valuePointer to location to store option argument, if any is found
Returns:
True if the option was set and its argument was stored into value; false otherwise.

Definition at line 536 of file ProgOptions.cpp.

References ProgOpt::args, error(), evaluate(), lookup_option(), and ProgOpt::type.

Referenced by main(), test_int_opt(), test_int_vect_opt(), test_real_opt(), test_string_opt(), and test_string_rank_subst().

{

    ProgOpt* opt = lookup_option( namestring );

    if( get_opt_type< T >() != opt->type ) { error( "Option '" + namestring + "' looked up with incompatible type" ); }

    // This call to evaluate is inefficient, because opt was already evaluated when it was parsed.
    if( opt->args.size() )
    {
        if( t ) evaluate( *opt, t, "" );
        return true;
    }
    else
        return false;
}
template<typename T >
void ProgOptions::getOptAllArgs ( const std::string &  namestring,
std::vector< T > &  values 
)

Get a list of values for the named option-- one value for each time it was given on the command line.

This function cannot be called with void as the template parameter; compilers will reject vector<void> as a type. This means it cannot be called for flag-type options. To count the number of times a given flag was specified, use numOptSet()

Parameters:
namestringSee similar argument to getOpt()
valuesReference to list to store values into. Will have as many entries as there were instances of this option on the command line
Examples:
GenLargeMesh.cpp.

Definition at line 554 of file ProgOptions.cpp.

References ProgOpt::args, error(), evaluate(), INT, INT_VECT, lookup_option(), and ProgOpt::type.

Referenced by main(), ToolContext::ParseCLOptions(), test_int_opt(), test_int_vect_opt(), test_real_opt(), test_string_opt(), and test_string_rank_subst().

{
    ProgOpt* opt = lookup_option( namestring );

    // special case: if user asks for list of int, but argument
    // was INT_VECT, concatenate all lists
    if( get_opt_type< T >() == INT && opt->type == INT_VECT )
    {
        for( unsigned i = 0; i < opt->args.size(); ++i )
            evaluate( *opt, &values, "", &i );
        return;
    }

    if( get_opt_type< T >() != opt->type ) { error( "Option '" + namestring + "' looked up with incompatible type" ); }

    values.resize( opt->args.size() );

    // These calls to evaluate are inefficient, because the arguments were evaluated when they were
    // parsed
    for( unsigned i = 0; i < opt->args.size(); ++i )
    {
        evaluate( *opt, &( values[i] ), "", &i );
    }
}
template<typename T >
T ProgOptions::getReqArg ( const std::string &  namestring)

Retrieve the value of a required command-line argument by name

Parameters:
namestringThe helpname that was given to addRequiredArg when the desired argument was created

Definition at line 593 of file ProgOptions.cpp.

References error(), evaluate(), lookup(), required_args, T, and value().

Referenced by test_int_arg(), test_int_vect_arg(), test_real_arg(), test_string_arg(), and test_string_rank_subst().

{

    ProgOpt* opt = lookup( required_args, namestring );

    if( !opt ) { error( "Could not look up required arg: " + namestring ); }

    // if parseProgramOptions succeeded, we can assume each required arg has a value,
    // so calling evaluate is valid
    T value;
    evaluate( *opt, &value, "" );
    return value;
}
ProgOpt * ProgOptions::lookup ( const std::map< std::string, ProgOpt * > &  table,
const std::string &  arg 
) [protected]

Definition at line 351 of file ProgOptions.cpp.

References long_names, number_option_name, and short_names.

Referenced by getArgs(), getReqArg(), lookup_option(), numOptSet(), and parseCommandLine().

{
    std::map< std::string, ProgOpt* >::const_iterator it = table.find( arg );
    if( it != table.end() )
        return it->second;
    else if( &table == &short_names && arg.size() == 1 && isdigit( arg[0] ) && !number_option_name.empty() &&
             ( it = long_names.find( number_option_name ) ) != long_names.end() )
        return it->second;
    else
        return 0;
}
ProgOpt * ProgOptions::lookup_option ( const std::string &  namestring) [protected]

Definition at line 363 of file ProgOptions.cpp.

References error(), get_namestrings(), long_names, lookup(), and short_names.

Referenced by getOpt(), and getOptAllArgs().

{
    std::string longname, shortname;
    get_namestrings( namestring, &longname, &shortname );

    ProgOpt* opt = lookup( long_names, longname );
    if( !opt ) opt = lookup( short_names, shortname );

    if( !opt ) { error( "Invalid option: " + namestring ); }

    return opt;
}
int ProgOptions::numOptSet ( const std::string &  namestring)
Parameters:
namestringSee similar argument to getOpt()
Returns:
The number of times the named option appeared on the command line.

Definition at line 579 of file ProgOptions.cpp.

References ProgOpt::args, error(), get_namestrings(), long_names, lookup(), and short_names.

Referenced by main(), ToolContext::ParseCLOptions(), test_flag_opt_long(), test_flag_opt_long_short(), test_flag_opt_short(), and test_squashed_short().

{
    std::string longname, shortname;
    get_namestrings( namestring, &longname, &shortname );

    ProgOpt* opt = lookup( long_names, longname );
    if( !opt ) opt = lookup( short_names, shortname );

    if( !opt ) { error( "Could not look up option: " + namestring ); }

    return opt->args.size();
}
void ProgOptions::parseCommandLine ( int  argc,
char *  argv[] 
)

Parse command-line inputs as given to main()

Examples:
addPCdata.cpp, ComputeTriDual.cpp, copyPartition.cpp, DirectAccessNoHoles.cpp, DirectAccessWithHoles.cpp, GenLargeMesh.cpp, LaplacianSmoother.cpp, and StructuredMeshSimple.cpp.

Definition at line 675 of file ProgOptions.cpp.

References arg_help_strings, args, ProgOpt::args, error(), evaluate(), expect_optional_args, FLAG, ProgOpt::flags, int_flag, long_names, lookup(), max_optional_args, optional_args_position, process_option(), progname, required_args, short_names, ProgOpt::storage, and ProgOpt::type.

Referenced by main(), ToolContext::ParseCLOptions(), test_flag_cancel(), test_flag_opt_long(), test_flag_opt_long_short(), test_flag_opt_short(), test_flag_store_false(), test_int_arg(), test_int_opt(), test_int_vect_arg(), test_int_vect_opt(), test_optional_arg(), test_optional_args(), test_real_arg(), test_real_opt(), test_squashed_short(), test_string_arg(), test_string_opt(), and test_string_rank_subst().

{
    const char* name = strrchr( argv[0], '/' );
    if( name )
        this->progname = ++name;
    else
        this->progname = argv[0];

    std::vector< const char* > args;
    std::list< ProgOpt* > expected_vals;
    bool no_more_flags = false;

    // Loop over all command line arguments
    for( int i = 1; i < argc; ++i )
    {
        std::string arg( argv[i] );
        if( arg.empty() ) continue;

        if( !expected_vals.empty() )
        {
            ProgOpt* opt = expected_vals.front();
            expected_vals.pop_front();
            assert( opt->type != FLAG );
            opt->args.push_back( arg );
            evaluate( *opt, opt->storage, arg );
        }
        else if( !no_more_flags && arg[0] == '-' )
        {
            if( arg.length() > 2 && arg[1] == '-' )
            {  // long opt
                size_t eq = arg.find_first_of( '=' );
                if( eq != std::string::npos )
                {
                    ProgOpt* opt = lookup( long_names, arg.substr( 2, eq - 2 ) );
                    process_option( opt, arg, arg.substr( eq + 1 ).c_str() );
                }
                else
                {
                    ProgOpt* opt = lookup( long_names, arg.substr( 2 ) );
                    if( process_option( opt, arg ) ) expected_vals.push_back( opt );
                }
            }
            else if( arg == "--" )
            {  // --
                no_more_flags = true;
            }
            else
                for( size_t f = 1; f < arg.length(); ++f )
                {  // for each short opt
                    ProgOpt* opt = lookup( short_names, std::string( 1, arg[f] ) );
                    if( opt && ( opt->flags & int_flag ) )
                    {
                        const char val[] = { arg[f], 0 };
                        process_option( opt, std::string( 1, arg[f] ), val );
                    }
                    else if( process_option( opt, std::string( 1, arg[f] ) ) )
                        expected_vals.push_back( opt );
                }
        }
        else
        {
            /* arguments */
            args.push_back( argv[i] );
        }
    } /* End loop over inputs */

    // Print error if any missing values
    if( !expected_vals.empty() )
    {
        error( "Missing value for option: -" + expected_vals.front()->shortname + ",--" +
               expected_vals.front()->longname );
    }

    // Process non-option arguments
    std::vector< help_line >::iterator arg_help_pos  = arg_help_strings.begin();
    std::vector< const char* >::iterator arg_val_pos = args.begin();
    std::vector< help_line >::iterator opt_args_pos  = arg_help_strings.end();
    size_t min_required_args                         = required_args.size();
    size_t max_required_args                         = required_args.size();
    if( expect_optional_args )
    {
        min_required_args--;
        if( max_optional_args )
            max_required_args += max_optional_args;
        else
            max_required_args = std::numeric_limits< int >::max();
        opt_args_pos = arg_help_pos + optional_args_position;
    }
    // check valid number of non-flag arguments
    if( args.size() < min_required_args )
    {
        size_t missing_pos = args.size();
        if( expect_optional_args && missing_pos >= optional_args_position ) ++missing_pos;

        const std::string& missed_arg = arg_help_strings[missing_pos].first->longname;
        error( "Did not find required positional argument: " + missed_arg );
    }
    else if( args.size() > max_required_args )
    {
        error( "Unexpected argument: " + std::string( args[max_required_args] ) );
    }

    // proccess arguments up to the first optional argument
    // (or all arguments if no optional args)
    while( arg_help_pos != opt_args_pos )
    {
        ProgOpt* opt = arg_help_pos->first;
        ++arg_help_pos;
        opt->args.push_back( *arg_val_pos );
        evaluate( *opt, opt->storage, *arg_val_pos );
        ++arg_val_pos;
    }
    // process any optional args
    if( arg_help_pos != arg_help_strings.end() )
    {
        assert( arg_help_pos == opt_args_pos );
        size_t num_opt_args = args.size() + 1 - required_args.size();
        ProgOpt* opt        = arg_help_pos->first;
        ++arg_help_pos;
        while( num_opt_args-- )
        {
            opt->args.push_back( *arg_val_pos );
            evaluate( *opt, opt->storage, *arg_val_pos );
            ++arg_val_pos;
        }
    }
    // process any remaining args
    while( arg_help_pos != arg_help_strings.end() )
    {
        assert( arg_val_pos != args.end() );
        ProgOpt* opt = arg_help_pos->first;
        ++arg_help_pos;
        opt->args.push_back( *arg_val_pos );
        evaluate( *opt, opt->storage, *arg_val_pos );
        ++arg_val_pos;
    }
    assert( arg_val_pos == args.end() );
}
void ProgOptions::printHelp ( std::ostream &  str = std::cout)

Print the full help to the given stream

Examples:
addPCdata.cpp, and copyPartition.cpp.

Definition at line 218 of file ProgOptions.cpp.

References arg_help_strings, brief_help, get_option_usage_prefix(), ProgOpt::longname, main_help, option_help_strings, and printUsage().

Referenced by main(), and process_option().

{

    /* Print introductory help text */
    if( !brief_help.empty() ) out << brief_help << std::endl;
    for( std::vector< std::string >::iterator i = main_help.begin(); i != main_help.end(); ++i )
    {
        if( ( *i ).length() ) { out << std::endl << *i << std::endl; }
    }

    printUsage( out );

    // max number of characters to pad argument/option names with
    // options with long names may exceed this, but will appear out of alignment in help text
    const int max_padding = 20;

    /* List required arguments, with help text */
    if( arg_help_strings.size() > 0 )
    {

        int max_arg_namelen = 0;

        for( std::vector< help_line >::iterator i = arg_help_strings.begin(); i != arg_help_strings.end(); ++i )
        {
            max_arg_namelen = std::max( max_arg_namelen, (int)( ( *i ).first->longname.length() ) );
        }

        max_arg_namelen = std::min( max_arg_namelen + 3, max_padding );

        out << "Arguments: " << std::endl;

        for( std::vector< help_line >::iterator i = arg_help_strings.begin(); i != arg_help_strings.end(); ++i )
        {
            ProgOpt* option   = ( *i ).first;
            std::string& info = ( *i ).second;

            std::stringstream s;
            s << "  " << option->longname;
            out << std::setw( max_arg_namelen ) << std::left << s.str();
            out << ": " << info << std::endl;
        }
    }

    /* List options, with help text */
    out << "Options: " << std::endl;
    int max_option_prefix_len = 0;

    for( std::vector< help_line >::iterator i = option_help_strings.begin(); i != option_help_strings.end(); ++i )
    {
        ProgOpt* option   = ( *i ).first;
        std::string& info = ( *i ).second;

        if( option )
        {

            if( max_option_prefix_len == 0 )
            {
                // iterate ahead in the option list to determine whitespace padding
                // stop if (*j).first is NULL, which indicates a help header message
                for( std::vector< help_line >::iterator j = i; j != option_help_strings.end() && ( *j ).first; ++j )
                {
                    int len               = get_option_usage_prefix( *( ( *j ).first ) ).length();
                    max_option_prefix_len = std::max( max_option_prefix_len, len );
                }
            }
            max_option_prefix_len     = std::min( max_option_prefix_len, max_padding );
            std::string option_prefix = get_option_usage_prefix( *option );

            out << std::setw( max_option_prefix_len ) << std::left << option_prefix;
            out << ": ";
        }
        else
        {
            // no option: this is a help header.  Reset max name length.
            max_option_prefix_len = 0;
        }
        out << info << std::endl;
    }
}
void ProgOptions::printUsage ( std::ostream &  str = std::cout)

Print only the usage message to the given stream

Definition at line 330 of file ProgOptions.cpp.

References arg_help_strings, expect_optional_args, moab::GeomUtil::first(), max_optional_args, optional_args_position, and progname.

Referenced by error(), and printHelp().

{

    out << "Usage: " << progname << " --help | [options] ";

    for( size_t i = 0; i < arg_help_strings.size(); ++i )
    {
        if( !expect_optional_args || i != optional_args_position )
            out << '<' << arg_help_strings[i].first->longname << "> ";
        else if( 0 == max_optional_args || max_optional_args > 3 )
            out << "[<" << arg_help_strings[i].first->longname << "> ...] ";
        else if( 1 == max_optional_args )
            out << "[" << arg_help_strings[i].first->longname << "] ";
        else
            for( unsigned j = 0; j < max_optional_args; ++j )
                out << "[" << arg_help_strings[i].first->longname << ( j + 1 ) << "] ";
    }

    out << std::endl;
}
void ProgOptions::printVersion ( std::ostream &  str = std::cout)

Print the version string to the given stream

Definition at line 213 of file ProgOptions.cpp.

References progversion.

Referenced by process_option().

{
    out << progversion << std::endl;
}
bool ProgOptions::process_option ( ProgOpt opt,
std::string  arg,
const char *  value = 0 
) [protected]

Definition at line 630 of file ProgOptions.cpp.

References ProgOpt::args, ProgOpt::cancel_opt, error(), evaluate(), FLAG, ProgOpt::flags, help_flag, printHelp(), printVersion(), ProgOpt::storage, store_false, ProgOpt::type, version_flag, and write_man_page().

Referenced by parseCommandLine().

{
    if( !opt )
    {
        if( arg == "--manpage" )
        {
            write_man_page( std::cout );
            exit( 0 );
        }

        error( "Unknown option: " + arg );
    }

    if( opt->flags & help_flag )
    {
        printHelp( std::cout );
        exit( EXIT_SUCCESS );
    }

    if( opt->flags & version_flag )
    {
        printVersion( std::cout );
        exit( EXIT_SUCCESS );
    }

    if( opt->type != FLAG )
    {
        if( !value ) return true;

        opt->args.push_back( value );
        evaluate( *opt, opt->storage, arg );
    }
    else
    {
        if( value ) { error( "Unexpected value for flag: " + arg ); }

        // do flag operations
        if( opt->cancel_opt ) { opt->cancel_opt->args.clear(); }
        if( opt->storage ) { *static_cast< bool* >( opt->storage ) = ( opt->flags & store_false ) ? false : true; }
        opt->args.push_back( "" );
    }

    return false;
}
void ProgOptions::setVersion ( const std::string &  version_string,
bool  addFlag = true 
)

Specify the program version

Set the program version to a given string. This will be printed when printVersion() is called.

Parameters:
version_stringThe version string
addflagIf true, a default '--version' option will be added. If false, the version will be set, but no option will be added to the parser.

Definition at line 128 of file ProgOptions.cpp.

References progversion, version_flag, and MBMesquite::version_string().

{
    progversion = version_string;
    if( addFlag ) { addOpt< void >( "version", "Print version number and exit", version_flag ); }
}
void ProgOptions::write_man_page ( std::ostream &  to_this_stream)

Write help data formatted for use as a unix man page.

Definition at line 814 of file ProgOptions.cpp.

References arg_help_strings, brief_help, expect_optional_args, FLAG, int_flag, main_help, max_optional_args, n, option_help_strings, optional_args_position, and progname.

Referenced by process_option().

{
    // a leading '.' is a control character.  strip it if present.
    std::string lprogname;
    if( progname.empty() || progname[0] != '.' )
        lprogname = progname;
    else
    {
        lprogname = progname.substr( 1 );
    }

    // Manpage controls:
    // .TH title
    // .SH section
    // .SS subsection
    // .P  paragraph
    // .HP hanging paragraph
    // .B  bold
    // .I  italic
    // .B  bold
    // .I  italic
    // .RS begin indent
    // .RE end indent
    // .RB alternating roman and blold
    // .BR alternating bold and roman

    std::vector< help_line >::iterator it;
    std::set< ProgOpt* > skip_list;

    // start man page
    s << std::endl << ".TH " << lprogname << " 1" << std::endl;

    // write NAME section
    s << std::endl << ".SH NAME" << std::endl << ".P " << std::endl << lprogname << " \\- ";
    if( brief_help.empty() && !main_help.empty() )
        s << main_help.front();
    else
        s << brief_help;
    s << std::endl << std::endl;

    // write SYNOPSIS section
    s << std::endl << ".SH SYNOPSIS" << std::endl << ".HP" << std::endl << ".B \"" << lprogname << '"' << std::endl;
    for( it = option_help_strings.begin(); it != option_help_strings.end(); ++it )
    {
        if( !it->first || skip_list.find( it->first ) != skip_list.end() || it->first->longname == "help" ) continue;

        if( it->first->type == FLAG )
        {
            char c = '[';
            s << ".RB";
            if( !it->first->shortname.empty() )
            {
                s << ' ' << c << " \"-" << it->first->shortname << '"';
                c = '|';
            }
            if( !it->first->longname.empty() ) { s << ' ' << c << " \"--" << it->first->longname << '"'; }
            if( it->first->cancel_opt )
            {
                skip_list.insert( it->first->cancel_opt );
                if( !it->first->cancel_opt->shortname.empty() )
                    s << " | \"-" << it->first->cancel_opt->shortname << '"';
                if( !it->first->cancel_opt->longname.empty() ) s << " | \"--" << it->first->cancel_opt->longname << '"';
            }
            s << " ]" << std::endl;
        }
        else if( it->first->flags & int_flag )
        {
            s << ".RB [ - <n>| \"--" << it->first->longname << "\" \"=" << it->first->get_argstring() << "]\""
              << std::endl;
        }
        else
        {
            s << ".RB [ ";
            if( !it->first->shortname.empty() )
                s << "\"-" << it->first->shortname << "\" \"\\ " << it->first->get_argstring();
            if( !it->first->shortname.empty() && !it->first->longname.empty() ) s << "|\" ";
            if( !it->first->longname.empty() )
                s << "\"--" << it->first->longname << "\" \"=" << it->first->get_argstring();
            s << "]\"" << std::endl;
        }
    }
    for( it = arg_help_strings.begin(); it != arg_help_strings.end(); ++it )
    {
        if( !it->first ) continue;

        if( !expect_optional_args || (unsigned)( it - arg_help_strings.begin() ) != optional_args_position )
            s << it->first->longname << ' ';
        else if( 1 == max_optional_args )
            s << '[' << it->first->longname << "] ";
        else
            s << '[' << it->first->longname << " ...] ";
    }
    s << std::endl;
    s << ".HP" << std::endl << ".B \"" << lprogname << " -h|--help\"" << std::endl;

    // write DESCRIPTION section
    s << std::endl << ".SH DESCRIPTION" << std::endl;
    if( main_help.empty() ) s << brief_help << std::endl;
    for( size_t i = 0; i < main_help.size(); ++i )
    {
        const std::string::size_type n = main_help[i].size();
        std::string::size_type j       = 0, k;
        s << std::endl << ".P" << std::endl;
        while( j != n )
        {
            if( main_help[i][j] == '\n' )
            {
                s << std::endl << ".P" << std::endl;
                ++j;
                continue;
            }
            k = main_help[i].find( "\n", j );
            if( k == std::string::npos ) k = n;
            if( main_help[i][j] == '.' ) s << '\\';
            s << main_help[i].substr( j, k - j );
            j = k;
        }
    }

    // write OPTIONS section
    s << std::endl << ".SH OPTIONS" << std::endl;
    for( it = arg_help_strings.begin(); it != arg_help_strings.end(); ++it )
    {
        if( it->first )
            s << ".IP \"" << it->first->longname << '"' << std::endl << it->second << std::endl;
        else
            s << ".SS " << it->first->longname << std::endl;
    }
    for( it = option_help_strings.begin(); it != option_help_strings.end(); ++it )
    {
        if( !it->first )
        {
            s << ".SS " << it->second << std::endl;
            continue;
        }

        s << ".IP \"";
        if( it->first->longname.empty() )
            s << "-" << it->first->shortname;
        else if( it->first->shortname.empty() )
            s << "--" << it->first->longname;
        else
            s << "-" << it->first->shortname << ", --" << it->first->longname;
        s << '"' << std::endl << it->second << std::endl;
    }
    s << std::endl;
}

Member Data Documentation

const int ProgOptions::add_cancel_opt = 1 << 1 [static]

Flag indicating that an option should be given a "cancel" flag. This creates, for option --foo, an additional option --no-foo that clears all previously read instances of the foo option

Definition at line 51 of file ProgOptions.hpp.

Referenced by addOpt(), main(), and test_flag_cancel().

std::string ProgOptions::brief_help [protected]

Definition at line 264 of file ProgOptions.hpp.

Referenced by printHelp(), ProgOptions(), and write_man_page().

const int ProgOptions::help_flag = 1 << 0 [static]

Flags for addOpt and addRequiredArg functions; may be combined with bitwise arithmetic (though not all combinations make sense!) Set for a flag that, when detected, prints help text and halts program. Constructor creates such a flag by default, so the user shouldn't need to use this directly.

Definition at line 46 of file ProgOptions.hpp.

Referenced by process_option(), and ProgOptions().

const int ProgOptions::int_flag = 1 << 3 [static]

Specify a numerical flag where any positive integer is an acceptable value. E.g. --dimension=3 is equivalent to -3. Only values in the range [0,9] are accepted and the flag type must be integer.

Definition at line 61 of file ProgOptions.hpp.

Referenced by addOpt(), get_option_usage_prefix(), main(), parse_options(), parseCommandLine(), and write_man_page().

std::map< std::string, ProgOpt* > ProgOptions::long_names [protected]

Definition at line 256 of file ProgOptions.hpp.

Referenced by addOpt(), lookup(), lookup_option(), numOptSet(), and parseCommandLine().

std::vector< std::string > ProgOptions::main_help [protected]

Definition at line 263 of file ProgOptions.hpp.

Referenced by printHelp(), ProgOptions(), and write_man_page().

unsigned ProgOptions::max_optional_args [protected]

Definition at line 267 of file ProgOptions.hpp.

Referenced by addOptionalArgs(), parseCommandLine(), printUsage(), and write_man_page().

std::string ProgOptions::number_option_name [protected]

Definition at line 274 of file ProgOptions.hpp.

Referenced by addOpt(), and lookup().

std::vector< help_line > ProgOptions::option_help_strings [protected]

Definition at line 267 of file ProgOptions.hpp.

Referenced by addOptionalArgs(), parseCommandLine(), printUsage(), and write_man_page().

std::string ProgOptions::progname [protected]

Definition at line 269 of file ProgOptions.hpp.

Referenced by parseCommandLine(), printUsage(), and write_man_page().

std::string ProgOptions::progversion [protected]

Definition at line 270 of file ProgOptions.hpp.

Referenced by printVersion(), and setVersion().

const int ProgOptions::rank_subst = 1 << 4 [static]

Substitue any occurance of the '' symbol in a string with the the MPI rank of this process in MPI_COMM_WORLD. This option has no effect if not compiled with MPI. This flag has no effect for non-string options.

Definition at line 68 of file ProgOptions.hpp.

Referenced by evaluate(), and test_string_rank_subst().

std::map< std::string, ProgOpt* > ProgOptions::required_args [protected]
std::map< std::string, ProgOpt* > ProgOptions::short_names [protected]

Definition at line 257 of file ProgOptions.hpp.

Referenced by addOpt(), lookup(), lookup_option(), numOptSet(), and parseCommandLine().

const int ProgOptions::store_false = 1 << 2 [static]

When applied to a flag argument (one with template type void), indicate that the value 'false' should be stored into the pointer that was given at option creation time. This overrides the default behavior, which is to store the value 'true'.

Definition at line 56 of file ProgOptions.hpp.

Referenced by addOpt(), process_option(), and test_flag_store_false().

const int ProgOptions::version_flag = 1 << 5 [static]

Set for a flag that, when detected, will call printVersion() and halt the program.

Definition at line 71 of file ProgOptions.hpp.

Referenced by process_option(), and setVersion().

List of all members.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines