00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <signal.h>
00032 #include <unistd.h>
00033 #include <fstream>
00034 #include <iomanip>
00035
00036
00037 #include "vc.h"
00038 #include "parser.h"
00039 #include "vc_cmd.h"
00040 #include "command_line_flags.h"
00041 #include "statistics.h"
00042
00043
00044 using namespace std;
00045 using namespace CVCL;
00046
00047
00048 static void parse_args(int argc, char **argv, CLFlags &flags,
00049 string& fileName);
00050 static void printUsage(const CLFlags& flags);
00051
00052
00053 static string programName;
00054
00055 IF_DEBUG(static DebugTimer runtime(CVCL::debugger.timer("total runtime")));
00056
00057 static ValidityChecker* vc = NULL;
00058
00059 void sighandler(int signum) {
00060 cerr << "\nInterrupted by signal " << signum;
00061 if(signum == SIGALRM)
00062 cerr << " (self-timeout)";
00063 cerr << ". " << programName << " is aborting.\n";
00064
00065 IF_DEBUG(CVCL::debugger.setElapsed(runtime));
00066 IF_DEBUG(debugger.printAll());
00067 if(vc != NULL && vc->getFlags()["stats"].getBool())
00068 cout << vc->getStatistics() << endl;
00069 exit(1);
00070 }
00071
00072 int main(int argc, char **argv)
00073 {
00074 CLFlags flags(ValidityChecker::createFlags());
00075 programName = string(argv[0]);
00076
00077 signal(SIGINT, sighandler);
00078 signal(SIGTERM, sighandler);
00079 signal(SIGQUIT, sighandler);
00080 signal(SIGALRM, sighandler);
00081
00082 string fileName("");
00083
00084 try {
00085 parse_args(argc, argv, flags, fileName);
00086 } catch(Exception& e) {
00087 cerr << "*** " << e;
00088 cerr << "\n\nRun with -help option for usage information." << endl;
00089 exit(1);
00090 }
00091
00092
00093 int timeout = flags["timeout"].getInt();
00094 if(timeout > 0) {
00095 alarm(timeout);
00096 }
00097
00098
00099
00100
00101
00102
00103 try {
00104 vc = ValidityChecker::create(flags);
00105 } catch(Exception& e) {
00106 cerr << "*** Fatal exception: " << e << endl;
00107 exit(1);
00108 }
00109
00110 IF_DEBUG(
00111 CVCL::debugger.init(&(vc->getFlags()["trace"].getStrVec()),
00112 &(vc->getFlags()["dump-trace"].getString()));
00113 );
00114
00115
00116
00117 if(!vc->getFlags()["help"].getBool()) {
00118 printUsage(vc->getFlags());
00119 return 0;
00120 }
00121 #ifndef VERSION
00122 #define VERSION "unknown"
00123 #endif
00124
00125 if(!vc->getFlags()["version"].getBool()) {
00126 cout << "This is CVC Lite version " << VERSION
00127 IF_DEBUG( << " (debug build)")
00128 << "\n\n";
00129 cout <<
00130 "Copyright (C) 2003 by the Board of Trustees of Leland Stanford Junior\n"
00131 "University and by New York University.\n\n"
00132 "THIS SOFTWARE PROVIDED AS-IS, WITHOUT ANY WARRANTIES. "
00133 "USE IT AT YOUR OWN RISK.\n"
00134 << endl;
00135 return 0;
00136 }
00137
00138 try {
00139
00140
00141 vc->getEM()->getOutputLang();
00142
00143 IF_DEBUG(CVCL::debugger.setCurrentTime(runtime));
00144
00145 vc->loadFile(fileName, vc->getEM()->getInputLang(),
00146 flags["interactive"].getBool());
00147 } catch(Exception& e) {
00148 cerr << "*** Fatal exception: " << e << endl;
00149 exit(1);
00150 }
00151
00152 IF_DEBUG(CVCL::debugger.setElapsed(runtime));
00153
00154 if (!flags["quiet"].getBool())
00155 cout << "\n" << programName << " is done.\n";
00156
00157
00158 IF_DEBUG(debugger.printAll());
00159
00160 if(vc->getFlags()["stats"].getBool()) vc->printStatistics();
00161
00162 TRACE_MSG("delete", "Deleting ValidityChecker [last trace from main.cpp]");
00163 delete vc;
00164 return 0;
00165 }
00166
00167 void printUsage(const CLFlags& flags) {
00168 cout << "Usage: " << programName << " [options]\n"
00169 << programName << " will read the input from STDIN and \n"
00170 << "print the result on STDOUT.\n"
00171 << "Boolean (b) options are set 'on' by +option and 'off' by -option\n"
00172 << "(for instance, +sat or -sat).\n"
00173 << "Integer (i), string (s) and vector (v) options \n"
00174 << "require a parameter, e.g. -width 80\n"
00175 << "Also, (v) options can appear multiple times setting "
00176 << "args on and off,\n"
00177 << "as in +trace \"enable this\" -trace \"disable that\".\n"
00178 << "Option names can be abbreviated to the "
00179 << "shortest unambiguous prefix.\n\n"
00180 << "The options are:\n";
00181 vector<string> names;
00182
00183 flags.countFlags("", names);
00184 for(size_t i=0,iend=names.size(); i!=iend; ++i) {
00185 const CLFlag& f(flags[names[i]]);
00186 string tpStr;
00187 string pref;
00188 string name(names[i]);
00189 CLFlagType tp = f.getType();
00190 switch(tp) {
00191 case CLFLAG_NULL: tpStr = "(null)"; break;
00192 case CLFLAG_BOOL:
00193 tpStr = "(b)"; pref = (f.getBool())? "+" : "-";
00194 break;
00195 case CLFLAG_INT:
00196 tpStr = "(i)"; pref = "-"; name = name+" "+int2string(f.getInt());
00197 break;
00198 case CLFLAG_STRING:
00199 tpStr = "(s)"; pref = "-"; name = name+" "+f.getString();
00200 break;
00201 case CLFLAG_STRVEC:
00202 tpStr = "(v)"; pref = "-"; name = name;
00203 break;
00204 default:
00205 DebugAssert(false, "printUsage: unknown flag type");
00206 }
00207 cout << " " << tpStr << " " << pref << setw(15);
00208 cout.setf(ios::left);
00209 cout << name << " " << f.getHelp() << "\n";
00210 }
00211 cout << endl;
00212 }
00213
00214
00215 void parse_args(int argc, char **argv, CLFlags &flags, string& fileName) {
00216
00217 argv++;
00218 argc--;
00219 bool seenFileName(false);
00220
00221 for( ; argc > 0; argc--, argv++) {
00222 if((*argv)[0] == '-' || (*argv)[0] == '+') {
00223
00224 vector<string> names;
00225 bool val = ((*argv)[0] == '+');
00226 size_t n = flags.countFlags((*argv)+1, names);
00227 if(n == 0)
00228 throw CLException(string(*argv) + " does not match any known option");
00229 else if(n > 1) {
00230 ostringstream ss;
00231 ss << *argv << " is ambiguous. Possible matches are:\n";
00232 for(size_t i=0,iend=names.size(); i!=iend; ++i) {
00233 ss << " " << names[i] << "\n";
00234 }
00235 throw CLException(ss.str());
00236 } else {
00237 string name = names[0];
00238
00239 CLFlagType tp = flags[name].getType();
00240 switch(tp) {
00241 case CLFLAG_BOOL: flags.setFlag(name, val); break;
00242 case CLFLAG_INT:
00243 argc--;
00244 if(argc <= 0)
00245 throw CLException(string(*argv)+" (-"+name
00246 +") expects an integer argument.");
00247 argv++;
00248
00249 flags.setFlag(name, atoi(*argv));
00250 break;
00251 case CLFLAG_STRING:
00252 argc--;
00253 if(argc <= 0)
00254 throw CLException(string(*argv)+" (-"+name
00255 +") expects a string argument.");
00256 argv++;
00257 flags.setFlag(name, *argv);
00258 break;
00259 case CLFLAG_STRVEC:
00260 argc--;
00261 if(argc <= 0)
00262 throw CLException(string(*argv)+" (-"+name
00263 +") expects a string argument.");
00264 argv++;
00265 flags.setFlag(name, pair<string,bool>(*argv,val));
00266 break;
00267 default:
00268 DebugAssert(false, "parse_args: Bad flag type: "+int2string(tp));
00269 }
00270 }
00271 } else if(seenFileName) {
00272 throw CLException("More than one file name given: "+fileName
00273 +" and "+string(*argv));
00274 } else {
00275 fileName = string(*argv);
00276 seenFileName = true;
00277 }
00278 }
00279 }