/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Christoph Renner co-programmer: */ #include "cmdline_parser.h" #include #include "src/lib/util/substring.h" /** * standard constructor */ CmdLineParser::CmdLineParser () { } /** * standard deconstructor */ CmdLineParser::~CmdLineParser () { } bool CmdLineParser::add( int id, const std::string & longOption, char shortOption, int numArgs, const std::string & argNames, const std::string& help, bool back ) { ArgTableEntry entry; entry.id = id; entry.longOption = longOption; entry.shortOption = shortOption; entry.numArgs = numArgs; entry.argNames = argNames; entry.help = help; if ( back ) argTable.push_back( entry ); else argTable.push_front( entry ); return true; } bool CmdLineParser::parse( ArgParserCallback cb, void * data, int argc, char ** argv ) { this->exeName = argv[0]; //put all args in vector std::vector args; for ( int i = 1; i 0 && args[ i + posArgs ][0] == '-' ) break; else posArgs++; } posArgs--; if ( it->numArgs > posArgs ) { PRINTF(1)( "%s needs %d arguments!\n", args[i].c_str(), it->numArgs ); return false; } std::vector argArgs; for (unsigned int j = 1; j <= it->numArgs; j++ ) argArgs.push_back( args[i+j] ); if ( !cb( *it, data, args[i], argArgs ) ) return false; i += it->numArgs; if ( finish ) { i++; break; } else { assert( it->numArgs == 0 ); } } } if ( !found ) { PRINTF(1)("%s: illegal option\n", args[i].c_str()); return false; } } return true; } bool CmdLineParser::matches( ArgTableEntry entry, std::string arg, bool & finish ) { finish = true; if ( arg.length() < 2 ) return false; if ( arg[0] == '-' ) { if ( arg[1] == '-' ) { arg.erase( 0, 2 ); if ( entry.longOption.find('%') != std::string::npos ) { //TODO implement bether match algo assert( entry.longOption.find('%') == entry.longOption.length()-1 ); std::string lo = entry.longOption; lo.erase( lo.length()-1, 1 ); //PRINTF(0)("%s %s\n", arg.c_str(), lo.c_str()); return arg.find( lo ) == 0; } else { return arg.find( entry.longOption ) != std::string::npos; } } else { if ( arg.find(entry.shortOption) != std::string::npos && arg.length() != 2 && entry.numArgs != 0 ) { PRINTF(1)("using multiple flags together is only alowed if none needs an arugument. %c needs %d arguments\n", entry.shortOption, entry.numArgs); //FIXME find beter solution exit(1); return false; } finish = arg.length()==2; return arg.find(entry.shortOption) != std::string::npos; } } else return false; } void CmdLineParser::showHelp() { printf("Usage: %s [options]\n", exeName.c_str()); printf("\n"); std::list > output; for ( ArgTable::iterator it = argTable.begin(); it != argTable.end(); it++ ) { output.push_back( std::vector() ); SubString substr( it->argNames ); std::string args; assert( it->numArgs == substr.size() ); for (unsigned int i = 0; inumArgs; i++ ) { args += " [" + substr[i] + "]"; } if ( it->shortOption != '\0' ) { output.back().push_back( " -" + std::string((char*)&it->shortOption, 1) ); output.back().back() += args; } else output.back().push_back( "" ); if ( it->longOption != "" ) { output.back().push_back( "--" + it->longOption ); output.back().back() += args; } else output.back().push_back( "" ); output.back().push_back( it->help ); } output.push_back( std::vector() ); output.back().push_back( "Option" ); output.back().push_back( "Long option" ); output.back().push_back( "Description" ); output.reverse(); unsigned int maxShort = 0; unsigned int maxLong = 0; std::list >::const_iterator it; for ( it = output.begin(); it != output.end(); it++ ) { if ( (*it)[0].length() > maxShort ) maxShort = (*it)[0].length(); if ( (*it)[1].length() > maxLong ) maxLong = (*it)[1].length(); } for ( it = output.begin(); it != output.end(); it++ ) { printf("%s ", (*it)[0].c_str()); for (unsigned int i = 0; i