Index: tools/lldb-mi/CMakeLists.txt =================================================================== --- tools/lldb-mi/CMakeLists.txt +++ tools/lldb-mi/CMakeLists.txt @@ -61,8 +61,6 @@ MICmnResources.cpp MICmnStreamStderr.cpp MICmnStreamStdin.cpp - MICmnStreamStdinLinux.cpp - MICmnStreamStdinWindows.cpp MICmnStreamStdout.cpp MICmnThreadMgrStd.cpp MIDriver.cpp @@ -143,8 +141,6 @@ MICmnResources.cpp MICmnStreamStderr.cpp MICmnStreamStdin.cpp - MICmnStreamStdinLinux.cpp - MICmnStreamStdinWindows.cpp MICmnStreamStdout.cpp MICmnThreadMgrStd.cpp MIDriver.cpp Index: tools/lldb-mi/MICmnStreamStdin.h =================================================================== --- tools/lldb-mi/MICmnStreamStdin.h +++ tools/lldb-mi/MICmnStreamStdin.h @@ -37,40 +37,11 @@ // Authors: Illya Rudkin 10/02/2014. // Changes: Factored out OS specific handling of reading stdin - IOR 16/06/2014. //-- -class CMICmnStreamStdin : public CMICmnBase, public CMIUtilThreadActiveObjBase, public MI::ISingleton +class CMICmnStreamStdin : public CMICmnBase, public MI::ISingleton { // Give singleton access to private constructors friend MI::ISingleton; - // Class: - public: - //++ - // Description: Visitor pattern. Driver(s) use this interface to get a callback - // on each new line of data received from stdin. - //-- - class IStreamStdin - { - public: - virtual bool ReadLine(const CMIUtilString &vStdInBuffer, bool &vrwbYesExit) = 0; - - /* dtor */ virtual ~IStreamStdin(void){}; - }; - - //++ - // Description: Specific OS stdin handling implementations are created and used by *this - // class. Seperates out functionality and enables handler to be set - // dynamically depended on the OS detected. - //-- - class IOSStdinHandler - { - public: - virtual bool InputAvailable(bool &vwbAvail) = 0; - virtual const MIchar *ReadLine(CMIUtilString &vwErrMsg) = 0; - virtual void InterruptReadLine(void){}; - - /* dtor */ virtual ~IOSStdinHandler(void){}; - }; - // Methods: public: bool Initialize(void); @@ -80,34 +51,14 @@ bool SetPrompt(const CMIUtilString &vNewPrompt); void SetEnablePrompt(const bool vbYes); bool GetEnablePrompt(void) const; - void SetCtrlCHit(void); - bool SetVisitor(IStreamStdin &vrVisitor); - bool SetOSStdinHandler(IOSStdinHandler &vrHandler); - void OnExitHandler(void); const MIchar *ReadLine(CMIUtilString &vwErrMsg); - // Overridden: - public: - // From CMIUtilThreadActiveObjBase - virtual const CMIUtilString &ThreadGetName(void) const; - - // Overridden: - protected: - // From CMIUtilThreadActiveObjBase - virtual bool ThreadRun(bool &vrIsAlive); - virtual bool - ThreadFinish(void); // Let this thread clean up after itself - // Methods: private: /* ctor */ CMICmnStreamStdin(void); /* ctor */ CMICmnStreamStdin(const CMICmnStreamStdin &); void operator=(const CMICmnStreamStdin &); - bool MonitorStdin(bool &vrwbYesExit); - bool - InputAvailable(bool &vbAvail); // Bytes are available on stdin - // Overridden: private: // From CMICmnBase @@ -115,13 +66,9 @@ // Attributes: private: - const CMIUtilString m_constStrThisThreadname; - IStreamStdin *m_pVisitor; CMIUtilString m_strPromptCurrent; // Command line prompt as shown to the user - volatile bool m_bKeyCtrlCHit; // True = User hit Ctrl-C, false = has not yet bool m_bShowPrompt; // True = Yes prompt is shown/output to the user (stdout), false = no prompt bool m_bRedrawPrompt; // True = Prompt needs to be redrawn - IOSStdinHandler *m_pStdinReadHandler; static const int m_constBufferSize = 2048; MIchar *m_pCmdBuffer; }; Index: tools/lldb-mi/MICmnStreamStdin.cpp =================================================================== --- tools/lldb-mi/MICmnStreamStdin.cpp +++ tools/lldb-mi/MICmnStreamStdin.cpp @@ -24,15 +24,7 @@ #include "MICmnStreamStdout.h" #include "MICmnResources.h" #include "MICmnLog.h" -#include "MICmnThreadMgrStd.h" #include "MIUtilSingletonHelper.h" -#include "MIDriver.h" -#if defined(_MSC_VER) -#include "MIUtilSystemWindows.h" -#include "MICmnStreamStdinWindows.h" -#else -#include "MICmnStreamStdinLinux.h" -#endif // defined( _MSC_VER ) #include // For std::strerror() //++ ------------------------------------------------------------------------------------ @@ -43,13 +35,9 @@ // Throws: None. //-- CMICmnStreamStdin::CMICmnStreamStdin(void) - : m_constStrThisThreadname("MI stdin thread") - , m_pVisitor(nullptr) - , m_strPromptCurrent("(gdb)") - , m_bKeyCtrlCHit(false) + : m_strPromptCurrent("(gdb)") , m_bShowPrompt(true) , m_bRedrawPrompt(true) - , m_pStdinReadHandler(nullptr) , m_pCmdBuffer(nullptr) { } @@ -88,41 +76,19 @@ // Note initialisation order is important here as some resources depend on previous MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - MI::ModuleInit(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg); -#ifdef _MSC_VER - MI::ModuleInit(IDS_MI_INIT_ERR_OS_STDIN_HANDLER, bOk, errMsg); - bOk = bOk && SetOSStdinHandler(CMICmnStreamStdinWindows::Instance()); -#else - MI::ModuleInit(IDS_MI_INIT_ERR_OS_STDIN_HANDLER, bOk, errMsg); - bOk = bOk && SetOSStdinHandler(CMICmnStreamStdinLinux::Instance()); -#endif // ( _MSC_VER ) - - // The OS specific stdin stream handler must be set before *this class initialises - if (bOk && m_pStdinReadHandler == nullptr) - { - CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER), errMsg.c_str())); - SetErrorDescription(strInitError); - return MIstatus::failure; - } if (bOk) - m_pCmdBuffer = new MIchar[m_constBufferSize]; - - // Other resources required - if (bOk) { - m_bKeyCtrlCHit = false; // Reset + m_pCmdBuffer = new MIchar[m_constBufferSize]; } - - m_bInitialized = bOk; - - if (!bOk) + else { CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_STREAMSTDIN), errMsg.c_str())); SetErrorDescription(strInitError); + return MIstatus::failure; } - + m_bInitialized = bOk; return MIstatus::success; } @@ -156,16 +122,6 @@ bool bOk = MIstatus::success; CMIUtilString errMsg; - m_pVisitor = nullptr; - m_bKeyCtrlCHit = false; - -// Note shutdown order is important here -#ifndef _MSC_VER - MI::ModuleShutdown(IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, bOk, errMsg); -#else - MI::ModuleShutdown(IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, bOk, errMsg); -#endif // ( _MSC_VER ) - MI::ModuleShutdown(IDS_MI_SHTDWN_ERR_THREADMGR, bOk, errMsg); MI::ModuleShutdown(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); MI::ModuleShutdown(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); @@ -214,23 +170,6 @@ } //++ ------------------------------------------------------------------------------------ -// Details: Wait on input from stream Stdin. On each line of input received it is -// validated and providing there are no errors on the stream or the input -// buffer is not exceeded the data is passed to the visitor. -// Type: Method. -// Args: vrVisitor - (W) A client deriver callback. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdin::SetVisitor(IStreamStdin &vrVisitor) -{ - m_pVisitor = &vrVisitor; - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ // Details: Set whether to display optional command line prompt. The prompt is output to // stdout. Disable it when this may interfere with the client reading stdout as // input and it tries to interpret the prompt text to. @@ -262,101 +201,6 @@ } //++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdin::InputAvailable(bool &vwbAvail) -{ - return m_pStdinReadHandler->InputAvailable(vwbAvail); -} - -//++ ------------------------------------------------------------------------------------ -// Details: The monitoring on new line data calls back to the visitor object registered -// with *this stdin monitoring. The monitoring to stops when the visitor returns -// true for bYesExit flag. Errors output to log file. -// This function runs in the thread "MI stdin monitor". -// Type: Method. -// vrwbYesAlive - (W) False = yes exit stdin monitoring, true = continue monitor. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdin::MonitorStdin(bool &vrwbYesAlive) -{ - if (m_bShowPrompt) - { - CMICmnStreamStdout &rStdoutMan = CMICmnStreamStdout::Instance(); - rStdoutMan.WriteMIResponse(m_strPromptCurrent.c_str()); - m_bRedrawPrompt = false; - } - - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - if (m_bKeyCtrlCHit) - { - CMIDriver &rMIDriver = CMIDriver::Instance(); - rMIDriver.SetExitApplicationFlag(false); - if (rMIDriver.GetExitApplicationFlag()) - { - vrwbYesAlive = false; - return MIstatus::success; - } - - // Reset - the MI Driver received SIGINT during a running debug programm session - m_bKeyCtrlCHit = false; - } - -#if MICONFIG_POLL_FOR_STD_IN - bool bAvail = true; - // Check if there is stdin available - if (InputAvailable(bAvail)) - { - // Early exit when there is no input - if (!bAvail) - return MIstatus::success; - } - else - { - vrwbYesAlive = false; - CMIDriver::Instance().SetExitApplicationFlag(true); - return MIstatus::failure; - } -#endif // MICONFIG_POLL_FOR_STD_IN - - // Read a line from std input - CMIUtilString stdinErrMsg; - const MIchar *pText = ReadLine(stdinErrMsg); - - // Did something go wrong - const bool bHaveError(!stdinErrMsg.empty()); - if ((pText == nullptr) || bHaveError) - { - if (bHaveError) - { - CMICmnStreamStdout::Instance().Write(stdinErrMsg); - } - return MIstatus::failure; - } - - // We have text so send it off to the visitor - bool bOk = MIstatus::success; - if (m_pVisitor != nullptr) - { - bool bYesExit = false; - bOk = m_pVisitor->ReadLine(CMIUtilString(pText), bYesExit); - m_bRedrawPrompt = true; - vrwbYesAlive = !bYesExit; - } - - return bOk; -} - -//++ ------------------------------------------------------------------------------------ // Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). // Type: Method. // Args: vwErrMsg - (W) Empty string ok or error description. @@ -389,93 +233,3 @@ return pText; } - -//++ ------------------------------------------------------------------------------------ -// Details: Inform *this stream that the user hit Control-C key to exit. -// The function is normally called by the SIGINT signal in sigint_handler() to -// simulate kill app from the client. -// This function is called by a Kernel thread. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. -//-- -void -CMICmnStreamStdin::SetCtrlCHit(void) -{ - CMIUtilThreadLock lock(m_mutex); - m_bKeyCtrlCHit = true; -} - -//++ ------------------------------------------------------------------------------------ -// Details: The main worker method for this thread. -// Type: Overridden. -// Args: vrbIsAlive - (W) True = *this thread is working, false = thread has exited. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdin::ThreadRun(bool &vrbIsAlive) -{ - return MonitorStdin(vrbIsAlive); -} - -//++ ------------------------------------------------------------------------------------ -// Details: Let this thread clean up after itself. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdin::ThreadFinish(void) -{ - // Do nothing - override to implement - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve *this thread object's name. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Text. -// Throws: None. -//-- -const CMIUtilString & -CMICmnStreamStdin::ThreadGetName(void) const -{ - return m_constStrThisThreadname; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Mandatory set the OS specific stream stdin handler. *this class utilises the -// handler to read data from the stdin stream and put into a queue for the -// driver to read when able. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdin::SetOSStdinHandler(IOSStdinHandler &vrHandler) -{ - m_pStdinReadHandler = &vrHandler; - - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Do some actions before exiting. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. -//-- -void -CMICmnStreamStdin::OnExitHandler(void) -{ - m_pStdinReadHandler->InterruptReadLine(); -} Index: tools/lldb-mi/MICmnStreamStdinLinux.h =================================================================== --- tools/lldb-mi/MICmnStreamStdinLinux.h +++ /dev/null @@ -1,73 +0,0 @@ -//===-- MICmnStreamStdinWindows.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -//++ -// File: MIUtilStreamStdin.h -// -// Overview: CMICmnStreamStdinLinux interface. -// -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. -// -// Copyright: None. -//-- - -#pragma once - -// In-house headers: -#include "MICmnBase.h" -#include "MICmnStreamStdin.h" -#include "MIUtilSingletonBase.h" - -//++ ============================================================================ -// Details: MI common code class. Specific OS stdin handling implementation. -// CMICmnStreamStdin instance is set with stdin handler before using the -// the stream. An instance of this class must be set up and ready to give -// to the CMICmnStreamStdin before it initialises other CMICmnStreamStdin -// will give an error. -// Gotchas: None. -// Authors: Illya Rudkin 16/06/2014. -// Changes: None. -//-- -class CMICmnStreamStdinLinux : public CMICmnBase, public CMICmnStreamStdin::IOSStdinHandler, public MI::ISingleton -{ - // Give singleton access to private constructors - friend MI::ISingleton; - - // Methods: - public: - bool Initialize(void); - bool Shutdown(void); - - // Overridden: - public: - // From CMICmnStreamStdin::IOSpecificReadStreamStdin - virtual bool InputAvailable(bool &vwbAvail); - virtual const MIchar *ReadLine(CMIUtilString &vwErrMsg); - virtual void InterruptReadLine(void); - - // Methods: - private: - /* ctor */ CMICmnStreamStdinLinux(void); - /* ctor */ CMICmnStreamStdinLinux(const CMICmnStreamStdin &); - void operator=(const CMICmnStreamStdin &); - - // Overridden: - private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnStreamStdinLinux(void); - - // Attributes: - private: - const MIuint m_constBufferSize; - FILE *m_pStdin; - MIchar *m_pCmdBuffer; - bool m_waitForInput; -}; Index: tools/lldb-mi/MICmnStreamStdinLinux.cpp =================================================================== --- tools/lldb-mi/MICmnStreamStdinLinux.cpp +++ /dev/null @@ -1,232 +0,0 @@ -//===-- MICmnStreamStdinLinux.cpp --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -//++ -// File: MIUtilStreamStdin.cpp -// -// Overview: CMICmnStreamStdinLinux implementation. -// -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. -// -// Copyright: None. -//-- - -// Third Party Headers: -#ifndef _WIN32 -#include -#include // For STDIN_FILENO -#endif -#include // For std::strerror() - -// In-house headers: -#include "MICmnStreamStdinLinux.h" -#include "MICmnLog.h" -#include "MICmnResources.h" -#include "MIUtilSingletonHelper.h" - -//++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdinLinux constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. -//-- -CMICmnStreamStdinLinux::CMICmnStreamStdinLinux(void) - : m_constBufferSize(1024) - , m_pStdin(nullptr) - , m_pCmdBuffer(nullptr) - , m_waitForInput(true) -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdinLinux destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. -//-- -CMICmnStreamStdinLinux::~CMICmnStreamStdinLinux(void) -{ - Shutdown(); -} - -//++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdinLinux::Initialize(void) -{ - if (m_bInitialized) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - - // Other resources required - if (bOk) - { - m_pCmdBuffer = new MIchar[m_constBufferSize]; - m_pStdin = stdin; - } - - // Clear error indicators for std input - ::clearerr(stdin); - - m_bInitialized = bOk; - - if (!bOk) - { - CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_OS_STDIN_HANDLER), errMsg.c_str())); - SetErrorDescription(strInitError); - return MIstatus::failure; - } - - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdinLinux::Shutdown(void) -{ - if (!m_bInitialized) - return MIstatus::success; - - m_bInitialized = false; - - ClrErrorDescription(); - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Tidy up - if (m_pCmdBuffer != nullptr) - { - delete[] m_pCmdBuffer; - m_pCmdBuffer = nullptr; - } - m_pStdin = nullptr; - - // Note shutdown order is important here - MI::ModuleShutdown(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - MI::ModuleShutdown(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - - if (!bOk) - { - SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER), errMsg.c_str()); - } - - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdinLinux::InputAvailable(bool &vwbAvail) -{ -#ifndef _WIN32 - // Wait for the input using select API. Timeout is used so that we get an - // opportunity to check if m_waitForInput has been set to false by other thread. - fd_set setOfStdin; - struct timeval tv; - - while (m_waitForInput) - { - FD_ZERO(&setOfStdin); - FD_SET(STDIN_FILENO, &setOfStdin); - tv.tv_sec = 1; - tv.tv_usec = 0; - int ret = ::select(STDIN_FILENO + 1, &setOfStdin, nullptr, nullptr, &tv); - if (ret == 0) // Timeout. Loop back if m_waitForInput is true - continue; - else if (ret == -1) // Error condition. Return - { - vwbAvail = false; - return MIstatus::failure; - } - else // Have some valid input - { - vwbAvail = true; - return MIstatus::success; - } - } -#endif - return MIstatus::failure; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). -// Type: Method. -// Args: vwErrMsg - (W) Empty string ok or error description. -// Return: MIchar * - text buffer pointer or NULL on failure. -// Throws: None. -//-- -const MIchar * -CMICmnStreamStdinLinux::ReadLine(CMIUtilString &vwErrMsg) -{ - vwErrMsg.clear(); - - // Read user input - const MIchar *pText = ::fgets(&m_pCmdBuffer[0], m_constBufferSize, stdin); - if (pText == nullptr) - { - if (::ferror(m_pStdin) != 0) - vwErrMsg = ::strerror(errno); - return nullptr; - } - - // Strip off new line characters - for (MIchar *pI = m_pCmdBuffer; *pI != '\0'; pI++) - { - if ((*pI == '\n') || (*pI == '\r')) - { - *pI = '\0'; - break; - } - } - - return pText; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Interrupt current and prevent new ReadLine operations. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. -//-- -void -CMICmnStreamStdinLinux::InterruptReadLine(void) -{ - m_waitForInput = false; -} Index: tools/lldb-mi/MICmnStreamStdinWindows.h =================================================================== --- tools/lldb-mi/MICmnStreamStdinWindows.h +++ /dev/null @@ -1,79 +0,0 @@ -//===-- MICmnStreamStdinWindows.h -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -//++ -// File: MIUtilStreamStdin.h -// -// Overview: CMICmnStreamStdinWindows interface. -// -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. -// -// Copyright: None. -//-- - -#pragma once - -// In-house headers: -#include "MICmnBase.h" -#include "MICmnStreamStdin.h" -#include "MIUtilSingletonBase.h" - -//++ ============================================================================ -// Details: MI common code class. Specific OS stdin handling implementation. -// CMICmnStreamStdin instance is set with stdin handler before using the -// the stream. An instance of this class must be set up and ready to give -// to the CMICmnStreamStdin before it initialises other CMICmnStreamStdin -// will give an error. -// Gotchas: None. -// Authors: Illya Rudkin 16/06/2014. -// Changes: None. -//-- -class CMICmnStreamStdinWindows : public CMICmnBase, - public CMICmnStreamStdin::IOSStdinHandler, - public MI::ISingleton -{ - // Give singleton access to private constructors - friend MI::ISingleton; - - // Methods: - public: - bool Initialize(void); - bool Shutdown(void); - - // Overridden: - public: - // From CMICmnStreamStdin::IOSpecificReadStreamStdin - virtual bool InputAvailable(bool &vwbAvail); - virtual const MIchar *ReadLine(CMIUtilString &vwErrMsg); - - // Methods: - private: - /* ctor */ CMICmnStreamStdinWindows(void); - /* ctor */ CMICmnStreamStdinWindows(const CMICmnStreamStdinWindows &); - void operator=(const CMICmnStreamStdinWindows &); - // - bool InputAvailableConsoleWin(bool &vwbAvail); - bool InputAvailableApplication(bool &vwbAvail); - - // Overridden: - private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnStreamStdinWindows(void); - - // Attributes: - private: - const MIuint m_constBufferSize; - FILE *m_pStdin; - MIchar *m_pCmdBuffer; - MIchar *m_pStdinBuffer; // Custom buffer to store std input - MIuint m_nBytesToBeRead; // Checks that ::fgets() is holding on to data while ::PeekNamedPipe() returns nothing which causes a problem - bool m_bRunningInConsoleWin; // True = The application is being run in a Windows command line prompt window, false = by other means -}; Index: tools/lldb-mi/MICmnStreamStdinWindows.cpp =================================================================== --- tools/lldb-mi/MICmnStreamStdinWindows.cpp +++ /dev/null @@ -1,285 +0,0 @@ -//===-- MICmnStreamStdinWindows.cpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -//++ -// File: MIUtilStreamStdin.cpp -// -// Overview: CMICmnStreamStdinWindows implementation. -// -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. -// -// Copyright: None. -//-- - -// Third Party Headers: -#if defined(_MSC_VER) -#include -#include -#include -#include -#endif // defined( _MSC_VER ) -#include - -// In-house headers: -#include "MICmnStreamStdinWindows.h" -#include "MICmnLog.h" -#include "MICmnResources.h" -#include "MIUtilSystemWindows.h" -#include "MIUtilSingletonHelper.h" - -//++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdinWindows constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. -//-- -CMICmnStreamStdinWindows::CMICmnStreamStdinWindows(void) - : m_constBufferSize(1024) - , m_pStdin(nullptr) - , m_pCmdBuffer(nullptr) - , m_pStdinBuffer(nullptr) - , m_nBytesToBeRead(0) - , m_bRunningInConsoleWin(false) -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdinWindows destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. -//-- -CMICmnStreamStdinWindows::~CMICmnStreamStdinWindows(void) -{ - Shutdown(); -} - -//++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdinWindows::Initialize(void) -{ - if (m_bInitialized) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - - // Other resources required - if (bOk) - { - m_pCmdBuffer = new MIchar[m_constBufferSize]; - m_pStdin = stdin; - -#if MICONFIG_CREATE_OWN_STDIN_BUFFER - // Give stdinput a user defined buffer - m_pStdinBuffer = new char[1024]; - ::setbuf(stdin, m_pStdinBuffer); -#endif // MICONFIG_CREATE_OWN_STDIN_BUFFER - - // Clear error indicators for std input - ::clearerr(stdin); - -#if defined(_MSC_VER) - m_bRunningInConsoleWin = ::_isatty(::fileno(stdin)); -#endif // #if defined( _MSC_VER ) - } - - m_bInitialized = bOk; - - if (!bOk) - { - CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_OS_STDIN_HANDLER), errMsg.c_str())); - SetErrorDescription(strInitError); - return MIstatus::failure; - } - - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdinWindows::Shutdown(void) -{ - if (!m_bInitialized) - return MIstatus::success; - - m_bInitialized = false; - - ClrErrorDescription(); - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Tidy up - if (m_pCmdBuffer != nullptr) - { - delete[] m_pCmdBuffer; - m_pCmdBuffer = nullptr; - } - m_pStdin = nullptr; - -#if MICONFIG_CREATE_OWN_STDIN_BUFFER - if (m_pStdinBuffer) - delete[] m_pStdinBuffer; - m_pStdinBuffer = nullptr; -#endif // MICONFIG_CREATE_OWN_STDIN_BUFFER - - // Note shutdown order is important here - MI::ModuleShutdown(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - MI::ModuleShutdown(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - - if (!bOk) - { - SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER), errMsg.c_str()); - } - - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdinWindows::InputAvailable(bool &vwbAvail) -{ - return m_bRunningInConsoleWin ? InputAvailableConsoleWin(vwbAvail) : InputAvailableApplication(vwbAvail); -} - -//++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. If running in a -// terminal use _kbhit(). -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdinWindows::InputAvailableConsoleWin(bool &vwbAvail) -{ -#if defined(_MSC_VER) - if (m_nBytesToBeRead == 0) - { - // Get a windows handle to std input stream - HANDLE handle = ::GetStdHandle(STD_INPUT_HANDLE); - DWORD nBytesWaiting = ::_kbhit(); - - // Save the number of bytes to be read so that we can check if input is available to be read - m_nBytesToBeRead = nBytesWaiting; - - // Return state of whether bytes are waiting or not - vwbAvail = (nBytesWaiting > 0); - } -#endif // #if defined( _MSC_VER ) - - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMICmnStreamStdinWindows::InputAvailableApplication(bool &vwbAvail) -{ -#if defined(_MSC_VER) - if (m_nBytesToBeRead == 0) - { - // Get a windows handle to std input stream - HANDLE handle = ::GetStdHandle(STD_INPUT_HANDLE); - DWORD nBytesWaiting = 0; - - // Ask how many bytes are available - if (::PeekNamedPipe(handle, nullptr, 0, nullptr, &nBytesWaiting, nullptr) == FALSE) - { - // This can occur when the client i.e. Eclipse closes the stdin stream 'cause it deems its work is finished - // for that debug session. May be we should be handling SIGKILL somehow? - const CMIUtilString osErrMsg(CMIUtilSystemWindows().GetOSLastError().StripCRAll()); - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE), osErrMsg.c_str())); - return MIstatus::failure; - } - - // Save the number of bytes to be read so that we can check if input is available to be read - m_nBytesToBeRead = nBytesWaiting; - - // Return state of whether bytes are waiting or not - vwbAvail = (nBytesWaiting > 0); - } -#endif // #if defined( _MSC_VER ) - - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). -// Type: Method. -// Args: vwErrMsg - (W) Empty string ok or error description. -// Return: MIchar * - text buffer pointer or NULL on failure. -// Throws: None. -//-- -const MIchar * -CMICmnStreamStdinWindows::ReadLine(CMIUtilString &vwErrMsg) -{ - vwErrMsg.clear(); - - // Read user input - const MIchar *pText = ::fgets(&m_pCmdBuffer[0], m_constBufferSize, stdin); - if (pText == nullptr) - { - if (::ferror(m_pStdin) != 0) - vwErrMsg = ::strerror(errno); - return nullptr; - } - - // Subtract the number of bytes read so that we can check if input is available to be read - m_nBytesToBeRead = m_nBytesToBeRead - ::strlen(pText); - - // Strip off new line characters - for (MIchar *pI = m_pCmdBuffer; *pI != '\0'; pI++) - { - if ((*pI == '\n') || (*pI == '\r')) - { - *pI = '\0'; - break; - } - } - - return pText; -} Index: tools/lldb-mi/MIDriver.cpp =================================================================== --- tools/lldb-mi/MIDriver.cpp +++ tools/lldb-mi/MIDriver.cpp @@ -955,7 +955,6 @@ { CMIUtilThreadLock lock(m_threadMutex); m_bExitApp = true; - m_rStdin.OnExitHandler(); return; } @@ -970,7 +969,6 @@ } m_bExitApp = true; - m_rStdin.OnExitHandler(); } //++ ------------------------------------------------------------------------------------