//===-- MIUtilStreamStdout.cpp ----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// //++ // File: MIUtilStreamcStdout.cpp // // Overview: CMICmnStreamStdout 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 "MICmnStreamStdout.h" #include "MICmnLog.h" #include "MICmnResources.h" #include "MIDriver.h" //++ ------------------------------------------------------------------------------------ // Details: CMICmnStreamStdout constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmnStreamStdout::CMICmnStreamStdout(void) { } //++ ------------------------------------------------------------------------------------ // Details: CMICmnStreamStdout destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- CMICmnStreamStdout::~CMICmnStreamStdout(void) { Shutdown(); } //++ ------------------------------------------------------------------------------------ // Details: Initialize resources for *this Stdout stream. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStdout::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(stdout). MI uses // ::flush(stdout) // It trys to ensure the process attached to the stdout steam gets ALL the data. //::setbuf( stdout, NULL ); #endif // _MSC_VER m_bInitialized = bOk; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Release resources for *this Stdout stream. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStdout::Shutdown(void) { if (--m_clientUsageRefCnt > 0) return MIstatus::success; if (!m_bInitialized) return MIstatus::success; ClrErrorDescription(); m_bInitialized = false; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Write an MI format type response to stdout. 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) MI formatted text. // 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 CMICmnStreamStdout::WriteMIResponse(const CMIUtilString &vText, const bool vbSendToLog /* = true */) { return WritePriv(vText, vText, vbSendToLog); } //++ ------------------------------------------------------------------------------------ // Details: Write text data to stdout. 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 CMICmnStreamStdout::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 text data to stdout. 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 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 CMICmnStreamStdout::WritePriv(const CMIUtilString &vText, const CMIUtilString &vTxtForLogFile, const bool vbSendToLog /* = true */) { if (vText.length() == 0) return MIstatus::failure; bool bOk = MIstatus::success; { // Grab the stdout thread lock while we print CMIUtilThreadLock _lock(m_mutex); // Send this text to stdout const MIint status = ::fputs(vText.c_str(), stdout); if (status == EOF) { const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_STDOUT_ERR_NOT_ALL_DATA_WRITTEN), vText.c_str())); SetErrorDescription(errMsg); bOk = MIstatus::failure; } else { ::fprintf(stdout, "\n"); ::fflush(stdout); } // Send this text to the log if (bOk && vbSendToLog) bOk &= m_pLog->WriteLog(vTxtForLogFile); } return bOk; } //++ ------------------------------------------------------------------------------------ // Details: Lock the availability of the stream stdout. 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 CMICmnStreamStdout::Lock(void) { m_mutex.Lock(); return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Release a previously locked stdout. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStdout::Unlock(void) { m_mutex.Unlock(); return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Take a text data and send to the stdout 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 CMICmnStreamStdout::TextToStdout(const CMIUtilString &vrTxt) { const bool bLock = CMICmnStreamStdout::Instance().Lock(); const bool bOk = bLock && CMICmnStreamStdout::Instance().WriteMIResponse(vrTxt); bLock &&CMICmnStreamStdout::Instance().Unlock(); return bOk; }