/* GetOpt_pp: Yet another C++ version of getopt. Copyright (C) 2007, 2008 Daniel Gutson, FuDePAN This file is part of GetOpt_pp. GetOpt_pp 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 3 of the License, or (at your option) any later version. board-games is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "getopt_pp.h" #ifdef __APPLE__ extern char** environ; #endif namespace GetOpt { const char GetOpt_pp::EMPTY_OPTION = 0; GETOPT_INLINE void GetOpt_pp::_init_flags() { std::stringstream ss; _flags = ss.flags(); } GETOPT_INLINE void GetOpt_pp::_parse(int argc, char* argv[]) { OptionData* currentData = NULL; _app_name = argv[0]; // parse arguments by their '-' or '--': // (this will be a state machine soon) for(int i=1; i < argc; i++) { const char current = argv[i][0]; const char next = argv[i][1]; if (current == '-' && (isalpha(next) || next == '-' ) ) { // see what's next, differentiate whether it's short or long: if (next == '-' && argv[i][2] != 0) { // long option currentData = &_longOps[&argv[i][2]]; } else { // short option // iterate over all of them, keeping the last one in currentData // (so the intermediates will generate 'existent' arguments, as of '-abc') size_t j=1; do { currentData = &_shortOps[argv[i][j]]; j++; } while (argv[i][j] != 0); } } else { // save value! if (currentData == NULL) currentData = &_shortOps[EMPTY_OPTION]; currentData->args.push_back(argv[i]); } } _last = _Option::OK; // TODO: IMPROVE!! } GETOPT_INLINE void GetOpt_pp::_parse_env() { // this will be optimized in version 3 std::string var_name; std::string var_value; size_t var=0; std::string::size_type pos; OptionData* data; while (environ[var] != NULL) { var_name = environ[var]; pos = var_name.find('='); if (pos != std::string::npos) { var_value = var_name.substr(pos+1); var_name = var_name.substr(0, pos); if (_longOps.find(var_name) == _longOps.end()) { data = &_longOps[var_name]; data->args.push_back(var_value); data->flags = OptionData::Envir; } } else (data = &_longOps[var_name])->flags = OptionData::Envir; var++; } } GETOPT_INLINE GetOpt_pp::GetOpt_pp(int argc, char* argv[]) : _exc(std::ios_base::goodbit) { _init_flags(); _parse(argc, argv); } GETOPT_INLINE GetOpt_pp::GetOpt_pp(int argc, char* argv[], _EnvTag) { _init_flags(); _parse(argc, argv); _parse_env(); } GETOPT_INLINE GetOpt_pp& GetOpt_pp::operator >> ( const _Option& opt) throw (GetOptEx) { if (_last != _Option::ParsingError) { _last = opt(_shortOps, _longOps, _flags); switch(_last) { case _Option::OK: break; case _Option::OptionNotFound: if (_exc & std::ios_base::eofbit ) throw OptionNotFoundEx(); break; case _Option::BadType: if (_exc & std::ios_base::failbit ) throw InvalidFormatEx(); break; case _Option::NoArgs: if (_exc & std::ios_base::eofbit ) throw ArgumentNotFoundEx(); break; case _Option::TooManyArgs: if (_exc & std::ios_base::failbit ) throw TooManyArgumentsEx(); break; case _Option::OptionNotFound_NoEx: break; // Ok, it will be read by casting to bool case _Option::ParsingError: break; // just to disable warning } } else if (_exc & std::ios_base::failbit ) throw ParsingErrorEx(); return *this; } GETOPT_INLINE GetOpt_pp& GetOpt_pp::operator >> ( std::ios_base& (*iomanip)(std::ios_base&)) { std::stringstream ss; ss.flags(_flags); _flags = (ss << iomanip).flags(); return *this; } GETOPT_INLINE bool GetOpt_pp::options_remain() const { bool remain = false; ShortOptions::const_iterator it = _shortOps.begin(); while (it != _shortOps.end() && !remain) { remain = (it->second.flags == OptionData::CmdLine_NotExtracted); ++it; } if (!remain) { LongOptions::const_iterator it2 = _longOps.begin(); while (it2 != _longOps.end() && !remain) { remain = (it2->second.flags == OptionData::CmdLine_NotExtracted); ++it; } } return remain; } } // namespace GetOpt