![]() |
VR-Link API Documentation for DIS
|
00001 /****************************************************************************** 00002 * 00003 * file: CmdLine.h 00004 * 00005 * Copyright (c) 2003, Michael E. Smoot . 00006 * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 00007 * All rights reverved. 00008 * 00009 * See the file COPYING in the top directory of this distribution for 00010 * more information. 00011 * 00012 * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 00013 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00014 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00015 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00016 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00017 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00018 * DEALINGS IN THE SOFTWARE. 00019 * 00020 *****************************************************************************/ 00021 00022 #ifndef DtCmdLine_CMDLINE_H 00023 #define DtCmdLine_CMDLINE_H 00024 00028 00029 #include "cmdSwitchArg.h" 00030 #include "cmdUnlabeledValueArg.h" 00031 #include "cmdUnlabeledMultiArg.h" 00032 00033 #include "cmdXorHandler.h" 00034 #include "cmdHelpVisitor.h" 00035 #include "cmdVersionVisitor.h" 00036 #include "cmdIgnoreRestVisitor.h" 00037 00038 #include "cmdLineOutput.h" 00039 #include "cmdStdOutput.h" 00040 00041 #include <string> 00042 #include <vector> 00043 #include <list> 00044 #include <iostream> 00045 #include <iomanip> 00046 #include <algorithm> 00047 00048 #include <vlutil/vlProcessControl.h> 00049 #include <vlutil/vlKeyboard.h> 00050 #include <vlutil/vlPrint.h> 00051 00052 #ifdef DtUSE_UTILITIES_NAMESPACE 00053 namespace DtUSE_UTILITIES_NAMESPACE 00054 { 00055 #endif 00056 00057 namespace DtCmdLine { 00058 00063 00064 class CmdLine : public CmdLineInterface 00065 { 00066 protected: 00067 00072 std::list<Arg*> _argList; 00073 00077 std::string _progName; 00078 00082 std::string _message; 00083 00087 std::string _version; 00088 00094 int _numRequired; 00095 00100 char _delimiter; 00101 00105 XorHandler _xorHandler; 00106 00112 std::list<Arg*> _argDeleteOnExitList; 00113 00119 std::list<Visitor*> _visitorDeleteOnExitList; 00120 00124 CmdLineOutput* _output; 00125 00132 bool _emptyCombined(const std::string& s); 00133 00134 bool myPressAnyKey; 00135 00136 private: 00137 00142 void _constructor(); 00143 00147 void deleteOnExit(Arg* ptr); 00148 00152 void deleteOnExit(Visitor* ptr); 00153 00158 bool _userSetOutput; 00159 00160 public: 00161 00172 CmdLine(const std::string& name, 00173 const std::string& message, 00174 const std::string& version = "none", 00175 #ifdef _WIN32 00176 bool pressAnyKey = true); 00177 #else 00178 bool pressAnyKey = false); 00179 #endif 00180 00191 CmdLine(const std::string& message, 00192 const char delimiter = ' ', 00193 const std::string& version = "none", 00194 #ifdef _WIN32 00195 bool pressAnyKey = true); 00196 #else 00197 bool pressAnyKey = false); 00198 #endif 00199 00203 virtual ~CmdLine(); 00204 00209 void add( Arg& a ); 00210 00215 void add( Arg* a ); 00216 00223 void xorAdd( Arg& a, Arg& b ); 00224 00230 void xorAdd( std::vector<Arg*>& xors ); 00231 00237 void parse(int argc, char** argv); 00238 00242 CmdLineOutput* getOutput(); 00243 00247 void setOutput(CmdLineOutput* co); 00248 00252 std::string& getVersion(); 00253 00257 std::string& getProgramName(); 00258 00262 std::list<Arg*>& getArgList(); 00263 00267 XorHandler& getXorHandler(); 00268 00272 char getDelimiter(); 00273 00277 std::string& getMessage(); 00278 }; 00279 00280 00282 //Begin CmdLine.cpp 00284 00285 inline CmdLine::CmdLine(const std::string& n, 00286 const std::string& m, 00287 const std::string& v, 00288 bool pressAnyKey) 00289 : _progName(n), 00290 _message(m), 00291 _version(v), 00292 _numRequired(0), 00293 _delimiter(' '), 00294 myPressAnyKey(pressAnyKey), 00295 _userSetOutput(false) 00296 { 00297 _constructor(); 00298 } 00299 00300 inline CmdLine::CmdLine(const std::string& m, 00301 char delim, 00302 const std::string& v, 00303 bool pressAnyKey) 00304 : _progName("not_set_yet"), 00305 _message(m), 00306 _version(v), 00307 _numRequired(0), 00308 _delimiter(delim), 00309 myPressAnyKey(pressAnyKey), 00310 _userSetOutput(false) 00311 { 00312 _constructor(); 00313 } 00314 00315 inline CmdLine::~CmdLine() 00316 { 00317 ArgListIterator argIter; 00318 VisitorListIterator visIter; 00319 00320 for( argIter = _argDeleteOnExitList.begin(); 00321 argIter != _argDeleteOnExitList.end(); 00322 ++argIter) 00323 delete *argIter; 00324 00325 for( visIter = _visitorDeleteOnExitList.begin(); 00326 visIter != _visitorDeleteOnExitList.end(); 00327 ++visIter) 00328 delete *visIter; 00329 00330 if ( !_userSetOutput ) 00331 delete _output; 00332 } 00333 00334 inline void CmdLine::_constructor() 00335 { 00336 _output = new StdOutput; 00337 00338 Visitor *v; 00339 00340 Arg::setDelimiter( _delimiter ); 00341 00342 v = new HelpVisitor( this, &_output, myPressAnyKey ); 00343 SwitchArg* help = new SwitchArg("h","help", 00344 "Displays usage information and exits.", 00345 false, v); 00346 add( help ); 00347 deleteOnExit(help); 00348 deleteOnExit(v); 00349 00350 v = new VersionVisitor( this, &_output, myPressAnyKey ); 00351 SwitchArg* vers = new SwitchArg("v","version", 00352 "Displays version information and exits.", 00353 false, v); 00354 add( vers ); 00355 deleteOnExit(vers); 00356 deleteOnExit(v); 00357 00358 v = new IgnoreRestVisitor(); 00359 SwitchArg* ignore = new SwitchArg(Arg::flagStartString(), 00360 Arg::ignoreNameString(), 00361 "Ignores the rest of the labeled arguments following this flag.", 00362 false, v); 00363 add( ignore ); 00364 deleteOnExit(ignore); 00365 deleteOnExit(v); 00366 } 00367 00368 inline void CmdLine::xorAdd( std::vector<Arg*>& ors ) 00369 { 00370 _xorHandler.add( ors ); 00371 00372 for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++) 00373 { 00374 (*it)->forceRequired(); 00375 (*it)->setRequireLabel( "OR required" ); 00376 00377 add( *it ); 00378 } 00379 } 00380 00381 inline void CmdLine::xorAdd( Arg& a, Arg& b ) 00382 { 00383 std::vector<Arg*> ors; 00384 ors.push_back( &a ); 00385 ors.push_back( &b ); 00386 xorAdd( ors ); 00387 } 00388 00389 inline void CmdLine::add( Arg& a ) 00390 { 00391 add( &a ); 00392 } 00393 00394 inline void CmdLine::add( Arg* a ) 00395 { 00396 for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) 00397 if ( *a == *(*it) ) 00398 throw( SpecificationException( "Argument with same flag/name already exists!", 00399 a->longID() ) ); 00400 00401 a->addToList( _argList ); 00402 00403 if ( a->isRequired() ) 00404 _numRequired++; 00405 } 00406 00407 inline void CmdLine::parse(int argc, char** argv) 00408 { 00409 try { 00410 00411 _progName = argv[0]; 00412 00414 std::vector<std::string> args; 00415 int i; 00416 for (i = 1; i < argc; i++) 00417 args.push_back(argv[i]); 00418 00419 int requiredCount = 0; 00420 00421 for (i = 0; (unsigned int)i < args.size(); i++) 00422 { 00423 bool matched = false; 00424 for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) 00425 { 00426 if ( (*it)->processArg( &i, args ) ) 00427 { 00428 requiredCount += _xorHandler.check( *it ); 00429 matched = true; 00430 break; 00431 } 00432 } 00433 00436 if ( !matched && _emptyCombined( args[i] ) ) 00437 matched = true; 00438 00439 if ( !matched && !Arg::ignoreRest() ) 00440 throw(CmdLineParseException("Couldn't find match for argument", 00441 args[i])); 00442 } 00443 00444 if ( requiredCount < _numRequired ) 00445 throw(CmdLineParseException("One or more required arguments missing!")); 00446 00447 if ( requiredCount > _numRequired ) 00448 throw(CmdLineParseException("Too many arguments!")); 00449 00450 } catch ( ArgException e ) { 00451 _output->failure(*this,e); 00452 00453 int oldNotifyLevel = DtNotifyLevel; 00454 DtNotifyLevel = 3; 00455 00456 if (myPressAnyKey) 00457 { 00458 DtInfo << "Press any key to continue" << std::endl; 00459 00460 while (DtPollBlockingInputChar() == '\0') 00461 { 00462 DtSleep(0.1); 00463 } 00464 } 00465 00466 DtNotifyLevel = oldNotifyLevel; 00467 00468 exit(1); 00469 } 00470 } 00471 00472 inline bool CmdLine::_emptyCombined(const std::string& s) 00473 { 00474 if ( s[0] != Arg::flagStartChar() ) 00475 return false; 00476 00477 for ( int i = 1; (unsigned int)i < s.length(); i++ ) 00478 if ( s[i] != Arg::blankChar() ) 00479 return false; 00480 00481 return true; 00482 } 00483 00484 inline void CmdLine::deleteOnExit(Arg* ptr) 00485 { 00486 _argDeleteOnExitList.push_back(ptr); 00487 } 00488 00489 inline void CmdLine::deleteOnExit(Visitor* ptr) 00490 { 00491 _visitorDeleteOnExitList.push_back(ptr); 00492 } 00493 00494 inline CmdLineOutput* CmdLine::getOutput() 00495 { 00496 return _output; 00497 } 00498 00499 inline void CmdLine::setOutput(CmdLineOutput* co) 00500 { 00501 _userSetOutput = true; 00502 _output = co; 00503 } 00504 00505 inline std::string& CmdLine::getVersion() 00506 { 00507 return _version; 00508 } 00509 00510 inline std::string& CmdLine::getProgramName() 00511 { 00512 return _progName; 00513 } 00514 00515 inline std::list<Arg*>& CmdLine::getArgList() 00516 { 00517 return _argList; 00518 } 00519 00520 inline XorHandler& CmdLine::getXorHandler() 00521 { 00522 return _xorHandler; 00523 } 00524 00525 inline char CmdLine::getDelimiter() 00526 { 00527 return _delimiter; 00528 } 00529 00530 inline std::string& CmdLine::getMessage() 00531 { 00532 return _message; 00533 } 00534 00536 //End CmdLine.cpp 00538 00539 00540 00541 } //namespace DtCmdLine 00542 00543 #ifdef DtUSE_UTILITIES_NAMESPACE 00544 } 00545 #endif 00546 00547 #endif