124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- IOChannel.cpp -------------------------------------------*- C++ -*-===// 224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The LLVM Compiler Infrastructure 424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source 624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details. 724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "IOChannel.h" 1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <map> 1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 14f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBCommandInterpreter.h" 15f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBDebugger.h" 16f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBError.h" 17f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBEvent.h" 18f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBFileSpec.h" 19f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBHostOS.h" 20f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBListener.h" 21f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBStringList.h" 2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 23d6e167d0fe8666347554226424bb39e36686e0d6Eli Friedman#include <string.h> 24d6e167d0fe8666347554226424bb39e36686e0d6Eli Friedman#include <limits.h> 25d6e167d0fe8666347554226424bb39e36686e0d6Eli Friedman 2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb; 2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnertypedef std::map<EditLine *, std::string> PromptMap; 2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst char *g_default_prompt = "(lldb) "; 3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerPromptMap g_prompt_map; 3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 32c5f0b99c2c2e40dca22cf11208da70ae979a37e8Caroline Tice// Printing the following string causes libedit to back up to the beginning of the line & blank it out. 33c5f0b99c2c2e40dca22cf11208da70ae979a37e8Caroline Ticeconst char undo_prompt_string[4] = { (char) 13, (char) 27, (char) 91, (char) 75}; 34c5f0b99c2c2e40dca22cf11208da70ae979a37e8Caroline Tice 3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic const char* 3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerel_prompt(EditLine *el) 3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner PromptMap::const_iterator pos = g_prompt_map.find (el); 3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (pos == g_prompt_map.end()) 4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return g_default_prompt; 4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return pos->second.c_str(); 4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst char * 4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::GetPrompt () 4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner PromptMap::const_iterator pos = g_prompt_map.find (m_edit_line); 4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (pos == g_prompt_map.end()) 4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return g_default_prompt; 5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return pos->second.c_str(); 5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 53bab9b647fad841cf7c301f0bd8b1da3c0e72bfa2Jim Inghambool 54bab9b647fad841cf7c301f0bd8b1da3c0e72bfa2Jim InghamIOChannel::EditLineHasCharacters () 55bab9b647fad841cf7c301f0bd8b1da3c0e72bfa2Jim Ingham{ 56bab9b647fad841cf7c301f0bd8b1da3c0e72bfa2Jim Ingham const LineInfo *line_info = el_line(m_edit_line); 57bab9b647fad841cf7c301f0bd8b1da3c0e72bfa2Jim Ingham if (line_info) 585d90ade8e8e0d776fe8e1b9e88fc1c86d02e8e4eJim Ingham { 595d90ade8e8e0d776fe8e1b9e88fc1c86d02e8e4eJim Ingham // Sometimes we get called after the user has submitted the line, but before editline has 605d90ade8e8e0d776fe8e1b9e88fc1c86d02e8e4eJim Ingham // cleared the buffer. In that case the cursor will be pointing at the newline. That's 615d90ade8e8e0d776fe8e1b9e88fc1c86d02e8e4eJim Ingham // equivalent to having no characters on the line, since it has already been submitted. 625d90ade8e8e0d776fe8e1b9e88fc1c86d02e8e4eJim Ingham if (*line_info->cursor == '\n') 635d90ade8e8e0d776fe8e1b9e88fc1c86d02e8e4eJim Ingham return false; 645d90ade8e8e0d776fe8e1b9e88fc1c86d02e8e4eJim Ingham else 655d90ade8e8e0d776fe8e1b9e88fc1c86d02e8e4eJim Ingham return line_info->cursor != line_info->buffer; 665d90ade8e8e0d776fe8e1b9e88fc1c86d02e8e4eJim Ingham } 67bab9b647fad841cf7c301f0bd8b1da3c0e72bfa2Jim Ingham else 68bab9b647fad841cf7c301f0bd8b1da3c0e72bfa2Jim Ingham return false; 69bab9b647fad841cf7c301f0bd8b1da3c0e72bfa2Jim Ingham} 70bab9b647fad841cf7c301f0bd8b1da3c0e72bfa2Jim Ingham 71bab9b647fad841cf7c301f0bd8b1da3c0e72bfa2Jim Ingham 728ab2c22f22bd5ff09c98441f148406e0a890084eJohnny Chenvoid 738ab2c22f22bd5ff09c98441f148406e0a890084eJohnny ChenIOChannel::EraseCharsBeforeCursor () 748ab2c22f22bd5ff09c98441f148406e0a890084eJohnny Chen{ 758ab2c22f22bd5ff09c98441f148406e0a890084eJohnny Chen const LineInfo *line_info = el_line(m_edit_line); 768ab2c22f22bd5ff09c98441f148406e0a890084eJohnny Chen el_deletestr(m_edit_line, line_info->cursor - line_info->buffer); 778ab2c22f22bd5ff09c98441f148406e0a890084eJohnny Chen} 788ab2c22f22bd5ff09c98441f148406e0a890084eJohnny Chen 7924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerunsigned char 8024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::ElCompletionFn (EditLine *e, int ch) 8124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 8224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner IOChannel *io_channel; 8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (el_get(e, EL_CLIENTDATA, &io_channel) == 0) 8424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 8524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return io_channel->HandleCompletion (e, ch); 8624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 8824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 8924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return CC_ERROR; 9024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 9124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 9224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 932eaca13a907b3c2ce41602b646d073851dc696ebJim Inghamvoid 942eaca13a907b3c2ce41602b646d073851dc696ebJim InghamIOChannel::ElResize() 952eaca13a907b3c2ce41602b646d073851dc696ebJim Ingham{ 962eaca13a907b3c2ce41602b646d073851dc696ebJim Ingham el_resize(m_edit_line); 972eaca13a907b3c2ce41602b646d073851dc696ebJim Ingham} 982eaca13a907b3c2ce41602b646d073851dc696ebJim Ingham 9924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerunsigned char 10024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::HandleCompletion (EditLine *e, int ch) 10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 10224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner assert (e == m_edit_line); 10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 10424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const LineInfo *line_info = el_line(m_edit_line); 10524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SBStringList completions; 10654e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton int page_size = 40; 10724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 10863094e0bb161580564954dee512955c1c79d3476Greg Clayton int num_completions = m_driver->GetDebugger().GetCommandInterpreter().HandleCompletion (line_info->buffer, 10963094e0bb161580564954dee512955c1c79d3476Greg Clayton line_info->cursor, 11063094e0bb161580564954dee512955c1c79d3476Greg Clayton line_info->lastchar, 11163094e0bb161580564954dee512955c1c79d3476Greg Clayton 0, 11263094e0bb161580564954dee512955c1c79d3476Greg Clayton -1, 11363094e0bb161580564954dee512955c1c79d3476Greg Clayton completions); 11424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 11524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (num_completions == -1) 11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 11724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner el_insertstr (m_edit_line, m_completion_key); 11824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return CC_REDISPLAY; 11924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 1206247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham else if (num_completions == -2) 1216247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham { 1226247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham el_deletestr (m_edit_line, line_info->cursor - line_info->buffer); 1236247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham el_insertstr (m_edit_line, completions.GetStringAtIndex(0)); 1246247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham return CC_REDISPLAY; 1256247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham } 12624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 12724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // If we get a longer match display that first. 12824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const char *completion_str = completions.GetStringAtIndex(0); 12924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (completion_str != NULL && *completion_str != '\0') 13024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 13124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner el_insertstr (m_edit_line, completion_str); 13224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return CC_REDISPLAY; 13324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (num_completions > 1) 13624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 13724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const char *comment = "\nAvailable completions:"; 13824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 13924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int num_elements = num_completions + 1; 1404a348081030cdd2af758fddc869518357d9befd3Caroline Tice OutWrite(comment, strlen (comment), NO_ASYNC); 14124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (num_completions < page_size) 14224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 14324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner for (int i = 1; i < num_elements; i++) 14424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 145bef1583b89e73de77c8b0897fcf42b5b1fcabe4cGreg Clayton completion_str = completions.GetStringAtIndex(i); 1464a348081030cdd2af758fddc869518357d9befd3Caroline Tice OutWrite("\n\t", 2, NO_ASYNC); 1474a348081030cdd2af758fddc869518357d9befd3Caroline Tice OutWrite(completion_str, strlen (completion_str), NO_ASYNC); 14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 1494a348081030cdd2af758fddc869518357d9befd3Caroline Tice OutWrite ("\n", 1, NO_ASYNC); 15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 15124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int cur_pos = 1; 15424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner char reply; 15524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int got_char; 15624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (cur_pos < num_elements) 15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 15824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int endpoint = cur_pos + page_size; 15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (endpoint > num_elements) 16024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner endpoint = num_elements; 16124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner for (; cur_pos < endpoint; cur_pos++) 16224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 163bef1583b89e73de77c8b0897fcf42b5b1fcabe4cGreg Clayton completion_str = completions.GetStringAtIndex(cur_pos); 1644a348081030cdd2af758fddc869518357d9befd3Caroline Tice OutWrite("\n\t", 2, NO_ASYNC); 1654a348081030cdd2af758fddc869518357d9befd3Caroline Tice OutWrite(completion_str, strlen (completion_str), NO_ASYNC); 16624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 16724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 16824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (cur_pos >= num_elements) 16924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 1704a348081030cdd2af758fddc869518357d9befd3Caroline Tice OutWrite("\n", 1, NO_ASYNC); 17124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 17224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 17324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 1744a348081030cdd2af758fddc869518357d9befd3Caroline Tice OutWrite("\nMore (Y/n/a): ", strlen ("\nMore (Y/n/a): "), NO_ASYNC); 17524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner reply = 'n'; 17624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner got_char = el_getc(m_edit_line, &reply); 17724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (got_char == -1 || reply == 'n') 17824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 17924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (reply == 'a') 18024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner page_size = num_elements - cur_pos; 18124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 18224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 18324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 18424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 18524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (num_completions == 0) 18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return CC_REFRESH_BEEP; 18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return CC_REDISPLAY; 19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 19124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 19224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::IOChannel 19324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner( 1944a348081030cdd2af758fddc869518357d9befd3Caroline Tice FILE *editline_in, 1954a348081030cdd2af758fddc869518357d9befd3Caroline Tice FILE *editline_out, 1964a348081030cdd2af758fddc869518357d9befd3Caroline Tice FILE *out, 19724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner FILE *err, 19824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Driver *driver 19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner) : 20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SBBroadcaster ("IOChannel"), 201757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice m_output_mutex (), 202757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice m_enter_elgets_time (), 20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_driver (driver), 20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_read_thread (LLDB_INVALID_HOST_THREAD), 20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_read_thread_should_exit (false), 20624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_out_file (out), 20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err_file (err), 20854e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton m_command_queue (), 20954e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton m_completion_key ("\t"), 2104a348081030cdd2af758fddc869518357d9befd3Caroline Tice m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), editline_in, editline_out, editline_out)), 21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_history (history_init()), 21254e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton m_history_event(), 2134a348081030cdd2af758fddc869518357d9befd3Caroline Tice m_getting_command (false), 2144a348081030cdd2af758fddc869518357d9befd3Caroline Tice m_expecting_prompt (false), 215388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice m_prompt_str (), 216388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice m_refresh_request_pending (false) 21724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 21824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner assert (m_edit_line); 21924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::el_set (m_edit_line, EL_PROMPT, el_prompt); 22024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::el_set (m_edit_line, EL_EDITOR, "emacs"); 22124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::el_set (m_edit_line, EL_HIST, history, m_history); 22224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 223882c554207e94f66ba8d652302a9d817f275dc4eCaroline Tice el_set (m_edit_line, EL_ADDFN, "lldb_complete", 22424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner "LLDB completion function", 22524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner IOChannel::ElCompletionFn); 226882c554207e94f66ba8d652302a9d817f275dc4eCaroline Tice el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL); 227882c554207e94f66ba8d652302a9d817f275dc4eCaroline Tice el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string 228abd370a4be26a5fc288ca090e80b12c1bc14ac8bJohnny Chen el_set (m_edit_line, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does. 2292a4e9af22db482a276a109af57b23a95d0f38ddfSean Callanan el_set (m_edit_line, EL_BIND, "\e[3~", "ed-delete-next-char", NULL); // Fix the delete key. 23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner el_set (m_edit_line, EL_CLIENTDATA, this); 23124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2323bbbdc3c3ca4d449e9033a6e8c1686b8b6ed0769Johnny Chen // Source $PWD/.editrc then $HOME/.editrc 2333bbbdc3c3ca4d449e9033a6e8c1686b8b6ed0769Johnny Chen ::el_source (m_edit_line, NULL); 2343bbbdc3c3ca4d449e9033a6e8c1686b8b6ed0769Johnny Chen 23524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner assert (m_history); 23624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::history (m_history, &m_history_event, H_SETSIZE, 800); 23724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::history (m_history, &m_history_event, H_SETUNIQUE, 1); 23824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Load history 23924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner HistorySaveLoad (false); 240757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 241757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice // Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere 242757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice // with each other when writing. 243757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 244757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice int error; 245757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice ::pthread_mutexattr_t attr; 246757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice error = ::pthread_mutexattr_init (&attr); 247757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice assert (error == 0); 248757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); 249757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice assert (error == 0); 250757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice error = ::pthread_mutex_init (&m_output_mutex, &attr); 251757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice assert (error == 0); 252757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice error = ::pthread_mutexattr_destroy (&attr); 253757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice assert (error == 0); 254757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 255757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice // Initialize time that ::el_gets was last called. 256757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 257757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice m_enter_elgets_time.tv_sec = 0; 258757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice m_enter_elgets_time.tv_usec = 0; 25924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 26024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::~IOChannel () 26224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Save history 26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner HistorySaveLoad (true); 26524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_history != NULL) 26724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::history_end (m_history); 26924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_history = NULL; 27024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_edit_line != NULL) 27324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::el_end (m_edit_line); 27524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_edit_line = NULL; 27624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 277757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 278757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice ::pthread_mutex_destroy (&m_output_mutex); 27924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 28124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid 28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::HistorySaveLoad (bool save) 28324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_history != NULL) 28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner char history_path[PATH_MAX]; 2874ead2e9a5a74f465d00b0301c165fbebf4ee4ff3Johnny Chen ::snprintf (history_path, sizeof(history_path), "~/.%s-history", SBHostOS::GetProgramFileSpec().GetFilename()); 28854e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton if ((size_t)SBFileSpec::ResolvePath (history_path, history_path, sizeof(history_path)) < sizeof(history_path) - 1) 28924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 29024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const char *path_ptr = history_path; 29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (save) 29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::history (m_history, &m_history_event, H_SAVE, path_ptr); 29324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::history (m_history, &m_history_event, H_LOAD, path_ptr); 29524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 29624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 29724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 29824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2994a348081030cdd2af758fddc869518357d9befd3Caroline Ticevoid 3004a348081030cdd2af758fddc869518357d9befd3Caroline TiceIOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len) 3014a348081030cdd2af758fddc869518357d9befd3Caroline Tice{ 3024a348081030cdd2af758fddc869518357d9befd3Caroline Tice // Make this a member variable. 3034a348081030cdd2af758fddc869518357d9befd3Caroline Tice // static std::string prompt_str; 3044a348081030cdd2af758fddc869518357d9befd3Caroline Tice IOChannel *io_channel = (IOChannel *) baton; 305388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice IOLocker locker (io_channel->m_output_mutex); 3064a348081030cdd2af758fddc869518357d9befd3Caroline Tice const char *bytes = (const char *) src; 3074a348081030cdd2af758fddc869518357d9befd3Caroline Tice 3084a348081030cdd2af758fddc869518357d9befd3Caroline Tice if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt) 3094a348081030cdd2af758fddc869518357d9befd3Caroline Tice { 3104a348081030cdd2af758fddc869518357d9befd3Caroline Tice io_channel->m_prompt_str.append (bytes, src_len); 3114a348081030cdd2af758fddc869518357d9befd3Caroline Tice // Log this to make sure the prompt is really what you think it is. 3124a348081030cdd2af758fddc869518357d9befd3Caroline Tice if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0) 3134a348081030cdd2af758fddc869518357d9befd3Caroline Tice { 3144a348081030cdd2af758fddc869518357d9befd3Caroline Tice io_channel->m_expecting_prompt = false; 315388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice io_channel->m_refresh_request_pending = false; 3164a348081030cdd2af758fddc869518357d9befd3Caroline Tice io_channel->OutWrite (io_channel->m_prompt_str.c_str(), 3174a348081030cdd2af758fddc869518357d9befd3Caroline Tice io_channel->m_prompt_str.size(), NO_ASYNC); 3184a348081030cdd2af758fddc869518357d9befd3Caroline Tice io_channel->m_prompt_str.clear(); 3194a348081030cdd2af758fddc869518357d9befd3Caroline Tice } 3204a348081030cdd2af758fddc869518357d9befd3Caroline Tice } 3214a348081030cdd2af758fddc869518357d9befd3Caroline Tice else 3224a348081030cdd2af758fddc869518357d9befd3Caroline Tice { 3234a348081030cdd2af758fddc869518357d9befd3Caroline Tice if (io_channel->m_prompt_str.size() > 0) 3244a348081030cdd2af758fddc869518357d9befd3Caroline Tice io_channel->m_prompt_str.clear(); 325388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice std::string tmp_str (bytes, src_len); 326388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice if (tmp_str.find (el_prompt (io_channel->m_edit_line)) == 0) 327388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice io_channel->m_refresh_request_pending = false; 3284a348081030cdd2af758fddc869518357d9befd3Caroline Tice io_channel->OutWrite (bytes, src_len, NO_ASYNC); 3294a348081030cdd2af758fddc869518357d9befd3Caroline Tice } 3304a348081030cdd2af758fddc869518357d9befd3Caroline Tice} 3314a348081030cdd2af758fddc869518357d9befd3Caroline Tice 332e09196066b61294d30c56ca86d8443bd3078a2f5Enrico GranataIOChannel::LibeditGetInputResult 33324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::LibeditGetInput (std::string &new_line) 33424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 335e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata IOChannel::LibeditGetInputResult retval = IOChannel::eLibeditGetInputResultUnknown; 33624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_edit_line != NULL) 33724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 33824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int line_len = 0; 339757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 340757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice // Set boolean indicating whether or not el_gets is trying to get input (i.e. whether or not to attempt 341757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice // to refresh the prompt after writing data). 342757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice SetGettingCommand (true); 3434a348081030cdd2af758fddc869518357d9befd3Caroline Tice m_expecting_prompt = true; 344757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 345757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice // Call el_gets to prompt the user and read the user's input. 34624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const char *line = ::el_gets (m_edit_line, &line_len); 347757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 348757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice // Re-set the boolean indicating whether or not el_gets is trying to get input. 349757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice SetGettingCommand (false); 350757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 35124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (line) 35224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 353e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata retval = IOChannel::eLibeditGetInputValid; 35424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // strip any newlines off the end of the string... 35524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (line_len > 0 && (line[line_len - 1] == '\n' || line[line_len - 1] == '\r')) 35624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner --line_len; 35724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (line_len > 0) 35824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 35924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::history (m_history, &m_history_event, H_ENTER, line); 36024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner new_line.assign (line, line_len); // Omit the newline 36124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 36224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 36324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 364e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata retval = IOChannel::eLibeditGetInputEmpty; 36524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Someone just hit ENTER, return the empty string 36624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner new_line.clear(); 36724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 36824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Return true to indicate success even if a string is empty 369e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata return retval; 370e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata } 371e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata else 372e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata { 373e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata retval = (line_len == 0 ? IOChannel::eLibeditGetInputEOF : IOChannel::eLibeditGetInputResultError); 37424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 37524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 37624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Return false to indicate failure. This can happen when the file handle 37724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // is closed (EOF). 37824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner new_line.clear(); 379e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata return retval; 38024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 38124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 38224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid * 38324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::IOReadThread (void *ptr) 38424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 38524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner IOChannel *myself = static_cast<IOChannel *> (ptr); 38624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner myself->Run(); 38724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return NULL; 38824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 38924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 39024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid 39124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::Run () 39224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 39324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SBListener listener("IOChannel::Run"); 39424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner std::string new_line; 39524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 39663094e0bb161580564954dee512955c1c79d3476Greg Clayton SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster()); 39724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner listener.StartListeningForEvents (interpreter_broadcaster, 39824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SBCommandInterpreter::eBroadcastBitResetPrompt | 39924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SBCommandInterpreter::eBroadcastBitThreadShouldExit | 400388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice SBCommandInterpreter::eBroadcastBitQuitCommandReceived); 40124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 40224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner listener.StartListeningForEvents (*this, 40324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner IOChannel::eBroadcastBitThreadShouldExit); 40424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 40524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner listener.StartListeningForEvents (*m_driver, 40624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Driver::eBroadcastBitReadyForInput | 40724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Driver::eBroadcastBitThreadShouldExit); 40824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 40924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Let anyone know that the IO channel is up and listening and ready for events 41024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner BroadcastEventByType (eBroadcastBitThreadDidStart); 41124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool done = false; 41224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (!done) 41324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 41424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SBEvent event; 41524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 41624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner listener.WaitForEvent (UINT32_MAX, event); 41724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!event.IsValid()) 41824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner continue; 41924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 42024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const uint32_t event_type = event.GetType(); 42124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 42224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (event.GetBroadcaster().IsValid()) 42324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 42424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (event.BroadcasterMatchesPtr (m_driver)) 42524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 42624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (event_type & Driver::eBroadcastBitReadyForInput) 42724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 42824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner std::string line; 42924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 43024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (CommandQueueIsEmpty()) 43124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 432e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata IOChannel::LibeditGetInputResult getline_result = LibeditGetInput(line); 433e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata if (getline_result == IOChannel::eLibeditGetInputEOF) 434e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata { 435e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata // EOF occurred 436e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata // pretend that a quit was typed so the user gets a potential 437e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata // chance to confirm 438e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata line.assign("quit"); 439e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata } 440e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata else if (getline_result == IOChannel::eLibeditGetInputResultError || getline_result == IOChannel::eLibeditGetInputResultUnknown) 44124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 442e09196066b61294d30c56ca86d8443bd3078a2f5Enrico Granata // some random error occurred, exit and don't ask because the state might be corrupt 44324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner done = true; 44424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner continue; 44524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 44624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 44724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 44824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 44924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner GetCommandFromQueue (line); 45024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 45124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 45224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN' 45324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // AND TAKE CARE OF THAT HERE. 45424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 45524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SBEvent line_event(IOChannel::eBroadcastBitHasUserInput, 45624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner line.c_str(), 45724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner line.size()); 45824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner BroadcastEvent (line_event); 45924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 46024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else if (event_type & Driver::eBroadcastBitThreadShouldExit) 46124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 46224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner done = true; 463ee6e790171b9a04023d0ea22603f0ac0ecb9a2c6Johnny Chen continue; 46424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 46524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 46624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else if (event.BroadcasterMatchesRef (interpreter_broadcaster)) 46724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 46824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner switch (event_type) 46924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 47024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner case SBCommandInterpreter::eBroadcastBitResetPrompt: 47124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 47224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const char *new_prompt = SBEvent::GetCStringFromEvent (event); 47324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (new_prompt) 47424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner g_prompt_map[m_edit_line] = new_prompt; 47524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 47624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 47724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 47824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner case SBCommandInterpreter::eBroadcastBitThreadShouldExit: 47924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner case SBCommandInterpreter::eBroadcastBitQuitCommandReceived: 48024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner done = true; 48124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 48224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 48324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 48424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else if (event.BroadcasterMatchesPtr (this)) 48524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 48624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (event_type & IOChannel::eBroadcastBitThreadShouldExit) 48724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 48824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner done = true; 489ee6e790171b9a04023d0ea22603f0ac0ecb9a2c6Johnny Chen continue; 49024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 49124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 49224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 49324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 49424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit); 49524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_driver = NULL; 496b9db9d5bb01963774f28540dbe2c5a11f586ff29Daniel Malea m_read_thread = 0; 49724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 49824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 49924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool 50024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::Start () 50124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 50209c81efd010d1c9ac8821bad00cdfc9747fcae79Greg Clayton if (IS_VALID_LLDB_HOST_THREAD(m_read_thread)) 50324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return true; 50424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 50524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this, 50624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner NULL); 50724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 50809c81efd010d1c9ac8821bad00cdfc9747fcae79Greg Clayton return (IS_VALID_LLDB_HOST_THREAD(m_read_thread)); 50924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 51024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 51124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool 51224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::Stop () 51324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 51409c81efd010d1c9ac8821bad00cdfc9747fcae79Greg Clayton if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread)) 51524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return true; 51624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 51724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner BroadcastEventByType (eBroadcastBitThreadShouldExit); 51824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 51924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Don't call Host::ThreadCancel since el_gets won't respond to this 52024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // function call -- the thread will just die and all local variables in 52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // IOChannel::Run() won't get destructed down which is bad since there is 52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // a local listener holding onto broadcasters... To ensure proper shutdown, 52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // a ^D (control-D) sequence (0x04) should be written to other end of the 52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // the "in" file handle that was passed into the contructor as closing the 52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // file handle doesn't seem to make el_gets() exit.... 52624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return SBHostOS::ThreadJoin (m_read_thread, NULL, NULL); 52724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 52824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 52924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid 53024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::RefreshPrompt () 53124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 532757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice // If we are not in the middle of getting input from the user, there is no need to 533757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice // refresh the prompt. 534388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice IOLocker locker (m_output_mutex); 535757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice if (! IsGettingCommand()) 536757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice return; 537757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 5384a348081030cdd2af758fddc869518357d9befd3Caroline Tice // If we haven't finished writing the prompt, there's no need to refresh it. 5394a348081030cdd2af758fddc869518357d9befd3Caroline Tice if (m_expecting_prompt) 5404a348081030cdd2af758fddc869518357d9befd3Caroline Tice return; 541757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 542388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice if (m_refresh_request_pending) 543388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice return; 544388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice 54524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::el_set (m_edit_line, EL_REFRESH); 546388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice m_refresh_request_pending = true; 54724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 54824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid 5504a348081030cdd2af758fddc869518357d9befd3Caroline TiceIOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous) 55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 552c2bc7944f7c2f10114426f447259a35acb0b1e18Enrico Granata if (len == 0 || buffer == NULL) 55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return; 554757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 555bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda // We're in the process of exiting -- IOChannel::Run() has already completed 556bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda // and set m_driver to NULL - it is time for us to leave now. We might not 557bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda // print the final ^D to stdout in this case. We need to do some re-work on 558bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda // how the I/O streams are managed at some point. 559bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda if (m_driver == NULL) 560bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda { 561bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda return; 562bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda } 563bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda 5644a348081030cdd2af758fddc869518357d9befd3Caroline Tice // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output. 5654a348081030cdd2af758fddc869518357d9befd3Caroline Tice IOLocker locker (m_output_mutex); 566b38df1e945846a5d956974ec157902a6ad748868Caroline Tice if (m_driver->EditlineReaderIsTop() && asynchronous) 567c5f0b99c2c2e40dca22cf11208da70ae979a37e8Caroline Tice ::fwrite (undo_prompt_string, 1, 4, m_out_file); 5684a348081030cdd2af758fddc869518357d9befd3Caroline Tice ::fwrite (buffer, 1, len, m_out_file); 5694a348081030cdd2af758fddc869518357d9befd3Caroline Tice if (asynchronous) 5704a348081030cdd2af758fddc869518357d9befd3Caroline Tice m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten); 57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 57224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 57324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid 5744a348081030cdd2af758fddc869518357d9befd3Caroline TiceIOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous) 57524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 576c2bc7944f7c2f10114426f447259a35acb0b1e18Enrico Granata if (len == 0 || buffer == NULL) 57724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return; 578757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 5794a348081030cdd2af758fddc869518357d9befd3Caroline Tice // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output. 5804a348081030cdd2af758fddc869518357d9befd3Caroline Tice IOLocker locker (m_output_mutex); 5814a348081030cdd2af758fddc869518357d9befd3Caroline Tice if (asynchronous) 582c5f0b99c2c2e40dca22cf11208da70ae979a37e8Caroline Tice ::fwrite (undo_prompt_string, 1, 4, m_err_file); 5834a348081030cdd2af758fddc869518357d9befd3Caroline Tice ::fwrite (buffer, 1, len, m_err_file); 5844a348081030cdd2af758fddc869518357d9befd3Caroline Tice if (asynchronous) 5854a348081030cdd2af758fddc869518357d9befd3Caroline Tice m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten); 58624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 58724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 58824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid 58924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::AddCommandToQueue (const char *command) 59024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 59124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_command_queue.push (std::string(command)); 59224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 59324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 59424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool 59524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::GetCommandFromQueue (std::string &cmd) 59624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 59724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_command_queue.empty()) 59824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return false; 59924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner cmd.swap(m_command_queue.front()); 60024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_command_queue.pop (); 60124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return true; 60224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 60324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 60424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint 60524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::CommandQueueSize () const 60624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 60724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return m_command_queue.size(); 60824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 60924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 61024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid 61124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::ClearCommandQueue () 61224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 61324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (!m_command_queue.empty()) 61424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_command_queue.pop(); 61524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 61624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 61724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool 61824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::CommandQueueIsEmpty () const 61924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 62024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return m_command_queue.empty(); 62124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 622757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 623757500e29b7856823f2f4aedd30f206ec009147eCaroline Ticebool 624757500e29b7856823f2f4aedd30f206ec009147eCaroline TiceIOChannel::IsGettingCommand () const 625757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice{ 626757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice return m_getting_command; 627757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice} 628757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 629757500e29b7856823f2f4aedd30f206ec009147eCaroline Ticevoid 630757500e29b7856823f2f4aedd30f206ec009147eCaroline TiceIOChannel::SetGettingCommand (bool new_value) 631757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice{ 632757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice m_getting_command = new_value; 633757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice} 634757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 635757500e29b7856823f2f4aedd30f206ec009147eCaroline TiceIOLocker::IOLocker (pthread_mutex_t &mutex) : 636757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice m_mutex_ptr (&mutex) 637757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice{ 638757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice if (m_mutex_ptr) 639757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice ::pthread_mutex_lock (m_mutex_ptr); 640757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 641757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice} 642757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice 643757500e29b7856823f2f4aedd30f206ec009147eCaroline TiceIOLocker::~IOLocker () 644757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice{ 645757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice if (m_mutex_ptr) 646757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice ::pthread_mutex_unlock (m_mutex_ptr); 647757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice} 648