00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <CommandLineParser.hpp>
00021 #include <CommandLineOption.hpp>
00022
00023 #include <RunningOptions.hpp>
00024
00025 #include <BaseName.hpp>
00026
00027 #include <config.h>
00028 #include <cvs-stamp.hpp>
00029
00030 #include <iomanip>
00031 #include <cstdlib>
00032 #include <cstdio>
00033
00034 void CommandLineParser::__treatOption(const int& optionNumber,
00035 int& argumentNumber)
00036 {
00037 CommandLineOption& currentOption = * __options[optionNumber];
00038 switch (currentOption.identifier()) {
00039 case CommandLineParser::help: {
00040 this->showHelp();
00041 std::exit(0);
00042 break;
00043 }
00044 case CommandLineParser::moreHelp: {
00045 this->showMoreHelp();
00046 std::exit(0);
00047 break;
00048 }
00049 case CommandLineParser::version: {
00050 this->showVersion();
00051 std::exit(0);
00052 break;
00053 }
00054 case CommandLineParser::noWindow: {
00055 RunningOptions::instance().setGUI(false);
00056 break;
00057 }
00058 case CommandLineParser::noPause: {
00059 RunningOptions::instance().setNoPauseOnError();
00060 break;
00061 }
00062 case CommandLineParser::verbosity: {
00063 if (argumentNumber+1>=__numberOfArguments) {
00064 this->showHelp();
00065 std::cerr << "\nerror: missing verbosity argument\n";
00066 std::exit(1);
00067 }
00068 argumentNumber++;
00069 if (sscanf(__arguments[argumentNumber], "%d", &__verbosity) <= 0) {
00070 this->showHelp();
00071 std::cerr << "\nerror: expecting an integer as verbosity argument\n";
00072 std::exit(1);
00073 }
00074 break;
00075 }
00076 default: {
00077 std::cerr << __FILE__ << ':' << __LINE__ << ": Option treatment not implemented\n";
00078 std::exit(1);
00079 }
00080 }
00081 }
00082
00083 void CommandLineParser::showHelp() const
00084 {
00085 this->showVersion();
00086 this->showUsage();
00087 }
00088
00089 void CommandLineParser::showBugReport() const
00090 {
00091 std::cout
00092 << "\nBUG REPORT: Please send bug reports to:\n"
00093 " ff3d-dev@nongnu.org or freefem@ann.jussieu.fr\n"
00094 "or better, use the Bug Tracking System:\n"
00095 " http://savannah.nongnu.org/bugs/?group=ff3d\n";
00096 }
00097
00098 void CommandLineParser::showLicence() const
00099 {
00100 std::cout <<
00101 "\nLICENCE:\n"
00102 "This program is free software; you can redistribute it and/or modify it\n"
00103 "under the terms of the GNU General Public License as published by the\n"
00104 "Free Software Foundation; either version 2, or (at your option) any later\n"
00105 "version."
00106 "\n"
00107 "This program is distributed in the hope that it will be useful, but\n"
00108 "WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00109 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
00110 "General Public License for more details.\n"
00111 "\n"
00112 "You should have received a copy of the GNU General Public License\n"
00113 "along with this program; if not, write to the Free Software\n"
00114 "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA\n"
00115 "02111-1307, USA.\n"
00116 "\n"
00117 "See the COPYING file in ff3d's root directory, the exact\n"
00118 "terms of this licence can also be consult online at GNU project\n"
00119 "official web site: http://www.gnu.org/copyleft/gpl.html\n";
00120 }
00121
00122 void CommandLineParser::showDescription() const
00123 {
00124 std::cout <<
00125 "\nDESCRIPTION:\n"
00126 "FreeFEM3D (aka ff3d) is a 3D solver of partial differential\n"
00127 "equations (PDE). It is a member of the familly of the freefem\n"
00128 "programs (see http://www.freefem.org).\n"
00129 "\n"
00130 "ff3d, as well as its cousins, is a PDE solver driven by a\n"
00131 "user-friendly language. It solves many kind of problems such as\n"
00132 "elasticity, fluids (Stokes and Navier-Stokes) and a lot more. The\n"
00133 "user has to enter the equation associated with the problem, giving\n"
00134 "either the PDE in strong formulation or weak (variational)\n"
00135 "formulation.\n"
00136 "\n"
00137 "ff3d can use either the Finite Elements method (the mesh of the\n"
00138 "geometry being provided by the user) or a Fictitious Domain like\n"
00139 "approach where the geometry is described using Constructive Solid\n"
00140 "Geometry (CSG). This description is done using the POV-Ray language\n"
00141 "but others such as VRML could be added.\n"
00142 "\n"
00143 "The processing of the results is left to the user. One can use\n"
00144 "various graphic tools: output in the MEdit mesh format or VTK are\n"
00145 "supported. The implementation of a VTK base visualization module is\n"
00146 "underway.\n"
00147 "\n"
00148 "The goal of ff3d is to provide a good teaching tool and a research\n"
00149 "toolbox (the code is written in C++ and its design is such that new\n"
00150 "methods can be easily implemented).\n";
00151 }
00152
00153 void CommandLineParser::showCredits() const
00154 {
00155 std::cout <<
00156 "\nCREDITS:\n"
00157 "Project leader\n"
00158 " Olivier Pironneau <Olivier.Pironneau@math.jussieu.fr>\n"
00159 "Developers\n"
00160 " Stéphane Del Pino <Stephane.DelPino@math.jussieu.fr>\n"
00161 " Cécile Dobrzynski <dobrzyns@ann.jussieu.fr>\n"
00162 " Pascal Havé <Pascal.Have@math.jussieu.fr>\n"
00163 "Debian Packager\n"
00164 " Christophe Prud'homme <prudhomm@debian.org>\n";
00165 }
00166
00167 void CommandLineParser::showMoreHelp() const
00168 {
00169 this->showHelp();
00170 this->showDescription();
00171 this->showLicence();
00172 this->showCredits();
00173 this->showBugReport();
00174 }
00175
00176 void CommandLineParser::showUsage() const
00177 {
00178 std::cout << "USAGE: " << baseName(this->__arguments[0])
00179 << " [ -<flag> [<val>] | --<name>[ <val>] ]... [filename]\n";
00180 size_t maxLongLenght = 0;
00181 size_t maxShortLenght = 0;
00182 size_t maxArgLenght = 0;
00183 for (size_t i=0; i<__options.size(); ++i) {
00184 maxLongLenght = std::max(maxLongLenght, __options[i]->longName().size());
00185 maxShortLenght = std::max(maxShortLenght, __options[i]->shortName().size());
00186 maxArgLenght = std::max(maxArgLenght, __options[i]->arguments().size());
00187 }
00188
00189 std::cout << std::setw(maxShortLenght+2)<< "Flag" << ','
00190 << std::setw(maxLongLenght) << "Name" <<' '
00191 << std::setw(maxArgLenght+1) << "Args"
00192 << " Description\n";
00193
00194 for (size_t i=0; i<__options.size(); ++i) {
00195 std::cout << std::setw(maxShortLenght+2)
00196 << __options[i]->shortName() << ','
00197 << std::setw(maxLongLenght)
00198 << __options[i]->longName() <<' '
00199 << std::setw(maxArgLenght+1) << __options[i]->arguments()
00200 << " " << __options[i]->description() << '\n';
00201 }
00202 std::cout << "Options are specified by doubled hyphens and their name\n"
00203 << "or by a single hyphen and the flag character.\n";
00204 }
00205
00206 void CommandLineParser::showVersion() const
00207 {
00208 std::cout << "ff3d - a General PDE solver - Ver. "
00209 << VERSION;
00210 #ifdef CVS_STAMP
00211 std::cout << " (cvs: " << CVS_STAMP << ')';
00212 #endif // CVS_STAMP
00213 std::cout << '\n';
00214 }
00215
00216 void CommandLineParser::__parse()
00217 {
00218 for (int i=1; i<__numberOfArguments; ++i) {
00219 std::string opt = __arguments[i];
00220 if (opt[0] == '-') {
00221 if (opt.size()>1) {
00222 if (opt[1] == '-') {
00223 OptionsLexerType::const_iterator iOption = __longOptionsLexer.find(opt);
00224 if (iOption == __longOptionsLexer.end()) {
00225 this->showHelp();
00226 std::cerr << "\nerror: unknown long argument '" << opt << "'\n";
00227 std::exit(1);
00228 break;
00229 } else {
00230 this->__treatOption(iOption->second, i);
00231 }
00232 } else {
00233 OptionsLexerType::const_iterator iOption = __shortOptionsLexer.find(opt);
00234 if (iOption == __shortOptionsLexer.end()) {
00235 this->showHelp();
00236 std::cerr << "\nerror: unknown short argument '" << opt << "'\n";
00237 std::exit(1);
00238 break;
00239 } else {
00240 this->__treatOption(iOption->second, i);
00241 }
00242 }
00243 } else {
00244 this->showHelp();
00245 std::cerr << "\nerror: '-' is not a valid option\n";
00246 std::exit(1);
00247 break;
00248 }
00249 } else {
00250 if (__filename.size() != 0) {
00251 this->showHelp();
00252 std::cerr << "\nerror: reading '" << opt
00253 << "' filename '" <<__filename
00254 << "' was already specified\n";
00255 std::exit(1);
00256 }
00257 __filename = opt;
00258 }
00259 }
00260 }
00261
00262 CommandLineParser::
00263 CommandLineParser(int argc,
00264 char** argv)
00265 : __numberOfArguments(argc),
00266 __arguments(argv),
00267 __verbosity(3)
00268 {
00269
00270 __options.push_back(new CommandLineOption(CommandLineParser::version,
00271 "--version", "-v",
00272 "Display version information and exit"));
00273
00274 __options.push_back(new CommandLineOption (CommandLineParser::help,
00275 "--help", "-h",
00276 "Display usage information and exit"));
00277
00278 __options.push_back(new CommandLineOption (CommandLineParser::moreHelp,
00279 "--more-help", "-H",
00280 "Display more usage information and exit"));
00281
00282 __options.push_back(new CommandLineOption (CommandLineParser::noWindow,
00283 "--no-window", "-nw",
00284 "Specifies that no GUI is to be used"));
00285
00286 __options.push_back(new CommandLineOption (CommandLineParser::noPause,
00287 "--no-pause", "-np",
00288 "No pause on error for debugging"));
00289
00290 CommandLineOption::ArgumentsType verbosityArguments[]
00291 = { CommandLineOption::integer,
00292 CommandLineOption::end };
00293 __options.push_back(new CommandLineOption(CommandLineParser::verbosity,
00294 "--verbosity", "-V",
00295 "Set level of verbosity",
00296 verbosityArguments));
00297
00298 for (size_t i=0; i < __options.size(); ++i) {
00299 const CommandLineOption& c = *(__options[i]);
00300 const std::string& shortName = c.shortName();
00301 const std::string& longName = c.longName();
00302
00303 ASSERT(__shortOptionsLexer.find(shortName) == __shortOptionsLexer.end());
00304 ASSERT(__longOptionsLexer.find(longName) == __longOptionsLexer.end());
00305
00306 __shortOptionsLexer[shortName] = i;
00307 __longOptionsLexer[longName] = i;
00308 }
00309
00310
00311 this->__parse();
00312
00313 if (not(RunningOptions::instance().useGUI())) {
00314 if (not(this->hasFilename())) {
00315 this->showHelp();
00316 std::cerr << "\nerror: when no GUI is used, filename is mandatory\n";
00317 std::cerr << " Check your DISPLAY variable or remove '-nw' option\n";
00318 std::exit(1);
00319 }
00320 }
00321 }
00322
00323 CommandLineParser::
00324 ~CommandLineParser()
00325 {
00326 for (OptionsList::iterator i = __options.begin();
00327 i != __options.end(); ++i) {
00328 delete *i;
00329 }
00330 }