blob: 25274581efedd438d7dd4c8468b528140e5892cb [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- IOChannel.cpp -------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "IOChannel.h"
11
12#include <map>
13
Eli Friedmanf2f321d2010-06-09 09:50:17 +000014#include "lldb/API/SBCommandInterpreter.h"
15#include "lldb/API/SBDebugger.h"
16#include "lldb/API/SBError.h"
17#include "lldb/API/SBEvent.h"
18#include "lldb/API/SBFileSpec.h"
19#include "lldb/API/SBHostOS.h"
20#include "lldb/API/SBListener.h"
21#include "lldb/API/SBStringList.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022
Eli Friedmand6e167d2010-06-09 19:11:30 +000023#include <string.h>
24#include <limits.h>
25
Chris Lattner24943d22010-06-08 16:52:24 +000026using namespace lldb;
27
28typedef std::map<EditLine *, std::string> PromptMap;
29const char *g_default_prompt = "(lldb) ";
30PromptMap g_prompt_map;
31
Caroline Ticec5f0b992011-05-04 16:44:57 +000032// Printing the following string causes libedit to back up to the beginning of the line & blank it out.
33const char undo_prompt_string[4] = { (char) 13, (char) 27, (char) 91, (char) 75};
34
Chris Lattner24943d22010-06-08 16:52:24 +000035static const char*
36el_prompt(EditLine *el)
37{
38 PromptMap::const_iterator pos = g_prompt_map.find (el);
39 if (pos == g_prompt_map.end())
40 return g_default_prompt;
41 return pos->second.c_str();
42}
43
44const char *
45IOChannel::GetPrompt ()
46{
47 PromptMap::const_iterator pos = g_prompt_map.find (m_edit_line);
48 if (pos == g_prompt_map.end())
49 return g_default_prompt;
50 return pos->second.c_str();
51}
52
Johnny Chen8ab2c222012-05-09 21:03:07 +000053void
54IOChannel::EraseCharsBeforeCursor ()
55{
56 const LineInfo *line_info = el_line(m_edit_line);
57 el_deletestr(m_edit_line, line_info->cursor - line_info->buffer);
58}
59
Chris Lattner24943d22010-06-08 16:52:24 +000060unsigned char
61IOChannel::ElCompletionFn (EditLine *e, int ch)
62{
63 IOChannel *io_channel;
64 if (el_get(e, EL_CLIENTDATA, &io_channel) == 0)
65 {
66 return io_channel->HandleCompletion (e, ch);
67 }
68 else
69 {
70 return CC_ERROR;
71 }
72}
73
74unsigned char
75IOChannel::HandleCompletion (EditLine *e, int ch)
76{
77 assert (e == m_edit_line);
78
79 const LineInfo *line_info = el_line(m_edit_line);
80 SBStringList completions;
Greg Clayton54e7afa2010-07-09 20:39:50 +000081 int page_size = 40;
Chris Lattner24943d22010-06-08 16:52:24 +000082
Greg Clayton63094e02010-06-23 01:19:29 +000083 int num_completions = m_driver->GetDebugger().GetCommandInterpreter().HandleCompletion (line_info->buffer,
84 line_info->cursor,
85 line_info->lastchar,
86 0,
87 -1,
88 completions);
Chris Lattner24943d22010-06-08 16:52:24 +000089
90 if (num_completions == -1)
91 {
92 el_insertstr (m_edit_line, m_completion_key);
93 return CC_REDISPLAY;
94 }
Jim Ingham6247dbe2011-07-12 03:12:18 +000095 else if (num_completions == -2)
96 {
97 el_deletestr (m_edit_line, line_info->cursor - line_info->buffer);
98 el_insertstr (m_edit_line, completions.GetStringAtIndex(0));
99 return CC_REDISPLAY;
100 }
Chris Lattner24943d22010-06-08 16:52:24 +0000101
102 // If we get a longer match display that first.
103 const char *completion_str = completions.GetStringAtIndex(0);
104 if (completion_str != NULL && *completion_str != '\0')
105 {
106 el_insertstr (m_edit_line, completion_str);
107 return CC_REDISPLAY;
108 }
109
110 if (num_completions > 1)
111 {
112 const char *comment = "\nAvailable completions:";
113
114 int num_elements = num_completions + 1;
Caroline Tice4a348082011-05-02 20:41:46 +0000115 OutWrite(comment, strlen (comment), NO_ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000116 if (num_completions < page_size)
117 {
118 for (int i = 1; i < num_elements; i++)
119 {
Greg Claytonbef15832010-07-14 00:18:15 +0000120 completion_str = completions.GetStringAtIndex(i);
Caroline Tice4a348082011-05-02 20:41:46 +0000121 OutWrite("\n\t", 2, NO_ASYNC);
122 OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000123 }
Caroline Tice4a348082011-05-02 20:41:46 +0000124 OutWrite ("\n", 1, NO_ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000125 }
126 else
127 {
128 int cur_pos = 1;
129 char reply;
130 int got_char;
131 while (cur_pos < num_elements)
132 {
133 int endpoint = cur_pos + page_size;
134 if (endpoint > num_elements)
135 endpoint = num_elements;
136 for (; cur_pos < endpoint; cur_pos++)
137 {
Greg Claytonbef15832010-07-14 00:18:15 +0000138 completion_str = completions.GetStringAtIndex(cur_pos);
Caroline Tice4a348082011-05-02 20:41:46 +0000139 OutWrite("\n\t", 2, NO_ASYNC);
140 OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000141 }
142
143 if (cur_pos >= num_elements)
144 {
Caroline Tice4a348082011-05-02 20:41:46 +0000145 OutWrite("\n", 1, NO_ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000146 break;
147 }
148
Caroline Tice4a348082011-05-02 20:41:46 +0000149 OutWrite("\nMore (Y/n/a): ", strlen ("\nMore (Y/n/a): "), NO_ASYNC);
Chris Lattner24943d22010-06-08 16:52:24 +0000150 reply = 'n';
151 got_char = el_getc(m_edit_line, &reply);
152 if (got_char == -1 || reply == 'n')
153 break;
154 if (reply == 'a')
155 page_size = num_elements - cur_pos;
156 }
157 }
158
159 }
160
161 if (num_completions == 0)
162 return CC_REFRESH_BEEP;
163 else
164 return CC_REDISPLAY;
165}
166
167IOChannel::IOChannel
168(
Caroline Tice4a348082011-05-02 20:41:46 +0000169 FILE *editline_in,
170 FILE *editline_out,
171 FILE *out,
Chris Lattner24943d22010-06-08 16:52:24 +0000172 FILE *err,
173 Driver *driver
174) :
175 SBBroadcaster ("IOChannel"),
Caroline Tice757500e2010-09-29 18:35:42 +0000176 m_output_mutex (),
177 m_enter_elgets_time (),
Chris Lattner24943d22010-06-08 16:52:24 +0000178 m_driver (driver),
179 m_read_thread (LLDB_INVALID_HOST_THREAD),
180 m_read_thread_should_exit (false),
181 m_out_file (out),
182 m_err_file (err),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000183 m_command_queue (),
184 m_completion_key ("\t"),
Caroline Tice4a348082011-05-02 20:41:46 +0000185 m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), editline_in, editline_out, editline_out)),
Chris Lattner24943d22010-06-08 16:52:24 +0000186 m_history (history_init()),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000187 m_history_event(),
Caroline Tice4a348082011-05-02 20:41:46 +0000188 m_getting_command (false),
189 m_expecting_prompt (false),
Caroline Tice388ca8f2011-05-03 20:53:11 +0000190 m_prompt_str (),
191 m_refresh_request_pending (false)
Chris Lattner24943d22010-06-08 16:52:24 +0000192{
193 assert (m_edit_line);
194 ::el_set (m_edit_line, EL_PROMPT, el_prompt);
195 ::el_set (m_edit_line, EL_EDITOR, "emacs");
196 ::el_set (m_edit_line, EL_HIST, history, m_history);
197
Caroline Tice882c5542011-05-04 21:39:02 +0000198 el_set (m_edit_line, EL_ADDFN, "lldb_complete",
Chris Lattner24943d22010-06-08 16:52:24 +0000199 "LLDB completion function",
200 IOChannel::ElCompletionFn);
Caroline Tice882c5542011-05-04 21:39:02 +0000201 el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
202 el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string
Johnny Chenabd370a2012-05-05 04:44:12 +0000203 el_set (m_edit_line, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does.
Chris Lattner24943d22010-06-08 16:52:24 +0000204 el_set (m_edit_line, EL_CLIENTDATA, this);
205
Johnny Chen3bbbdc32012-05-07 18:18:08 +0000206 // Source $PWD/.editrc then $HOME/.editrc
207 ::el_source (m_edit_line, NULL);
208
Chris Lattner24943d22010-06-08 16:52:24 +0000209 assert (m_history);
210 ::history (m_history, &m_history_event, H_SETSIZE, 800);
211 ::history (m_history, &m_history_event, H_SETUNIQUE, 1);
212 // Load history
213 HistorySaveLoad (false);
Caroline Tice757500e2010-09-29 18:35:42 +0000214
215 // Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere
216 // with each other when writing.
217
218 int error;
219 ::pthread_mutexattr_t attr;
220 error = ::pthread_mutexattr_init (&attr);
221 assert (error == 0);
222 error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
223 assert (error == 0);
224 error = ::pthread_mutex_init (&m_output_mutex, &attr);
225 assert (error == 0);
226 error = ::pthread_mutexattr_destroy (&attr);
227 assert (error == 0);
228
229 // Initialize time that ::el_gets was last called.
230
231 m_enter_elgets_time.tv_sec = 0;
232 m_enter_elgets_time.tv_usec = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000233}
234
235IOChannel::~IOChannel ()
236{
237 // Save history
238 HistorySaveLoad (true);
239
240 if (m_history != NULL)
241 {
242 ::history_end (m_history);
243 m_history = NULL;
244 }
245
246 if (m_edit_line != NULL)
247 {
248 ::el_end (m_edit_line);
249 m_edit_line = NULL;
250 }
Caroline Tice757500e2010-09-29 18:35:42 +0000251
252 ::pthread_mutex_destroy (&m_output_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000253}
254
255void
256IOChannel::HistorySaveLoad (bool save)
257{
258 if (m_history != NULL)
259 {
260 char history_path[PATH_MAX];
Johnny Chen4ead2e92010-08-27 22:35:26 +0000261 ::snprintf (history_path, sizeof(history_path), "~/.%s-history", SBHostOS::GetProgramFileSpec().GetFilename());
Greg Clayton54e7afa2010-07-09 20:39:50 +0000262 if ((size_t)SBFileSpec::ResolvePath (history_path, history_path, sizeof(history_path)) < sizeof(history_path) - 1)
Chris Lattner24943d22010-06-08 16:52:24 +0000263 {
264 const char *path_ptr = history_path;
265 if (save)
266 ::history (m_history, &m_history_event, H_SAVE, path_ptr);
267 else
268 ::history (m_history, &m_history_event, H_LOAD, path_ptr);
269 }
270 }
271}
272
Caroline Tice4a348082011-05-02 20:41:46 +0000273void
274IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
275{
276 // Make this a member variable.
277 // static std::string prompt_str;
278 IOChannel *io_channel = (IOChannel *) baton;
Caroline Tice388ca8f2011-05-03 20:53:11 +0000279 IOLocker locker (io_channel->m_output_mutex);
Caroline Tice4a348082011-05-02 20:41:46 +0000280 const char *bytes = (const char *) src;
281
282 if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt)
283 {
284 io_channel->m_prompt_str.append (bytes, src_len);
285 // Log this to make sure the prompt is really what you think it is.
286 if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0)
287 {
288 io_channel->m_expecting_prompt = false;
Caroline Tice388ca8f2011-05-03 20:53:11 +0000289 io_channel->m_refresh_request_pending = false;
Caroline Tice4a348082011-05-02 20:41:46 +0000290 io_channel->OutWrite (io_channel->m_prompt_str.c_str(),
291 io_channel->m_prompt_str.size(), NO_ASYNC);
292 io_channel->m_prompt_str.clear();
293 }
Caroline Tice4a348082011-05-02 20:41:46 +0000294 }
295 else
296 {
297 if (io_channel->m_prompt_str.size() > 0)
298 io_channel->m_prompt_str.clear();
Caroline Tice388ca8f2011-05-03 20:53:11 +0000299 std::string tmp_str (bytes, src_len);
300 if (tmp_str.find (el_prompt (io_channel->m_edit_line)) == 0)
301 io_channel->m_refresh_request_pending = false;
Caroline Tice4a348082011-05-02 20:41:46 +0000302 io_channel->OutWrite (bytes, src_len, NO_ASYNC);
303 }
304}
305
Chris Lattner24943d22010-06-08 16:52:24 +0000306bool
307IOChannel::LibeditGetInput (std::string &new_line)
308{
309 if (m_edit_line != NULL)
310 {
311 int line_len = 0;
Caroline Tice757500e2010-09-29 18:35:42 +0000312
313 // Set boolean indicating whether or not el_gets is trying to get input (i.e. whether or not to attempt
314 // to refresh the prompt after writing data).
315 SetGettingCommand (true);
Caroline Tice4a348082011-05-02 20:41:46 +0000316 m_expecting_prompt = true;
Caroline Tice757500e2010-09-29 18:35:42 +0000317
318 // Call el_gets to prompt the user and read the user's input.
Chris Lattner24943d22010-06-08 16:52:24 +0000319 const char *line = ::el_gets (m_edit_line, &line_len);
Caroline Tice757500e2010-09-29 18:35:42 +0000320
321 // Re-set the boolean indicating whether or not el_gets is trying to get input.
322 SetGettingCommand (false);
323
Chris Lattner24943d22010-06-08 16:52:24 +0000324 if (line)
325 {
326 // strip any newlines off the end of the string...
327 while (line_len > 0 && (line[line_len - 1] == '\n' || line[line_len - 1] == '\r'))
328 --line_len;
329 if (line_len > 0)
330 {
331 ::history (m_history, &m_history_event, H_ENTER, line);
332 new_line.assign (line, line_len); // Omit the newline
333 }
334 else
335 {
336 // Someone just hit ENTER, return the empty string
337 new_line.clear();
338 }
339 // Return true to indicate success even if a string is empty
340 return true;
341 }
342 }
343 // Return false to indicate failure. This can happen when the file handle
344 // is closed (EOF).
345 new_line.clear();
346 return false;
347}
348
349void *
350IOChannel::IOReadThread (void *ptr)
351{
352 IOChannel *myself = static_cast<IOChannel *> (ptr);
353 myself->Run();
354 return NULL;
355}
356
357void
358IOChannel::Run ()
359{
360 SBListener listener("IOChannel::Run");
361 std::string new_line;
362
Greg Clayton63094e02010-06-23 01:19:29 +0000363 SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster());
Chris Lattner24943d22010-06-08 16:52:24 +0000364 listener.StartListeningForEvents (interpreter_broadcaster,
365 SBCommandInterpreter::eBroadcastBitResetPrompt |
366 SBCommandInterpreter::eBroadcastBitThreadShouldExit |
Caroline Tice388ca8f2011-05-03 20:53:11 +0000367 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
Chris Lattner24943d22010-06-08 16:52:24 +0000368
369 listener.StartListeningForEvents (*this,
370 IOChannel::eBroadcastBitThreadShouldExit);
371
372 listener.StartListeningForEvents (*m_driver,
373 Driver::eBroadcastBitReadyForInput |
374 Driver::eBroadcastBitThreadShouldExit);
375
376 // Let anyone know that the IO channel is up and listening and ready for events
377 BroadcastEventByType (eBroadcastBitThreadDidStart);
378 bool done = false;
379 while (!done)
380 {
381 SBEvent event;
382
383 listener.WaitForEvent (UINT32_MAX, event);
384 if (!event.IsValid())
385 continue;
386
387 const uint32_t event_type = event.GetType();
388
389 if (event.GetBroadcaster().IsValid())
390 {
391 if (event.BroadcasterMatchesPtr (m_driver))
392 {
393 if (event_type & Driver::eBroadcastBitReadyForInput)
394 {
395 std::string line;
396
397 if (CommandQueueIsEmpty())
398 {
399 if (LibeditGetInput(line) == false)
400 {
401 // EOF or some other file error occurred
402 done = true;
403 continue;
404 }
405 }
406 else
407 {
408 GetCommandFromQueue (line);
409 }
410
411 // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN'
412 // AND TAKE CARE OF THAT HERE.
413
414 SBEvent line_event(IOChannel::eBroadcastBitHasUserInput,
415 line.c_str(),
416 line.size());
417 BroadcastEvent (line_event);
418 }
419 else if (event_type & Driver::eBroadcastBitThreadShouldExit)
420 {
421 done = true;
Johnny Chenee6e7902011-08-10 22:06:24 +0000422 continue;
Chris Lattner24943d22010-06-08 16:52:24 +0000423 }
424 }
425 else if (event.BroadcasterMatchesRef (interpreter_broadcaster))
426 {
427 switch (event_type)
428 {
429 case SBCommandInterpreter::eBroadcastBitResetPrompt:
430 {
431 const char *new_prompt = SBEvent::GetCStringFromEvent (event);
432 if (new_prompt)
433 g_prompt_map[m_edit_line] = new_prompt;
434 }
435 break;
436
437 case SBCommandInterpreter::eBroadcastBitThreadShouldExit:
438 case SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
439 done = true;
440 break;
441 }
442 }
443 else if (event.BroadcasterMatchesPtr (this))
444 {
445 if (event_type & IOChannel::eBroadcastBitThreadShouldExit)
446 {
447 done = true;
Johnny Chenee6e7902011-08-10 22:06:24 +0000448 continue;
Chris Lattner24943d22010-06-08 16:52:24 +0000449 }
450 }
451 }
452 }
453 BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit);
454 m_driver = NULL;
455 m_read_thread = NULL;
456}
457
458bool
459IOChannel::Start ()
460{
Greg Clayton09c81ef2011-02-08 01:34:25 +0000461 if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner24943d22010-06-08 16:52:24 +0000462 return true;
463
464 m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this,
465 NULL);
466
Greg Clayton09c81ef2011-02-08 01:34:25 +0000467 return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
Chris Lattner24943d22010-06-08 16:52:24 +0000468}
469
470bool
471IOChannel::Stop ()
472{
Greg Clayton09c81ef2011-02-08 01:34:25 +0000473 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner24943d22010-06-08 16:52:24 +0000474 return true;
475
476 BroadcastEventByType (eBroadcastBitThreadShouldExit);
477
478 // Don't call Host::ThreadCancel since el_gets won't respond to this
479 // function call -- the thread will just die and all local variables in
480 // IOChannel::Run() won't get destructed down which is bad since there is
481 // a local listener holding onto broadcasters... To ensure proper shutdown,
482 // a ^D (control-D) sequence (0x04) should be written to other end of the
483 // the "in" file handle that was passed into the contructor as closing the
484 // file handle doesn't seem to make el_gets() exit....
485 return SBHostOS::ThreadJoin (m_read_thread, NULL, NULL);
486}
487
488void
489IOChannel::RefreshPrompt ()
490{
Caroline Tice757500e2010-09-29 18:35:42 +0000491 // If we are not in the middle of getting input from the user, there is no need to
492 // refresh the prompt.
Caroline Tice388ca8f2011-05-03 20:53:11 +0000493 IOLocker locker (m_output_mutex);
Caroline Tice757500e2010-09-29 18:35:42 +0000494 if (! IsGettingCommand())
495 return;
496
Caroline Tice4a348082011-05-02 20:41:46 +0000497 // If we haven't finished writing the prompt, there's no need to refresh it.
498 if (m_expecting_prompt)
499 return;
Caroline Tice757500e2010-09-29 18:35:42 +0000500
Caroline Tice388ca8f2011-05-03 20:53:11 +0000501 if (m_refresh_request_pending)
502 return;
503
Chris Lattner24943d22010-06-08 16:52:24 +0000504 ::el_set (m_edit_line, EL_REFRESH);
Caroline Tice388ca8f2011-05-03 20:53:11 +0000505 m_refresh_request_pending = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000506}
507
508void
Caroline Tice4a348082011-05-02 20:41:46 +0000509IOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous)
Chris Lattner24943d22010-06-08 16:52:24 +0000510{
511 if (len == 0)
512 return;
Caroline Tice757500e2010-09-29 18:35:42 +0000513
Jason Molendabedc6672011-08-12 02:40:17 +0000514 // We're in the process of exiting -- IOChannel::Run() has already completed
515 // and set m_driver to NULL - it is time for us to leave now. We might not
516 // print the final ^D to stdout in this case. We need to do some re-work on
517 // how the I/O streams are managed at some point.
518 if (m_driver == NULL)
519 {
520 return;
521 }
522
Caroline Tice4a348082011-05-02 20:41:46 +0000523 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
524 IOLocker locker (m_output_mutex);
Caroline Ticeb38df1e2011-05-09 23:06:58 +0000525 if (m_driver->EditlineReaderIsTop() && asynchronous)
Caroline Ticec5f0b992011-05-04 16:44:57 +0000526 ::fwrite (undo_prompt_string, 1, 4, m_out_file);
Caroline Tice4a348082011-05-02 20:41:46 +0000527 ::fwrite (buffer, 1, len, m_out_file);
528 if (asynchronous)
529 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
Chris Lattner24943d22010-06-08 16:52:24 +0000530}
531
532void
Caroline Tice4a348082011-05-02 20:41:46 +0000533IOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous)
Chris Lattner24943d22010-06-08 16:52:24 +0000534{
535 if (len == 0)
536 return;
Caroline Tice757500e2010-09-29 18:35:42 +0000537
Caroline Tice4a348082011-05-02 20:41:46 +0000538 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
539 IOLocker locker (m_output_mutex);
540 if (asynchronous)
Caroline Ticec5f0b992011-05-04 16:44:57 +0000541 ::fwrite (undo_prompt_string, 1, 4, m_err_file);
Caroline Tice4a348082011-05-02 20:41:46 +0000542 ::fwrite (buffer, 1, len, m_err_file);
543 if (asynchronous)
544 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
Chris Lattner24943d22010-06-08 16:52:24 +0000545}
546
547void
548IOChannel::AddCommandToQueue (const char *command)
549{
550 m_command_queue.push (std::string(command));
551}
552
553bool
554IOChannel::GetCommandFromQueue (std::string &cmd)
555{
556 if (m_command_queue.empty())
557 return false;
558 cmd.swap(m_command_queue.front());
559 m_command_queue.pop ();
560 return true;
561}
562
563int
564IOChannel::CommandQueueSize () const
565{
566 return m_command_queue.size();
567}
568
569void
570IOChannel::ClearCommandQueue ()
571{
572 while (!m_command_queue.empty())
573 m_command_queue.pop();
574}
575
576bool
577IOChannel::CommandQueueIsEmpty () const
578{
579 return m_command_queue.empty();
580}
Caroline Tice757500e2010-09-29 18:35:42 +0000581
582bool
583IOChannel::IsGettingCommand () const
584{
585 return m_getting_command;
586}
587
588void
589IOChannel::SetGettingCommand (bool new_value)
590{
591 m_getting_command = new_value;
592}
593
Caroline Tice757500e2010-09-29 18:35:42 +0000594IOLocker::IOLocker (pthread_mutex_t &mutex) :
595 m_mutex_ptr (&mutex)
596{
597 if (m_mutex_ptr)
598 ::pthread_mutex_lock (m_mutex_ptr);
599
600}
601
602IOLocker::~IOLocker ()
603{
604 if (m_mutex_ptr)
605 ::pthread_mutex_unlock (m_mutex_ptr);
606}