/* * Copyright (C) 2000,2003 Daniel Heck * * 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 * of the License, or (at your option) any later version. * * This program 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, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * $Id: argp.cc,v 1.3 2003/10/20 16:15:34 dheck Exp $ */ #include "argp.hh" #include using namespace std; using px::argp::ArgParser; ArgParser::ArgParser() { } ArgParser::~ArgParser(){ } void ArgParser::on_error (ErrorType t, const std::string &arg) { cerr << "Error: " << errormsg(t, arg) << endl; } void ArgParser::on_argument (const std::string &/*arg*/) { } void ArgParser::on_option (int /*id*/, const std::string &/*param*/) { } void ArgParser::def (int id, const std::string &name, char abbr, bool takesparam) { m_opts.push_back (Option(id, abbr, string("--") + name, takesparam)); } void ArgParser::def (bool *boolvar, const std::string &name, char abbr) { Option opt(-1, abbr, string("--") + name, false); opt.boolvar = boolvar; m_opts.push_back(opt); } string ArgParser::errormsg(ErrorType t, const std::string &arg) const { string errmsg; switch (t) { case InvalidParam: errmsg = "Invalid parameter for option `"; break; case AmbiguousOpt: errmsg = "Ambiguous command line option `"; break; case UnknownOpt: errmsg = "Unknown command line option `"; break; case MissingParam: errmsg = "Missing parameter for option `"; break; default: return string(); } errmsg += arg; errmsg += "'."; return errmsg; } void ArgParser::process_option(Option &opt, const std::string ¶m) { if (opt.boolvar) *opt.boolvar = true; else on_option(opt.id, param); } void ArgParser::getlongopt (const std::string &arg) { string::const_iterator eqpos = find(arg.begin(), arg.end(), '='); string optname(arg.begin(), eqpos); option_iterator i, j; j = i = find_prefix (m_opts.begin(), m_opts.end(), optname); if (i == m_opts.end()) { on_error (UnknownOpt, optname); } else if (find_prefix(++j, m_opts.end(), optname) != m_opts.end()) { on_error (AmbiguousOpt, optname); } else if (i->takesparam) { if (eqpos != arg.end()) { process_option (*i, string(eqpos+1, arg.end())); } else if (!m_arglist.empty()) { process_option (*i, m_arglist.front()); m_arglist.pop_front(); } else on_error (MissingParam, optname); } else if (eqpos != arg.end()) { on_error (InvalidParam, optname); } else process_option(*i, ""); } void ArgParser::getshortopt (const std::string &arg) { option_iterator i = m_opts.begin(); for (; i != m_opts.end(); ++i) if (i->shortopt == arg[1]) break; string option = arg.substr(0, 2); if (i == m_opts.end()) { on_error (UnknownOpt, option); } else if (i->takesparam) { string param = arg.substr(2); if (param.empty()) { if (!m_arglist.empty()) { param = m_arglist.front(); m_arglist.pop_front(); process_option (*i, param); } else on_error (MissingParam, option); } else process_option (*i, param); } else { process_option (*i, ""); // The following characters can be options in their own right // (single-character options can be grouped, as in -hvx), so // put them back into the argument list. std::string newarg("-"); newarg.append(arg.begin()+2, arg.end()); if (newarg != "-") m_arglist.push_front(newarg); } } void ArgParser::parse () { bool no_more_opts = false; while (!m_arglist.empty()) { std::string arg = m_arglist.front(); m_arglist.pop_front(); if (!no_more_opts && arg.size() >= 2 && arg[0] == '-') { // Note: "-" is treated as an ordinary argument if (arg[1] == '-') { if (arg.size() == 2) // "--" terminates the option list no_more_opts = true; else getlongopt (arg); } else getshortopt (arg); } else on_argument (arg); } }