blob: f14e1b2148f2c5cd04d9c1eead94bece5cd87fa0 [file] [log] [blame]
Chris Lattner30fdc8d2010-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 Friedmana382d472010-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 Lattner30fdc8d2010-06-08 16:52:24 +000022
Eli Friedman07b16272010-06-09 19:11:30 +000023#include <string.h>
24#include <limits.h>
25
Chris Lattner30fdc8d2010-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 Ticefe1bdf22011-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 Lattner30fdc8d2010-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
53unsigned char
54IOChannel::ElCompletionFn (EditLine *e, int ch)
55{
56 IOChannel *io_channel;
57 if (el_get(e, EL_CLIENTDATA, &io_channel) == 0)
58 {
59 return io_channel->HandleCompletion (e, ch);
60 }
61 else
62 {
63 return CC_ERROR;
64 }
65}
66
67unsigned char
68IOChannel::HandleCompletion (EditLine *e, int ch)
69{
70 assert (e == m_edit_line);
71
72 const LineInfo *line_info = el_line(m_edit_line);
73 SBStringList completions;
Greg Claytonc982c762010-07-09 20:39:50 +000074 int page_size = 40;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000075
Greg Clayton66111032010-06-23 01:19:29 +000076 int num_completions = m_driver->GetDebugger().GetCommandInterpreter().HandleCompletion (line_info->buffer,
77 line_info->cursor,
78 line_info->lastchar,
79 0,
80 -1,
81 completions);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082
83 if (num_completions == -1)
84 {
85 el_insertstr (m_edit_line, m_completion_key);
86 return CC_REDISPLAY;
87 }
Jim Inghama5a97eb2011-07-12 03:12:18 +000088 else if (num_completions == -2)
89 {
90 el_deletestr (m_edit_line, line_info->cursor - line_info->buffer);
91 el_insertstr (m_edit_line, completions.GetStringAtIndex(0));
92 return CC_REDISPLAY;
93 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094
95 // If we get a longer match display that first.
96 const char *completion_str = completions.GetStringAtIndex(0);
97 if (completion_str != NULL && *completion_str != '\0')
98 {
99 el_insertstr (m_edit_line, completion_str);
100 return CC_REDISPLAY;
101 }
102
103 if (num_completions > 1)
104 {
105 const char *comment = "\nAvailable completions:";
106
107 int num_elements = num_completions + 1;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000108 OutWrite(comment, strlen (comment), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109 if (num_completions < page_size)
110 {
111 for (int i = 1; i < num_elements; i++)
112 {
Greg Claytonb1320972010-07-14 00:18:15 +0000113 completion_str = completions.GetStringAtIndex(i);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000114 OutWrite("\n\t", 2, NO_ASYNC);
115 OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116 }
Caroline Tice969ed3d2011-05-02 20:41:46 +0000117 OutWrite ("\n", 1, NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000118 }
119 else
120 {
121 int cur_pos = 1;
122 char reply;
123 int got_char;
124 while (cur_pos < num_elements)
125 {
126 int endpoint = cur_pos + page_size;
127 if (endpoint > num_elements)
128 endpoint = num_elements;
129 for (; cur_pos < endpoint; cur_pos++)
130 {
Greg Claytonb1320972010-07-14 00:18:15 +0000131 completion_str = completions.GetStringAtIndex(cur_pos);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000132 OutWrite("\n\t", 2, NO_ASYNC);
133 OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000134 }
135
136 if (cur_pos >= num_elements)
137 {
Caroline Tice969ed3d2011-05-02 20:41:46 +0000138 OutWrite("\n", 1, NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000139 break;
140 }
141
Caroline Tice969ed3d2011-05-02 20:41:46 +0000142 OutWrite("\nMore (Y/n/a): ", strlen ("\nMore (Y/n/a): "), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143 reply = 'n';
144 got_char = el_getc(m_edit_line, &reply);
145 if (got_char == -1 || reply == 'n')
146 break;
147 if (reply == 'a')
148 page_size = num_elements - cur_pos;
149 }
150 }
151
152 }
153
154 if (num_completions == 0)
155 return CC_REFRESH_BEEP;
156 else
157 return CC_REDISPLAY;
158}
159
160IOChannel::IOChannel
161(
Caroline Tice969ed3d2011-05-02 20:41:46 +0000162 FILE *editline_in,
163 FILE *editline_out,
164 FILE *out,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000165 FILE *err,
166 Driver *driver
167) :
168 SBBroadcaster ("IOChannel"),
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000169 m_output_mutex (),
170 m_enter_elgets_time (),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000171 m_driver (driver),
172 m_read_thread (LLDB_INVALID_HOST_THREAD),
173 m_read_thread_should_exit (false),
174 m_out_file (out),
175 m_err_file (err),
Greg Claytonc982c762010-07-09 20:39:50 +0000176 m_command_queue (),
177 m_completion_key ("\t"),
Caroline Tice969ed3d2011-05-02 20:41:46 +0000178 m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), editline_in, editline_out, editline_out)),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000179 m_history (history_init()),
Greg Claytonc982c762010-07-09 20:39:50 +0000180 m_history_event(),
Caroline Tice969ed3d2011-05-02 20:41:46 +0000181 m_getting_command (false),
182 m_expecting_prompt (false),
Caroline Tice86a73f92011-05-03 20:53:11 +0000183 m_prompt_str (),
184 m_refresh_request_pending (false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000185{
186 assert (m_edit_line);
187 ::el_set (m_edit_line, EL_PROMPT, el_prompt);
188 ::el_set (m_edit_line, EL_EDITOR, "emacs");
189 ::el_set (m_edit_line, EL_HIST, history, m_history);
190
Caroline Tice0de8d452011-05-04 21:39:02 +0000191 el_set (m_edit_line, EL_ADDFN, "lldb_complete",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000192 "LLDB completion function",
193 IOChannel::ElCompletionFn);
Caroline Tice0de8d452011-05-04 21:39:02 +0000194 el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
195 el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string
Johnny Chen66b7c592012-05-05 04:44:12 +0000196 el_set (m_edit_line, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197 el_set (m_edit_line, EL_CLIENTDATA, this);
198
Johnny Chen5a4b4b82012-05-07 18:18:08 +0000199 // Source $PWD/.editrc then $HOME/.editrc
200 ::el_source (m_edit_line, NULL);
201
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000202 assert (m_history);
203 ::history (m_history, &m_history_event, H_SETSIZE, 800);
204 ::history (m_history, &m_history_event, H_SETUNIQUE, 1);
205 // Load history
206 HistorySaveLoad (false);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000207
208 // Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere
209 // with each other when writing.
210
211 int error;
212 ::pthread_mutexattr_t attr;
213 error = ::pthread_mutexattr_init (&attr);
214 assert (error == 0);
215 error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
216 assert (error == 0);
217 error = ::pthread_mutex_init (&m_output_mutex, &attr);
218 assert (error == 0);
219 error = ::pthread_mutexattr_destroy (&attr);
220 assert (error == 0);
221
222 // Initialize time that ::el_gets was last called.
223
224 m_enter_elgets_time.tv_sec = 0;
225 m_enter_elgets_time.tv_usec = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226}
227
228IOChannel::~IOChannel ()
229{
230 // Save history
231 HistorySaveLoad (true);
232
233 if (m_history != NULL)
234 {
235 ::history_end (m_history);
236 m_history = NULL;
237 }
238
239 if (m_edit_line != NULL)
240 {
241 ::el_end (m_edit_line);
242 m_edit_line = NULL;
243 }
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000244
245 ::pthread_mutex_destroy (&m_output_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000246}
247
248void
249IOChannel::HistorySaveLoad (bool save)
250{
251 if (m_history != NULL)
252 {
253 char history_path[PATH_MAX];
Johnny Chen23fd10c2010-08-27 22:35:26 +0000254 ::snprintf (history_path, sizeof(history_path), "~/.%s-history", SBHostOS::GetProgramFileSpec().GetFilename());
Greg Claytonc982c762010-07-09 20:39:50 +0000255 if ((size_t)SBFileSpec::ResolvePath (history_path, history_path, sizeof(history_path)) < sizeof(history_path) - 1)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256 {
257 const char *path_ptr = history_path;
258 if (save)
259 ::history (m_history, &m_history_event, H_SAVE, path_ptr);
260 else
261 ::history (m_history, &m_history_event, H_LOAD, path_ptr);
262 }
263 }
264}
265
Caroline Tice969ed3d2011-05-02 20:41:46 +0000266void
267IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
268{
269 // Make this a member variable.
270 // static std::string prompt_str;
271 IOChannel *io_channel = (IOChannel *) baton;
Caroline Tice86a73f92011-05-03 20:53:11 +0000272 IOLocker locker (io_channel->m_output_mutex);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000273 const char *bytes = (const char *) src;
274
275 if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt)
276 {
277 io_channel->m_prompt_str.append (bytes, src_len);
278 // Log this to make sure the prompt is really what you think it is.
279 if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0)
280 {
281 io_channel->m_expecting_prompt = false;
Caroline Tice86a73f92011-05-03 20:53:11 +0000282 io_channel->m_refresh_request_pending = false;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000283 io_channel->OutWrite (io_channel->m_prompt_str.c_str(),
284 io_channel->m_prompt_str.size(), NO_ASYNC);
285 io_channel->m_prompt_str.clear();
286 }
Caroline Tice969ed3d2011-05-02 20:41:46 +0000287 }
288 else
289 {
290 if (io_channel->m_prompt_str.size() > 0)
291 io_channel->m_prompt_str.clear();
Caroline Tice86a73f92011-05-03 20:53:11 +0000292 std::string tmp_str (bytes, src_len);
293 if (tmp_str.find (el_prompt (io_channel->m_edit_line)) == 0)
294 io_channel->m_refresh_request_pending = false;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000295 io_channel->OutWrite (bytes, src_len, NO_ASYNC);
296 }
297}
298
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000299bool
300IOChannel::LibeditGetInput (std::string &new_line)
301{
302 if (m_edit_line != NULL)
303 {
304 int line_len = 0;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000305
306 // Set boolean indicating whether or not el_gets is trying to get input (i.e. whether or not to attempt
307 // to refresh the prompt after writing data).
308 SetGettingCommand (true);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000309 m_expecting_prompt = true;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000310
311 // Call el_gets to prompt the user and read the user's input.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000312 const char *line = ::el_gets (m_edit_line, &line_len);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000313
314 // Re-set the boolean indicating whether or not el_gets is trying to get input.
315 SetGettingCommand (false);
316
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000317 if (line)
318 {
319 // strip any newlines off the end of the string...
320 while (line_len > 0 && (line[line_len - 1] == '\n' || line[line_len - 1] == '\r'))
321 --line_len;
322 if (line_len > 0)
323 {
324 ::history (m_history, &m_history_event, H_ENTER, line);
325 new_line.assign (line, line_len); // Omit the newline
326 }
327 else
328 {
329 // Someone just hit ENTER, return the empty string
330 new_line.clear();
331 }
332 // Return true to indicate success even if a string is empty
333 return true;
334 }
335 }
336 // Return false to indicate failure. This can happen when the file handle
337 // is closed (EOF).
338 new_line.clear();
339 return false;
340}
341
342void *
343IOChannel::IOReadThread (void *ptr)
344{
345 IOChannel *myself = static_cast<IOChannel *> (ptr);
346 myself->Run();
347 return NULL;
348}
349
350void
351IOChannel::Run ()
352{
353 SBListener listener("IOChannel::Run");
354 std::string new_line;
355
Greg Clayton66111032010-06-23 01:19:29 +0000356 SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000357 listener.StartListeningForEvents (interpreter_broadcaster,
358 SBCommandInterpreter::eBroadcastBitResetPrompt |
359 SBCommandInterpreter::eBroadcastBitThreadShouldExit |
Caroline Tice86a73f92011-05-03 20:53:11 +0000360 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000361
362 listener.StartListeningForEvents (*this,
363 IOChannel::eBroadcastBitThreadShouldExit);
364
365 listener.StartListeningForEvents (*m_driver,
366 Driver::eBroadcastBitReadyForInput |
367 Driver::eBroadcastBitThreadShouldExit);
368
369 // Let anyone know that the IO channel is up and listening and ready for events
370 BroadcastEventByType (eBroadcastBitThreadDidStart);
371 bool done = false;
372 while (!done)
373 {
374 SBEvent event;
375
376 listener.WaitForEvent (UINT32_MAX, event);
377 if (!event.IsValid())
378 continue;
379
380 const uint32_t event_type = event.GetType();
381
382 if (event.GetBroadcaster().IsValid())
383 {
384 if (event.BroadcasterMatchesPtr (m_driver))
385 {
386 if (event_type & Driver::eBroadcastBitReadyForInput)
387 {
388 std::string line;
389
390 if (CommandQueueIsEmpty())
391 {
392 if (LibeditGetInput(line) == false)
393 {
394 // EOF or some other file error occurred
395 done = true;
396 continue;
397 }
398 }
399 else
400 {
401 GetCommandFromQueue (line);
402 }
403
404 // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN'
405 // AND TAKE CARE OF THAT HERE.
406
407 SBEvent line_event(IOChannel::eBroadcastBitHasUserInput,
408 line.c_str(),
409 line.size());
410 BroadcastEvent (line_event);
411 }
412 else if (event_type & Driver::eBroadcastBitThreadShouldExit)
413 {
414 done = true;
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000415 continue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000416 }
417 }
418 else if (event.BroadcasterMatchesRef (interpreter_broadcaster))
419 {
420 switch (event_type)
421 {
422 case SBCommandInterpreter::eBroadcastBitResetPrompt:
423 {
424 const char *new_prompt = SBEvent::GetCStringFromEvent (event);
425 if (new_prompt)
426 g_prompt_map[m_edit_line] = new_prompt;
427 }
428 break;
429
430 case SBCommandInterpreter::eBroadcastBitThreadShouldExit:
431 case SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
432 done = true;
433 break;
434 }
435 }
436 else if (event.BroadcasterMatchesPtr (this))
437 {
438 if (event_type & IOChannel::eBroadcastBitThreadShouldExit)
439 {
440 done = true;
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000441 continue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000442 }
443 }
444 }
445 }
446 BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit);
447 m_driver = NULL;
448 m_read_thread = NULL;
449}
450
451bool
452IOChannel::Start ()
453{
Greg Clayton2da6d492011-02-08 01:34:25 +0000454 if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000455 return true;
456
457 m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this,
458 NULL);
459
Greg Clayton2da6d492011-02-08 01:34:25 +0000460 return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000461}
462
463bool
464IOChannel::Stop ()
465{
Greg Clayton2da6d492011-02-08 01:34:25 +0000466 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000467 return true;
468
469 BroadcastEventByType (eBroadcastBitThreadShouldExit);
470
471 // Don't call Host::ThreadCancel since el_gets won't respond to this
472 // function call -- the thread will just die and all local variables in
473 // IOChannel::Run() won't get destructed down which is bad since there is
474 // a local listener holding onto broadcasters... To ensure proper shutdown,
475 // a ^D (control-D) sequence (0x04) should be written to other end of the
476 // the "in" file handle that was passed into the contructor as closing the
477 // file handle doesn't seem to make el_gets() exit....
478 return SBHostOS::ThreadJoin (m_read_thread, NULL, NULL);
479}
480
481void
482IOChannel::RefreshPrompt ()
483{
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000484 // If we are not in the middle of getting input from the user, there is no need to
485 // refresh the prompt.
Caroline Tice86a73f92011-05-03 20:53:11 +0000486 IOLocker locker (m_output_mutex);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000487 if (! IsGettingCommand())
488 return;
489
Caroline Tice969ed3d2011-05-02 20:41:46 +0000490 // If we haven't finished writing the prompt, there's no need to refresh it.
491 if (m_expecting_prompt)
492 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000493
Caroline Tice86a73f92011-05-03 20:53:11 +0000494 if (m_refresh_request_pending)
495 return;
496
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000497 ::el_set (m_edit_line, EL_REFRESH);
Caroline Tice86a73f92011-05-03 20:53:11 +0000498 m_refresh_request_pending = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000499}
500
501void
Caroline Tice969ed3d2011-05-02 20:41:46 +0000502IOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000503{
504 if (len == 0)
505 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000506
Jason Molenda7efc7e92011-08-12 02:40:17 +0000507 // We're in the process of exiting -- IOChannel::Run() has already completed
508 // and set m_driver to NULL - it is time for us to leave now. We might not
509 // print the final ^D to stdout in this case. We need to do some re-work on
510 // how the I/O streams are managed at some point.
511 if (m_driver == NULL)
512 {
513 return;
514 }
515
Caroline Tice969ed3d2011-05-02 20:41:46 +0000516 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
517 IOLocker locker (m_output_mutex);
Caroline Tice9088b062011-05-09 23:06:58 +0000518 if (m_driver->EditlineReaderIsTop() && asynchronous)
Caroline Ticefe1bdf22011-05-04 16:44:57 +0000519 ::fwrite (undo_prompt_string, 1, 4, m_out_file);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000520 ::fwrite (buffer, 1, len, m_out_file);
521 if (asynchronous)
522 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000523}
524
525void
Caroline Tice969ed3d2011-05-02 20:41:46 +0000526IOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000527{
528 if (len == 0)
529 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000530
Caroline Tice969ed3d2011-05-02 20:41:46 +0000531 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
532 IOLocker locker (m_output_mutex);
533 if (asynchronous)
Caroline Ticefe1bdf22011-05-04 16:44:57 +0000534 ::fwrite (undo_prompt_string, 1, 4, m_err_file);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000535 ::fwrite (buffer, 1, len, m_err_file);
536 if (asynchronous)
537 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000538}
539
540void
541IOChannel::AddCommandToQueue (const char *command)
542{
543 m_command_queue.push (std::string(command));
544}
545
546bool
547IOChannel::GetCommandFromQueue (std::string &cmd)
548{
549 if (m_command_queue.empty())
550 return false;
551 cmd.swap(m_command_queue.front());
552 m_command_queue.pop ();
553 return true;
554}
555
556int
557IOChannel::CommandQueueSize () const
558{
559 return m_command_queue.size();
560}
561
562void
563IOChannel::ClearCommandQueue ()
564{
565 while (!m_command_queue.empty())
566 m_command_queue.pop();
567}
568
569bool
570IOChannel::CommandQueueIsEmpty () const
571{
572 return m_command_queue.empty();
573}
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000574
575bool
576IOChannel::IsGettingCommand () const
577{
578 return m_getting_command;
579}
580
581void
582IOChannel::SetGettingCommand (bool new_value)
583{
584 m_getting_command = new_value;
585}
586
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000587IOLocker::IOLocker (pthread_mutex_t &mutex) :
588 m_mutex_ptr (&mutex)
589{
590 if (m_mutex_ptr)
591 ::pthread_mutex_lock (m_mutex_ptr);
592
593}
594
595IOLocker::~IOLocker ()
596{
597 if (m_mutex_ptr)
598 ::pthread_mutex_unlock (m_mutex_ptr);
599}