CmdLine.h

Go to the documentation of this file.
00001 
00002 /****************************************************************************** 
00003  * 
00004  *  file:  CmdLine.h
00005  * 
00006  *  Copyright (c) 2003, Michael E. Smoot .
00007  *  Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
00008  *  All rights reverved.
00009  * 
00010  *  See the file COPYING in the top directory of this distribution for
00011  *  more information.
00012  *  
00013  *  THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 
00014  *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
00015  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
00016  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
00017  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
00018  *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
00019  *  DEALINGS IN THE SOFTWARE.  
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 //Begin CmdLine.cpp
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      // this step is necessary so that we have easy access to mutable strings.
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           // checks to see if the argument is an empty combined switch ...
00442           // and if so, then we've actually matched it
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 //End CmdLine.cpp
00485 
00486 
00487 
00488 } //namespace TCLAP
00489 #endif 

Generated on Sun Mar 11 15:33:24 2007 for MetalWarriors by  doxygen 1.4.7