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
00166 void _constructor();
00167
00168
00173 bool _userSetOutput;
00174
00178 bool _helpAndVersion;
00179
00180 public:
00181
00194 CmdLine(const std::string& message,
00195 const char delimiter = ' ',
00196 const std::string& version = "none",
00197 bool helpAndVersion = true);
00198
00202 virtual ~CmdLine();
00203
00208 void add( Arg& a );
00209
00214 void add( Arg* a );
00215
00222 void xorAdd( Arg& a, Arg& b );
00223
00229 void xorAdd( std::vector<Arg*>& xors );
00230
00236 void parse(int argc, const char * const * argv);
00237
00243 void parse(std::vector<std::string>& args);
00244
00248 CmdLineOutput* getOutput();
00249
00253 void setOutput(CmdLineOutput* co);
00254
00258 std::string& getVersion();
00259
00263 std::string& getProgramName();
00264
00268 std::list<Arg*>& getArgList();
00269
00273 XorHandler& getXorHandler();
00274
00278 char getDelimiter();
00279
00283 std::string& getMessage();
00284
00288 bool hasHelpAndVersion();
00289
00295 void setExceptionHandling(const bool state);
00296
00303 bool getExceptionHandling() const;
00304
00308 void reset();
00309
00310 };
00311
00312
00314
00316
00317 inline CmdLine::CmdLine(const std::string& m,
00318 char delim,
00319 const std::string& v,
00320 bool help )
00321 : _progName("not_set_yet"),
00322 _message(m),
00323 _version(v),
00324 _numRequired(0),
00325 _delimiter(delim),
00326 _handleExceptions(true),
00327 _userSetOutput(false),
00328 _helpAndVersion(help)
00329 {
00330 _constructor();
00331 }
00332
00333 inline CmdLine::~CmdLine()
00334 {
00335 ClearContainer(_argDeleteOnExitList);
00336 ClearContainer(_visitorDeleteOnExitList);
00337
00338 if ( !_userSetOutput ) {
00339 delete _output;
00340 _output = 0;
00341 }
00342 }
00343
00344 inline void CmdLine::_constructor()
00345 {
00346 _output = new StdOutput;
00347
00348 Arg::setDelimiter( _delimiter );
00349
00350 Visitor* v;
00351
00352 if ( _helpAndVersion )
00353 {
00354 v = new HelpVisitor( this, &_output );
00355 SwitchArg* help = new SwitchArg("h","help",
00356 "Displays usage information and exits.",
00357 false, v);
00358 add( help );
00359 deleteOnExit(help);
00360 deleteOnExit(v);
00361
00362 v = new VersionVisitor( this, &_output );
00363 SwitchArg* vers = new SwitchArg("","version",
00364 "Displays version information and exits.",
00365 false, v);
00366 add( vers );
00367 deleteOnExit(vers);
00368 deleteOnExit(v);
00369 }
00370
00371 v = new IgnoreRestVisitor();
00372 SwitchArg* ignore = new SwitchArg(Arg::flagStartString(),
00373 Arg::ignoreNameString(),
00374 "Ignores the rest of the labeled arguments following this flag.",
00375 false, v);
00376 add( ignore );
00377 deleteOnExit(ignore);
00378 deleteOnExit(v);
00379 }
00380
00381 inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
00382 {
00383 _xorHandler.add( ors );
00384
00385 for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
00386 {
00387 (*it)->forceRequired();
00388 (*it)->setRequireLabel( "OR required" );
00389
00390 add( *it );
00391 }
00392 }
00393
00394 inline void CmdLine::xorAdd( Arg& a, Arg& b )
00395 {
00396 std::vector<Arg*> ors;
00397 ors.push_back( &a );
00398 ors.push_back( &b );
00399 xorAdd( ors );
00400 }
00401
00402 inline void CmdLine::add( Arg& a )
00403 {
00404 add( &a );
00405 }
00406
00407 inline void CmdLine::add( Arg* a )
00408 {
00409 for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
00410 if ( *a == *(*it) )
00411 throw( SpecificationException(
00412 "Argument with same flag/name already exists!",
00413 a->longID() ) );
00414
00415 a->addToList( _argList );
00416
00417 if ( a->isRequired() )
00418 _numRequired++;
00419 }
00420
00421
00422 inline void CmdLine::parse(int argc, const char * const * argv)
00423 {
00424
00425
00426 std::vector<std::string> args;
00427 for (int i = 0; i < argc; i++)
00428 args.push_back(argv[i]);
00429
00430 parse(args);
00431 }
00432
00433 inline void CmdLine::parse(std::vector<std::string>& args)
00434 {
00435 bool shouldExit = false;
00436 int estat = 0;
00437
00438 try {
00439 _progName = args.front();
00440 args.erase(args.begin());
00441
00442 int requiredCount = 0;
00443
00444 for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) {
00445 bool matched = false;
00446 for (ArgListIterator it = _argList.begin();
00447 it != _argList.end(); it++) {
00448 if ( (*it)->processArg( &i, args ) )
00449 {
00450 requiredCount += _xorHandler.check( *it );
00451 matched = true;
00452 break;
00453 }
00454 }
00455
00456
00457
00458 if ( !matched && _emptyCombined( args[i] ) )
00459 matched = true;
00460
00461 if ( !matched && !Arg::ignoreRest() )
00462 throw(CmdLineParseException("Couldn't find match "
00463 "for argument",
00464 args[i]));
00465 }
00466
00467 if ( requiredCount < _numRequired )
00468 missingArgsException();
00469
00470 if ( requiredCount > _numRequired )
00471 throw(CmdLineParseException("Too many arguments!"));
00472
00473 } catch ( ArgException& e ) {
00474
00475 if ( !_handleExceptions) {
00476 throw;
00477 }
00478
00479 try {
00480 _output->failure(*this,e);
00481 } catch ( ExitException &ee ) {
00482 estat = ee.getExitStatus();
00483 shouldExit = true;
00484 }
00485 } catch (ExitException &ee) {
00486
00487 if ( !_handleExceptions) {
00488 throw;
00489 }
00490
00491 estat = ee.getExitStatus();
00492 shouldExit = true;
00493 }
00494
00495 if (shouldExit)
00496 exit(estat);
00497 }
00498
00499 inline bool CmdLine::_emptyCombined(const std::string& s)
00500 {
00501 if ( s.length() > 0 && s[0] != Arg::flagStartChar() )
00502 return false;
00503
00504 for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
00505 if ( s[i] != Arg::blankChar() )
00506 return false;
00507
00508 return true;
00509 }
00510
00511 inline void CmdLine::missingArgsException()
00512 {
00513 int count = 0;
00514
00515 std::string missingArgList;
00516 for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
00517 {
00518 if ( (*it)->isRequired() && !(*it)->isSet() )
00519 {
00520 missingArgList += (*it)->getName();
00521 missingArgList += ", ";
00522 count++;
00523 }
00524 }
00525 missingArgList = missingArgList.substr(0,missingArgList.length()-2);
00526
00527 std::string msg;
00528 if ( count > 1 )
00529 msg = "Required arguments missing: ";
00530 else
00531 msg = "Required argument missing: ";
00532
00533 msg += missingArgList;
00534
00535 throw(CmdLineParseException(msg));
00536 }
00537
00538 inline void CmdLine::deleteOnExit(Arg* ptr)
00539 {
00540 _argDeleteOnExitList.push_back(ptr);
00541 }
00542
00543 inline void CmdLine::deleteOnExit(Visitor* ptr)
00544 {
00545 _visitorDeleteOnExitList.push_back(ptr);
00546 }
00547
00548 inline CmdLineOutput* CmdLine::getOutput()
00549 {
00550 return _output;
00551 }
00552
00553 inline void CmdLine::setOutput(CmdLineOutput* co)
00554 {
00555 _userSetOutput = true;
00556 _output = co;
00557 }
00558
00559 inline std::string& CmdLine::getVersion()
00560 {
00561 return _version;
00562 }
00563
00564 inline std::string& CmdLine::getProgramName()
00565 {
00566 return _progName;
00567 }
00568
00569 inline std::list<Arg*>& CmdLine::getArgList()
00570 {
00571 return _argList;
00572 }
00573
00574 inline XorHandler& CmdLine::getXorHandler()
00575 {
00576 return _xorHandler;
00577 }
00578
00579 inline char CmdLine::getDelimiter()
00580 {
00581 return _delimiter;
00582 }
00583
00584 inline std::string& CmdLine::getMessage()
00585 {
00586 return _message;
00587 }
00588
00589 inline bool CmdLine::hasHelpAndVersion()
00590 {
00591 return _helpAndVersion;
00592 }
00593
00594 inline void CmdLine::setExceptionHandling(const bool state)
00595 {
00596 _handleExceptions = state;
00597 }
00598
00599 inline bool CmdLine::getExceptionHandling() const
00600 {
00601 return _handleExceptions;
00602 }
00603
00604 inline void CmdLine::reset()
00605 {
00606 for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
00607 {
00608 (*it)->reset();
00609 }
00610
00611 _progName.clear();
00612 }
00613
00615
00617
00618
00619
00620 }
00621 #endif