2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author: Lukasz Janyst <ljanyst@cern.ch>
2014-01-07 14:08:37 +04:00
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
# include "cling/Interpreter/Interpreter.h"
# include "cling/MetaProcessor/MetaProcessor.h"
# include "cling/UserInterface/UserInterface.h"
# include "clang/Basic/LangOptions.h"
# include "clang/Frontend/CompilerInstance.h"
# include "llvm/Support/Signals.h"
# include "llvm/Support/PrettyStackTrace.h"
# include "llvm/Support/ManagedStatic.h"
# include <iostream>
2014-08-11 15:38:26 +04:00
# include <fstream>
2012-09-05 13:37:39 +04:00
# include <vector>
# include <string>
2016-08-08 13:09:41 +03:00
# if defined(WIN32) && defined(_MSC_VER)
# include <crtdbg.h>
# endif
2012-09-05 13:37:39 +04:00
int main ( int argc , char * * argv ) {
llvm : : llvm_shutdown_obj shutdownTrigger ;
2016-08-08 13:09:41 +03:00
llvm : : sys : : PrintStackTraceOnErrorSignal ( argv [ 0 ] ) ;
llvm : : PrettyStackTraceProgram X ( argc , argv ) ;
# if defined(_WIN32) && defined(_MSC_VER)
// Suppress error dialogs to avoid hangs on build nodes.
// One can use an environment variable (Cling_GuiOnAssert) to enable
// the error dialogs.
const char * EnablePopups = getenv ( " Cling_GuiOnAssert " ) ;
if ( EnablePopups = = nullptr | | EnablePopups [ 0 ] = = ' 0 ' ) {
: : _set_error_mode ( _OUT_TO_STDERR ) ;
_CrtSetReportMode ( _CRT_WARN , _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG ) ;
_CrtSetReportFile ( _CRT_WARN , _CRTDBG_FILE_STDERR ) ;
_CrtSetReportMode ( _CRT_ERROR , _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG ) ;
_CrtSetReportFile ( _CRT_ERROR , _CRTDBG_FILE_STDERR ) ;
_CrtSetReportMode ( _CRT_ASSERT , _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG ) ;
_CrtSetReportFile ( _CRT_ASSERT , _CRTDBG_FILE_STDERR ) ;
}
# endif
2012-09-05 13:37:39 +04:00
// Set up the interpreter
cling : : Interpreter interp ( argc , argv ) ;
if ( interp . getOptions ( ) . Help ) {
return 0 ;
}
clang : : CompilerInstance * CI = interp . getCI ( ) ;
interp . AddIncludePath ( " . " ) ;
for ( size_t I = 0 , N = interp . getOptions ( ) . LibsToLoad . size ( ) ; I < N ; + + I ) {
interp . loadFile ( interp . getOptions ( ) . LibsToLoad [ I ] ) ;
}
2013-08-06 14:31:58 +04:00
// Interactive means no input (or one input that's "-")
2014-04-24 19:17:33 +04:00
std : : vector < std : : string > & Inputs = interp . getOptions ( ) . Inputs ;
2013-08-06 14:31:58 +04:00
bool Interactive = Inputs . empty ( ) | | ( Inputs . size ( ) = = 1
2014-04-24 19:17:33 +04:00
& & Inputs [ 0 ] = = " - " ) ;
2013-08-06 14:31:58 +04:00
cling : : UserInterface ui ( interp ) ;
// If we are not interactive we're supposed to parse files
if ( ! Interactive ) {
for ( size_t I = 0 , N = Inputs . size ( ) ; I < N ; + + I ) {
2014-08-11 15:38:26 +04:00
std : : string cmd ;
2013-08-06 14:31:58 +04:00
cling : : Interpreter : : CompilationResult compRes ;
2014-08-11 15:38:26 +04:00
if ( ! interp . lookupFileOrLibrary ( Inputs [ I ] ) . empty ( ) ) {
std : : ifstream infile ( interp . lookupFileOrLibrary ( Inputs [ I ] ) ) ;
std : : string line ;
std : : getline ( infile , line ) ;
if ( line [ 0 ] = = ' # ' & & line [ 1 ] = = ' ! ' ) {
2014-08-11 17:09:02 +04:00
// TODO: Check whether the filename specified after #! is the current
// executable.
2014-08-11 15:38:26 +04:00
while ( std : : getline ( infile , line ) ) {
ui . getMetaProcessor ( ) - > process ( line . c_str ( ) , compRes , 0 ) ;
}
continue ;
}
else
cmd + = " .x " ;
}
cmd + = Inputs [ I ] ;
ui . getMetaProcessor ( ) - > process ( cmd . c_str ( ) , compRes , 0 ) ;
2013-08-06 14:31:58 +04:00
}
}
else {
ui . runInteractively ( interp . getOptions ( ) . NoLogo ) ;
}
2014-08-04 06:05:42 +04:00
bool ret = CI - > getDiagnostics ( ) . getClient ( ) - > getNumErrors ( ) ;
2013-08-06 14:31:58 +04:00
// if we are running with -verify a reported has to be returned as unsuccess.
// This is relevant especially for the test suite.
if ( CI - > getDiagnosticOpts ( ) . VerifyDiagnostics ) {
// If there was an error that came from the verifier we must return 1 as
// an exit code for the process. This will make the test fail as expected.
clang : : DiagnosticConsumer * client = CI - > getDiagnostics ( ) . getClient ( ) ;
client - > EndSourceFile ( ) ;
ret = client - > getNumErrors ( ) ;
// The interpreter expects BeginSourceFile/EndSourceFiles to be balanced.
client - > BeginSourceFile ( CI - > getLangOpts ( ) , & CI - > getPreprocessor ( ) ) ;
}
2016-12-15 16:32:50 +03:00
// Only for test/OutputRedirect.C, but shouldn't affect performance too much.
: : fflush ( stdout ) ;
: : fflush ( stderr ) ;
2013-08-06 14:31:58 +04:00
return ret ;
2012-09-05 13:37:39 +04:00
}