ArgumentParser.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 //========================================================
00028 // Yet another command line parser. 
00029 // Francois Faure, iMAGIS-GRAVIR, May 2001
00030 //========================================================
00031 #include "ArgumentParser.h"
00032 
00033 namespace sofa
00034 {
00035 
00036 namespace helper
00037 {
00038 
00039 typedef std::istringstream istrstream; 
00040 
00041 ArgumentBase::ArgumentBase(char s, string l, string h, bool m)
00042 : shortName(s)
00043 , longName(l)
00044 , help(h)
00045 , mandatory(m)
00046 , isSet(false)
00047 {}
00048     
00050 ArgumentBase::~ArgumentBase()
00051 {}
00052     
00054 void ArgumentBase::print () const
00055 {
00056     std::cout << "-" << shortName <<",\t--"<< longName <<":\t" << help;
00057     if( mandatory ) std::cout<< " (required) ";
00058     std::cout << "  (default: "; printValue();
00059     std::cout << ")" << std::endl;
00060 }
00061 
00062 
00063 //========================================================================
00065 ArgumentParser::ArgumentParser( const string& helpstr, char hlpShrt, const string& hlpLng )
00066 : files(NULL)
00067 , globalHelp( helpstr )
00068 , helpShortName(hlpShrt)
00069 , helpLongName(hlpLng)
00070 {}
00071 
00073 ArgumentParser::ArgumentParser( std::vector<std::string>* files, const string& helpstr, char hlpShrt, const string& hlpLng )
00074 : files(files)
00075 , globalHelp( helpstr )
00076 , helpShortName(hlpShrt)
00077 , helpLongName(hlpLng)
00078 {}
00079 
00081 ArgumentParser::~ArgumentParser()
00082 {
00083     for( ArgVec::const_iterator a=commands.begin(), aend=commands.end(); a!=aend; ++a )
00084         delete (*a);
00085 }
00086 
00091 void ArgumentParser::operator () ( int argc, char** argv )
00092 {
00093     std::list<std::string> str;
00094     for (int i=1;i<argc;++i)
00095         str.push_back(std::string(argv[i]));
00096     (*this)(str);
00097 }
00098 
00099 void ArgumentParser::operator () ( std::list<std::string> str )
00100 {
00101     string shHelp("-");  shHelp.push_back( helpShortName ); 
00102     string lgHelp("--"); lgHelp.append( helpLongName ); 
00103     string name;
00104     while( !str.empty() ){
00105         name = str.front();
00106         str.pop_front();
00107 //      std::cout << "name = " << name << std::endl;
00108 //      std::cout << "lgHelp = " << lgHelp << std::endl;
00109 //      std::cout << "shHelp = " << shHelp << std::endl;
00110         
00111         // display help
00112         if( name == shHelp || name == lgHelp )
00113         {
00114             if( globalHelp.size()>0 ) std::cout<< globalHelp <<std::endl;
00115             std::cout << "(short name, long name, description, default value)\n-h,\t--help: this help" << std::endl;
00116             for( ArgVec::const_iterator a=commands.begin(), aend=commands.end(); a!=aend; ++a )
00117                 (*a)->print();
00118             if( files )
00119                 std::cout << "others: file names" << std::endl;
00120             exit(1);
00121         }
00122 
00123         // not an option
00124         else if( files && name[0]!='-' ){
00125             files->push_back(name);
00126         }
00127 
00128         // indicating the next argument is not an option
00129         else if( files && name=="--" ){
00130             files->push_back(str.front());
00131             str.pop_front();
00132         }
00133 
00134         // long name
00135         else if( name.length() > 1 && name[0]=='-' && name[1]=='-' ){
00136             string a;
00137             for( unsigned int i=2; i<name.length(); ++i ){
00138                 a += name[i];
00139             }
00140             if( longName.find(a) != longName.end() ){
00141                 if( !(longName[ a ]->read( str ))) 
00142                     std::cerr<< "\ncould not read value for option " << name << std::endl << std::endl;
00143                 else parameter_set[longName[ a ]] = true;
00144             }
00145             else std::cerr << "\nUnknown option " << name << std::endl << std::endl;
00146         }
00147         
00148         // short names (possibly concatenated)
00149         else if( name.length() > 1 && name[0]=='-' && name[1]!='-' ){
00150             for( unsigned int i=1; i<name.length(); ++i ){
00151                 char a = name[i];
00152                 if( shortName.find(a) != shortName.end() ){
00153                     if( !(shortName[ a ]->read( str ))) 
00154                         std::cerr<< "\ncould not read value for option " << name << std::endl << std::endl;
00155                     else parameter_set[shortName[ a ]] = true;
00156                 }
00157                 else std::cerr << "\nUnknown option " << name[i] << std::endl << std::endl;
00158             }
00159         }
00160         
00161         //
00162         else std::cerr << "Unknown option " << name << std::endl;
00163     }
00164 
00165     // Unset mandatory arguments ?
00166     bool unset = false;
00167     for( ArgVec::const_iterator cm = commands.begin(), cmend=commands.end(); cm != cmend; ++cm )
00168     {
00169         if( (*cm)->mandatory && !(*cm)->isSet ){
00170             if( !unset )
00171             {
00172                 std::cout << "Please set the following parameters: (short name, long name, description)" << std::endl;
00173                 unset = true;
00174             }
00175             (*cm)->print();                 
00176         }
00177     }   
00178     if( unset ) exit(1);
00179 }
00180 
00181 } // namespace helper
00182 
00183 } // namespace sofa

Generated on Sun Nov 23 02:29:29 2008 for Sofa by  doxygen 1.5.7.1