UniversalIndentGUI 1.2.0
|
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 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 //Begin CmdLine.cpp 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 // this step is necessary so that we have easy access to 00425 // mutable strings. 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 // checks to see if the argument is an empty combined 00457 // switch and if so, then we've actually matched it 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 // If we're not handling the exceptions, rethrow. 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 // If we're not handling the exceptions, rethrow. 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 //End CmdLine.cpp 00617 00618 00619 00620 } //namespace TCLAP 00621 #endif