No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

634 líneas
14 KiB

  1. // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
  2. /******************************************************************************
  3. *
  4. * file: CmdLine.h
  5. *
  6. * Copyright (c) 2003, Michael E. Smoot .
  7. * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
  8. * All rights reverved.
  9. *
  10. * See the file COPYING in the top directory of this distribution for
  11. * more information.
  12. *
  13. * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
  14. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  16. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  19. * DEALINGS IN THE SOFTWARE.
  20. *
  21. *****************************************************************************/
  22. #ifndef TCLAP_CMDLINE_H
  23. #define TCLAP_CMDLINE_H
  24. #include "SwitchArg.h"
  25. #include "MultiSwitchArg.h"
  26. #include "UnlabeledValueArg.h"
  27. #include "UnlabeledMultiArg.h"
  28. #include "XorHandler.h"
  29. #include "HelpVisitor.h"
  30. #include "VersionVisitor.h"
  31. #include "IgnoreRestVisitor.h"
  32. #include "CmdLineOutput.h"
  33. #include "StdOutput.h"
  34. #include "Constraint.h"
  35. #include "ValuesConstraint.h"
  36. #include <string>
  37. #include <vector>
  38. #include <list>
  39. #include <iostream>
  40. #include <iomanip>
  41. #include <algorithm>
  42. #include <stdlib.h> // Needed for exit(), which isn't defined in some envs.
  43. namespace TCLAP {
  44. template<typename T> void DelPtr(T ptr)
  45. {
  46. delete ptr;
  47. }
  48. template<typename C> void ClearContainer(C &c)
  49. {
  50. typedef typename C::value_type value_type;
  51. std::for_each(c.begin(), c.end(), DelPtr<value_type>);
  52. c.clear();
  53. }
  54. /**
  55. * The base class that manages the command line definition and passes
  56. * along the parsing to the appropriate Arg classes.
  57. */
  58. class CmdLine : public CmdLineInterface
  59. {
  60. protected:
  61. /**
  62. * The list of arguments that will be tested against the
  63. * command line.
  64. */
  65. std::list<Arg*> _argList;
  66. /**
  67. * The name of the program. Set to argv[0].
  68. */
  69. std::string _progName;
  70. /**
  71. * A message used to describe the program. Used in the usage output.
  72. */
  73. std::string _message;
  74. /**
  75. * The version to be displayed with the --version switch.
  76. */
  77. std::string _version;
  78. /**
  79. * The number of arguments that are required to be present on
  80. * the command line. This is set dynamically, based on the
  81. * Args added to the CmdLine object.
  82. */
  83. int _numRequired;
  84. /**
  85. * The character that is used to separate the argument flag/name
  86. * from the value. Defaults to ' ' (space).
  87. */
  88. char _delimiter;
  89. /**
  90. * The handler that manages xoring lists of args.
  91. */
  92. XorHandler _xorHandler;
  93. /**
  94. * A list of Args to be explicitly deleted when the destructor
  95. * is called. At the moment, this only includes the three default
  96. * Args.
  97. */
  98. std::list<Arg*> _argDeleteOnExitList;
  99. /**
  100. * A list of Visitors to be explicitly deleted when the destructor
  101. * is called. At the moment, these are the Vistors created for the
  102. * default Args.
  103. */
  104. std::list<Visitor*> _visitorDeleteOnExitList;
  105. /**
  106. * Object that handles all output for the CmdLine.
  107. */
  108. CmdLineOutput* _output;
  109. /**
  110. * Should CmdLine handle parsing exceptions internally?
  111. */
  112. bool _handleExceptions;
  113. /**
  114. * Throws an exception listing the missing args.
  115. */
  116. void missingArgsException();
  117. /**
  118. * Checks whether a name/flag string matches entirely matches
  119. * the Arg::blankChar. Used when multiple switches are combined
  120. * into a single argument.
  121. * \param s - The message to be used in the usage.
  122. */
  123. bool _emptyCombined(const std::string& s);
  124. /**
  125. * Perform a delete ptr; operation on ptr when this object is deleted.
  126. */
  127. void deleteOnExit(Arg* ptr);
  128. /**
  129. * Perform a delete ptr; operation on ptr when this object is deleted.
  130. */
  131. void deleteOnExit(Visitor* ptr);
  132. private:
  133. /**
  134. * Prevent accidental copying.
  135. */
  136. CmdLine(const CmdLine& rhs);
  137. CmdLine& operator=(const CmdLine& rhs);
  138. /**
  139. * Encapsulates the code common to the constructors
  140. * (which is all of it).
  141. */
  142. void _constructor();
  143. /**
  144. * Is set to true when a user sets the output object. We use this so
  145. * that we don't delete objects that are created outside of this lib.
  146. */
  147. bool _userSetOutput;
  148. /**
  149. * Whether or not to automatically create help and version switches.
  150. */
  151. bool _helpAndVersion;
  152. public:
  153. /**
  154. * Command line constructor. Defines how the arguments will be
  155. * parsed.
  156. * \param message - The message to be used in the usage
  157. * output.
  158. * \param delimiter - The character that is used to separate
  159. * the argument flag/name from the value. Defaults to ' ' (space).
  160. * \param version - The version number to be used in the
  161. * --version switch.
  162. * \param helpAndVersion - Whether or not to create the Help and
  163. * Version switches. Defaults to true.
  164. */
  165. CmdLine(const std::string& message,
  166. const char delimiter = ' ',
  167. const std::string& version = "none",
  168. bool helpAndVersion = true);
  169. /**
  170. * Deletes any resources allocated by a CmdLine object.
  171. */
  172. virtual ~CmdLine();
  173. /**
  174. * Adds an argument to the list of arguments to be parsed.
  175. * \param a - Argument to be added.
  176. */
  177. void add( Arg& a );
  178. /**
  179. * An alternative add. Functionally identical.
  180. * \param a - Argument to be added.
  181. */
  182. void add( Arg* a );
  183. /**
  184. * Add two Args that will be xor'd. If this method is used, add does
  185. * not need to be called.
  186. * \param a - Argument to be added and xor'd.
  187. * \param b - Argument to be added and xor'd.
  188. */
  189. void xorAdd( Arg& a, Arg& b );
  190. /**
  191. * Add a list of Args that will be xor'd. If this method is used,
  192. * add does not need to be called.
  193. * \param xors - List of Args to be added and xor'd.
  194. */
  195. void xorAdd( std::vector<Arg*>& xors );
  196. /**
  197. * Parses the command line.
  198. * \param argc - Number of arguments.
  199. * \param argv - Array of arguments.
  200. */
  201. void parse(int argc, const char * const * argv);
  202. /**
  203. * Parses the command line.
  204. * \param args - A vector of strings representing the args.
  205. * args[0] is still the program name.
  206. */
  207. void parse(std::vector<std::string>& args);
  208. /**
  209. *
  210. */
  211. CmdLineOutput* getOutput();
  212. /**
  213. *
  214. */
  215. void setOutput(CmdLineOutput* co);
  216. /**
  217. *
  218. */
  219. std::string& getVersion();
  220. /**
  221. *
  222. */
  223. std::string& getProgramName();
  224. /**
  225. *
  226. */
  227. std::list<Arg*>& getArgList();
  228. /**
  229. *
  230. */
  231. XorHandler& getXorHandler();
  232. /**
  233. *
  234. */
  235. char getDelimiter();
  236. /**
  237. *
  238. */
  239. std::string& getMessage();
  240. /**
  241. *
  242. */
  243. bool hasHelpAndVersion();
  244. /**
  245. * Disables or enables CmdLine's internal parsing exception handling.
  246. *
  247. * @param state Should CmdLine handle parsing exceptions internally?
  248. */
  249. void setExceptionHandling(const bool state);
  250. /**
  251. * Returns the current state of the internal exception handling.
  252. *
  253. * @retval true Parsing exceptions are handled internally.
  254. * @retval false Parsing exceptions are propagated to the caller.
  255. */
  256. bool getExceptionHandling() const;
  257. /**
  258. * Allows the CmdLine object to be reused.
  259. */
  260. void reset();
  261. };
  262. ///////////////////////////////////////////////////////////////////////////////
  263. //Begin CmdLine.cpp
  264. ///////////////////////////////////////////////////////////////////////////////
  265. inline CmdLine::CmdLine(const std::string& m,
  266. char delim,
  267. const std::string& v,
  268. bool help )
  269. :
  270. _argList(std::list<Arg*>()),
  271. _progName("not_set_yet"),
  272. _message(m),
  273. _version(v),
  274. _numRequired(0),
  275. _delimiter(delim),
  276. _xorHandler(XorHandler()),
  277. _argDeleteOnExitList(std::list<Arg*>()),
  278. _visitorDeleteOnExitList(std::list<Visitor*>()),
  279. _output(0),
  280. _handleExceptions(true),
  281. _userSetOutput(false),
  282. _helpAndVersion(help)
  283. {
  284. _constructor();
  285. }
  286. inline CmdLine::~CmdLine()
  287. {
  288. ClearContainer(_argDeleteOnExitList);
  289. ClearContainer(_visitorDeleteOnExitList);
  290. if ( !_userSetOutput ) {
  291. delete _output;
  292. _output = 0;
  293. }
  294. }
  295. inline void CmdLine::_constructor()
  296. {
  297. _output = new StdOutput;
  298. Arg::setDelimiter( _delimiter );
  299. Visitor* v;
  300. if ( _helpAndVersion )
  301. {
  302. v = new HelpVisitor( this, &_output );
  303. SwitchArg* help = new SwitchArg("h","help",
  304. "Displays usage information and exits.",
  305. false, v);
  306. add( help );
  307. deleteOnExit(help);
  308. deleteOnExit(v);
  309. v = new VersionVisitor( this, &_output );
  310. SwitchArg* vers = new SwitchArg("","version",
  311. "Displays version information and exits.",
  312. false, v);
  313. add( vers );
  314. deleteOnExit(vers);
  315. deleteOnExit(v);
  316. }
  317. v = new IgnoreRestVisitor();
  318. SwitchArg* ignore = new SwitchArg(Arg::flagStartString(),
  319. Arg::ignoreNameString(),
  320. "Ignores the rest of the labeled arguments following this flag.",
  321. false, v);
  322. add( ignore );
  323. deleteOnExit(ignore);
  324. deleteOnExit(v);
  325. }
  326. inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
  327. {
  328. _xorHandler.add( ors );
  329. for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
  330. {
  331. (*it)->forceRequired();
  332. (*it)->setRequireLabel( "OR required" );
  333. add( *it );
  334. }
  335. }
  336. inline void CmdLine::xorAdd( Arg& a, Arg& b )
  337. {
  338. std::vector<Arg*> ors;
  339. ors.push_back( &a );
  340. ors.push_back( &b );
  341. xorAdd( ors );
  342. }
  343. inline void CmdLine::add( Arg& a )
  344. {
  345. add( &a );
  346. }
  347. inline void CmdLine::add( Arg* a )
  348. {
  349. for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
  350. if ( *a == *(*it) )
  351. throw( SpecificationException(
  352. "Argument with same flag/name already exists!",
  353. a->longID() ) );
  354. a->addToList( _argList );
  355. if ( a->isRequired() )
  356. _numRequired++;
  357. }
  358. inline void CmdLine::parse(int argc, const char * const * argv)
  359. {
  360. // this step is necessary so that we have easy access to
  361. // mutable strings.
  362. std::vector<std::string> args;
  363. for (int i = 0; i < argc; i++)
  364. args.push_back(argv[i]);
  365. parse(args);
  366. }
  367. inline void CmdLine::parse(std::vector<std::string>& args)
  368. {
  369. bool shouldExit = false;
  370. int estat = 0;
  371. try {
  372. _progName = args.front();
  373. args.erase(args.begin());
  374. int requiredCount = 0;
  375. for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
  376. {
  377. bool matched = false;
  378. for (ArgListIterator it = _argList.begin();
  379. it != _argList.end(); it++) {
  380. if ( (*it)->processArg( &i, args ) )
  381. {
  382. requiredCount += _xorHandler.check( *it );
  383. matched = true;
  384. break;
  385. }
  386. }
  387. // checks to see if the argument is an empty combined
  388. // switch and if so, then we've actually matched it
  389. if ( !matched && _emptyCombined( args[i] ) )
  390. matched = true;
  391. if ( !matched && !Arg::ignoreRest() )
  392. throw(CmdLineParseException("Couldn't find match "
  393. "for argument",
  394. args[i]));
  395. }
  396. if ( requiredCount < _numRequired )
  397. missingArgsException();
  398. if ( requiredCount > _numRequired )
  399. throw(CmdLineParseException("Too many arguments!"));
  400. } catch ( ArgException& e ) {
  401. // If we're not handling the exceptions, rethrow.
  402. if ( !_handleExceptions) {
  403. throw;
  404. }
  405. try {
  406. _output->failure(*this,e);
  407. } catch ( ExitException &ee ) {
  408. estat = ee.getExitStatus();
  409. shouldExit = true;
  410. }
  411. } catch (ExitException &ee) {
  412. // If we're not handling the exceptions, rethrow.
  413. if ( !_handleExceptions) {
  414. throw;
  415. }
  416. estat = ee.getExitStatus();
  417. shouldExit = true;
  418. }
  419. if (shouldExit)
  420. exit(estat);
  421. }
  422. inline bool CmdLine::_emptyCombined(const std::string& s)
  423. {
  424. if ( s.length() > 0 && s[0] != Arg::flagStartChar() )
  425. return false;
  426. for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
  427. if ( s[i] != Arg::blankChar() )
  428. return false;
  429. return true;
  430. }
  431. inline void CmdLine::missingArgsException()
  432. {
  433. int count = 0;
  434. std::string missingArgList;
  435. for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
  436. {
  437. if ( (*it)->isRequired() && !(*it)->isSet() )
  438. {
  439. missingArgList += (*it)->getName();
  440. missingArgList += ", ";
  441. count++;
  442. }
  443. }
  444. missingArgList = missingArgList.substr(0,missingArgList.length()-2);
  445. std::string msg;
  446. if ( count > 1 )
  447. msg = "Required arguments missing: ";
  448. else
  449. msg = "Required argument missing: ";
  450. msg += missingArgList;
  451. throw(CmdLineParseException(msg));
  452. }
  453. inline void CmdLine::deleteOnExit(Arg* ptr)
  454. {
  455. _argDeleteOnExitList.push_back(ptr);
  456. }
  457. inline void CmdLine::deleteOnExit(Visitor* ptr)
  458. {
  459. _visitorDeleteOnExitList.push_back(ptr);
  460. }
  461. inline CmdLineOutput* CmdLine::getOutput()
  462. {
  463. return _output;
  464. }
  465. inline void CmdLine::setOutput(CmdLineOutput* co)
  466. {
  467. if ( !_userSetOutput )
  468. delete _output;
  469. _userSetOutput = true;
  470. _output = co;
  471. }
  472. inline std::string& CmdLine::getVersion()
  473. {
  474. return _version;
  475. }
  476. inline std::string& CmdLine::getProgramName()
  477. {
  478. return _progName;
  479. }
  480. inline std::list<Arg*>& CmdLine::getArgList()
  481. {
  482. return _argList;
  483. }
  484. inline XorHandler& CmdLine::getXorHandler()
  485. {
  486. return _xorHandler;
  487. }
  488. inline char CmdLine::getDelimiter()
  489. {
  490. return _delimiter;
  491. }
  492. inline std::string& CmdLine::getMessage()
  493. {
  494. return _message;
  495. }
  496. inline bool CmdLine::hasHelpAndVersion()
  497. {
  498. return _helpAndVersion;
  499. }
  500. inline void CmdLine::setExceptionHandling(const bool state)
  501. {
  502. _handleExceptions = state;
  503. }
  504. inline bool CmdLine::getExceptionHandling() const
  505. {
  506. return _handleExceptions;
  507. }
  508. inline void CmdLine::reset()
  509. {
  510. for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
  511. (*it)->reset();
  512. _progName.clear();
  513. }
  514. ///////////////////////////////////////////////////////////////////////////////
  515. //End CmdLine.cpp
  516. ///////////////////////////////////////////////////////////////////////////////
  517. } //namespace TCLAP
  518. #endif