nils
nils

Reputation: 2524

"Conditional" parsing of command-line arguments

Say I have an executable (running on mac, win, and linux)

 a.out [-a] [-b] [-r -i <file> -o <file> -t <double> -n <int> ]

where an argument in [ ] means that it is optional. However, if the last argument -r is set then -i,-o,-t, and -n have to be supplied, too.

There are lots of good C++-libraries out there to parse command-line arguments, e.g. gflags (http://code.google.com/p/gflags/), tclap (http://tclap.sourceforge.net/), simpleopt(http://code.jellycan.com/simpleopt/), boost.program_options (http://www.boost.org/doc/libs/1_52_0/doc/html/program_options.html), etc. But I wondered if there is one that lets me encode these conditional relationships between arguments directly, w/o manually coding error handling

if ( argR.isSet() && ( ! argI.isSet() || ! argO.isSet() || ... ) ) ...

and manually setting up the --help.

The library tclap allows to XOR arguments, e.g. either -a or -b is allowed but not both. So, in that terminology an AND for arguments would be nice.

Does anybody know a versatile, light-weight, and cross-platform library that can do that?

Upvotes: 9

Views: 2266

Answers (4)

350740378
350740378

Reputation: 11

do you want to parse a command line?you can use simpleopt,it can be used as followings:downLoad simpleopt from: https://code.google.com/archive/p/simpleopt/downloads

test: int _tmain(int argc, TCHAR * argv[]) argv can be:1.txt 2.txt *.cpp

Upvotes: -1

Sean
Sean

Reputation: 10216

I have part of the TCLAP snippet of code lying around that seems to fit the error handling portion that you're looking for, however it doesn't match exactly what you're looking for:

# include "tclap/CmdLine.h"

namespace TCLAP {

class RequiredDependentArgException : public ArgException {
public:
  /**
   * Constructor.
   * \param text - The text of the exception.
   * \param parentArg - The text identifying the parent argument source
   * \param dependentArg - The text identifying the required dependent argument
   * of the exception.
   */
  RequiredDependentArgException(
    const TCLAP::Arg& parentArg,
    const TCLAP::Arg& requiredArg)
  : ArgException(
    std::string( "Required argument ") +
    requiredArg.toString() +
    std::string(" missing when the ") +
    parentArg.toString() +
    std::string(" flag is specified."),
    requiredArg.toString())
  { }
};

} // namespace TCLAP

And then make use of the new exception after TCLAP::CmdLine::parse has been called:

if (someArg.isSet() && !conditionallyRequiredArg.isSet()) {
  throw(TCLAP::RequiredDependentArgException(someArg, conditionallyRequiredArg));
}

I remember looking in to extending and adding an additional class that would handle this logic, but then I realized the only thing I was actually looking for was nice error reporting because the logic wasn't entirely straightforward and couldn't be easily condensed (at least, not in a way that was useful to the next poor guy who came along). A contrived scenario dissuaded me from pursuing it further, something to the effect of, "if A is true, B must be set but C can't be set if D is of value N." Expressing such things in native C++ is the way to go, especially when it comes time to do very strict argument checks at CLI arg parse time.

For truly pathological cases and requirements, create a state machine using something like Boost.MSM (Multi-State Machine). HTH.

Upvotes: 0

DSimon
DSimon

Reputation: 3420

You could change the argument syntax so that -r takes four values in a row.

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409206

You could two passes over the arguments; If -r is in the options you reset the parser and start over with the new mandatory options added.


You could also look into how the TCLAP XorHandler works, and create your own AndHandler.

Upvotes: 2

Related Questions