1 /********************* */
4 ** Original author: mdeters
5 ** Major contributors: cconway
6 ** Minor contributors (to current version): barrett, dejan, taking
7 ** This file is part of the CVC4 prototype.
8 ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)
9 ** Courant Institute of Mathematical Sciences
10 ** New York University
11 ** See the file COPYING in the top-level source directory for licensing
12 ** information.\endverbatim
14 ** \brief Main driver for CVC4 executable
16 ** Main driver for CVC4 executable.
28 #include "cvc4autoconfig.h"
29 #include "main/main.h"
30 #include "main/interactive_shell.h"
31 #include "parser/parser.h"
32 #include "parser/parser_builder.h"
33 #include "parser/parser_exception.h"
34 #include "expr/expr_manager.h"
35 #include "smt/smt_engine.h"
36 #include "expr/command.h"
37 #include "util/Assert.h"
38 #include "util/configuration.h"
39 #include "util/options.h"
40 #include "util/output.h"
41 #include "util/result.h"
42 #include "util/stats.h"
46 using namespace CVC4::parser
;
47 using namespace CVC4::main
;
49 int runCvc4(int argc
, char* argv
[]);
50 void doCommand(SmtEngine
&, Command
*);
55 /** Global options variable */
61 /** Just the basename component of argv[0] */
64 /** A pointer to the StatisticsRegistry (the signal handlers need it) */
65 CVC4::StatisticsRegistry
* pStatistics
;
70 // no more % chars in here without being escaped; it's used as a
71 // printf() format string
72 const string usageMessage
= "\
73 usage: %s [options] [input-file]\n\
75 Without an input file, or with `-', CVC4 reads from standard input.\n\
81 ss
<< "usage: " << options
.binary_name
<< " [options] [input-file]" << endl
83 << "Without an input file, or with `-', CVC4 reads from standard input." << endl
85 << "CVC4 options:" << endl
;
86 Options::printUsage( ss
.str(), *options
.out
);
90 * CVC4's main() routine is just an exception-safe wrapper around CVC4.
91 * Please don't construct anything here. Even if the constructor is
92 * inside the try { }, an exception during destruction can cause
93 * problems. That's why main() wraps runCvc4() in the first place.
94 * Put everything in runCvc4().
96 int main(int argc
, char* argv
[]) {
98 return runCvc4(argc
, argv
);
99 } catch(OptionException
& e
) {
100 #ifdef CVC4_COMPETITION_MODE
101 *options
.out
<< "unknown" << endl
;
103 cerr
<< "CVC4 Error:" << endl
<< e
<< endl
;
106 } catch(Exception
& e
) {
107 #ifdef CVC4_COMPETITION_MODE
108 *options
.out
<< "unknown" << endl
;
110 *options
.err
<< "CVC4 Error:" << endl
<< e
<< endl
;
111 if(options
.statistics
&& pStatistics
!= NULL
) {
112 pStatistics
->flushStatistics(*options
.err
);
115 } catch(bad_alloc
&) {
116 #ifdef CVC4_COMPETITION_MODE
117 *options
.out
<< "unknown" << endl
;
119 *options
.err
<< "CVC4 ran out of memory." << endl
;
120 if(options
.statistics
&& pStatistics
!= NULL
) {
121 pStatistics
->flushStatistics(*options
.err
);
125 #ifdef CVC4_COMPETITION_MODE
126 *options
.out
<< "unknown" << endl
;
128 *options
.err
<< "CVC4 threw an exception of unknown type." << endl
;
134 int runCvc4(int argc
, char* argv
[]) {
136 // Initialize the signal handlers
142 int firstArgIndex
= options
.parseOptions(argc
, argv
);
144 progName
= options
.binary_name
.c_str();
149 } else if( options
.languageHelp
) {
150 Options::printLanguageHelp(*options
.out
);
152 } else if( options
.version
) {
153 *options
.out
<< Configuration::about().c_str() << flush
;
157 segvNoSpin
= options
.segvNoSpin
;
159 // If in competition mode, set output stream option to flush immediately
160 #ifdef CVC4_COMPETITION_MODE
161 *options
.out
<< unitbuf
;
164 // We only accept one input file
165 if(argc
> firstArgIndex
+ 1) {
166 throw Exception("Too many input files specified.");
169 // If no file supplied we will read from standard input
170 const bool inputFromStdin
=
171 firstArgIndex
>= argc
|| !strcmp("-", argv
[firstArgIndex
]);
173 // if we're reading from stdin on a TTY, default to interactive mode
174 if(!options
.interactiveSetByUser
) {
175 options
.interactive
= inputFromStdin
&& isatty(fileno(stdin
));
178 // Determine which messages to show based on smtcomp_mode and verbosity
179 if(Configuration::isMuzzledBuild()) {
180 Debug
.setStream(CVC4::null_os
);
181 Trace
.setStream(CVC4::null_os
);
182 Notice
.setStream(CVC4::null_os
);
183 Chat
.setStream(CVC4::null_os
);
184 Message
.setStream(CVC4::null_os
);
185 Warning
.setStream(CVC4::null_os
);
186 Dump
.setStream(CVC4::null_os
);
188 if(options
.verbosity
< 2) {
189 Chat
.setStream(CVC4::null_os
);
191 if(options
.verbosity
< 1) {
192 Notice
.setStream(CVC4::null_os
);
194 if(options
.verbosity
< 0) {
195 Message
.setStream(CVC4::null_os
);
196 Warning
.setStream(CVC4::null_os
);
200 // Create the expression manager
201 ExprManager
exprMgr(options
);
203 // Create the SmtEngine
204 SmtEngine
smt(&exprMgr
);
206 // signal handlers need access
207 pStatistics
= smt
.getStatisticsRegistry();
209 // Auto-detect input language by filename extension
210 const char* filename
= inputFromStdin
? "<stdin>" : argv
[firstArgIndex
];
212 ReferenceStat
< const char* > s_statFilename("filename", filename
);
213 RegisterStatistic
statFilenameReg(exprMgr
, &s_statFilename
);
215 if(options
.inputLanguage
== language::input::LANG_AUTO
) {
216 if( inputFromStdin
) {
217 // We can't do any fancy detection on stdin
218 options
.inputLanguage
= language::input::LANG_CVC4
;
220 unsigned len
= strlen(filename
);
221 if(len
>= 5 && !strcmp(".smt2", filename
+ len
- 5)) {
222 options
.inputLanguage
= language::input::LANG_SMTLIB_V2
;
223 } else if(len
>= 4 && !strcmp(".smt", filename
+ len
- 4)) {
224 options
.inputLanguage
= language::input::LANG_SMTLIB
;
225 } else if(( len
>= 4 && !strcmp(".cvc", filename
+ len
- 4) )
226 || ( len
>= 5 && !strcmp(".cvc4", filename
+ len
- 5) )) {
227 options
.inputLanguage
= language::input::LANG_CVC4
;
232 if(options
.outputLanguage
== language::output::LANG_AUTO
) {
233 options
.outputLanguage
= language::toOutputLanguage(options
.inputLanguage
);
236 // Determine which messages to show based on smtcomp_mode and verbosity
237 if(Configuration::isMuzzledBuild()) {
238 Debug
.setStream(CVC4::null_os
);
239 Trace
.setStream(CVC4::null_os
);
240 Notice
.setStream(CVC4::null_os
);
241 Chat
.setStream(CVC4::null_os
);
242 Message
.setStream(CVC4::null_os
);
243 Warning
.setStream(CVC4::null_os
);
244 Dump
.setStream(CVC4::null_os
);
246 if(options
.verbosity
< 2) {
247 Chat
.setStream(CVC4::null_os
);
249 if(options
.verbosity
< 1) {
250 Notice
.setStream(CVC4::null_os
);
252 if(options
.verbosity
< 0) {
253 Message
.setStream(CVC4::null_os
);
254 Warning
.setStream(CVC4::null_os
);
257 Debug
.getStream() << Expr::setlanguage(options
.outputLanguage
);
258 Trace
.getStream() << Expr::setlanguage(options
.outputLanguage
);
259 Notice
.getStream() << Expr::setlanguage(options
.outputLanguage
);
260 Chat
.getStream() << Expr::setlanguage(options
.outputLanguage
);
261 Message
.getStream() << Expr::setlanguage(options
.outputLanguage
);
262 Warning
.getStream() << Expr::setlanguage(options
.outputLanguage
);
263 Dump
.getStream() << Expr::setlanguage(options
.outputLanguage
)
264 << Expr::setdepth(-1)
265 << Expr::printtypes(false);
268 Parser
* replayParser
= NULL
;
269 if( options
.replayFilename
!= "" ) {
270 ParserBuilder
replayParserBuilder(&exprMgr
, options
.replayFilename
, options
);
272 if( options
.replayFilename
== "-") {
273 if( inputFromStdin
) {
274 throw OptionException("Replay file and input file can't both be stdin.");
276 replayParserBuilder
.withStreamInput(cin
);
278 replayParser
= replayParserBuilder
.build();
279 options
.replayStream
= new Parser::ExprStream(replayParser
);
281 if( options
.replayLog
!= NULL
) {
282 *options
.replayLog
<< Expr::setlanguage(options
.outputLanguage
) << Expr::setdepth(-1);
285 // Parse and execute commands until we are done
287 if( options
.interactive
) {
288 InteractiveShell
shell(exprMgr
, options
);
289 Message() << Configuration::getPackageName()
290 << " " << Configuration::getVersionString();
291 if(Configuration::isSubversionBuild()) {
292 Message() << " [" << Configuration::getSubversionId() << "]";
294 Message() << (Configuration::isDebugBuild() ? " DEBUG" : "")
296 << (Configuration::isAssertionBuild() ? "on" : "off")
298 if(replayParser
!= NULL
) {
299 // have the replay parser use the declarations input interactively
300 replayParser
->useDeclarationsFrom(shell
.getParser());
302 while((cmd
= shell
.readCommand())) {
307 ParserBuilder
parserBuilder(&exprMgr
, filename
, options
);
309 if( inputFromStdin
) {
310 parserBuilder
.withStreamInput(cin
);
313 Parser
*parser
= parserBuilder
.build();
314 if(replayParser
!= NULL
) {
315 // have the replay parser use the file's declarations
316 replayParser
->useDeclarationsFrom(parser
);
318 while((cmd
= parser
->nextCommand())) {
326 if( options
.replayStream
!= NULL
) {
327 // this deletes the expression parser too
328 delete options
.replayStream
;
329 options
.replayStream
= NULL
;
332 string result
= smt
.getInfo(":status").getValue();
335 if(result
== "sat") {
337 } else if(result
== "unsat") {
343 #ifdef CVC4_COMPETITION_MODE
344 // exit, don't return
345 // (don't want destructors to run)
349 ReferenceStat
< Result
> s_statSatResult("sat/unsat", result
);
350 RegisterStatistic
statSatResultReg(exprMgr
, &s_statSatResult
);
352 if(options
.statistics
) {
353 smt
.getStatisticsRegistry()->flushStatistics(*options
.err
);
359 /** Executes a command. Deletes the command after execution. */
360 void doCommand(SmtEngine
& smt
, Command
* cmd
) {
361 if( options
.parseOnly
) {
365 CommandSequence
*seq
= dynamic_cast<CommandSequence
*>(cmd
);
367 for(CommandSequence::iterator subcmd
= seq
->begin();
368 subcmd
!= seq
->end();
370 doCommand(smt
, *subcmd
);
373 if(options
.verbosity
> 0) {
374 *options
.out
<< "Invoking: " << *cmd
<< endl
;
377 if(options
.verbosity
>= 0) {
378 cmd
->invoke(&smt
, *options
.out
);