00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef TCLAP_CMDLINE_H
00024 #define TCLAP_CMDLINE_H
00025
00026 #include <tclap/SwitchArg.h>
00027 #include <tclap/UnlabeledValueArg.h>
00028 #include <tclap/UnlabeledMultiArg.h>
00029
00030 #include <tclap/XorHandler.h>
00031 #include <tclap/HelpVisitor.h>
00032 #include <tclap/VersionVisitor.h>
00033 #include <tclap/IgnoreRestVisitor.h>
00034
00035 #include <string>
00036 #include <vector>
00037 #include <list>
00038 #include <iostream>
00039 #include <algorithm>
00040
00041 namespace TCLAP {
00042
00047 class CmdLine : public CmdLineInterface
00048 {
00049 protected:
00050
00055 std::list<Arg*> _argList;
00056
00060 std::string _progName;
00061
00065 std::string _message;
00066
00070 std::string _version;
00071
00077 int _numRequired;
00078
00083 char _delimiter;
00084
00088 XorHandler _xorHandler;
00089
00095 std::list<Arg*> _argDeleteOnExitList;
00096
00102 std::list<Visitor*> _visitorDeleteOnExitList;
00103
00110 bool _emptyCombined(const std::string& s);
00111
00116 void _shortUsage( std::ostream& os );
00117
00123 void _longUsage( std::ostream& os );
00124
00125 private:
00126
00131 void _constructor();
00132
00136 void deleteOnExit(Arg* ptr);
00137
00141 void deleteOnExit(Visitor* ptr);
00142
00143 public:
00144
00155 CmdLine(const std::string& name,
00156 const std::string& message,
00157 const std::string& version = "none" );
00158
00169 CmdLine(const std::string& message,
00170 const char delimiter = ' ',
00171 const std::string& version = "none" );
00172
00176 virtual ~CmdLine();
00177
00182 void add( Arg& a );
00183
00188 void add( Arg* a );
00189
00196 void xorAdd( Arg& a, Arg& b );
00197
00203 void xorAdd( std::vector<Arg*>& xors );
00204
00210 virtual void usage( int exitVal = 0 );
00211
00217 virtual void version( int exitVal = 0 );
00218
00224 virtual void failure( const ArgException& e );
00225
00231 void parse(int argc, char** argv);
00232 };
00233
00234
00236
00238
00239 inline CmdLine::CmdLine(const std::string& n,
00240 const std::string& m,
00241 const std::string& v )
00242 : _progName(n),
00243 _message(m),
00244 _version(v),
00245 _numRequired(0),
00246 _delimiter(' ')
00247 {
00248 _constructor();
00249 }
00250
00251 inline CmdLine::CmdLine(const std::string& m,
00252 char delim,
00253 const std::string& v )
00254 : _progName("not_set_yet"),
00255 _message(m),
00256 _version(v),
00257 _numRequired(0),
00258 _delimiter(delim)
00259 {
00260 _constructor();
00261 }
00262
00263 inline CmdLine::~CmdLine()
00264 {
00265 std::list<Arg*>::iterator argIter;
00266 std::list<Visitor*>::iterator visIter;
00267
00268 for( argIter = _argDeleteOnExitList.begin();
00269 argIter != _argDeleteOnExitList.end();
00270 ++argIter)
00271 delete *argIter;
00272
00273 for( visIter = _visitorDeleteOnExitList.begin();
00274 visIter != _visitorDeleteOnExitList.end();
00275 ++visIter)
00276 delete *visIter;
00277 }
00278
00279 inline void CmdLine::_constructor()
00280 {
00281 Visitor *v;
00282
00283 Arg::setDelimiter( _delimiter );
00284
00285 v = new HelpVisitor( this );
00286 SwitchArg* help = new SwitchArg("h","help",
00287 "Displays usage information and exits.",
00288 false, v);
00289 add( *help );
00290 deleteOnExit(help);
00291 deleteOnExit(v);
00292
00293 v = new VersionVisitor( this );
00294 SwitchArg* vers = new SwitchArg("v","version",
00295 "Displays version information and exits.",
00296 false, v);
00297 add( *vers );
00298 deleteOnExit(vers);
00299 deleteOnExit(v);
00300
00301 v = new IgnoreRestVisitor();
00302 SwitchArg* ignore = new SwitchArg(Arg::flagStartString(),
00303 Arg::ignoreNameString(),
00304 "Ignores the rest of the labeled arguments following this flag.",
00305 false, v);
00306 add( *ignore );
00307 deleteOnExit(ignore);
00308 deleteOnExit(v);
00309 }
00310
00311 inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
00312 {
00313 _xorHandler.add( ors );
00314
00315 for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
00316 {
00317 (*it)->forceRequired();
00318 (*it)->setRequireLabel( "OR required" );
00319
00320 add( *it );
00321 }
00322 }
00323
00324 inline void CmdLine::xorAdd( Arg& a, Arg& b )
00325 {
00326 std::vector<Arg*> ors;
00327 ors.push_back( &a );
00328 ors.push_back( &b );
00329 xorAdd( ors );
00330 }
00331
00332 inline void CmdLine::add( Arg& a )
00333 {
00334 add( &a );
00335 }
00336
00337 inline void CmdLine::add( Arg* a )
00338 {
00339 for( ArgIterator iter = _argList.begin(); iter != _argList.end(); iter++ )
00340 if ( *a == *(*iter) )
00341 throw( SpecificationException(
00342 "Argument with same flag/name already exists!",
00343 a->longID() ) );
00344
00345 a->addToList( _argList );
00346
00347 if ( a->isRequired() ) _numRequired++;
00348 }
00349
00350 inline void CmdLine::version(int exitVal)
00351 {
00352 std::cout << std::endl << _progName << " version: "
00353 << _version << std::endl << std::endl;
00354 exit( exitVal );
00355 }
00356
00357 inline void CmdLine::_shortUsage( std::ostream& os )
00358 {
00359 std::string s = _progName + " " + _xorHandler.shortUsage();
00360
00361 for (ArgIterator it = _argList.begin(); it != _argList.end(); it++)
00362 if ( !_xorHandler.contains( (*it) ) )
00363 s += " " + (*it)->shortID();
00364
00365 spacePrint( os, s, 75, 3, (int)(_progName.length()) + 2 );
00366 }
00367
00368 inline void CmdLine::_longUsage( std::ostream& os )
00369 {
00370 _xorHandler.printLongUsage( os );
00371
00372 for (ArgIterator it = _argList.begin(); it != _argList.end(); it++)
00373 if ( !_xorHandler.contains( (*it) ) )
00374 {
00375 spacePrint( os, (*it)->longID(), 75, 3, 3 );
00376 spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
00377 os << std::endl;
00378 }
00379
00380 os << std::endl;
00381 spacePrint( os, _message, 75, 3, 0 );
00382 }
00383
00384 inline void CmdLine::usage( int exitVal )
00385 {
00386 std::cout << std::endl << "USAGE: " << std::endl << std::endl;
00387
00388 _shortUsage( std::cout );
00389
00390 std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl;
00391
00392 _longUsage( std::cout );
00393
00394 std::cout << std::endl;
00395
00396 exit( exitVal );
00397 }
00398
00399 inline void CmdLine::failure( const ArgException& e )
00400 {
00401 std::cerr << "PARSE ERROR: " << e.argId() << std::endl
00402 << " " << e.error() << std::endl << std::endl;
00403
00404 std::cerr << "Brief USAGE: " << std::endl;
00405
00406 _shortUsage( std::cerr );
00407
00408 std::cerr << std::endl << "For complete USAGE and HELP type: "
00409 << std::endl << " " << _progName << " --help"
00410 << std::endl << std::endl;
00411
00412 exit(1);
00413 }
00414
00415 inline void CmdLine::parse(int argc, char** argv)
00416 {
00417 try {
00418
00419 _progName = argv[0];
00420
00421
00422 std::vector<std::string> args;
00423 for (int i = 1; i < argc; i++)
00424 args.push_back(argv[i]);
00425
00426 int requiredCount = 0;
00427
00428 for (int i = 0; (unsigned int)i < args.size(); i++)
00429 {
00430 bool matched = false;
00431 for (ArgIterator it = _argList.begin(); it != _argList.end(); it++)
00432 {
00433 if ( (*it)->processArg( &i, args ) )
00434 {
00435 requiredCount += _xorHandler.check( *it );
00436 matched = true;
00437 break;
00438 }
00439 }
00440
00441
00442
00443 if ( !matched && _emptyCombined( args[i] ) )
00444 matched = true;
00445
00446 if ( !matched && !Arg::ignoreRest() )
00447 throw(CmdLineParseException("Couldn't find match for argument",
00448 args[i]));
00449 }
00450
00451 if ( requiredCount < _numRequired )
00452 throw(CmdLineParseException("One or more required arguments missing!"));
00453
00454 if ( requiredCount > _numRequired )
00455 throw(CmdLineParseException("Too many arguments!"));
00456
00457 } catch ( ArgException& e ) { failure(e); }
00458 }
00459
00460 inline bool CmdLine::_emptyCombined(const std::string& s)
00461 {
00462 if ( s[0] != Arg::flagStartChar() )
00463 return false;
00464
00465 for ( int i = 1; (unsigned int)i < s.length(); i++ )
00466 if ( s[i] != Arg::blankChar() )
00467 return false;
00468
00469 return true;
00470 }
00471
00472 inline void CmdLine::deleteOnExit(Arg* ptr)
00473 {
00474 _argDeleteOnExitList.push_back(ptr);
00475 }
00476
00477 inline void CmdLine::deleteOnExit(Visitor* ptr)
00478 {
00479 _visitorDeleteOnExitList.push_back(ptr);
00480 }
00481
00483
00485
00486
00487
00488 }
00489 #endif