$search
00001 // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 00002 00003 /****************************************************************************** 00004 * 00005 * file: CmdLine.h 00006 * 00007 * Copyright (c) 2003, Michael E. Smoot . 00008 * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 00009 * All rights reverved. 00010 * 00011 * See the file COPYING in the top directory of this distribution for 00012 * more information. 00013 * 00014 * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00017 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00019 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00020 * DEALINGS IN THE SOFTWARE. 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> // Needed for exit(), which isn't defined in some envs. 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 //Begin CmdLine.cpp 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 // this step is necessary so that we have easy access to 00436 // mutable strings. 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 // checks to see if the argument is an empty combined 00469 // switch and if so, then we've actually matched it 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 // If we're not handling the exceptions, rethrow. 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 // If we're not handling the exceptions, rethrow. 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 //End CmdLine.cpp 00629 00630 00631 00632 } //namespace TCLAP 00633 #endif