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