//===-- MICmnStreamStderr.cpp ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// //++ // File: MICmnStreamStderr.cpp // // Overview: CMICmnStreamStderr implementation. // // Environment: Compilers: Visual C++ 12. // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 // Libraries: See MIReadmetxt. // // Copyright: None. //-- // In-house headers: #include "MICmnStreamStderr.h" #include "MICmnLog.h" #include "MICmnResources.h" #include "MIDriver.h" //++ ------------------------------------------------------------------------------------ // Details: CMICmnStreamStderr constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmnStreamStderr::CMICmnStreamStderr( void ) { } //++ ------------------------------------------------------------------------------------ // Details: CMICmnStreamStderr destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- CMICmnStreamStderr::~CMICmnStreamStderr( void ) { Shutdown(); } //++ ------------------------------------------------------------------------------------ // Details: Initialize resources for *this stderr stream. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStderr::Initialize( void ) { m_clientUsageRefCnt++; if( m_bInitialized ) return MIstatus::success; bool bOk = MIstatus::success; #ifdef _MSC_VER // Debugging / I/O issues with client. // This is only required on Windows if you do not use ::flush(stderr). MI uses // ::flush(stderr) // It trys to ensure the process attached to the stderr steam gets ALL the data. //::setbuf( stderr, NULL ); #endif // _MSC_VER m_bInitialized = bOk; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Release resources for *this stderr stream. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStderr::Shutdown( void ) { if( --m_clientUsageRefCnt > 0 ) return MIstatus::success; if( !m_bInitialized ) return MIstatus::success; ClrErrorDescription(); m_bInitialized = false; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Write text data to stderr. Prefix the message with "MI:". The text data does // not need to include a carrage line return as this is added to the text. The // function also then passes the text data into the CMICmnLog logger. // Type: Method. // Args: vText - (R) Text data. // vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStderr::Write( const CMIUtilString & vText, const bool vbSendToLog /* = true */ ) { if( vText.length() == 0 ) return MIstatus::failure; const CMIUtilString strPrefixed( CMIUtilString::Format( "%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), vText.c_str() ) ); return WritePriv( strPrefixed, vText, vbSendToLog ); } //++ ------------------------------------------------------------------------------------ // Details: Write an LLDB text message to stderr. // The text data does not need to include a carrage line return as this is added // to the text. The function also then passes the text data into the CMICmnLog // logger. // Type: Method. // Args: vText - (R) Text data. // vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStderr::WriteLLDBMsg( const CMIUtilString & vText, const bool vbSendToLog /* = true */ ) { if( vText.length() == 0 ) return MIstatus::failure; const CMIUtilString strPrefixed( CMIUtilString::Format( "LLDB: %s", vText.c_str() ) ); return WritePriv( vText, strPrefixed, vbSendToLog ); } //++ ------------------------------------------------------------------------------------ // Details: Write text data to stderr. The text data does not need to // include a carrage line return as this is added to the text. The function also // then passes the text data into the CMICmnLog logger. // Type: Method. // Args: vText - (R) Text data. May be prefixed with MI app's short name. // vTxtForLogFile - (R) Text data. // vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStderr::WritePriv( const CMIUtilString & vText, const CMIUtilString & vTxtForLogFile, const bool vbSendToLog /* = true */ ) { if( vText.length() == 0 ) return MIstatus::failure; bool bOk = MIstatus::success; { // Grab the stderr thread lock while we print CMIUtilThreadLock _lock( m_mutex ); // Send this text to stderr const MIuint status = ::fputs( vText.c_str(), stderr ); if( status == EOF ) { const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN ), vText.c_str() ) ); SetErrorDescription( errMsg ); bOk = MIstatus::failure; } else { ::fprintf( stderr, "\n" ); ::fflush( stderr ); } // Send this text to the log if( bOk && vbSendToLog ) bOk &= m_pLog->WriteLog( vTxtForLogFile ); } return bOk; } //++ ------------------------------------------------------------------------------------ // Details: Lock the availability of the stream stderr. Other users of *this stream will // be stalled until it is available (Unlock()). // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStderr::Lock( void ) { m_mutex.Lock(); return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Release a previously locked stderr. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStderr::Unlock( void ) { m_mutex.Unlock(); return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Take MI Driver text message and send to the stderr stream. Also output to the // MI Log file. // Type: Static method. // Args: vrTxt - (R) Text. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnStreamStderr::TextToStderr( const CMIUtilString & vrTxt ) { const bool bLock = CMICmnStreamStderr::Instance().Lock(); const bool bOk = bLock && CMICmnStreamStderr::Instance().Write( vrTxt ); bLock && CMICmnStreamStderr::Instance().Unlock(); return bOk; } //++ ------------------------------------------------------------------------------------ // Details: Take an LLDB message and send to the stderr stream. The message is not always // an error message. The user has typed a command in to the Eclipse console (by- // passing Eclipse) and this is the result message from LLDB back to the user. // Also output to the MI Log file. // Type: Static method. // Args: vrTxt - (R) Text. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnStreamStderr::LLDBMsgToConsole( const CMIUtilString & vrTxt ) { const bool bLock = CMICmnStreamStderr::Instance().Lock(); const bool bOk = bLock && CMICmnStreamStderr::Instance().WriteLLDBMsg( vrTxt ); bLock && CMICmnStreamStderr::Instance().Unlock(); return bOk; }