Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

cmdline_parser.cc

Go to the documentation of this file.
00001 /*
00002  *  File:       cucu.c
00003  *              $Id: cmdline_parser.cc,v 1.3 2002/04/29 09:34:10 alec Exp $
00004  *
00005  *  Author:     Alec Panoviciu (alecu@email.com)
00006  *
00007  *  Comments:
00008  *
00009  *  Revision history:
00010  *
00011  *  $Log: cmdline_parser.cc,v $
00012  *  Revision 1.3  2002/04/29 09:34:10  alec
00013  *  scanner ptree building compiles
00014  *
00015  */
00016 
00017 /* 
00018   Copyright (C) 2002 Alexandru Panoviciu (alecu@email.com)
00019 
00020   This program is free software; you can redistribute it and/or modify
00021   it under the terms of the GNU General Public License as published by
00022   the Free Software Foundation; either version 2 of the License, or
00023   (at your option) any later version.
00024 
00025   This program is distributed in the hope that it will be useful,
00026   but WITHOUT ANY WARRANTY; without even the implied warranty of
00027   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00028   GNU General Public License for more details.
00029 
00030   You should have received a copy of the GNU General Public License
00031   along with this program; if not, write to the Free Software
00032   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00033 
00034  */
00035 
00036 
00037 #include <sstream>
00038 
00039 #include "cmdline_parser.hh"
00040 
00041 CmdLineParser::CmdLineAtom::operator string () const
00042 {
00043   string s;
00044   string args;
00045 
00046   switch (tag)
00047   {
00048   case k_string: args = " <string>"; break;
00049   case k_bool: args = " [=yes|no|true|false]"; break;
00050   case k_int: args = " <integer>"; break;
00051   case k_float: args = " <float>"; break;
00052   default: ASSERT(0, "bad cmd line atom tag");
00053   }
00054   
00055   if ((sOpt != "") && (lOpt != "")) s = "-" + sOpt + " | --" + lOpt;
00056   else
00057     if (sOpt != "") s = "-" + sOpt;
00058     else s = "--" + lOpt;
00059 
00060   s += args;
00061   
00062   if (multi)
00063     if (optional) s = "(" + s + ")*";
00064     else s = "(" + s + ")+";
00065   else
00066     if (optional) s = "[" + s + "]";
00067     else if ((sOpt != "") && (lOpt != "")) s = "(" + s + ")";
00068 
00069   return s;
00070 }
00071 
00072 #define COLS 80
00073 #define TS 30
00074 ostream& CmdLineParser::CmdLineAtom::dumpDescription (ostream &os) const
00075 {
00076   string syn = (string) *this;
00077   int c = syn.length(); //column number (we wrap at 80);
00078   int i = 0; //index into the description string
00079   
00080   os << syn; c %= COLS;
00081   
00082   int aux = c + 5;
00083   while (c++ < max(TS, aux)) os << ' '; // :)
00084 
00085   for (int i = 0; i < description.length(); )
00086   {
00087     int wb = min(description.find(' ', i + 1), description.length());
00088     if (c + wb - i > COLS)
00089     {
00090       os << endl;
00091       for (c = 0; c++ < TS; os << ' ');
00092     }
00093     c += wb - i;
00094     while (i < wb) os << description[i++];
00095   }
00096   return os;
00097 }
00098 
00099 
00100 int CmdLineParser::parse (int argc, char *argv[])
00101   throw (CmdLineParseException)
00102 {
00103 
00104   //first set the invocation property with the command line string list
00105   for (int i = 0; i < argc; i++)
00106     pr["invocation"] << argv[i];
00107 
00108   for (int i = 0; i < argc; i++)
00109   {
00110     string s = argv[i];
00111     
00112     if (s[0] != '-') return i;
00113     if (s == "--") return i + 1;
00114     
00115     bool isLong = s[1] == '-'; //long form ?
00116     int c = isLong ? 2 : 1;
00117     string opt;
00118     int n;
00119     while ((s[c] != '=') && (c < s.length())) opt += s[c++];
00120     
00121     for (n = 0; n < desc.size(); n++)
00122     {
00123       if ((isLong && (opt == desc[n].lOpt)) ||
00124           (!isLong && (opt == desc[n].sOpt)))
00125       {
00126         switch (desc[n].tag) {
00127         case CmdLineAtom::k_string:
00128           {
00129             string val;
00130             if (c + 1 < s.length()) val.assign(s, c + 1, s.length() - c - 1);
00131             else if (i + 1 < argc) val = argv[++i];
00132             else throw CmdLineParseException("string argument expected after option \"" + opt + "\"");
00133             if (desc[n].multi) pr[desc[n].prop] << val;
00134             else pr[desc[n].prop] = val;
00135           }
00136           break;
00137         case CmdLineAtom::k_bool:
00138           {
00139             string val;
00140             bool bval;
00141             
00142             if (c + 1 < s.length()) val.assign(s, c + 1, s.length() - c - 1);
00143             else if ((i + 1 < argc) && (argv[i + 1][0] != '-')) val = argv[++i];
00144             else val = "yes";
00145 
00146             if ((val == "yes") || (val == "true") ||
00147                 (val == "YES") || (val == "TRUE")) bval = true;
00148             else if ((val == "no") || (val == "false") ||
00149                 (val == "NO") || (val == "FALSE")) bval = false;
00150             else throw CmdLineParseException("value of boolean option \"" + opt + "\" must be one of yes/no/false/true");
00151             if (desc[n].multi) pr[desc[n].prop] << bval;
00152             else pr[desc[n].prop] = bval;
00153           }
00154           break;
00155         case CmdLineAtom::k_int:
00156           {
00157             string val;
00158             int ival;
00159             
00160             if (c + 1 < s.length()) val.assign(s, c + 1, s.length() - c - 1);
00161             else if (i + 1 < argc) val = argv[++i];
00162             else throw CmdLineParseException("integer value expected after option \"" + opt + "\"");
00163 
00164             if (!(istringstream(val) >> ival))
00165               throw CmdLineParseException("bad integer argument for option \"" + opt + "\"");
00166             if (desc[n].multi) pr[desc[n].prop] << ival;
00167             else pr[desc[n].prop] = ival;
00168           }
00169           break;
00170         case CmdLineAtom::k_float:
00171           {
00172             string val;
00173             float fval;
00174             
00175             if (c + 1 < s.length()) val.assign(s, c + 1, s.length() - c - 1);
00176             else if (i + 1 < argc) val = argv[++i];
00177             else throw CmdLineParseException("integer value expected after option \"" + opt + "\"");
00178 
00179             if (!(istringstream(val) >> fval))
00180               throw CmdLineParseException("bad floating point argument for option \"" + opt + "\"");
00181             if (desc[n].multi) pr[desc[n].prop] << fval;
00182             else pr[desc[n].prop] = fval;
00183           }
00184           break;
00185         }
00186         break;
00187       }
00188     }
00189     
00190     if (n == desc.size())
00191       throw CmdLineParseException("unknown option \"" + opt + "\"");
00192   }
00193 }
00194 
00195 
00196 void CmdLineParser::printUsage (ostream &os)
00197 {
00198   os << "Usage: " << endl << progName << ' ';
00199   for (int i = 0; i < desc.size(); i++)
00200     os << (string) desc[i] << ' ';
00201 
00202   os << endl << endl << "Options: " << endl << endl;
00203   
00204   for (int i = 0; i < desc.size(); i++) {
00205     desc[i].dumpDescription(os);
00206     os << endl << endl;
00207   }
00208   
00209   os << endl << endl;
00210 }

Generated at Tue Jul 9 21:05:43 2002 for CppCC by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001