]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/lldb-mi/MICmnStreamStderr.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / tools / lldb-mi / MICmnStreamStderr.cpp
1 //===-- MICmnStreamStderr.cpp ------------------------------------*- C++
2 //-*-===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 // In-house headers:
12 #include "MICmnStreamStderr.h"
13 #include "MICmnLog.h"
14 #include "MICmnResources.h"
15 #include "MIDriver.h"
16
17 //++
18 //------------------------------------------------------------------------------------
19 // Details: CMICmnStreamStderr constructor.
20 // Type:    Method.
21 // Args:    None.
22 // Return:  None.
23 // Throws:  None.
24 //--
25 CMICmnStreamStderr::CMICmnStreamStderr() {}
26
27 //++
28 //------------------------------------------------------------------------------------
29 // Details: CMICmnStreamStderr destructor.
30 // Type:    Overridable.
31 // Args:    None.
32 // Return:  None.
33 // Throws:  None.
34 //--
35 CMICmnStreamStderr::~CMICmnStreamStderr() { Shutdown(); }
36
37 //++
38 //------------------------------------------------------------------------------------
39 // Details: Initialize resources for *this stderr stream.
40 // Type:    Method.
41 // Args:    None.
42 // Return:  MIstatus::success - Functional succeeded.
43 //          MIstatus::failure - Functional failed.
44 // Throws:  None.
45 //--
46 bool CMICmnStreamStderr::Initialize() {
47   m_clientUsageRefCnt++;
48
49   if (m_bInitialized)
50     return MIstatus::success;
51
52   bool bOk = MIstatus::success;
53
54 #ifdef _MSC_VER
55 // Debugging / I/O issues with client.
56 // This is only required on Windows if you do not use ::flush(stderr). MI uses
57 // ::flush(stderr)
58 // It trys to ensure the process attached to the stderr steam gets ALL the data.
59 //::setbuf( stderr, NULL );
60 #endif // _MSC_VER
61
62   m_bInitialized = bOk;
63
64   return MIstatus::success;
65 }
66
67 //++
68 //------------------------------------------------------------------------------------
69 // Details: Release resources for *this stderr stream.
70 // Type:    Method.
71 // Args:    None.
72 // Return:  MIstatus::success - Functional succeeded.
73 //          MIstatus::failure - Functional failed.
74 // Throws:  None.
75 //--
76 bool CMICmnStreamStderr::Shutdown() {
77   if (--m_clientUsageRefCnt > 0)
78     return MIstatus::success;
79
80   if (!m_bInitialized)
81     return MIstatus::success;
82
83   ClrErrorDescription();
84
85   m_bInitialized = false;
86
87   return MIstatus::success;
88 }
89
90 //++
91 //------------------------------------------------------------------------------------
92 // Details: Write text data to stderr. Prefix the message with "MI:". The text
93 // data does
94 //          not need to include a carriage line return as this is added to the
95 //          text. The
96 //          function also then passes the text data into the CMICmnLog logger.
97 // Type:    Method.
98 // Args:    vText       - (R) Text data.
99 //          vbSendToLog - (R) True = Yes send to the Log file too, false = do
100 //          not. (Dflt = true)
101 // Return:  MIstatus::success - Functional succeeded.
102 //          MIstatus::failure - Functional failed.
103 // Throws:  None.
104 //--
105 bool CMICmnStreamStderr::Write(const CMIUtilString &vText,
106                                const bool vbSendToLog /* = true */) {
107   if (vText.length() == 0)
108     return MIstatus::failure;
109
110   const CMIUtilString strPrefixed(CMIUtilString::Format(
111       "%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(),
112       vText.c_str()));
113
114   return WritePriv(strPrefixed, vText, vbSendToLog);
115 }
116
117 //++
118 //------------------------------------------------------------------------------------
119 // Details: Write an LLDB text message to stderr.
120 //          The text data does not need to include a carriage line return as
121 //          this is added
122 //          to the text. The function also then passes the text data into the
123 //          CMICmnLog
124 //          logger.
125 // Type:    Method.
126 // Args:    vText       - (R) Text data.
127 //          vbSendToLog - (R) True = Yes send to the Log file too, false = do
128 //          not. (Dflt = true)
129 // Return:  MIstatus::success - Functional succeeded.
130 //          MIstatus::failure - Functional failed.
131 // Throws:  None.
132 //--
133 bool CMICmnStreamStderr::WriteLLDBMsg(const CMIUtilString &vText,
134                                       const bool vbSendToLog /* = true */) {
135   if (vText.length() == 0)
136     return MIstatus::failure;
137
138   const CMIUtilString strPrefixed(
139       CMIUtilString::Format("LLDB: %s", vText.c_str()));
140
141   return WritePriv(vText, strPrefixed, vbSendToLog);
142 }
143
144 //++
145 //------------------------------------------------------------------------------------
146 // Details: Write text data to stderr. The text data does not need to
147 //          include a carriage line return as this is added to the text. The
148 //          function also
149 //          then passes the text data into the CMICmnLog logger.
150 // Type:    Method.
151 // Args:    vText           - (R) Text data. May be prefixed with MI app's short
152 // name.
153 //          vTxtForLogFile  - (R) Text data.
154 //          vbSendToLog     - (R) True = Yes send to the Log file too, false =
155 //          do not. (Dflt = true)
156 // Return:  MIstatus::success - Functional succeeded.
157 //          MIstatus::failure - Functional failed.
158 // Throws:  None.
159 //--
160 bool CMICmnStreamStderr::WritePriv(const CMIUtilString &vText,
161                                    const CMIUtilString &vTxtForLogFile,
162                                    const bool vbSendToLog /* = true */) {
163   if (vText.length() == 0)
164     return MIstatus::failure;
165
166   bool bOk = MIstatus::success;
167   {
168     // Grab the stderr thread lock while we print
169     CMIUtilThreadLock _lock(m_mutex);
170
171     // Send this text to stderr
172     const MIint status = ::fputs(vText.c_str(), stderr);
173     if (status == EOF) {
174       const CMIUtilString errMsg(CMIUtilString::Format(
175           MIRSRC(IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN), vText.c_str()));
176       SetErrorDescription(errMsg);
177       bOk = MIstatus::failure;
178     } else {
179       ::fprintf(stderr, "\n");
180       ::fflush(stderr);
181     }
182
183     // Send this text to the log
184     if (bOk && vbSendToLog)
185       bOk &= m_pLog->WriteLog(vTxtForLogFile);
186   }
187
188   return bOk;
189 }
190
191 //++
192 //------------------------------------------------------------------------------------
193 // Details: Lock the availability of the stream stderr. Other users of *this
194 // stream will
195 //          be stalled until it is available (Unlock()).
196 // Type:    Method.
197 // Args:    None.
198 // Return:  MIstatus::success - Functional succeeded.
199 //          MIstatus::failure - Functional failed.
200 // Throws:  None.
201 //--
202 bool CMICmnStreamStderr::Lock() {
203   m_mutex.Lock();
204   return MIstatus::success;
205 }
206
207 //++
208 //------------------------------------------------------------------------------------
209 // Details: Release a previously locked stderr.
210 // Type:    Method.
211 // Args:    None.
212 // Return:  MIstatus::success - Functional succeeded.
213 //          MIstatus::failure - Functional failed.
214 // Throws:  None.
215 //--
216 bool CMICmnStreamStderr::Unlock() {
217   m_mutex.Unlock();
218   return MIstatus::success;
219 }
220
221 //++
222 //------------------------------------------------------------------------------------
223 // Details: Take MI Driver text message and send to the stderr stream. Also
224 // output to the
225 //           MI Log file.
226 // Type:    Static method.
227 // Args:    vrTxt   - (R) Text.
228 // Return:  MIstatus::success - Functionality succeeded.
229 //          MIstatus::failure - Functionality failed.
230 // Throws:  None.
231 //--
232 bool CMICmnStreamStderr::TextToStderr(const CMIUtilString &vrTxt) {
233   const bool bLock = CMICmnStreamStderr::Instance().Lock();
234   const bool bOk = bLock && CMICmnStreamStderr::Instance().Write(vrTxt);
235   bLock &&CMICmnStreamStderr::Instance().Unlock();
236
237   return bOk;
238 }
239
240 //++
241 //------------------------------------------------------------------------------------
242 // Details: Take an LLDB message and send to the stderr stream. The message is
243 // not always
244 //          an error message. The user has typed a command in to the Eclipse
245 //          console (by-
246 //          passing Eclipse) and this is the result message from LLDB back to
247 //          the user.
248 //          Also output to the MI Log file.
249 // Type:    Static method.
250 // Args:    vrTxt   - (R) Text.
251 // Return:  MIstatus::success - Functionality succeeded.
252 //          MIstatus::failure - Functionality failed.
253 // Throws:  None.
254 //--
255 bool CMICmnStreamStderr::LLDBMsgToConsole(const CMIUtilString &vrTxt) {
256   const bool bLock = CMICmnStreamStderr::Instance().Lock();
257   const bool bOk = bLock && CMICmnStreamStderr::Instance().WriteLLDBMsg(vrTxt);
258   bLock &&CMICmnStreamStderr::Instance().Unlock();
259
260   return bOk;
261 }