main.cpp

Go to the documentation of this file.
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 #endif
00036 
00037 using namespace std;
00038 using namespace CVC3;
00039 
00040 
00041 static void parse_args(int argc, char **argv, CLFlags &flags,
00042            string& fileName);
00043 static void printUsage(const CLFlags& flags);
00044 
00045 // Our own name 
00046 static string programName;
00047 
00048 static ValidityChecker* vc = NULL;
00049 IF_DEBUG(static DebugTimer* pRuntime = NULL;)
00050 
00051 #ifndef _MSC_VER
00052 void sighandler(int signum) {
00053   cerr << "\nInterrupted by signal " << signum;
00054   if(signum == SIGALRM)
00055     cerr << " (self-timeout)";
00056   cerr << ".  " << programName << " is aborting.\n";
00057   // Print the debugging info
00058   IF_DEBUG(if (pRuntime != NULL) CVC3::debugger.setElapsed(*pRuntime));
00059   IF_DEBUG(debugger.printAll());
00060   if(vc != NULL && vc->getFlags()["stats"].getBool())
00061     cout << vc->getStatistics() << endl;
00062   exit(1);
00063 }
00064 #else
00065 DWORD WINAPI thread_timeout(PVOID timeout) {
00066   Sleep((int)timeout * 1000);
00067   cerr << "self-timeout." << endl;
00068   ExitProcess(1);
00069 }
00070 #endif
00071 
00072 
00073 int main(int argc, char **argv)
00074 {
00075   CLFlags flags(ValidityChecker::createFlags());
00076   programName = string(argv[0]);
00077   IF_DEBUG(DebugTimer runtime(CVC3::debugger.timer("total runtime")));
00078   IF_DEBUG(pRuntime = &runtime);
00079 
00080 #ifndef _MSC_VER
00081   signal(SIGINT, sighandler);
00082   signal(SIGTERM, sighandler);
00083   signal(SIGQUIT, sighandler);
00084   signal(SIGALRM, sighandler);
00085 #endif
00086   
00087   string fileName("");
00088 
00089   try {
00090     parse_args(argc, argv, flags, fileName);
00091   } catch(Exception& e) {
00092     cerr << "*** " << e;
00093     cerr << "\n\nRun with -help option for usage information." << endl;
00094     exit(1);
00095   }
00096 
00097   // Set the timeout, if given in the command line options
00098   int timeout = flags["timeout"].getInt();
00099   if(timeout > 0) {
00100 #ifndef _MSC_VER
00101     alarm(timeout);
00102 #else
00103     // http://msdn2.microsoft.com/en-us/library/ms682453.aspx
00104     CreateThread(NULL, 0, thread_timeout, (PVOID)timeout, 0, NULL);
00105 #endif
00106   }
00107 
00108   /*
00109    * Create and run the validity checker
00110    */ 
00111 
00112   // Debugging code may throw an exception
00113   try {
00114     vc = ValidityChecker::create(flags);
00115   } catch(Exception& e) {
00116     cerr << "*** Fatal exception: " << e << endl;
00117     exit(1);
00118   }
00119 
00120   // -h flag sets "help" to false (+h would make it true, but that's
00121   // not what the user normally types in).
00122   if(!vc->getFlags()["help"].getBool()) {
00123     printUsage(vc->getFlags());
00124     return 0;
00125   }
00126 #ifndef VERSION
00127 #define VERSION "unknown"
00128 #endif
00129   // Similarly, -version sets the flag "version" to false
00130   if(!vc->getFlags()["version"].getBool()) {
00131     cout << "This is CVC3 version " << VERSION
00132       IF_DEBUG( << " (debug build)")
00133    << "\n\n";
00134     cout <<
00135       "Copyright (C) 2003-2007 by the Board of Trustees of Leland Stanford Junior\n" 
00136       "University, New York University, and the University of Iowa.\n\n"
00137       "THIS SOFTWARE PROVIDED AS-IS, WITHOUT ANY WARRANTIES. "
00138       "USE IT AT YOUR OWN RISK.\n"
00139    << endl;
00140     return 0;
00141   }
00142 
00143   try {
00144     // Test if the output language is correctly specified; if not, an
00145     // exception will be thrown
00146     vc->getEM()->getOutputLang();
00147     // Set the timer
00148     IF_DEBUG(CVC3::debugger.setCurrentTime(runtime));
00149     // Read the input file
00150     vc->loadFile(fileName, vc->getEM()->getInputLang(),
00151                  flags["interactive"].getBool());
00152   } catch(Exception& e) {
00153     cerr << "*** Fatal exception: " << e << endl;
00154     exit(1);
00155   }
00156 
00157   IF_DEBUG(CVC3::debugger.setElapsed(runtime));
00158 
00159   // Print the debugging info
00160   IF_DEBUG(debugger.printAll());
00161   // Print statistics
00162   if(vc->getFlags()["stats"].getBool()) vc->printStatistics();
00163   // Destruct the system
00164   TRACE_MSG("delete", "Deleting ValidityChecker [last trace from main.cpp]");
00165   try {
00166     delete vc;
00167   } catch(Exception& e) {
00168     cerr << "*** Fatal exception: " << e << endl;
00169     exit(1);
00170   }
00171 
00172   return 0;
00173 }
00174 
00175 void printUsage(const CLFlags& flags) {
00176   cout << "Usage: " << programName << " [options]\n"
00177        << programName << " will read the input from STDIN and \n"
00178        << "print the result on STDOUT.\n"
00179        << "Boolean (b) options are set 'on' by +option and 'off' by -option\n"
00180        << "(for instance, +sat or -sat).\n"
00181        << "Integer (i), string (s) and vector (v) options \n"
00182        << "require a parameter, e.g. -width 80\n" 
00183        << "Also, (v) options can appear multiple times setting "
00184        << "args on and off,\n"
00185        << "as in +trace \"enable this\" -trace \"disable that\".\n"
00186        << "Option names can be abbreviated to the "
00187        << "shortest unambiguous prefix.\n\n"
00188        << "The options are:\n";
00189   vector<string> names;
00190   // Get all the names of options (they all match the empty string)
00191   flags.countFlags("", names);
00192   for(size_t i=0,iend=names.size(); i!=iend; ++i) {
00193     const CLFlag& f(flags[names[i]]);
00194     string tpStr; // Print type of the option
00195     string pref; // Print + or - in front of the option
00196     string name(names[i]); // Print name and optionally the value
00197     CLFlagType tp = f.getType();
00198     switch(tp) {
00199     case CLFLAG_NULL: tpStr = "(null)"; break;
00200     case CLFLAG_BOOL:
00201       tpStr = "(b)"; pref = (f.getBool())? "+" : "-";
00202       break;
00203     case CLFLAG_INT:
00204       tpStr = "(i)"; pref = "-"; name = name+" "+int2string(f.getInt());
00205       break;
00206     case CLFLAG_STRING:
00207       tpStr = "(s)"; pref = "-"; name = name+" "+f.getString();
00208       break;
00209     case CLFLAG_STRVEC:
00210       tpStr = "(v)"; pref = "-"; name = name;
00211       break;
00212     default:
00213       DebugAssert(false, "printUsage: unknown flag type");
00214     }
00215     cout << " " << tpStr << " " << pref << setw(15);
00216     cout.setf(ios::left);
00217     cout << name << " " << f.getHelp() << "\n";
00218   }
00219   cout << endl;
00220 }
00221   
00222 
00223 void parse_args(int argc, char **argv, CLFlags &flags, string& fileName) {
00224   /* skip 0'th argument */
00225   argv++;
00226   argc--;
00227   bool seenFileName(false);
00228 
00229   for( ; argc > 0; argc--, argv++) {
00230     if((*argv)[0] == '-' || (*argv)[0] == '+') {
00231       // A command-line option
00232       vector<string> names;
00233       bool val = ((*argv)[0] == '+');
00234       size_t n = flags.countFlags((*argv)+1, names);
00235       if(n == 0)
00236   throw CLException(string(*argv) + " does not match any known option");
00237       else if(n > 1) {
00238   ostringstream ss;
00239   ss << *argv << " is ambiguous.  Possible matches are:\n";
00240   for(size_t i=0,iend=names.size(); i!=iend; ++i) {
00241     ss << "  " << names[i] << "\n";
00242   }
00243   throw CLException(ss.str());
00244       } else {
00245   string name = names[0];
00246   // Single match; process the option
00247   CLFlagType tp = flags[name].getType();
00248   switch(tp) {
00249   case CLFLAG_BOOL: flags.setFlag(name, val); break;
00250   case CLFLAG_INT:
00251     argc--;
00252     if(argc <= 0)
00253       throw CLException(string(*argv)+" (-"+name
00254             +") expects an integer argument.");
00255     argv++;
00256     // FIXME: test for *argv being an integer string
00257     flags.setFlag(name, atoi(*argv));
00258     break;
00259   case CLFLAG_STRING:
00260     argc--;
00261     if(argc <= 0)
00262       throw CLException(string(*argv)+" (-"+name
00263             +") expects a string argument.");
00264     argv++;
00265     flags.setFlag(name, *argv);
00266     break;
00267   case CLFLAG_STRVEC:
00268     argc--;
00269     if(argc <= 0)
00270       throw CLException(string(*argv)+" (-"+name
00271             +") expects a string argument.");
00272     argv++;
00273     flags.setFlag(name, pair<string,bool>(*argv,val));
00274     break;
00275   default:
00276     DebugAssert(false, "parse_args: Bad flag type: "+int2string(tp));
00277   }
00278       }
00279     } else if(seenFileName) {
00280       throw CLException("More than one file name given: "+fileName
00281       +" and "+string(*argv));
00282     } else {
00283       fileName = string(*argv);
00284       seenFileName = true;
00285     }
00286   }
00287 }

Generated on Tue Jul 3 14:33:37 2007 for CVC3 by  doxygen 1.5.1