VR-Link API Documentation for HLA 1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cmdLine.h
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * file: CmdLine.h
4  *
5  * Copyright (c) 2003, Michael E. Smoot .
6  * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
7  * All rights reverved.
8  *
9  * See the file COPYING in the top directory of this distribution for
10  * more information.
11  *
12  * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
13  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
15  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18  * DEALINGS IN THE SOFTWARE.
19  *
20  *****************************************************************************/
21 
22 #ifndef DtCmdLine_CMDLINE_H
23 #define DtCmdLine_CMDLINE_H
24 
28 
29 #include "cmdSwitchArg.h"
30 #include "cmdUnlabeledValueArg.h"
31 #include "cmdUnlabeledMultiArg.h"
32 
33 #include "cmdXorHandler.h"
34 #include "cmdHelpVisitor.h"
35 #include "cmdVersionVisitor.h"
36 #include "cmdIgnoreRestVisitor.h"
37 
38 #include "cmdLineOutput.h"
39 #include "cmdStdOutput.h"
40 
41 #include <string>
42 #include <vector>
43 #include <list>
44 #include <iostream>
45 #include <iomanip>
46 #include <algorithm>
47 
49 #include <vlutil/vlKeyboard.h>
50 #include <vlutil/vlPrint.h>
51 
52 #ifdef DtUSE_UTILITIES_NAMESPACE
53 namespace DtUSE_UTILITIES_NAMESPACE
54 {
55 #endif
56 
57 namespace DtCmdLine {
58 
63 
64  class CmdLine : public CmdLineInterface
65  {
66  protected:
67 
72  std::list<Arg*> _argList;
73 
77  std::string _progName;
78 
82  std::string _message;
83 
87  std::string _version;
88 
95 
101 
106 
112  std::list<Arg*> _argDeleteOnExitList;
113 
119  std::list<Visitor*> _visitorDeleteOnExitList;
120 
125 
132  bool _emptyCombined(const std::string& s);
133 
135 
136  private:
137 
142  void _constructor();
143 
147  void deleteOnExit(Arg* ptr);
148 
152  void deleteOnExit(Visitor* ptr);
153 
159 
160  public:
161 
172  CmdLine(const std::string& name,
173  const std::string& message,
174  const std::string& version = "none",
175 #ifdef _WIN32
176  bool pressAnyKey = true);
177 #else
178  bool pressAnyKey = false);
179 #endif
180 
191  CmdLine(const std::string& message,
192  const char delimiter = ' ',
193  const std::string& version = "none",
194 #ifdef _WIN32
195  bool pressAnyKey = true);
196 #else
197  bool pressAnyKey = false);
198 #endif
199 
203  virtual ~CmdLine();
204 
209  void add( Arg& a );
210 
215  void add( Arg* a );
216 
223  void xorAdd( Arg& a, Arg& b );
224 
230  void xorAdd( std::vector<Arg*>& xors );
231 
239  void parse(int argc, char** argv, bool printOnError = true)
240  throw(CmdLineParseException);
241 
251  char** checkHelpOption( int & argc, char** argv, bool & result, bool removeFromArgs = true );
252 
256  CmdLineOutput* getOutput();
257 
261  void setOutput(CmdLineOutput* co);
262 
266  std::string& getVersion();
267 
271  std::string& getProgramName();
272 
276  std::list<Arg*>& getArgList();
277 
281  XorHandler& getXorHandler();
282 
286  char getDelimiter();
287 
291  std::string& getMessage();
292  };
293 
294 
296  //Begin CmdLine.cpp
298 
299  inline CmdLine::CmdLine(const std::string& n,
300  const std::string& m,
301  const std::string& v,
302  bool pressAnyKey)
303  : _progName(n),
304  _message(m),
305  _version(v),
306  _numRequired(0),
307  _delimiter(' '),
308  myPressAnyKey(pressAnyKey),
309  _userSetOutput(false)
310  {
311  _constructor();
312  }
313 
314  inline CmdLine::CmdLine(const std::string& m,
315  char delim,
316  const std::string& v,
317  bool pressAnyKey)
318  : _progName(m),
319  _message(m),
320  _version(v),
321  _numRequired(0),
322  _delimiter(delim),
323  myPressAnyKey(pressAnyKey),
324  _userSetOutput(false)
325  {
326  _constructor();
327  }
328 
330  {
331  ArgListIterator argIter;
332  VisitorListIterator visIter;
333 
334  for( argIter = _argDeleteOnExitList.begin();
335  argIter != _argDeleteOnExitList.end();
336  ++argIter)
337  delete *argIter;
338 
339  for( visIter = _visitorDeleteOnExitList.begin();
340  visIter != _visitorDeleteOnExitList.end();
341  ++visIter)
342  delete *visIter;
343 
344  if ( !_userSetOutput )
345  delete _output;
346  }
347 
348  inline void CmdLine::_constructor()
349  {
350  _output = new StdOutput;
351 
352  Visitor *v;
353 
355 
356  v = new HelpVisitor( this, &_output, myPressAnyKey );
357  SwitchArg* help = new SwitchArg("h","help",
358  "Displays usage information and exits.",
359  false, v);
360  add( help );
361  deleteOnExit(help);
362  deleteOnExit(v);
363 
364  v = new VersionVisitor( this, &_output, myPressAnyKey );
365  SwitchArg* vers = new SwitchArg("v","version",
366  "Displays version information and exits.",
367  false, v);
368  add( vers );
369  deleteOnExit(vers);
370  deleteOnExit(v);
371 
372  v = new IgnoreRestVisitor();
373  SwitchArg* ignore = new SwitchArg(Arg::flagStartString(),
375  "Ignores the rest of the labeled arguments following this flag.",
376  false, v);
377  add( ignore );
378  deleteOnExit(ignore);
379  deleteOnExit(v);
380  }
381 
382  inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
383  {
384  _xorHandler.add( ors );
385 
386  for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
387  {
388  (*it)->forceRequired();
389  (*it)->setRequireLabel( "OR required" );
390 
391  add( *it );
392  }
393  }
394 
395  inline void CmdLine::xorAdd( Arg& a, Arg& b )
396  {
397  std::vector<Arg*> ors;
398  ors.push_back( &a );
399  ors.push_back( &b );
400  xorAdd( ors );
401  }
402 
403  inline void CmdLine::add( Arg& a )
404  {
405  add( &a );
406  }
407 
408  inline void CmdLine::add( Arg* a )
409  {
410  for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
411  if ( *a == *(*it) )
412  {
413  throw( SpecificationException( "Argument with same flag/name already exists!",
414  a->longID() ) );
415  }
416 
417  a->addToList( _argList );
418 
419  if ( a->isRequired() )
420  _numRequired++;
421  }
422 
423  inline char** CmdLine::checkHelpOption( int & argc, char** argv, bool & result, bool removeFromArgs )
424  {
425  // TODO consider making a DtFilename and getting the file's name rather than the (potential) absolute path
426  _progName = argv[0];
427 
428  // cache the old argument count
429  int oldArgc = argc;
430 
431  // vector of command line arguments
432  std::vector<std::string> args;
433  for (int i = 1; i < argc; i++)
434  args.push_back(argv[i]);
435 
436  std::vector<std::string>::iterator prev;
437  std::vector<std::string>::iterator cur;
438  std::vector<std::string>::iterator end = args.end();
439 
440  // get the beginning
441  cur = args.begin();
442 
443  // finished early?
444  bool finished = false;
445 
446  while( ( cur != end && finished == false ) )
447  {
448  if( (*cur) == "--help" )
449  {
450  if( removeFromArgs )
451  {
452  // subtract an argument
453  argc--;
454 
455  // erase it
456  args.erase(cur);
457  }
458 
459  // set back to the previous
460  cur = prev;
461 
462  // we've finished
463  finished = true;
464 
465  // break out
466  break;
467  }
468  // This is necessary due to usage of /SUBSYSTEM:WINDOWS with MSVC
469 #ifdef _WIN32
470  else if ((*cur) == "-h")
471  {
472  if (removeFromArgs)
473  {
474  // subtract an argument
475  argc--;
476 
477  // erase it
478  args.erase(cur);
479  }
480 
481  // set back to the previous
482  cur = prev;
483 
484  // we've finished
485  finished = true;
486 
487  // break out
488  break;
489  }
490 #endif
491  else
492  {
493  prev = cur;
494  ++cur;
495  }
496  }
497 
498  // set the result
499  result = finished;
500 
501  if( ( removeFromArgs == true ) && ( finished == true ) )
502  {
503  // ok so we found help, and removed it which means we
504  // altered the argv's, we need to reconstruct and give back
505  // otherwise return what we had
506  char ** new_argv = new char * [ args.size() ];
507  for( unsigned int i = 0; i < args.size(); ++i )
508  {
509  new_argv[i] = new char[ args[i].length() + 1 ];
510  memcpy( new_argv[i], args[i].c_str(), args[i].length() );
511  }
512 
513  return new_argv;
514  }
515 
516  // restore the old argc
517  argc = oldArgc;
518  return argv;
519  }
520 
521  inline void CmdLine::parse(int argc, char** argv, bool printOnError)
522  throw(CmdLineParseException)
523  {
524  try {
525 
526  _progName = argv[0];
527 
529  std::vector<std::string> args;
530  int i;
531  for (i = 1; i < argc; i++)
532  args.push_back(argv[i]);
533 
534  int requiredCount = 0;
535 
536  for (i = 0; (unsigned int)i < args.size(); i++)
537  {
538  bool matched = false;
539  for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
540  {
541  if ( (*it)->processArg( &i, args ) )
542  {
543  requiredCount += _xorHandler.check( *it );
544  matched = true;
545  break;
546  }
547  }
548 
551  if ( !matched && _emptyCombined( args[i] ) )
552  matched = true;
553 
554  if ( !matched && !Arg::ignoreRest() )
555  throw(CmdLineParseException("Couldn't find match for argument",
556  args[i]));
557  }
558 
559  if ( requiredCount < _numRequired )
560  throw(CmdLineParseException("One or more required arguments missing!"));
561 
562  if ( requiredCount > _numRequired )
563  throw(CmdLineParseException("Too many arguments!"));
564 
565  } catch ( ArgException e ) {
566 
567  if( printOnError == false )
568  {
569  throw(CmdLineParseException(e.error()));
570  return;
571  }
572  _output->failure(*this,e);
573 
574  int oldNotifyLevel = DtNotifyLevel;
575  DtNotifyLevel = 3;
576 
577  if (myPressAnyKey)
578  {
579  DtInfo << "Press any key to continue" << std::endl;
580 
581  while (DtPollBlockingInputChar() == '\0')
582  {
583  DtSleep(0.1);
584  }
585  }
586 
587  DtNotifyLevel = oldNotifyLevel;
588 
589  exit(1);
590  }
591  }
592 
593  inline bool CmdLine::_emptyCombined(const std::string& s)
594  {
595  if ( s[0] != Arg::flagStartChar() )
596  return false;
597 
598  for ( int i = 1; (unsigned int)i < s.length(); i++ )
599  if ( s[i] != Arg::blankChar() )
600  return false;
601 
602  return true;
603  }
604 
605  inline void CmdLine::deleteOnExit(Arg* ptr)
606  {
607  _argDeleteOnExitList.push_back(ptr);
608  }
609 
610  inline void CmdLine::deleteOnExit(Visitor* ptr)
611  {
612  _visitorDeleteOnExitList.push_back(ptr);
613  }
614 
616  {
617  return _output;
618  }
619 
621  {
622  _userSetOutput = true;
623  _output = co;
624  }
625 
626  inline std::string& CmdLine::getVersion()
627  {
628  return _version;
629  }
630 
631  inline std::string& CmdLine::getProgramName()
632  {
633  return _progName;
634  }
635 
636  inline std::list<Arg*>& CmdLine::getArgList()
637  {
638  return _argList;
639  }
640 
642  {
643  return _xorHandler;
644  }
645 
646  inline char CmdLine::getDelimiter()
647  {
648  return _delimiter;
649  }
650 
651  inline std::string& CmdLine::getMessage()
652  {
653  return _message;
654  }
655 
657  //End CmdLine.cpp
659 
660 
661 
662 } //namespace DtCmdLine
663 
664 #ifdef DtUSE_UTILITIES_NAMESPACE
665 }
666 #endif
667 
668 #endif

Document ID: Generated on Thu Feb 22 04:26:36 EST 2018 from SVN revision 186468
Copyright © 2005-2016 VT MÄK. All Rights Reserved (www.mak.com)