| //===-- MICmnStreamStdout.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 "MICmnStreamStdout.h" |
| #include "MICmnLog.h" |
| #include "MICmnResources.h" |
| #include "MIDriver.h" |
| |
| //++ |
| //------------------------------------------------------------------------------------ |
| // Details: CMICmnStreamStdout constructor. |
| // Type: Method. |
| // Args: None. |
| // Return: None. |
| // Throws: None. |
| //-- |
| CMICmnStreamStdout::CMICmnStreamStdout() {} |
| |
| //++ |
| //------------------------------------------------------------------------------------ |
| // Details: CMICmnStreamStdout destructor. |
| // Type: Overridable. |
| // Args: None. |
| // Return: None. |
| // Throws: None. |
| //-- |
| CMICmnStreamStdout::~CMICmnStreamStdout() { 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() { |
| 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() { |
| 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 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) 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 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 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 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 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) |
| // Don't call the CMICmnBase::SetErrorDescription() because it will cause |
| // a stack overflow: |
| // CMICmnBase::SetErrorDescription -> CMICmnStreamStdout::Write -> |
| // CMICmnStreamStdout::WritePriv -> CMICmnBase::SetErrorDescription |
| 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() { |
| 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() { |
| 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 bSendToLog = true; |
| return CMICmnStreamStdout::Instance().WriteMIResponse(vrTxt, bSendToLog); |
| } |
| |
| //++ |
| //------------------------------------------------------------------------------------ |
| // Details: Write prompt to stdout if it's enabled. |
| // Type: Static method. |
| // Args: None. |
| // Return: MIstatus::success - Function succeeded. |
| // MIstatus::failure - Function failed. |
| // Throws: None. |
| //-- |
| bool CMICmnStreamStdout::WritePrompt() { |
| const CMICmnStreamStdin &rStdinMan = CMICmnStreamStdin::Instance(); |
| if (rStdinMan.GetEnablePrompt()) |
| return TextToStdout(rStdinMan.GetPrompt()); |
| return MIstatus::success; |
| } |