//===-- MICmnStreamStderr.cpp ------------------------------------*- C++ //-*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // 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() {} //++ //------------------------------------------------------------------------------------ // Details: CMICmnStreamStderr destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- CMICmnStreamStderr::~CMICmnStreamStderr() { 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() { 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() { 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 carriage 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 carriage 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 carriage 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 MIint 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() { 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() { 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; }