www.pudn.com > cppcc.rar > cmdline_parser.cc
/* * File: cucu.c * $Id: cmdline_parser.cc,v 1.3 2002/04/29 09:34:10 alec Exp $ * * Author: Alec Panoviciu (alecu@email.com) * * Comments: * * Revision history: * * $Log: cmdline_parser.cc,v $ * Revision 1.3 2002/04/29 09:34:10 alec * scanner ptree building compiles * */ /* Copyright (C) 2002 Alexandru Panoviciu (alecu@email.com) 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 */ #include#include "cmdline_parser.hh" CmdLineParser::CmdLineAtom::operator string () const { string s; string args; switch (tag) { case k_string: args = " "; break; case k_bool: args = " [=yes|no|true|false]"; break; case k_int: args = " "; break; case k_float: args = " "; break; default: ASSERT(0, "bad cmd line atom tag"); } if ((sOpt != "") && (lOpt != "")) s = "-" + sOpt + " | --" + lOpt; else if (sOpt != "") s = "-" + sOpt; else s = "--" + lOpt; s += args; if (multi) if (optional) s = "(" + s + ")*"; else s = "(" + s + ")+"; else if (optional) s = "[" + s + "]"; else if ((sOpt != "") && (lOpt != "")) s = "(" + s + ")"; return s; } #define COLS 80 #define TS 30 ostream& CmdLineParser::CmdLineAtom::dumpDescription (ostream &os) const { string syn = (string) *this; int c = syn.length(); //column number (we wrap at 80); int i = 0; //index into the description string os << syn; c %= COLS; int aux = c + 5; while (c++ < max(TS, aux)) os << ' '; // :) for (int i = 0; i < description.length(); ) { int wb = min(description.find(' ', i + 1), description.length()); if (c + wb - i > COLS) { os << endl; for (c = 0; c++ < TS; os << ' '); } c += wb - i; while (i < wb) os << description[i++]; } return os; } int CmdLineParser::parse (int argc, char *argv[]) throw (CmdLineParseException) { //first set the invocation property with the command line string list for (int i = 0; i < argc; i++) pr["invocation"] << argv[i]; for (int i = 0; i < argc; i++) { string s = argv[i]; if (s[0] != '-') return i; if (s == "--") return i + 1; bool isLong = s[1] == '-'; //long form ? int c = isLong ? 2 : 1; string opt; int n; while ((s[c] != '=') && (c < s.length())) opt += s[c++]; for (n = 0; n < desc.size(); n++) { if ((isLong && (opt == desc[n].lOpt)) || (!isLong && (opt == desc[n].sOpt))) { switch (desc[n].tag) { case CmdLineAtom::k_string: { string val; if (c + 1 < s.length()) val.assign(s, c + 1, s.length() - c - 1); else if (i + 1 < argc) val = argv[++i]; else throw CmdLineParseException("string argument expected after option \"" + opt + "\""); if (desc[n].multi) pr[desc[n].prop] << val; else pr[desc[n].prop] = val; } break; case CmdLineAtom::k_bool: { string val; bool bval; if (c + 1 < s.length()) val.assign(s, c + 1, s.length() - c - 1); else if ((i + 1 < argc) && (argv[i + 1][0] != '-')) val = argv[++i]; else val = "yes"; if ((val == "yes") || (val == "true") || (val == "YES") || (val == "TRUE")) bval = true; else if ((val == "no") || (val == "false") || (val == "NO") || (val == "FALSE")) bval = false; else throw CmdLineParseException("value of boolean option \"" + opt + "\" must be one of yes/no/false/true"); if (desc[n].multi) pr[desc[n].prop] << bval; else pr[desc[n].prop] = bval; } break; case CmdLineAtom::k_int: { string val; int ival; if (c + 1 < s.length()) val.assign(s, c + 1, s.length() - c - 1); else if (i + 1 < argc) val = argv[++i]; else throw CmdLineParseException("integer value expected after option \"" + opt + "\""); if (!(istringstream(val) >> ival)) throw CmdLineParseException("bad integer argument for option \"" + opt + "\""); if (desc[n].multi) pr[desc[n].prop] << ival; else pr[desc[n].prop] = ival; } break; case CmdLineAtom::k_float: { string val; float fval; if (c + 1 < s.length()) val.assign(s, c + 1, s.length() - c - 1); else if (i + 1 < argc) val = argv[++i]; else throw CmdLineParseException("integer value expected after option \"" + opt + "\""); if (!(istringstream(val) >> fval)) throw CmdLineParseException("bad floating point argument for option \"" + opt + "\""); if (desc[n].multi) pr[desc[n].prop] << fval; else pr[desc[n].prop] = fval; } break; } break; } } if (n == desc.size()) throw CmdLineParseException("unknown option \"" + opt + "\""); } } void CmdLineParser::printUsage (ostream &os) { os << "Usage: " << endl << progName << ' '; for (int i = 0; i < desc.size(); i++) os << (string) desc[i] << ' '; os << endl << endl << "Options: " << endl << endl; for (int i = 0; i < desc.size(); i++) { desc[i].dumpDescription(os); os << endl << endl; } os << endl << endl; }