Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/parser/cmdline_parser/cmdline_parser.cc @ 8965

Last change on this file since 8965 was 8316, checked in by bensch, 18 years ago

trunk: fixed most -Wall warnings… but there are still many missing :/

File size: 6.1 KB
RevLine 
[7241]1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Christoph Renner
[7319]13   co-programmer:
[7241]14*/
15
16#include "cmdline_parser.h"
17
[7250]18#include "src/lib/util/substring.h"
19
[7241]20using namespace std;
21
22
23/**
24 * standard constructor
25 */
26CmdLineParser::CmdLineParser ()
27{
28}
29
30
31/**
32 * standard deconstructor
33 */
34CmdLineParser::~CmdLineParser ()
35{
36}
37
38
[7250]39bool CmdLineParser::add( int id, const std::string & longOption, char shortOption, int numArgs, const std::string & argNames, const std::string& help, bool back )
[7241]40{
41  ArgTableEntry entry;
[7319]42
[7241]43  entry.id = id;
44  entry.longOption = longOption;
45  entry.shortOption = shortOption;
46  entry.numArgs = numArgs;
[7250]47  entry.argNames = argNames;
48  entry.help = help;
[7319]49
[7241]50  if ( back )
51    argTable.push_back( entry );
52  else
53    argTable.push_front( entry );
[8316]54  return true;
[7241]55}
56
57
58bool CmdLineParser::parse( ArgParserCallback cb, void * data, int argc, char ** argv )
59{
[7250]60  this->exeName = argv[0];
[7319]61
[7241]62  //put all args in vector
63  std::vector<std::string> args;
[7319]64
[7241]65  for ( int i = 1; i<argc; i++ )
[7243]66  {
67    std::string s = argv[i];
[7319]68
[7243]69    if ( s.find( "=" ) == std::string::npos )
70    {
[7260]71      if ( s.length() > 2 && s[0] == '-' && s[1] != '-' )
72      {
[8316]73        for (unsigned int j = 1; j < s.length(); j++ )
[7260]74        {
75          std::string t = "-";
76          t += s[j];
77          args.push_back( t );
78        }
79      }
80      else
81      {
82        args.push_back(s);
83      }
[7243]84    }
85    else
86    {
87      std::string op = s;
88      std::string ar = s;
89      op.erase( op.find("=") );
90      ar.erase( 0, ar.find("=")+1);
[7319]91
[7246]92      //PRINTF(0)("'%s' '%s'\n", op.c_str(), ar.c_str());
[7243]93      args.push_back( op );
94      args.push_back( ar );
95    }
96  }
[7319]97
[8316]98  unsigned int i = 0;
[7319]99
[7241]100  ArgTable::iterator it;
101  bool finish;
102  bool found;
[7319]103
[7241]104  while ( i < args.size() )
105  {
106    found = false;
107    for ( it = argTable.begin(); it != argTable.end(); it++ )
108    {
109      if ( matches( *it, args[i], finish ) )
110      {
111        found = true;
[7319]112
[8316]113        unsigned int posArgs = 1;
[7319]114
[7260]115        while ( i + posArgs < args.size() )
[7241]116        {
[7260]117          if ( args[ i + posArgs ].length() > 0 && args[ i + posArgs ][0] == '-' )
118            break;
119          else
120            posArgs++;
121        }
[7319]122
[7260]123        posArgs--;
[7319]124
[7260]125        if ( it->numArgs > posArgs )
126        {
[7243]127          PRINTF(1)( "%s needs %d arguments!\n", args[i].c_str(), it->numArgs );
128          return false;
[7241]129        }
[7319]130
[7243]131        std::vector<MultiType> argArgs;
[7319]132
[8316]133        for (unsigned int j = 1; j <= it->numArgs; j++ )
[7241]134          argArgs.push_back( args[i+j] );
[7319]135
[7241]136        if ( !cb( *it, data, args[i], argArgs ) )
137          return false;
[7319]138
[7259]139        i += it->numArgs;
[7319]140
[7241]141        if ( finish )
[7259]142        {
143          i++;
[7241]144          break;
[7259]145        }
[7319]146        else
147        {
[7241]148          assert( it->numArgs == 0 );
149        }
150      }
151    }
[7319]152
[7241]153    if ( !found )
154    {
155      PRINTF(1)("%s: illegal option\n", args[i].c_str());
156      return false;
157    }
158  }
[7319]159
[7241]160  return true;
161}
162
163bool CmdLineParser::matches( ArgTableEntry entry, std::string arg, bool & finish )
164{
165  finish = true;
[7319]166
[7241]167  if ( arg.length() < 2 )
168    return false;
[7319]169
[7241]170  if ( arg[0] == '-' )
171  {
172    if ( arg[1] == '-' )
173    {
174      arg.erase( 0, 2 );
[7319]175
[7243]176      if ( entry.longOption.find('%') != std::string::npos )
[7241]177      {
178        //TODO implement bether match algo
[7243]179        assert( entry.longOption.find('%') == entry.longOption.length()-1 );
180        std::string lo = entry.longOption;
181        lo.erase( lo.length()-1, 1 );
[7246]182        //PRINTF(0)("%s %s\n", arg.c_str(), lo.c_str());
[7243]183        return arg.find( lo ) == 0;
[7241]184      }
185      else
186      {
[7243]187        return arg.find( entry.longOption ) != std::string::npos;
[7241]188      }
189    }
190    else
191    {
[7259]192      if ( arg.find(entry.shortOption) != std::string::npos && arg.length() != 2 && entry.numArgs != 0 )
[7241]193      {
[7259]194        PRINTF(1)("using multiple flags together is only alowed if none needs an arugument. %c needs %d arguments\n", entry.shortOption, entry.numArgs);
195        //FIXME find beter solution
196        exit(1);
[7241]197        return false;
198      }
[7243]199      finish = arg.length()==2;
[7241]200      return arg.find(entry.shortOption) != std::string::npos;
201    }
202  }
[7260]203  else
204    return false;
[7241]205}
[7250]206
207void CmdLineParser::showHelp()
208{
209  printf("Usage: %s [options]\n", exeName.c_str());
210  printf("\n");
[7319]211
[7250]212  std::list<std::vector<std::string> > output;
[7319]213
[7250]214  for ( ArgTable::iterator it = argTable.begin(); it != argTable.end(); it++ )
215  {
216    output.push_back( std::vector<std::string>() );
[7319]217
[7250]218    SubString substr( it->argNames );
219    std::string args;
[7319]220    assert( it->numArgs == substr.size() );
221
[8316]222    for (unsigned int i = 0; i<it->numArgs; i++ )
[7250]223    {
224      args += " [" + substr[i] + "]";
225    }
[7319]226
[7250]227    if ( it->shortOption != '\0' )
228    {
229      output.back().push_back( " -" + std::string((char*)&it->shortOption, 1) );
230      output.back().back() += args;
231    }
232    else
233      output.back().push_back( "" );
[7319]234
[7250]235    if ( it->longOption != "" )
236    {
237      output.back().push_back( "--" + it->longOption );
[7319]238
[7250]239      output.back().back() += args;
240    }
241    else
242      output.back().push_back( "" );
[7319]243
[7250]244    output.back().push_back( it->help );
245  }
[7319]246
[7250]247  output.push_back( std::vector<std::string>() );
248  output.back().push_back( "Option" );
249  output.back().push_back( "Long option" );
[7253]250  output.back().push_back( "Description" );
[7319]251
[7250]252  output.reverse();
[7319]253
[8316]254  unsigned int maxShort = 0;
255  unsigned int maxLong = 0;
[7319]256
[7250]257  std::list<std::vector<std::string> >::const_iterator it;
[7319]258
[7250]259  for ( it = output.begin(); it != output.end(); it++ )
260  {
261    if ( (*it)[0].length() > maxShort )
262      maxShort = (*it)[0].length();
[7319]263
[7250]264    if ( (*it)[1].length() > maxLong )
265      maxLong = (*it)[1].length();
266  }
[7319]267
[7250]268  for ( it = output.begin(); it != output.end(); it++ )
269  {
270    printf("%s ", (*it)[0].c_str());
[7319]271
[8316]272    for (unsigned  int i = 0; i<maxShort-(*it)[0].length(); i++ )
[7250]273      printf(" ");
[7319]274
[7250]275    printf("%s ", (*it)[1].c_str());
[7319]276
[8316]277    for (unsigned int i = 0; i<maxLong-(*it)[1].length(); i++ )
[7250]278      printf(" ");
[7319]279
[7250]280    printf("%s\n", (*it)[2].c_str());
281  }
[7319]282
[7250]283  exit(0);
284}
Note: See TracBrowser for help on using the repository browser.