00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef TCLAP_CMDLINE_H
00025 #define TCLAP_CMDLINE_H
00026
00027 #include <tclap/SwitchArg.h>
00028 #include <tclap/MultiSwitchArg.h>
00029 #include <tclap/UnlabeledValueArg.h>
00030 #include <tclap/UnlabeledMultiArg.h>
00031
00032 #include <tclap/XorHandler.h>
00033 #include <tclap/HelpVisitor.h>
00034 #include <tclap/VersionVisitor.h>
00035 #include <tclap/IgnoreRestVisitor.h>
00036
00037 #include <tclap/CmdLineOutput.h>
00038 #include <tclap/StdOutput.h>
00039
00040 #include <tclap/Constraint.h>
00041 #include <tclap/ValuesConstraint.h>
00042
00043 #include <string>
00044 #include <vector>
00045 #include <list>
00046 #include <iostream>
00047 #include <iomanip>
00048 #include <algorithm>
00049 #include <stdlib.h>
00050
00051 namespace TCLAP {
00052
00053 template<typename T> void DelPtr(T ptr)
00054 {
00055 delete ptr;
00056 }
00057
00058 template<typename C> void ClearContainer(C &c)
00059 {
00060 typedef typename C::value_type value_type;
00061 std::for_each(c.begin(), c.end(), DelPtr<value_type>);
00062 c.clear();
00063 }
00064
00065
00070 class CmdLine : public CmdLineInterface
00071 {
00072 protected:
00073
00078 std::list<Arg*> _argList;
00079
00083 std::string _progName;
00084
00088 std::string _message;
00089
00093 std::string _version;
00094
00100 int _numRequired;
00101
00106 char _delimiter;
00107
00111 XorHandler _xorHandler;
00112
00118 std::list<Arg*> _argDeleteOnExitList;
00119
00125 std::list<Visitor*> _visitorDeleteOnExitList;
00126
00130 CmdLineOutput* _output;
00131
00135 bool _handleExceptions;
00136
00140 void missingArgsException();
00141
00148 bool _emptyCombined(const std::string& s);
00149
00153 void deleteOnExit(Arg* ptr);
00154
00158 void deleteOnExit(Visitor* ptr);
00159
00160 private:
00161
00165 CmdLine(const CmdLine& rhs);
00166 CmdLine& operator=(const CmdLine& rhs);
00167
00172 void _constructor();
00173
00174
00179 bool _userSetOutput;
00180
00184 bool _helpAndVersion;
00185
00186 public:
00187
00200 CmdLine(const std::string& message,
00201 const char delimiter = ' ',
00202 const std::string& version = "none",
00203 bool helpAndVersion = true);
00204
00208 virtual ~CmdLine();
00209
00214 void add( Arg& a );
00215
00220 void add( Arg* a );
00221
00228 void xorAdd( Arg& a, Arg& b );
00229
00235 void xorAdd( std::vector<Arg*>& xors );
00236
00242 void parse(int argc, const char * const * argv);
00243
00249 void parse(std::vector<std::string>& args);
00250
00254 CmdLineOutput* getOutput();
00255
00259 void setOutput(CmdLineOutput* co);
00260
00264 std::string& getVersion();
00265
00269 std::string& getProgramName();
00270
00274 std::list<Arg*>& getArgList();
00275
00279 XorHandler& getXorHandler();
00280
00284 char getDelimiter();
00285
00289 std::string& getMessage();
00290
00294 bool hasHelpAndVersion();
00295
00301 void setExceptionHandling(const bool state);
00302
00309 bool getExceptionHandling() const;
00310
00314 void reset();
00315
00316 };
00317
00318
00320
00322
00323 inline CmdLine::CmdLine(const std::string& m,
00324 char delim,
00325 const std::string& v,
00326 bool help )
00327 :
00328 _argList(std::list<Arg*>()),
00329 _progName("not_set_yet"),
00330 _message(m),
00331 _version(v),
00332 _numRequired(0),
00333 _delimiter(delim),
00334 _xorHandler(XorHandler()),
00335 _argDeleteOnExitList(std::list<Arg*>()),
00336 _visitorDeleteOnExitList(std::list<Visitor*>()),
00337 _output(0),
00338 _handleExceptions(true),
00339 _userSetOutput(false),
00340 _helpAndVersion(help)
00341 {
00342 _constructor();
00343 }
00344
00345 inline CmdLine::~CmdLine()
00346 {
00347 ClearContainer(_argDeleteOnExitList);
00348 ClearContainer(_visitorDeleteOnExitList);
00349
00350 if ( !_userSetOutput ) {
00351 delete _output;
00352 _output = 0;
00353 }
00354 }
00355
00356 inline void CmdLine::_constructor()
00357 {
00358 _output = new StdOutput;
00359
00360 Arg::setDelimiter( _delimiter );
00361
00362 Visitor* v;
00363
00364 if ( _helpAndVersion )
00365 {
00366 v = new HelpVisitor( this, &_output );
00367 SwitchArg* help = new SwitchArg("h","help",
00368 "Displays usage information and exits.",
00369 false, v);
00370 add( help );
00371 deleteOnExit(help);
00372 deleteOnExit(v);
00373
00374 v = new VersionVisitor( this, &_output );
00375 SwitchArg* vers = new SwitchArg("","version",
00376 "Displays version information and exits.",
00377 false, v);
00378 add( vers );
00379 deleteOnExit(vers);
00380 deleteOnExit(v);
00381 }
00382
00383 v = new IgnoreRestVisitor();
00384 SwitchArg* ignore = new SwitchArg(Arg::flagStartString(),
00385 Arg::ignoreNameString(),
00386 "Ignores the rest of the labeled arguments following this flag.",
00387 false, v);
00388 add( ignore );
00389 deleteOnExit(ignore);
00390 deleteOnExit(v);
00391 }
00392
00393 inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
00394 {
00395 _xorHandler.add( ors );
00396
00397 for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
00398 {
00399 (*it)->forceRequired();
00400 (*it)->setRequireLabel( "OR required" );
00401 add( *it );
00402 }
00403 }
00404
00405 inline void CmdLine::xorAdd( Arg& a, Arg& b )
00406 {
00407 std::vector<Arg*> ors;
00408 ors.push_back( &a );
00409 ors.push_back( &b );
00410 xorAdd( ors );
00411 }
00412
00413 inline void CmdLine::add( Arg& a )
00414 {
00415 add( &a );
00416 }
00417
00418 inline void CmdLine::add( Arg* a )
00419 {
00420 for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
00421 if ( *a == *(*it) )
00422 throw( SpecificationException(
00423 "Argument with same flag/name already exists!",
00424 a->longID() ) );
00425
00426 a->addToList( _argList );
00427
00428 if ( a->isRequired() )
00429 _numRequired++;
00430 }
00431
00432
00433 inline void CmdLine::parse(int argc, const char * const * argv)
00434 {
00435
00436
00437 std::vector<std::string> args;
00438 for (int i = 0; i < argc; i++)
00439 args.push_back(argv[i]);
00440
00441 parse(args);
00442 }
00443
00444 inline void CmdLine::parse(std::vector<std::string>& args)
00445 {
00446 bool shouldExit = false;
00447 int estat = 0;
00448
00449 try {
00450 _progName = args.front();
00451 args.erase(args.begin());
00452
00453 int requiredCount = 0;
00454
00455 for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
00456 {
00457 bool matched = false;
00458 for (ArgListIterator it = _argList.begin();
00459 it != _argList.end(); it++) {
00460 if ( (*it)->processArg( &i, args ) )
00461 {
00462 requiredCount += _xorHandler.check( *it );
00463 matched = true;
00464 break;
00465 }
00466 }
00467
00468
00469
00470 if ( !matched && _emptyCombined( args[i] ) )
00471 matched = true;
00472
00473 if ( !matched && !Arg::ignoreRest() )
00474 throw(CmdLineParseException("Couldn't find match "
00475 "for argument",
00476 args[i]));
00477 }
00478
00479 if ( requiredCount < _numRequired )
00480 missingArgsException();
00481
00482 if ( requiredCount > _numRequired )
00483 throw(CmdLineParseException("Too many arguments!"));
00484
00485 } catch ( ArgException& e ) {
00486
00487 if ( !_handleExceptions) {
00488 throw;
00489 }
00490
00491 try {
00492 _output->failure(*this,e);
00493 } catch ( ExitException &ee ) {
00494 estat = ee.getExitStatus();
00495 shouldExit = true;
00496 }
00497 } catch (ExitException &ee) {
00498
00499 if ( !_handleExceptions) {
00500 throw;
00501 }
00502
00503 estat = ee.getExitStatus();
00504 shouldExit = true;
00505 }
00506
00507 if (shouldExit)
00508 exit(estat);
00509 }
00510
00511 inline bool CmdLine::_emptyCombined(const std::string& s)
00512 {
00513 if ( s.length() > 0 && s[0] != Arg::flagStartChar() )
00514 return false;
00515
00516 for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
00517 if ( s[i] != Arg::blankChar() )
00518 return false;
00519
00520 return true;
00521 }
00522
00523 inline void CmdLine::missingArgsException()
00524 {
00525 int count = 0;
00526
00527 std::string missingArgList;
00528 for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
00529 {
00530 if ( (*it)->isRequired() && !(*it)->isSet() )
00531 {
00532 missingArgList += (*it)->getName();
00533 missingArgList += ", ";
00534 count++;
00535 }
00536 }
00537 missingArgList = missingArgList.substr(0,missingArgList.length()-2);
00538
00539 std::string msg;
00540 if ( count > 1 )
00541 msg = "Required arguments missing: ";
00542 else
00543 msg = "Required argument missing: ";
00544
00545 msg += missingArgList;
00546
00547 throw(CmdLineParseException(msg));
00548 }
00549
00550 inline void CmdLine::deleteOnExit(Arg* ptr)
00551 {
00552 _argDeleteOnExitList.push_back(ptr);
00553 }
00554
00555 inline void CmdLine::deleteOnExit(Visitor* ptr)
00556 {
00557 _visitorDeleteOnExitList.push_back(ptr);
00558 }
00559
00560 inline CmdLineOutput* CmdLine::getOutput()
00561 {
00562 return _output;
00563 }
00564
00565 inline void CmdLine::setOutput(CmdLineOutput* co)
00566 {
00567 if ( !_userSetOutput )
00568 delete _output;
00569 _userSetOutput = true;
00570 _output = co;
00571 }
00572
00573 inline std::string& CmdLine::getVersion()
00574 {
00575 return _version;
00576 }
00577
00578 inline std::string& CmdLine::getProgramName()
00579 {
00580 return _progName;
00581 }
00582
00583 inline std::list<Arg*>& CmdLine::getArgList()
00584 {
00585 return _argList;
00586 }
00587
00588 inline XorHandler& CmdLine::getXorHandler()
00589 {
00590 return _xorHandler;
00591 }
00592
00593 inline char CmdLine::getDelimiter()
00594 {
00595 return _delimiter;
00596 }
00597
00598 inline std::string& CmdLine::getMessage()
00599 {
00600 return _message;
00601 }
00602
00603 inline bool CmdLine::hasHelpAndVersion()
00604 {
00605 return _helpAndVersion;
00606 }
00607
00608 inline void CmdLine::setExceptionHandling(const bool state)
00609 {
00610 _handleExceptions = state;
00611 }
00612
00613 inline bool CmdLine::getExceptionHandling() const
00614 {
00615 return _handleExceptions;
00616 }
00617
00618 inline void CmdLine::reset()
00619 {
00620 for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
00621 (*it)->reset();
00622
00623 _progName.clear();
00624 }
00625
00627
00629
00630
00631
00632 }
00633 #endif