CVC3
|
00001 /*****************************************************************************/ 00002 /*! 00003 * \file main.cpp 00004 * \brief Main program for cvc3 00005 * 00006 * Author: Clark Barrett 00007 * 00008 * Created: Wed Dec 4 17:21:10 2002 00009 * 00010 * <hr> 00011 * 00012 * License to use, copy, modify, sell and/or distribute this software 00013 * and its documentation for any purpose is hereby granted without 00014 * royalty, subject to the terms and conditions defined in the \ref 00015 * LICENSE file provided with this distribution. 00016 * 00017 * <hr> 00018 * 00019 */ 00020 /*****************************************************************************/ 00021 00022 #include <signal.h> 00023 #include <fstream> 00024 #include <iomanip> 00025 00026 #include "os.h" 00027 #include "vc.h" 00028 #include "parser.h" 00029 #include "vc_cmd.h" 00030 #include "command_line_flags.h" 00031 #include "statistics.h" 00032 00033 #ifdef _MSC_VER 00034 #include <windows.h> 00035 #else 00036 #include <unistd.h> 00037 #endif 00038 00039 00040 using namespace std; 00041 using namespace CVC3; 00042 00043 00044 static void parse_args(int argc, char **argv, CLFlags &flags, 00045 string& fileName); 00046 static void printUsage(const CLFlags& flags, bool followDisplay); 00047 00048 // Our own name 00049 static string programName; 00050 00051 static ValidityChecker* vc = NULL; 00052 IF_DEBUG(static DebugTimer* pRuntime = NULL;) 00053 00054 #ifndef _MSC_VER 00055 void sighandler(int signum) { 00056 cerr << "\nInterrupted by signal " << signum; 00057 if(signum == SIGALRM) 00058 cerr << " (self-timeout)"; 00059 cerr << ". " << programName << " is aborting.\n"; 00060 // Print the debugging info 00061 IF_DEBUG(if (pRuntime != NULL) CVC3::debugger.setElapsed(*pRuntime);) 00062 IF_DEBUG(debugger.printAll();) 00063 if(vc != NULL && vc->getFlags()["stats"].getBool()) 00064 cout << vc->getStatistics() << endl; 00065 if(vc != NULL) { 00066 // If deletion causes another signal, don't keep trying. 00067 // This is here to ensure that logs are dumped, etc. 00068 ValidityChecker* toDelete = vc; 00069 vc = NULL; 00070 delete toDelete; 00071 } 00072 abort(); 00073 } 00074 #else 00075 DWORD WINAPI thread_timeout(PVOID timeout) { 00076 Sleep((int)timeout * 1000); 00077 cerr << "(self-timeout)." << endl; 00078 if(vc != NULL && vc->getFlags()["stats"].getBool()) 00079 cout << vc->getStatistics() << endl; 00080 if(vc != NULL) { 00081 // If deletion causes another signal, don't keep trying. 00082 // This is here to ensure that logs are dumped, etc. 00083 ValidityChecker* toDelete = vc; 00084 vc = NULL; 00085 delete toDelete; 00086 } 00087 ExitProcess(1); 00088 } 00089 #endif 00090 00091 00092 int main(int argc, char **argv) 00093 { 00094 CLFlags flags(ValidityChecker::createFlags()); 00095 programName = string(argv[0]); 00096 IF_DEBUG(DebugTimer runtime(CVC3::debugger.timer("total runtime"));) 00097 IF_DEBUG(pRuntime = &runtime;) 00098 00099 #ifndef _MSC_VER 00100 signal(SIGINT, sighandler); 00101 signal(SIGTERM, sighandler); 00102 signal(SIGQUIT, sighandler); 00103 signal(SIGALRM, sighandler); 00104 signal(SIGSEGV, sighandler); 00105 #endif 00106 00107 string fileName(""); 00108 00109 try { 00110 parse_args(argc, argv, flags, fileName); 00111 } catch(Exception& e) { 00112 cerr << "*** " << e; 00113 cerr << "\n\nRun with -help option for usage information." << endl; 00114 exit(1); 00115 } 00116 00117 // In SMT-LIBv2, don't save the model between distinct check-sats 00118 // (unless user specifically requested it) 00119 if(flags["lang"].getString() != "" && 00120 getLanguage(flags["lang"].getString()) == SMTLIB_V2_LANG && 00121 !flags["internal::userSetNoSaveModel"].getBool()) { 00122 flags.setFlag("no-save-model", true); 00123 } 00124 00125 // Set the timeout, if given in the command line options 00126 int timeout = flags["timeout"].getInt(); 00127 if(timeout > 0) { 00128 #ifndef _MSC_VER 00129 alarm(timeout); 00130 #else 00131 // http://msdn2.microsoft.com/en-us/library/ms682453.aspx 00132 CreateThread(NULL, 0, thread_timeout, (PVOID)timeout, 0, NULL); 00133 #endif 00134 } 00135 00136 /* 00137 * Create and run the validity checker 00138 */ 00139 00140 // Debugging code may throw an exception 00141 try { 00142 vc = ValidityChecker::create(flags); 00143 } catch(Exception& e) { 00144 cerr << "*** Fatal exception: " << e << endl; 00145 exit(1); 00146 } 00147 00148 // -h flag sets "help" to false (+h would make it true, but that's 00149 // not what the user normally types in). 00150 if(!vc->getFlags()["help"].getBool()) { 00151 printUsage(vc->getFlags(), true); 00152 return 0; 00153 } 00154 if(!vc->getFlags()["unsupported"].getBool()) { 00155 printUsage(vc->getFlags(), false); 00156 return 0; 00157 } 00158 #ifndef VERSION 00159 #define VERSION "unknown" 00160 #endif 00161 // Similarly, -version sets the flag "version" to false 00162 if(!vc->getFlags()["version"].getBool()) { 00163 cout << "This is CVC3 version " << VERSION 00164 IF_DEBUG( << " (debug build)") 00165 << "\n\n"; 00166 cout << 00167 "Copyright (C) 2003-2010 by the Board of Trustees of Leland Stanford Junior\n" 00168 "University, New York University, and the University of Iowa.\n\n" 00169 "THIS SOFTWARE PROVIDED AS-IS, WITHOUT ANY WARRANTIES. " 00170 "USE IT AT YOUR OWN RISK.\n" 00171 << endl; 00172 return 0; 00173 } 00174 00175 try { 00176 // Calling getOutputLang() tests if the output language is 00177 // correctly specified; if not, an exception will be thrown 00178 InputLanguage outlang = vc->getEM()->getOutputLang(); 00179 if(outlang == SPASS_LANG && 00180 vc->getFlags()["translate"].getBool() && 00181 !vc->getFlags()["liftITE"].modified()) { 00182 // SPASS doesn't support ITE; make sure there are none 00183 vc->getFlags().setFlag("liftITE", true); 00184 } 00185 // Set the timer 00186 IF_DEBUG(CVC3::debugger.setCurrentTime(runtime);) 00187 // Read the input file 00188 vc->loadFile(fileName, vc->getEM()->getInputLang(), 00189 flags["interactive"].getBool()); 00190 } catch(Exception& e) { 00191 cerr << "*** Fatal exception: " << e << endl; 00192 exit(1); 00193 } 00194 00195 IF_DEBUG(CVC3::debugger.setElapsed(runtime);) 00196 00197 // Print the debugging info 00198 IF_DEBUG(debugger.printAll();) 00199 // Print statistics 00200 if(vc->getFlags()["stats"].getBool()) vc->printStatistics(); 00201 // Destruct the system 00202 TRACE_MSG("delete", "Deleting ValidityChecker [last trace from main.cpp]"); 00203 try { 00204 // The signal handler deletes the vc. If deletion segfaults, we don't 00205 // want to try it again. 00206 ValidityChecker* toDelete = vc; 00207 vc = NULL; 00208 delete toDelete; 00209 } catch(Exception& e) { 00210 cerr << "*** Fatal exception: " << e << endl; 00211 exit(1); 00212 } 00213 00214 return 0; 00215 } 00216 00217 void printUsage(const CLFlags& flags, bool followDisplay) { 00218 cout << "Usage: " << programName << " [options]\n" 00219 << programName << " will read the input from STDIN and \n" 00220 << "print the result on STDOUT.\n" 00221 << "Boolean (b) options are set 'on' by +option and 'off' by -option\n" 00222 << "(for instance, +model or -model).\n" 00223 << "Integer (i), string (s) and vector (v) options \n" 00224 << "require a parameter, e.g. -width 80\n" 00225 << "Also, (v) options can appear multiple times setting " 00226 << "args on and off,\n" 00227 << "as in +trace \"enable this\" -trace \"disable that\".\n" 00228 << "Option names can be abbreviated to the " 00229 << "shortest unambiguous prefix.\n\n" 00230 << "The options are:\n"; 00231 vector<string> names; 00232 // Get all the names of options (they all match the empty string) 00233 flags.countFlags("", names); 00234 for(size_t i=0,iend=names.size(); i!=iend; ++i) { 00235 const CLFlag& f(flags[names[i]]); 00236 if (f.display() != followDisplay) continue; 00237 string tpStr; // Print type of the option 00238 string pref; // Print + or - in front of the option 00239 string name(names[i]); // Print name and optionally the value 00240 CLFlagType tp = f.getType(); 00241 switch(tp) { 00242 case CLFLAG_NULL: tpStr = "(null)"; break; 00243 case CLFLAG_BOOL: 00244 tpStr = "(b)"; pref = (f.getBool())? "+" : "-"; 00245 break; 00246 case CLFLAG_INT: 00247 tpStr = "(i)"; pref = "-"; name = name+" "+int2string(f.getInt()); 00248 break; 00249 case CLFLAG_STRING: 00250 tpStr = "(s)"; pref = "-"; name = name+" "+f.getString(); 00251 break; 00252 case CLFLAG_STRVEC: 00253 tpStr = "(v)"; pref = "-"; name = name; 00254 break; 00255 default: 00256 DebugAssert(false, "printUsage: unknown flag type"); 00257 } 00258 cout << " " << tpStr << " " << pref << setw(25); 00259 cout.setf(ios::left); 00260 cout << name << " " << f.getHelp() << "\n"; 00261 } 00262 cout << endl; 00263 } 00264 00265 00266 void parse_args(int argc, char **argv, CLFlags &flags, string& fileName) { 00267 /* skip 0'th argument */ 00268 argv++; 00269 argc--; 00270 bool seenFileName(false); 00271 00272 for( ; argc > 0; argc--, argv++) { 00273 if((*argv)[0] == '-' || (*argv)[0] == '+') { 00274 // A command-line option 00275 vector<string> names; 00276 bool val = ((*argv)[0] == '+'); 00277 size_t n = flags.countFlags((*argv)+1, names); 00278 if(n == 0) 00279 throw CLException(string(*argv) + " does not match any known option"); 00280 else if(n > 1) { 00281 ostringstream ss; 00282 ss << *argv << " is ambiguous. Possible matches are:\n"; 00283 for(size_t i=0,iend=names.size(); i!=iend; ++i) { 00284 ss << " " << names[i] << "\n"; 00285 } 00286 throw CLException(ss.str()); 00287 } else { 00288 string name = names[0]; 00289 if(name == "no-save-model") { 00290 flags.setFlag("internal::userSetNoSaveModel", true); 00291 } 00292 // Single match; process the option 00293 CLFlagType tp = flags[name].getType(); 00294 switch(tp) { 00295 case CLFLAG_BOOL: flags.setFlag(name, val); break; 00296 case CLFLAG_INT: 00297 argc--; 00298 if(argc <= 0) 00299 throw CLException(string(*argv)+" (-"+name 00300 +") expects an integer argument."); 00301 argv++; 00302 // FIXME: test for *argv being an integer string 00303 flags.setFlag(name, atoi(*argv)); 00304 break; 00305 case CLFLAG_STRING: 00306 argc--; 00307 if(argc <= 0) 00308 throw CLException(string(*argv)+" (-"+name 00309 +") expects a string argument."); 00310 argv++; 00311 flags.setFlag(name, *argv); 00312 break; 00313 case CLFLAG_STRVEC: 00314 argc--; 00315 if(argc <= 0) 00316 throw CLException(string(*argv)+" (-"+name 00317 +") expects a string argument."); 00318 argv++; 00319 flags.setFlag(name, pair<string,bool>(*argv,val)); 00320 break; 00321 default: 00322 DebugAssert(false, "parse_args: Bad flag type: "+int2string(tp)); 00323 } 00324 } 00325 } else if(seenFileName) { 00326 throw CLException("More than one file name given: "+fileName 00327 +" and "+string(*argv)); 00328 } else { 00329 fileName = string(*argv); 00330 seenFileName = true; 00331 } 00332 } 00333 }