blob: b64c8f510f39cbcf9b055359d26613273acbeda6 [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
191 // Source $PWD/.editrc then $HOME/.editrc
192 ::el_source (m_edit_line, NULL);
193
Caroline Tice0de8d452011-05-04 21:39:02 +0000194 el_set (m_edit_line, EL_ADDFN, "lldb_complete",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000195 "LLDB completion function",
196 IOChannel::ElCompletionFn);
Caroline Tice0de8d452011-05-04 21:39:02 +0000197 el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
198 el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000199 el_set (m_edit_line, EL_CLIENTDATA, this);
200
201 assert (m_history);
202 ::history (m_history, &m_history_event, H_SETSIZE, 800);
203 ::history (m_history, &m_history_event, H_SETUNIQUE, 1);
204 // Load history
205 HistorySaveLoad (false);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000206
207 // Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere
208 // with each other when writing.
209
210 int error;
211 ::pthread_mutexattr_t attr;
212 error = ::pthread_mutexattr_init (&attr);
213 assert (error == 0);
214 error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
215 assert (error == 0);
216 error = ::pthread_mutex_init (&m_output_mutex, &attr);
217 assert (error == 0);
218 error = ::pthread_mutexattr_destroy (&attr);
219 assert (error == 0);
220
221 // Initialize time that ::el_gets was last called.
222
223 m_enter_elgets_time.tv_sec = 0;
224 m_enter_elgets_time.tv_usec = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000225}
226
227IOChannel::~IOChannel ()
228{
229 // Save history
230 HistorySaveLoad (true);
231
232 if (m_history != NULL)
233 {
234 ::history_end (m_history);
235 m_history = NULL;
236 }
237
238 if (m_edit_line != NULL)
239 {
240 ::el_end (m_edit_line);
241 m_edit_line = NULL;
242 }
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000243
244 ::pthread_mutex_destroy (&m_output_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000245}
246
247void
248IOChannel::HistorySaveLoad (bool save)
249{
250 if (m_history != NULL)
251 {
252 char history_path[PATH_MAX];
Johnny Chen23fd10c2010-08-27 22:35:26 +0000253 ::snprintf (history_path, sizeof(history_path), "~/.%s-history", SBHostOS::GetProgramFileSpec().GetFilename());
Greg Claytonc982c762010-07-09 20:39:50 +0000254 if ((size_t)SBFileSpec::ResolvePath (history_path, history_path, sizeof(history_path)) < sizeof(history_path) - 1)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000255 {
256 const char *path_ptr = history_path;
257 if (save)
258 ::history (m_history, &m_history_event, H_SAVE, path_ptr);
259 else
260 ::history (m_history, &m_history_event, H_LOAD, path_ptr);
261 }
262 }
263}
264
Caroline Tice969ed3d2011-05-02 20:41:46 +0000265void
266IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
267{
268 // Make this a member variable.
269 // static std::string prompt_str;
270 IOChannel *io_channel = (IOChannel *) baton;
Caroline Tice86a73f92011-05-03 20:53:11 +0000271 IOLocker locker (io_channel->m_output_mutex);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000272 const char *bytes = (const char *) src;
273
274 if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt)
275 {
276 io_channel->m_prompt_str.append (bytes, src_len);
277 // Log this to make sure the prompt is really what you think it is.
278 if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0)
279 {
280 io_channel->m_expecting_prompt = false;
Caroline Tice86a73f92011-05-03 20:53:11 +0000281 io_channel->m_refresh_request_pending = false;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000282 io_channel->OutWrite (io_channel->m_prompt_str.c_str(),
283 io_channel->m_prompt_str.size(), NO_ASYNC);
284 io_channel->m_prompt_str.clear();
285 }
Caroline Tice969ed3d2011-05-02 20:41:46 +0000286 }
287 else
288 {
289 if (io_channel->m_prompt_str.size() > 0)
290 io_channel->m_prompt_str.clear();
Caroline Tice86a73f92011-05-03 20:53:11 +0000291 std::string tmp_str (bytes, src_len);
292 if (tmp_str.find (el_prompt (io_channel->m_edit_line)) == 0)
293 io_channel->m_refresh_request_pending = false;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000294 io_channel->OutWrite (bytes, src_len, NO_ASYNC);
295 }
296}
297
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000298bool
299IOChannel::LibeditGetInput (std::string &new_line)
300{
301 if (m_edit_line != NULL)
302 {
303 int line_len = 0;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000304
305 // Set boolean indicating whether or not el_gets is trying to get input (i.e. whether or not to attempt
306 // to refresh the prompt after writing data).
307 SetGettingCommand (true);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000308 m_expecting_prompt = true;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000309
310 // Call el_gets to prompt the user and read the user's input.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000311 const char *line = ::el_gets (m_edit_line, &line_len);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000312
313 // Re-set the boolean indicating whether or not el_gets is trying to get input.
314 SetGettingCommand (false);
315
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000316 if (line)
317 {
318 // strip any newlines off the end of the string...
319 while (line_len > 0 && (line[line_len - 1] == '\n' || line[line_len - 1] == '\r'))
320 --line_len;
321 if (line_len > 0)
322 {
323 ::history (m_history, &m_history_event, H_ENTER, line);
324 new_line.assign (line, line_len); // Omit the newline
325 }
326 else
327 {
328 // Someone just hit ENTER, return the empty string
329 new_line.clear();
330 }
331 // Return true to indicate success even if a string is empty
332 return true;
333 }
334 }
335 // Return false to indicate failure. This can happen when the file handle
336 // is closed (EOF).
337 new_line.clear();
338 return false;
339}
340
341void *
342IOChannel::IOReadThread (void *ptr)
343{
344 IOChannel *myself = static_cast<IOChannel *> (ptr);
345 myself->Run();
346 return NULL;
347}
348
349void
350IOChannel::Run ()
351{
352 SBListener listener("IOChannel::Run");
353 std::string new_line;
354
Greg Clayton66111032010-06-23 01:19:29 +0000355 SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356 listener.StartListeningForEvents (interpreter_broadcaster,
357 SBCommandInterpreter::eBroadcastBitResetPrompt |
358 SBCommandInterpreter::eBroadcastBitThreadShouldExit |
Caroline Tice86a73f92011-05-03 20:53:11 +0000359 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000360
361 listener.StartListeningForEvents (*this,
362 IOChannel::eBroadcastBitThreadShouldExit);
363
364 listener.StartListeningForEvents (*m_driver,
365 Driver::eBroadcastBitReadyForInput |
366 Driver::eBroadcastBitThreadShouldExit);
367
368 // Let anyone know that the IO channel is up and listening and ready for events
369 BroadcastEventByType (eBroadcastBitThreadDidStart);
370 bool done = false;
371 while (!done)
372 {
373 SBEvent event;
374
375 listener.WaitForEvent (UINT32_MAX, event);
376 if (!event.IsValid())
377 continue;
378
379 const uint32_t event_type = event.GetType();
380
381 if (event.GetBroadcaster().IsValid())
382 {
383 if (event.BroadcasterMatchesPtr (m_driver))
384 {
385 if (event_type & Driver::eBroadcastBitReadyForInput)
386 {
387 std::string line;
388
389 if (CommandQueueIsEmpty())
390 {
391 if (LibeditGetInput(line) == false)
392 {
393 // EOF or some other file error occurred
394 done = true;
395 continue;
396 }
397 }
398 else
399 {
400 GetCommandFromQueue (line);
401 }
402
403 // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN'
404 // AND TAKE CARE OF THAT HERE.
405
406 SBEvent line_event(IOChannel::eBroadcastBitHasUserInput,
407 line.c_str(),
408 line.size());
409 BroadcastEvent (line_event);
410 }
411 else if (event_type & Driver::eBroadcastBitThreadShouldExit)
412 {
413 done = true;
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000414 continue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000415 }
416 }
417 else if (event.BroadcasterMatchesRef (interpreter_broadcaster))
418 {
419 switch (event_type)
420 {
421 case SBCommandInterpreter::eBroadcastBitResetPrompt:
422 {
423 const char *new_prompt = SBEvent::GetCStringFromEvent (event);
424 if (new_prompt)
425 g_prompt_map[m_edit_line] = new_prompt;
426 }
427 break;
428
429 case SBCommandInterpreter::eBroadcastBitThreadShouldExit:
430 case SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
431 done = true;
432 break;
433 }
434 }
435 else if (event.BroadcasterMatchesPtr (this))
436 {
437 if (event_type & IOChannel::eBroadcastBitThreadShouldExit)
438 {
439 done = true;
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000440 continue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000441 }
442 }
443 }
444 }
445 BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit);
446 m_driver = NULL;
447 m_read_thread = NULL;
448}
449
450bool
451IOChannel::Start ()
452{
Greg Clayton2da6d492011-02-08 01:34:25 +0000453 if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000454 return true;
455
456 m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this,
457 NULL);
458
Greg Clayton2da6d492011-02-08 01:34:25 +0000459 return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000460}
461
462bool
463IOChannel::Stop ()
464{
Greg Clayton2da6d492011-02-08 01:34:25 +0000465 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000466 return true;
467
468 BroadcastEventByType (eBroadcastBitThreadShouldExit);
469
470 // Don't call Host::ThreadCancel since el_gets won't respond to this
471 // function call -- the thread will just die and all local variables in
472 // IOChannel::Run() won't get destructed down which is bad since there is
473 // a local listener holding onto broadcasters... To ensure proper shutdown,
474 // a ^D (control-D) sequence (0x04) should be written to other end of the
475 // the "in" file handle that was passed into the contructor as closing the
476 // file handle doesn't seem to make el_gets() exit....
477 return SBHostOS::ThreadJoin (m_read_thread, NULL, NULL);
478}
479
480void
481IOChannel::RefreshPrompt ()
482{
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000483 // If we are not in the middle of getting input from the user, there is no need to
484 // refresh the prompt.
Caroline Tice86a73f92011-05-03 20:53:11 +0000485 IOLocker locker (m_output_mutex);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000486 if (! IsGettingCommand())
487 return;
488
Caroline Tice969ed3d2011-05-02 20:41:46 +0000489 // If we haven't finished writing the prompt, there's no need to refresh it.
490 if (m_expecting_prompt)
491 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000492
Caroline Tice86a73f92011-05-03 20:53:11 +0000493 if (m_refresh_request_pending)
494 return;
495
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000496 ::el_set (m_edit_line, EL_REFRESH);
Caroline Tice86a73f92011-05-03 20:53:11 +0000497 m_refresh_request_pending = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000498}
499
500void
Caroline Tice969ed3d2011-05-02 20:41:46 +0000501IOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000502{
503 if (len == 0)
504 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000505
Jason Molenda7efc7e92011-08-12 02:40:17 +0000506 // We're in the process of exiting -- IOChannel::Run() has already completed
507 // and set m_driver to NULL - it is time for us to leave now. We might not
508 // print the final ^D to stdout in this case. We need to do some re-work on
509 // how the I/O streams are managed at some point.
510 if (m_driver == NULL)
511 {
512 return;
513 }
514
Caroline Tice969ed3d2011-05-02 20:41:46 +0000515 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
516 IOLocker locker (m_output_mutex);
Caroline Tice9088b062011-05-09 23:06:58 +0000517 if (m_driver->EditlineReaderIsTop() && asynchronous)
Caroline Ticefe1bdf22011-05-04 16:44:57 +0000518 ::fwrite (undo_prompt_string, 1, 4, m_out_file);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000519 ::fwrite (buffer, 1, len, m_out_file);
520 if (asynchronous)
521 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000522}
523
524void
Caroline Tice969ed3d2011-05-02 20:41:46 +0000525IOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000526{
527 if (len == 0)
528 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000529
Caroline Tice969ed3d2011-05-02 20:41:46 +0000530 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
531 IOLocker locker (m_output_mutex);
532 if (asynchronous)
Caroline Ticefe1bdf22011-05-04 16:44:57 +0000533 ::fwrite (undo_prompt_string, 1, 4, m_err_file);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000534 ::fwrite (buffer, 1, len, m_err_file);
535 if (asynchronous)
536 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000537}
538
539void
540IOChannel::AddCommandToQueue (const char *command)
541{
542 m_command_queue.push (std::string(command));
543}
544
545bool
546IOChannel::GetCommandFromQueue (std::string &cmd)
547{
548 if (m_command_queue.empty())
549 return false;
550 cmd.swap(m_command_queue.front());
551 m_command_queue.pop ();
552 return true;
553}
554
555int
556IOChannel::CommandQueueSize () const
557{
558 return m_command_queue.size();
559}
560
561void
562IOChannel::ClearCommandQueue ()
563{
564 while (!m_command_queue.empty())
565 m_command_queue.pop();
566}
567
568bool
569IOChannel::CommandQueueIsEmpty () const
570{
571 return m_command_queue.empty();
572}
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000573
574bool
575IOChannel::IsGettingCommand () const
576{
577 return m_getting_command;
578}
579
580void
581IOChannel::SetGettingCommand (bool new_value)
582{
583 m_getting_command = new_value;
584}
585
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000586IOLocker::IOLocker (pthread_mutex_t &mutex) :
587 m_mutex_ptr (&mutex)
588{
589 if (m_mutex_ptr)
590 ::pthread_mutex_lock (m_mutex_ptr);
591
592}
593
594IOLocker::~IOLocker ()
595{
596 if (m_mutex_ptr)
597 ::pthread_mutex_unlock (m_mutex_ptr);
598}