]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MICmnStreamStdin.cpp
1 //===-- MICmnStreamStdin.cpp ------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // Third Party Headers
11 #ifdef _MSC_VER
12 #include <windows.h>
13 #endif
14 #include <string.h>
15
16 // In-house headers:
17 #include "MICmnLog.h"
18 #include "MICmnResources.h"
19 #include "MICmnStreamStdin.h"
20 #include "MICmnStreamStdout.h"
21 #include "MIDriver.h"
22 #include "MIUtilSingletonHelper.h"
23
24 //++
25 //------------------------------------------------------------------------------------
26 // Details: CMICmnStreamStdin constructor.
27 // Type:    Method.
28 // Args:    None.
29 // Return:  None.
30 // Throws:  None.
31 //--
32 CMICmnStreamStdin::CMICmnStreamStdin()
33     : m_strPromptCurrent("(gdb)"), m_bShowPrompt(true), m_pCmdBuffer(nullptr) {}
34
35 //++
36 //------------------------------------------------------------------------------------
37 // Details: CMICmnStreamStdin destructor.
38 // Type:    Overridable.
39 // Args:    None.
40 // Return:  None.
41 // Throws:  None.
42 //--
43 CMICmnStreamStdin::~CMICmnStreamStdin() { Shutdown(); }
44
45 //++
46 //------------------------------------------------------------------------------------
47 // Details: Initialize resources for *this Stdin stream.
48 // Type:    Method.
49 // Args:    None.
50 // Return:  MIstatus::success - Functional succeeded.
51 //          MIstatus::failure - Functional failed.
52 // Throws:  None.
53 //--
54 bool CMICmnStreamStdin::Initialize() {
55   m_clientUsageRefCnt++;
56
57   if (m_bInitialized)
58     return MIstatus::success;
59
60   bool bOk = MIstatus::success;
61   CMIUtilString errMsg;
62
63   // Note initialisation order is important here as some resources depend on
64   // previous
65   MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg);
66   MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg);
67
68   if (bOk) {
69     m_pCmdBuffer = new char[m_constBufferSize];
70   } else {
71     CMIUtilString strInitError(CMIUtilString::Format(
72         MIRSRC(IDS_MI_INIT_ERR_STREAMSTDIN), errMsg.c_str()));
73     SetErrorDescription(strInitError);
74
75     return MIstatus::failure;
76   }
77   m_bInitialized = bOk;
78
79   return MIstatus::success;
80 }
81
82 //++
83 //------------------------------------------------------------------------------------
84 // Details: Release resources for *this Stdin stream.
85 // Type:    Method.
86 // Args:    None.
87 // Return:  MIstatus::success - Functional succeeded.
88 //          MIstatus::failure - Functional failed.
89 // Throws:  None.
90 //--
91 bool CMICmnStreamStdin::Shutdown() {
92   if (--m_clientUsageRefCnt > 0)
93     return MIstatus::success;
94
95   if (!m_bInitialized)
96     return MIstatus::success;
97
98   m_bInitialized = false;
99
100   ClrErrorDescription();
101
102   if (m_pCmdBuffer != nullptr) {
103     delete[] m_pCmdBuffer;
104     m_pCmdBuffer = nullptr;
105   }
106
107   bool bOk = MIstatus::success;
108   CMIUtilString errMsg;
109
110   MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg);
111   MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg);
112
113   if (!bOk) {
114     SetErrorDescriptionn(MIRSRC(IDE_MI_SHTDWN_ERR_STREAMSTDIN), errMsg.c_str());
115   }
116
117   return MIstatus::success;
118 }
119
120 //++
121 //------------------------------------------------------------------------------------
122 // Details: Validate and set the text that forms the prompt on the command line.
123 // Type:    Method.
124 // Args:    vNewPrompt  - (R) Text description.
125 // Return:  MIstatus::success - Functional succeeded.
126 //          MIstatus::failure - Functional failed.
127 // Throws:  None.
128 //--
129 bool CMICmnStreamStdin::SetPrompt(const CMIUtilString &vNewPrompt) {
130   if (vNewPrompt.empty()) {
131     const CMIUtilString msg(CMIUtilString::Format(
132         MIRSRC(IDS_STDIN_ERR_INVALID_PROMPT), vNewPrompt.c_str()));
133     CMICmnStreamStdout::Instance().Write(msg);
134     return MIstatus::failure;
135   }
136
137   m_strPromptCurrent = vNewPrompt;
138
139   return MIstatus::success;
140 }
141
142 //++
143 //------------------------------------------------------------------------------------
144 // Details: Retrieve the command line prompt text currently being used.
145 // Type:    Method.
146 // Args:    None.
147 // Return:  const CMIUtilString & - Functional failed.
148 // Throws:  None.
149 //--
150 const CMIUtilString &CMICmnStreamStdin::GetPrompt() const {
151   return m_strPromptCurrent;
152 }
153
154 //++
155 //------------------------------------------------------------------------------------
156 // Details: Set whether to display optional command line prompt. The prompt is
157 // output to
158 //          stdout. Disable it when this may interfere with the client reading
159 //          stdout as
160 //          input and it tries to interpret the prompt text to.
161 // Type:    Method.
162 // Args:    vbYes   - (R) True = Yes prompt is shown/output to the user
163 // (stdout), false = no prompt.
164 // Return:  MIstatus::success - Functional succeeded.
165 //          MIstatus::failure - Functional failed.
166 // Throws:  None.
167 //--
168 void CMICmnStreamStdin::SetEnablePrompt(const bool vbYes) {
169   m_bShowPrompt = vbYes;
170 }
171
172 //++
173 //------------------------------------------------------------------------------------
174 // Details: Get whether to display optional command line prompt. The prompt is
175 // output to
176 //          stdout. Disable it when this may interfere with the client reading
177 //          stdout as
178 //          input and it tries to interpret the prompt text to.
179 // Type:    Method.
180 // Args:    None.
181 // Return:  bool - True = Yes prompt is shown/output to the user (stdout), false
182 // = no prompt.
183 // Throws:  None.
184 //--
185 bool CMICmnStreamStdin::GetEnablePrompt() const { return m_bShowPrompt; }
186
187 //++
188 //------------------------------------------------------------------------------------
189 // Details: Wait on new line of data from stdin stream (completed by '\n' or
190 // '\r').
191 // Type:    Method.
192 // Args:    vwErrMsg    - (W) Empty string ok or error description.
193 // Return:  char * - text buffer pointer or NULL on failure.
194 // Throws:  None.
195 //--
196 const char *CMICmnStreamStdin::ReadLine(CMIUtilString &vwErrMsg) {
197   vwErrMsg.clear();
198
199   // Read user input
200   const char *pText = ::fgets(&m_pCmdBuffer[0], m_constBufferSize, stdin);
201   if (pText == nullptr) {
202 #ifdef _MSC_VER
203     // Was Ctrl-C hit?
204     // On Windows, Ctrl-C gives an ERROR_OPERATION_ABORTED as error on the
205     // command-line.
206     // The end-of-file indicator is also set, so without this check we will exit
207     // next if statement.
208     if (::GetLastError() == ERROR_OPERATION_ABORTED)
209       return nullptr;
210 #endif
211     if (::feof(stdin)) {
212       const bool bForceExit = true;
213       CMIDriver::Instance().SetExitApplicationFlag(bForceExit);
214     } else if (::ferror(stdin) != 0)
215       vwErrMsg = ::strerror(errno);
216     return nullptr;
217   }
218
219   // Strip off new line characters
220   for (char *pI = m_pCmdBuffer; *pI != '\0'; pI++) {
221     if ((*pI == '\n') || (*pI == '\r')) {
222       *pI = '\0';
223       break;
224     }
225   }
226
227   return pText;
228 }