Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7259 was 7259, checked in by rennerc, 18 years ago

fixed a bug

File size: 5.6 KB
Line 
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
13   co-programmer:
14*/
15
16#include "cmdline_parser.h"
17
18#include "src/lib/util/substring.h"
19
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
39bool CmdLineParser::add( int id, const std::string & longOption, char shortOption, int numArgs, const std::string & argNames, const std::string& help, bool back )
40{
41  ArgTableEntry entry;
42 
43  entry.id = id;
44  entry.longOption = longOption;
45  entry.shortOption = shortOption;
46  entry.numArgs = numArgs;
47  entry.argNames = argNames;
48  entry.help = help;
49 
50  if ( back )
51    argTable.push_back( entry );
52  else
53    argTable.push_front( entry );
54}
55
56
57bool CmdLineParser::parse( ArgParserCallback cb, void * data, int argc, char ** argv )
58{
59  this->exeName = argv[0];
60 
61  //put all args in vector
62  std::vector<std::string> args;
63 
64  for ( int i = 1; i<argc; i++ )
65  {
66    std::string s = argv[i];
67   
68    if ( s.find( "=" ) == std::string::npos )
69    {
70      args.push_back(s);
71    }
72    else
73    {
74      std::string op = s;
75      std::string ar = s;
76      op.erase( op.find("=") );
77      ar.erase( 0, ar.find("=")+1);
78     
79      //PRINTF(0)("'%s' '%s'\n", op.c_str(), ar.c_str());
80      args.push_back( op );
81      args.push_back( ar );
82    }
83  }
84 
85  int i = 0;
86 
87  ArgTable::iterator it;
88  bool finish;
89  bool found;
90 
91  while ( i < args.size() )
92  {
93    found = false;
94    for ( it = argTable.begin(); it != argTable.end(); it++ )
95    {
96      if ( matches( *it, args[i], finish ) )
97      {
98        found = true;
99       
100        if ( it->numArgs + i >= args.size() )
101        {
102          PRINTF(1)( "%s needs %d arguments!\n", args[i].c_str(), it->numArgs );
103          return false;
104        }
105       
106        std::vector<MultiType> argArgs;
107       
108        for ( int j = 1; j <= it->numArgs; j++ )
109          argArgs.push_back( args[i+j] );
110       
111        if ( !cb( *it, data, args[i], argArgs ) )
112          return false;
113       
114        i += it->numArgs;
115       
116        if ( finish )
117        {
118          i++;
119          break;
120        }
121        else 
122        { 
123          assert( it->numArgs == 0 );
124        }
125      }
126    }
127   
128    if ( !found )
129    {
130      PRINTF(1)("%s: illegal option\n", args[i].c_str());
131      return false;
132    }
133  }
134 
135  return true;
136}
137
138bool CmdLineParser::matches( ArgTableEntry entry, std::string arg, bool & finish )
139{
140  finish = true;
141 
142  if ( arg.length() < 2 )
143    return false;
144 
145  if ( arg[0] == '-' )
146  {
147    if ( arg[1] == '-' )
148    {
149      arg.erase( 0, 2 );
150     
151      if ( entry.longOption.find('%') != std::string::npos )
152      {
153        //TODO implement bether match algo
154        assert( entry.longOption.find('%') == entry.longOption.length()-1 );
155        std::string lo = entry.longOption;
156        lo.erase( lo.length()-1, 1 );
157        //PRINTF(0)("%s %s\n", arg.c_str(), lo.c_str());
158        return arg.find( lo ) == 0;
159      }
160      else
161      {
162        return arg.find( entry.longOption ) != std::string::npos;
163      }
164    }
165    else
166    {
167      if ( arg.find(entry.shortOption) != std::string::npos && arg.length() != 2 && entry.numArgs != 0 )
168      {
169        PRINTF(1)("using multiple flags together is only alowed if none needs an arugument. %c needs %d arguments\n", entry.shortOption, entry.numArgs);
170        //FIXME find beter solution
171        exit(1);
172        return false;
173      }
174      finish = arg.length()==2;
175      return arg.find(entry.shortOption) != std::string::npos;
176    }
177  }
178}
179
180void CmdLineParser::showHelp()
181{
182  printf("Usage: %s [options]\n", exeName.c_str());
183  printf("\n");
184 
185  std::list<std::vector<std::string> > output;
186 
187  for ( ArgTable::iterator it = argTable.begin(); it != argTable.end(); it++ )
188  {
189    output.push_back( std::vector<std::string>() );
190   
191    SubString substr( it->argNames );
192    std::string args;
193    assert( it->numArgs == substr.getCount() );
194     
195    for ( int i = 0; i<it->numArgs; i++ )
196    {
197      args += " [" + substr[i] + "]";
198    }
199   
200    if ( it->shortOption != '\0' )
201    {
202      output.back().push_back( " -" + std::string((char*)&it->shortOption, 1) );
203      output.back().back() += args;
204    }
205    else
206      output.back().push_back( "" );
207   
208    if ( it->longOption != "" )
209    {
210      output.back().push_back( "--" + it->longOption );
211     
212      output.back().back() += args;
213    }
214    else
215      output.back().push_back( "" );
216   
217    output.back().push_back( it->help );
218  }
219 
220  output.push_back( std::vector<std::string>() );
221  output.back().push_back( "Option" );
222  output.back().push_back( "Long option" );
223  output.back().push_back( "Description" );
224 
225  output.reverse();
226 
227  int maxShort = 0;
228  int maxLong = 0;
229 
230  std::list<std::vector<std::string> >::const_iterator it;
231 
232  for ( it = output.begin(); it != output.end(); it++ )
233  {
234    if ( (*it)[0].length() > maxShort )
235      maxShort = (*it)[0].length();
236   
237    if ( (*it)[1].length() > maxLong )
238      maxLong = (*it)[1].length();
239  }
240 
241  for ( it = output.begin(); it != output.end(); it++ )
242  {
243    printf("%s ", (*it)[0].c_str());
244   
245    for ( int i = 0; i<maxShort-(*it)[0].length(); i++ )
246      printf(" ");
247   
248    printf("%s ", (*it)[1].c_str());
249   
250    for ( int i = 0; i<maxLong-(*it)[1].length(); i++ )
251      printf(" ");
252   
253    printf("%s\n", (*it)[2].c_str());
254  }
255 
256  exit(0);
257}
Note: See TracBrowser for help on using the repository browser.