20b4c2bc28144e9e42643081c94a2c011493b847
1 /********************* */
2 /*! \file driver_unified.cpp
4 ** Original author: mdeters
5 ** Major contributors: cconway
6 ** Minor contributors (to current version): barrett, dejan, taking, kshitij
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 CVC4 executable (cvc4) unified for both
15 ** sequential and portfolio versions
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 "expr/command.h"
36 #include "util/Assert.h"
37 #include "util/configuration.h"
38 #include "options/options.h"
39 #include "main/command_executor.h"
40 # ifdef PORTFOLIO_BUILD
41 # include "main/command_executor_portfolio.h"
43 #include "main/options.h"
44 #include "smt/options.h"
45 #include "theory/uf/options.h"
46 #include "util/output.h"
47 #include "util/dump.h"
48 #include "util/result.h"
52 using namespace CVC4::parser
;
53 using namespace CVC4::main
;
57 /** Global options variable */
58 CVC4_THREADLOCAL(Options
*) pOptions
;
63 /** Just the basename component of argv[0] */
66 /** A pointer to the CommandExecutor (the signal handlers need it) */
67 CVC4::main::CommandExecutor
* pExecutor
;
69 }/* CVC4::main namespace */
73 void printUsage(Options
& opts
, bool full
) {
75 ss
<< "usage: " << opts
[options::binary_name
] << " [options] [input-file]" << endl
77 << "Without an input file, or with `-', CVC4 reads from standard input." << endl
79 << "CVC4 options:" << endl
;
81 Options::printUsage( ss
.str(), *opts
[options::out
] );
83 Options::printShortUsage( ss
.str(), *opts
[options::out
] );
87 int runCvc4(int argc
, char* argv
[], Options
& opts
) {
90 TimerStat
s_totalTime("totalTime");
93 // For the signal handlers' benefit
96 // Initialize the signal handlers
102 vector
<string
> filenames
= opts
.parseOptions(argc
, argv
);
104 # ifndef PORTFOLIO_BUILD
105 if( opts
.wasSetByUser(options::threads
) ||
106 ! opts
[options::threadArgv
].empty() ) {
107 throw OptionException("Thread options cannot be used with sequential CVC4. Please build and use the portfolio binary `pcvc4'.");
111 progName
= opts
[options::binary_name
].c_str();
113 if( opts
[options::help
] ) {
114 printUsage(opts
, true);
116 } else if( opts
[options::languageHelp
] ) {
117 Options::printLanguageHelp(*opts
[options::out
]);
119 } else if( opts
[options::version
] ) {
120 *opts
[options::out
] << Configuration::about().c_str() << flush
;
124 segvNoSpin
= opts
[options::segvNoSpin
];
126 // If in competition mode, set output stream option to flush immediately
127 #ifdef CVC4_COMPETITION_MODE
128 *opts
[options::out
] << unitbuf
;
129 #endif /* CVC4_COMPETITION_MODE */
131 // We only accept one input file
132 if(filenames
.size() > 1) {
133 throw Exception("Too many input files specified.");
136 // If no file supplied we will read from standard input
137 const bool inputFromStdin
= filenames
.empty() || filenames
[0] == "-";
139 // if we're reading from stdin on a TTY, default to interactive mode
140 if(!opts
.wasSetByUser(options::interactive
)) {
141 opts
.set(options::interactive
, inputFromStdin
&& isatty(fileno(stdin
)));
144 // Auto-detect input language by filename extension
145 const char* filename
= inputFromStdin
? "<stdin>" : filenames
[0].c_str();
147 if(opts
[options::inputLanguage
] == language::input::LANG_AUTO
) {
148 if( inputFromStdin
) {
149 // We can't do any fancy detection on stdin
150 opts
.set(options::inputLanguage
, language::input::LANG_CVC4
);
152 unsigned len
= strlen(filename
);
153 if(len
>= 5 && !strcmp(".smt2", filename
+ len
- 5)) {
154 opts
.set(options::inputLanguage
, language::input::LANG_SMTLIB_V2
);
155 } else if(len
>= 4 && !strcmp(".smt", filename
+ len
- 4)) {
156 opts
.set(options::inputLanguage
, language::input::LANG_SMTLIB
);
157 } else if((len
>= 2 && !strcmp(".p", filename
+ len
- 2))
158 || (len
>= 5 && !strcmp(".tptp", filename
+ len
- 5))) {
159 opts
.set(options::inputLanguage
, language::input::LANG_TPTP
);
160 } else if(( len
>= 4 && !strcmp(".cvc", filename
+ len
- 4) )
161 || ( len
>= 5 && !strcmp(".cvc4", filename
+ len
- 5) )) {
162 opts
.set(options::inputLanguage
, language::input::LANG_CVC4
);
167 if(opts
[options::outputLanguage
] == language::output::LANG_AUTO
) {
168 opts
.set(options::outputLanguage
, language::toOutputLanguage(opts
[options::inputLanguage
]));
171 // Determine which messages to show based on smtcomp_mode and verbosity
172 if(Configuration::isMuzzledBuild()) {
173 DebugChannel
.setStream(CVC4::null_os
);
174 TraceChannel
.setStream(CVC4::null_os
);
175 NoticeChannel
.setStream(CVC4::null_os
);
176 ChatChannel
.setStream(CVC4::null_os
);
177 MessageChannel
.setStream(CVC4::null_os
);
178 WarningChannel
.setStream(CVC4::null_os
);
179 DumpChannel
.setStream(CVC4::null_os
);
182 // important even for muzzled builds (to get result output right)
183 *opts
[options::out
] << Expr::setlanguage(opts
[options::outputLanguage
]);
185 // Create the expression manager using appropriate options
186 # ifndef PORTFOLIO_BUILD
187 ExprManager
exprMgr(opts
);
189 vector
<Options
> threadOpts
= parseThreadSpecificOptions(opts
);
190 ExprManager
exprMgr(threadOpts
[0]);
193 # ifndef PORTFOLIO_BUILD
194 CommandExecutor
cmdExecutor(exprMgr
, opts
);
196 CommandExecutorPortfolio
cmdExecutor(exprMgr
, opts
, threadOpts
);
199 // give access to the signal handlers for stats output
200 pExecutor
= &cmdExecutor
;
202 Parser
* replayParser
= NULL
;
203 if( opts
[options::replayFilename
] != "" ) {
204 ParserBuilder
replayParserBuilder(&exprMgr
, opts
[options::replayFilename
], opts
);
206 if( opts
[options::replayFilename
] == "-") {
207 if( inputFromStdin
) {
208 throw OptionException("Replay file and input file can't both be stdin.");
210 replayParserBuilder
.withStreamInput(cin
);
212 replayParser
= replayParserBuilder
.build();
213 opts
.set(options::replayStream
, new Parser::ExprStream(replayParser
));
215 if( opts
[options::replayLog
] != NULL
) {
216 *opts
[options::replayLog
] << Expr::setlanguage(opts
[options::outputLanguage
]) << Expr::setdepth(-1);
220 RegisterStatistic
statTotalTime(&cmdExecutor
.getStatisticsRegistry(), &s_totalTime
);
222 // Filename statistics
223 ReferenceStat
< const char* > s_statFilename("filename", filename
);
224 RegisterStatistic
statFilenameReg(&cmdExecutor
.getStatisticsRegistry(), &s_statFilename
);
226 // Parse and execute commands until we are done
229 if( opts
[options::interactive
] ) {
230 InteractiveShell
shell(exprMgr
, opts
);
231 Message() << Configuration::getPackageName()
232 << " " << Configuration::getVersionString();
233 if(Configuration::isSubversionBuild()) {
234 Message() << " [" << Configuration::getSubversionId() << "]";
236 Message() << (Configuration::isDebugBuild() ? " DEBUG" : "")
238 << (Configuration::isAssertionBuild() ? "on" : "off")
240 if(replayParser
!= NULL
) {
241 // have the replay parser use the declarations input interactively
242 replayParser
->useDeclarationsFrom(shell
.getParser());
244 while((cmd
= shell
.readCommand())) {
245 status
= cmdExecutor
.doCommand(cmd
) && status
;
249 ParserBuilder
parserBuilder(&exprMgr
, filename
, opts
);
251 if( inputFromStdin
) {
252 #if defined(CVC4_COMPETITION_MODE) && !defined(CVC4_SMTCOMP_APPLICATION_TRACK)
253 parserBuilder
.withStreamInput(cin
);
254 #else /* CVC4_COMPETITION_MODE && !CVC4_SMTCOMP_APPLICATION_TRACK */
255 parserBuilder
.withLineBufferedStreamInput(cin
);
256 #endif /* CVC4_COMPETITION_MODE && !CVC4_SMTCOMP_APPLICATION_TRACK */
259 Parser
*parser
= parserBuilder
.build();
260 if(replayParser
!= NULL
) {
261 // have the replay parser use the file's declarations
262 replayParser
->useDeclarationsFrom(parser
);
264 while(status
&& (cmd
= parser
->nextCommand())) {
265 if(dynamic_cast<QuitCommand
*>(cmd
) != NULL
) {
269 status
= cmdExecutor
.doCommand(cmd
);
276 if( opts
[options::replayStream
] != NULL
) {
277 // this deletes the expression parser too
278 delete opts
[options::replayStream
];
279 opts
.set(options::replayStream
, NULL
);
283 string result
= "unknown";
285 result
= cmdExecutor
.getSmtEngineStatus();
287 if(result
== "sat") {
289 } else if(result
== "unsat") {
295 // there was some kind of error
299 #ifdef CVC4_COMPETITION_MODE
300 // exit, don't return (don't want destructors to run)
301 // _exit() from unistd.h doesn't run global destructors
302 // or other on_exit/atexit stuff.
304 #endif /* CVC4_COMPETITION_MODE */
306 ReferenceStat
< Result
> s_statSatResult("sat/unsat", result
);
307 RegisterStatistic
statSatResultReg(&cmdExecutor
.getStatisticsRegistry(), &s_statSatResult
);
311 // Set the global executor pointer to NULL first. If we get a
312 // signal while dumping statistics, we don't want to try again.
314 if(opts
[options::statistics
]) {
315 cmdExecutor
.flushStatistics(*opts
[options::err
]);
319 if(opts
[options::earlyExit
] && opts
.wasSetByUser(options::earlyExit
)) {
322 #else /* CVC4_DEBUG */
323 if(opts
[options::earlyExit
]) {
326 #endif /* CVC4_DEBUG */