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, 2012 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 Driver for (sequential) CVC4 executable
16 ** Driver for (sequential) 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/dump.h"
42 #include "util/result.h"
43 #include "util/stats.h"
47 using namespace CVC4::parser
;
48 using namespace CVC4::main
;
50 static bool doCommand(SmtEngine
&, Command
*, Options
&);
54 /** Global options variable */
55 CVC4_THREADLOCAL(Options
*) pOptions
;
60 /** Just the basename component of argv[0] */
63 /** A pointer to the StatisticsRegistry (the signal handlers need it) */
64 CVC4::StatisticsRegistry
* pStatistics
;
69 void printUsage(Options
& options
, bool full
) {
71 ss
<< "usage: " << options
.binary_name
<< " [options] [input-file]" << endl
73 << "Without an input file, or with `-', CVC4 reads from standard input." << endl
75 << "CVC4 options:" << endl
;
77 Options::printUsage( ss
.str(), *options
.out
);
79 Options::printShortUsage( ss
.str(), *options
.out
);
83 int runCvc4(int argc
, char* argv
[], Options
& options
) {
85 // For the signal handlers' benefit
88 // Initialize the signal handlers
94 int firstArgIndex
= options
.parseOptions(argc
, argv
);
96 progName
= options
.binary_name
.c_str();
99 printUsage(options
, true);
101 } else if( options
.languageHelp
) {
102 Options::printLanguageHelp(*options
.out
);
104 } else if( options
.version
) {
105 *options
.out
<< Configuration::about().c_str() << flush
;
109 segvNoSpin
= options
.segvNoSpin
;
111 // If in competition mode, set output stream option to flush immediately
112 #ifdef CVC4_COMPETITION_MODE
113 *options
.out
<< unitbuf
;
116 // We only accept one input file
117 if(argc
> firstArgIndex
+ 1) {
118 throw Exception("Too many input files specified.");
121 // If no file supplied we will read from standard input
122 const bool inputFromStdin
=
123 firstArgIndex
>= argc
|| !strcmp("-", argv
[firstArgIndex
]);
125 // if we're reading from stdin on a TTY, default to interactive mode
126 if(!options
.interactiveSetByUser
) {
127 options
.interactive
= inputFromStdin
&& isatty(fileno(stdin
));
130 // Determine which messages to show based on smtcomp_mode and verbosity
131 if(Configuration::isMuzzledBuild()) {
132 Debug
.setStream(CVC4::null_os
);
133 Trace
.setStream(CVC4::null_os
);
134 Notice
.setStream(CVC4::null_os
);
135 Chat
.setStream(CVC4::null_os
);
136 Message
.setStream(CVC4::null_os
);
137 Warning
.setStream(CVC4::null_os
);
138 Dump
.setStream(CVC4::null_os
);
140 if(options
.verbosity
< 2) {
141 Chat
.setStream(CVC4::null_os
);
143 if(options
.verbosity
< 1) {
144 Notice
.setStream(CVC4::null_os
);
146 if(options
.verbosity
< 0) {
147 Message
.setStream(CVC4::null_os
);
148 Warning
.setStream(CVC4::null_os
);
152 // Create the expression manager
153 ExprManager
exprMgr(options
);
155 // Create the SmtEngine
156 SmtEngine
smt(&exprMgr
);
158 // signal handlers need access
159 pStatistics
= smt
.getStatisticsRegistry();
161 // Auto-detect input language by filename extension
162 const char* filename
= inputFromStdin
? "<stdin>" : argv
[firstArgIndex
];
164 ReferenceStat
< const char* > s_statFilename("filename", filename
);
165 RegisterStatistic
statFilenameReg(exprMgr
, &s_statFilename
);
167 if(options
.inputLanguage
== language::input::LANG_AUTO
) {
168 if( inputFromStdin
) {
169 // We can't do any fancy detection on stdin
170 options
.inputLanguage
= language::input::LANG_CVC4
;
172 unsigned len
= strlen(filename
);
173 if(len
>= 5 && !strcmp(".smt2", filename
+ len
- 5)) {
174 options
.inputLanguage
= language::input::LANG_SMTLIB_V2
;
175 } else if(len
>= 4 && !strcmp(".smt", filename
+ len
- 4)) {
176 options
.inputLanguage
= language::input::LANG_SMTLIB
;
177 } else if(( len
>= 4 && !strcmp(".cvc", filename
+ len
- 4) )
178 || ( len
>= 5 && !strcmp(".cvc4", filename
+ len
- 5) )) {
179 options
.inputLanguage
= language::input::LANG_CVC4
;
184 if(options
.outputLanguage
== language::output::LANG_AUTO
) {
185 options
.outputLanguage
= language::toOutputLanguage(options
.inputLanguage
);
188 // Determine which messages to show based on smtcomp_mode and verbosity
189 if(Configuration::isMuzzledBuild()) {
190 Debug
.setStream(CVC4::null_os
);
191 Trace
.setStream(CVC4::null_os
);
192 Notice
.setStream(CVC4::null_os
);
193 Chat
.setStream(CVC4::null_os
);
194 Message
.setStream(CVC4::null_os
);
195 Warning
.setStream(CVC4::null_os
);
196 Dump
.setStream(CVC4::null_os
);
198 if(options
.verbosity
< 2) {
199 Chat
.setStream(CVC4::null_os
);
201 if(options
.verbosity
< 1) {
202 Notice
.setStream(CVC4::null_os
);
204 if(options
.verbosity
< 0) {
205 Message
.setStream(CVC4::null_os
);
206 Warning
.setStream(CVC4::null_os
);
209 Debug
.getStream() << Expr::setlanguage(options
.outputLanguage
);
210 Trace
.getStream() << Expr::setlanguage(options
.outputLanguage
);
211 Notice
.getStream() << Expr::setlanguage(options
.outputLanguage
);
212 Chat
.getStream() << Expr::setlanguage(options
.outputLanguage
);
213 Message
.getStream() << Expr::setlanguage(options
.outputLanguage
);
214 Warning
.getStream() << Expr::setlanguage(options
.outputLanguage
);
215 Dump
.getStream() << Expr::setlanguage(options
.outputLanguage
)
216 << Expr::setdepth(-1)
217 << Expr::printtypes(false);
220 Parser
* replayParser
= NULL
;
221 if( options
.replayFilename
!= "" ) {
222 ParserBuilder
replayParserBuilder(&exprMgr
, options
.replayFilename
, options
);
224 if( options
.replayFilename
== "-") {
225 if( inputFromStdin
) {
226 throw OptionException("Replay file and input file can't both be stdin.");
228 replayParserBuilder
.withStreamInput(cin
);
230 replayParser
= replayParserBuilder
.build();
231 options
.replayStream
= new Parser::ExprStream(replayParser
);
233 if( options
.replayLog
!= NULL
) {
234 *options
.replayLog
<< Expr::setlanguage(options
.outputLanguage
) << Expr::setdepth(-1);
237 // Parse and execute commands until we are done
240 if( options
.interactive
) {
241 InteractiveShell
shell(exprMgr
, options
);
242 Message() << Configuration::getPackageName()
243 << " " << Configuration::getVersionString();
244 if(Configuration::isSubversionBuild()) {
245 Message() << " [" << Configuration::getSubversionId() << "]";
247 Message() << (Configuration::isDebugBuild() ? " DEBUG" : "")
249 << (Configuration::isAssertionBuild() ? "on" : "off")
251 if(replayParser
!= NULL
) {
252 // have the replay parser use the declarations input interactively
253 replayParser
->useDeclarationsFrom(shell
.getParser());
255 while((cmd
= shell
.readCommand())) {
256 status
= doCommand(smt
,cmd
, options
) && status
;
260 ParserBuilder
parserBuilder(&exprMgr
, filename
, options
);
262 if( inputFromStdin
) {
263 parserBuilder
.withLineBufferedStreamInput(cin
);
266 Parser
*parser
= parserBuilder
.build();
267 if(replayParser
!= NULL
) {
268 // have the replay parser use the file's declarations
269 replayParser
->useDeclarationsFrom(parser
);
271 while((cmd
= parser
->nextCommand())) {
272 status
= doCommand(smt
, cmd
, options
) && status
;
279 if( options
.replayStream
!= NULL
) {
280 // this deletes the expression parser too
281 delete options
.replayStream
;
282 options
.replayStream
= NULL
;
286 string result
= "unknown";
288 result
= smt
.getInfo(":status").getValue();
290 if(result
== "sat") {
292 } else if(result
== "unsat") {
298 // there was some kind of error
302 #ifdef CVC4_COMPETITION_MODE
303 // exit, don't return
304 // (don't want destructors to run)
308 ReferenceStat
< Result
> s_statSatResult("sat/unsat", result
);
309 RegisterStatistic
statSatResultReg(exprMgr
, &s_statSatResult
);
311 if(options
.statistics
) {
312 pStatistics
->flushInformation(*options
.err
);
318 /** Executes a command. Deletes the command after execution. */
319 static bool doCommand(SmtEngine
& smt
, Command
* cmd
, Options
& options
) {
320 if( options
.parseOnly
) {
327 CommandSequence
*seq
= dynamic_cast<CommandSequence
*>(cmd
);
329 for(CommandSequence::iterator subcmd
= seq
->begin();
330 subcmd
!= seq
->end();
332 status
= doCommand(smt
, *subcmd
, options
) && status
;
335 if(options
.verbosity
> 0) {
336 *options
.out
<< "Invoking: " << *cmd
<< endl
;
339 if(options
.verbosity
>= 0) {
340 cmd
->invoke(&smt
, *options
.out
);
344 status
= status
&& cmd
->ok();