/* * 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.1 2003/01/19 17:19:32 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 ¶m) { } void ArgParser::def (int id, char abbr, const std::string &name, bool takesparam) { m_opts.push_back (Option(id, abbr, string("--") + name, takesparam)); } 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::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()) { on_option (i->id, string(eqpos+1, arg.end())); } else if (!m_arglist.empty()) { on_option (i->id, m_arglist.front()); m_arglist.pop_front(); } else on_error (MissingParam, optname); } else if (eqpos != arg.end()) { on_error (InvalidParam, optname); } else on_option(i->id, ""); } 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(); on_option (i->id, param); } else on_error (MissingParam, option); } else on_option (i->id, param); } else { on_option (i->id, ""); // 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); } }