Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: merged the new_class_id branche back to the trunk.
merged with command:
svn merge https://svn.orxonox.net/orxonox/branches/new_class_id trunk -r9683:HEAD
no conflicts… puh..

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