blob: 92bd3720fc73036d0a74e5e23e42499a8d688e6b [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
Jim Ingham6d10c172012-06-01 01:03:40 +000053bool
54IOChannel::EditLineHasCharacters ()
55{
56 const LineInfo *line_info = el_line(m_edit_line);
57 if (line_info)
Jim Inghamcfc09352012-07-27 23:57:19 +000058 {
59 // Sometimes we get called after the user has submitted the line, but before editline has
60 // cleared the buffer. In that case the cursor will be pointing at the newline. That's
61 // equivalent to having no characters on the line, since it has already been submitted.
62 if (*line_info->cursor == '\n')
63 return false;
64 else
65 return line_info->cursor != line_info->buffer;
66 }
Jim Ingham6d10c172012-06-01 01:03:40 +000067 else
68 return false;
69}
70
71
Johnny Chenfd02a892012-05-09 21:03:07 +000072void
73IOChannel::EraseCharsBeforeCursor ()
74{
75 const LineInfo *line_info = el_line(m_edit_line);
76 el_deletestr(m_edit_line, line_info->cursor - line_info->buffer);
77}
78
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079unsigned char
80IOChannel::ElCompletionFn (EditLine *e, int ch)
81{
82 IOChannel *io_channel;
83 if (el_get(e, EL_CLIENTDATA, &io_channel) == 0)
84 {
85 return io_channel->HandleCompletion (e, ch);
86 }
87 else
88 {
89 return CC_ERROR;
90 }
91}
92
93unsigned char
94IOChannel::HandleCompletion (EditLine *e, int ch)
95{
96 assert (e == m_edit_line);
97
98 const LineInfo *line_info = el_line(m_edit_line);
99 SBStringList completions;
Greg Claytonc982c762010-07-09 20:39:50 +0000100 int page_size = 40;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101
Greg Clayton66111032010-06-23 01:19:29 +0000102 int num_completions = m_driver->GetDebugger().GetCommandInterpreter().HandleCompletion (line_info->buffer,
103 line_info->cursor,
104 line_info->lastchar,
105 0,
106 -1,
107 completions);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000108
109 if (num_completions == -1)
110 {
111 el_insertstr (m_edit_line, m_completion_key);
112 return CC_REDISPLAY;
113 }
Jim Inghama5a97eb2011-07-12 03:12:18 +0000114 else if (num_completions == -2)
115 {
116 el_deletestr (m_edit_line, line_info->cursor - line_info->buffer);
117 el_insertstr (m_edit_line, completions.GetStringAtIndex(0));
118 return CC_REDISPLAY;
119 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120
121 // If we get a longer match display that first.
122 const char *completion_str = completions.GetStringAtIndex(0);
123 if (completion_str != NULL && *completion_str != '\0')
124 {
125 el_insertstr (m_edit_line, completion_str);
126 return CC_REDISPLAY;
127 }
128
129 if (num_completions > 1)
130 {
131 const char *comment = "\nAvailable completions:";
132
133 int num_elements = num_completions + 1;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000134 OutWrite(comment, strlen (comment), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000135 if (num_completions < page_size)
136 {
137 for (int i = 1; i < num_elements; i++)
138 {
Greg Claytonb1320972010-07-14 00:18:15 +0000139 completion_str = completions.GetStringAtIndex(i);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000140 OutWrite("\n\t", 2, NO_ASYNC);
141 OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000142 }
Caroline Tice969ed3d2011-05-02 20:41:46 +0000143 OutWrite ("\n", 1, NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000144 }
145 else
146 {
147 int cur_pos = 1;
148 char reply;
149 int got_char;
150 while (cur_pos < num_elements)
151 {
152 int endpoint = cur_pos + page_size;
153 if (endpoint > num_elements)
154 endpoint = num_elements;
155 for (; cur_pos < endpoint; cur_pos++)
156 {
Greg Claytonb1320972010-07-14 00:18:15 +0000157 completion_str = completions.GetStringAtIndex(cur_pos);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000158 OutWrite("\n\t", 2, NO_ASYNC);
159 OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160 }
161
162 if (cur_pos >= num_elements)
163 {
Caroline Tice969ed3d2011-05-02 20:41:46 +0000164 OutWrite("\n", 1, NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000165 break;
166 }
167
Caroline Tice969ed3d2011-05-02 20:41:46 +0000168 OutWrite("\nMore (Y/n/a): ", strlen ("\nMore (Y/n/a): "), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169 reply = 'n';
170 got_char = el_getc(m_edit_line, &reply);
171 if (got_char == -1 || reply == 'n')
172 break;
173 if (reply == 'a')
174 page_size = num_elements - cur_pos;
175 }
176 }
177
178 }
179
180 if (num_completions == 0)
181 return CC_REFRESH_BEEP;
182 else
183 return CC_REDISPLAY;
184}
185
186IOChannel::IOChannel
187(
Caroline Tice969ed3d2011-05-02 20:41:46 +0000188 FILE *editline_in,
189 FILE *editline_out,
190 FILE *out,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191 FILE *err,
192 Driver *driver
193) :
194 SBBroadcaster ("IOChannel"),
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000195 m_output_mutex (),
196 m_enter_elgets_time (),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197 m_driver (driver),
198 m_read_thread (LLDB_INVALID_HOST_THREAD),
199 m_read_thread_should_exit (false),
200 m_out_file (out),
201 m_err_file (err),
Greg Claytonc982c762010-07-09 20:39:50 +0000202 m_command_queue (),
203 m_completion_key ("\t"),
Caroline Tice969ed3d2011-05-02 20:41:46 +0000204 m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), editline_in, editline_out, editline_out)),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205 m_history (history_init()),
Greg Claytonc982c762010-07-09 20:39:50 +0000206 m_history_event(),
Caroline Tice969ed3d2011-05-02 20:41:46 +0000207 m_getting_command (false),
208 m_expecting_prompt (false),
Caroline Tice86a73f92011-05-03 20:53:11 +0000209 m_prompt_str (),
210 m_refresh_request_pending (false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000211{
212 assert (m_edit_line);
213 ::el_set (m_edit_line, EL_PROMPT, el_prompt);
214 ::el_set (m_edit_line, EL_EDITOR, "emacs");
215 ::el_set (m_edit_line, EL_HIST, history, m_history);
216
Caroline Tice0de8d452011-05-04 21:39:02 +0000217 el_set (m_edit_line, EL_ADDFN, "lldb_complete",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000218 "LLDB completion function",
219 IOChannel::ElCompletionFn);
Caroline Tice0de8d452011-05-04 21:39:02 +0000220 el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
221 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 +0000222 el_set (m_edit_line, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does.
Sean Callanan9690a412012-07-11 22:55:32 +0000223 el_set (m_edit_line, EL_BIND, "\e[3~", "ed-delete-next-char", NULL); // Fix the delete key.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000224 el_set (m_edit_line, EL_CLIENTDATA, this);
225
Johnny Chen5a4b4b82012-05-07 18:18:08 +0000226 // Source $PWD/.editrc then $HOME/.editrc
227 ::el_source (m_edit_line, NULL);
228
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000229 assert (m_history);
230 ::history (m_history, &m_history_event, H_SETSIZE, 800);
231 ::history (m_history, &m_history_event, H_SETUNIQUE, 1);
232 // Load history
233 HistorySaveLoad (false);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000234
235 // Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere
236 // with each other when writing.
237
238 int error;
239 ::pthread_mutexattr_t attr;
240 error = ::pthread_mutexattr_init (&attr);
241 assert (error == 0);
242 error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
243 assert (error == 0);
244 error = ::pthread_mutex_init (&m_output_mutex, &attr);
245 assert (error == 0);
246 error = ::pthread_mutexattr_destroy (&attr);
247 assert (error == 0);
248
249 // Initialize time that ::el_gets was last called.
250
251 m_enter_elgets_time.tv_sec = 0;
252 m_enter_elgets_time.tv_usec = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000253}
254
255IOChannel::~IOChannel ()
256{
257 // Save history
258 HistorySaveLoad (true);
259
260 if (m_history != NULL)
261 {
262 ::history_end (m_history);
263 m_history = NULL;
264 }
265
266 if (m_edit_line != NULL)
267 {
268 ::el_end (m_edit_line);
269 m_edit_line = NULL;
270 }
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000271
272 ::pthread_mutex_destroy (&m_output_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000273}
274
275void
276IOChannel::HistorySaveLoad (bool save)
277{
278 if (m_history != NULL)
279 {
280 char history_path[PATH_MAX];
Johnny Chen23fd10c2010-08-27 22:35:26 +0000281 ::snprintf (history_path, sizeof(history_path), "~/.%s-history", SBHostOS::GetProgramFileSpec().GetFilename());
Greg Claytonc982c762010-07-09 20:39:50 +0000282 if ((size_t)SBFileSpec::ResolvePath (history_path, history_path, sizeof(history_path)) < sizeof(history_path) - 1)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000283 {
284 const char *path_ptr = history_path;
285 if (save)
286 ::history (m_history, &m_history_event, H_SAVE, path_ptr);
287 else
288 ::history (m_history, &m_history_event, H_LOAD, path_ptr);
289 }
290 }
291}
292
Caroline Tice969ed3d2011-05-02 20:41:46 +0000293void
294IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
295{
296 // Make this a member variable.
297 // static std::string prompt_str;
298 IOChannel *io_channel = (IOChannel *) baton;
Caroline Tice86a73f92011-05-03 20:53:11 +0000299 IOLocker locker (io_channel->m_output_mutex);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000300 const char *bytes = (const char *) src;
301
302 if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt)
303 {
304 io_channel->m_prompt_str.append (bytes, src_len);
305 // Log this to make sure the prompt is really what you think it is.
306 if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0)
307 {
308 io_channel->m_expecting_prompt = false;
Caroline Tice86a73f92011-05-03 20:53:11 +0000309 io_channel->m_refresh_request_pending = false;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000310 io_channel->OutWrite (io_channel->m_prompt_str.c_str(),
311 io_channel->m_prompt_str.size(), NO_ASYNC);
312 io_channel->m_prompt_str.clear();
313 }
Caroline Tice969ed3d2011-05-02 20:41:46 +0000314 }
315 else
316 {
317 if (io_channel->m_prompt_str.size() > 0)
318 io_channel->m_prompt_str.clear();
Caroline Tice86a73f92011-05-03 20:53:11 +0000319 std::string tmp_str (bytes, src_len);
320 if (tmp_str.find (el_prompt (io_channel->m_edit_line)) == 0)
321 io_channel->m_refresh_request_pending = false;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000322 io_channel->OutWrite (bytes, src_len, NO_ASYNC);
323 }
324}
325
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326bool
327IOChannel::LibeditGetInput (std::string &new_line)
328{
329 if (m_edit_line != NULL)
330 {
331 int line_len = 0;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000332
333 // Set boolean indicating whether or not el_gets is trying to get input (i.e. whether or not to attempt
334 // to refresh the prompt after writing data).
335 SetGettingCommand (true);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000336 m_expecting_prompt = true;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000337
338 // Call el_gets to prompt the user and read the user's input.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000339 const char *line = ::el_gets (m_edit_line, &line_len);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000340
341 // Re-set the boolean indicating whether or not el_gets is trying to get input.
342 SetGettingCommand (false);
343
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000344 if (line)
345 {
346 // strip any newlines off the end of the string...
347 while (line_len > 0 && (line[line_len - 1] == '\n' || line[line_len - 1] == '\r'))
348 --line_len;
349 if (line_len > 0)
350 {
351 ::history (m_history, &m_history_event, H_ENTER, line);
352 new_line.assign (line, line_len); // Omit the newline
353 }
354 else
355 {
356 // Someone just hit ENTER, return the empty string
357 new_line.clear();
358 }
359 // Return true to indicate success even if a string is empty
360 return true;
361 }
362 }
363 // Return false to indicate failure. This can happen when the file handle
364 // is closed (EOF).
365 new_line.clear();
366 return false;
367}
368
369void *
370IOChannel::IOReadThread (void *ptr)
371{
372 IOChannel *myself = static_cast<IOChannel *> (ptr);
373 myself->Run();
374 return NULL;
375}
376
377void
378IOChannel::Run ()
379{
380 SBListener listener("IOChannel::Run");
381 std::string new_line;
382
Greg Clayton66111032010-06-23 01:19:29 +0000383 SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000384 listener.StartListeningForEvents (interpreter_broadcaster,
385 SBCommandInterpreter::eBroadcastBitResetPrompt |
386 SBCommandInterpreter::eBroadcastBitThreadShouldExit |
Caroline Tice86a73f92011-05-03 20:53:11 +0000387 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388
389 listener.StartListeningForEvents (*this,
390 IOChannel::eBroadcastBitThreadShouldExit);
391
392 listener.StartListeningForEvents (*m_driver,
393 Driver::eBroadcastBitReadyForInput |
394 Driver::eBroadcastBitThreadShouldExit);
395
396 // Let anyone know that the IO channel is up and listening and ready for events
397 BroadcastEventByType (eBroadcastBitThreadDidStart);
398 bool done = false;
399 while (!done)
400 {
401 SBEvent event;
402
403 listener.WaitForEvent (UINT32_MAX, event);
404 if (!event.IsValid())
405 continue;
406
407 const uint32_t event_type = event.GetType();
408
409 if (event.GetBroadcaster().IsValid())
410 {
411 if (event.BroadcasterMatchesPtr (m_driver))
412 {
413 if (event_type & Driver::eBroadcastBitReadyForInput)
414 {
415 std::string line;
416
417 if (CommandQueueIsEmpty())
418 {
419 if (LibeditGetInput(line) == false)
420 {
421 // EOF or some other file error occurred
422 done = true;
423 continue;
424 }
425 }
426 else
427 {
428 GetCommandFromQueue (line);
429 }
430
431 // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN'
432 // AND TAKE CARE OF THAT HERE.
433
434 SBEvent line_event(IOChannel::eBroadcastBitHasUserInput,
435 line.c_str(),
436 line.size());
437 BroadcastEvent (line_event);
438 }
439 else if (event_type & Driver::eBroadcastBitThreadShouldExit)
440 {
441 done = true;
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000442 continue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000443 }
444 }
445 else if (event.BroadcasterMatchesRef (interpreter_broadcaster))
446 {
447 switch (event_type)
448 {
449 case SBCommandInterpreter::eBroadcastBitResetPrompt:
450 {
451 const char *new_prompt = SBEvent::GetCStringFromEvent (event);
452 if (new_prompt)
453 g_prompt_map[m_edit_line] = new_prompt;
454 }
455 break;
456
457 case SBCommandInterpreter::eBroadcastBitThreadShouldExit:
458 case SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
459 done = true;
460 break;
461 }
462 }
463 else if (event.BroadcasterMatchesPtr (this))
464 {
465 if (event_type & IOChannel::eBroadcastBitThreadShouldExit)
466 {
467 done = true;
Johnny Chen25f3a3c2011-08-10 22:06:24 +0000468 continue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000469 }
470 }
471 }
472 }
473 BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit);
474 m_driver = NULL;
Daniel Maleaa85e6b62012-12-07 22:21:08 +0000475 m_read_thread = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000476}
477
478bool
479IOChannel::Start ()
480{
Greg Clayton2da6d492011-02-08 01:34:25 +0000481 if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000482 return true;
483
484 m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this,
485 NULL);
486
Greg Clayton2da6d492011-02-08 01:34:25 +0000487 return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000488}
489
490bool
491IOChannel::Stop ()
492{
Greg Clayton2da6d492011-02-08 01:34:25 +0000493 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000494 return true;
495
496 BroadcastEventByType (eBroadcastBitThreadShouldExit);
497
498 // Don't call Host::ThreadCancel since el_gets won't respond to this
499 // function call -- the thread will just die and all local variables in
500 // IOChannel::Run() won't get destructed down which is bad since there is
501 // a local listener holding onto broadcasters... To ensure proper shutdown,
502 // a ^D (control-D) sequence (0x04) should be written to other end of the
503 // the "in" file handle that was passed into the contructor as closing the
504 // file handle doesn't seem to make el_gets() exit....
505 return SBHostOS::ThreadJoin (m_read_thread, NULL, NULL);
506}
507
508void
509IOChannel::RefreshPrompt ()
510{
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000511 // If we are not in the middle of getting input from the user, there is no need to
512 // refresh the prompt.
Caroline Tice86a73f92011-05-03 20:53:11 +0000513 IOLocker locker (m_output_mutex);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000514 if (! IsGettingCommand())
515 return;
516
Caroline Tice969ed3d2011-05-02 20:41:46 +0000517 // If we haven't finished writing the prompt, there's no need to refresh it.
518 if (m_expecting_prompt)
519 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000520
Caroline Tice86a73f92011-05-03 20:53:11 +0000521 if (m_refresh_request_pending)
522 return;
523
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000524 ::el_set (m_edit_line, EL_REFRESH);
Caroline Tice86a73f92011-05-03 20:53:11 +0000525 m_refresh_request_pending = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000526}
527
528void
Caroline Tice969ed3d2011-05-02 20:41:46 +0000529IOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000530{
Enrico Granatacd4d24d2012-10-16 20:57:12 +0000531 if (len == 0 || buffer == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000532 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000533
Jason Molenda7efc7e92011-08-12 02:40:17 +0000534 // We're in the process of exiting -- IOChannel::Run() has already completed
535 // and set m_driver to NULL - it is time for us to leave now. We might not
536 // print the final ^D to stdout in this case. We need to do some re-work on
537 // how the I/O streams are managed at some point.
538 if (m_driver == NULL)
539 {
540 return;
541 }
542
Caroline Tice969ed3d2011-05-02 20:41:46 +0000543 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
544 IOLocker locker (m_output_mutex);
Caroline Tice9088b062011-05-09 23:06:58 +0000545 if (m_driver->EditlineReaderIsTop() && asynchronous)
Caroline Ticefe1bdf22011-05-04 16:44:57 +0000546 ::fwrite (undo_prompt_string, 1, 4, m_out_file);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000547 ::fwrite (buffer, 1, len, m_out_file);
548 if (asynchronous)
549 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000550}
551
552void
Caroline Tice969ed3d2011-05-02 20:41:46 +0000553IOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000554{
Enrico Granatacd4d24d2012-10-16 20:57:12 +0000555 if (len == 0 || buffer == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000556 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000557
Caroline Tice969ed3d2011-05-02 20:41:46 +0000558 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
559 IOLocker locker (m_output_mutex);
560 if (asynchronous)
Caroline Ticefe1bdf22011-05-04 16:44:57 +0000561 ::fwrite (undo_prompt_string, 1, 4, m_err_file);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000562 ::fwrite (buffer, 1, len, m_err_file);
563 if (asynchronous)
564 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000565}
566
567void
568IOChannel::AddCommandToQueue (const char *command)
569{
570 m_command_queue.push (std::string(command));
571}
572
573bool
574IOChannel::GetCommandFromQueue (std::string &cmd)
575{
576 if (m_command_queue.empty())
577 return false;
578 cmd.swap(m_command_queue.front());
579 m_command_queue.pop ();
580 return true;
581}
582
583int
584IOChannel::CommandQueueSize () const
585{
586 return m_command_queue.size();
587}
588
589void
590IOChannel::ClearCommandQueue ()
591{
592 while (!m_command_queue.empty())
593 m_command_queue.pop();
594}
595
596bool
597IOChannel::CommandQueueIsEmpty () const
598{
599 return m_command_queue.empty();
600}
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000601
602bool
603IOChannel::IsGettingCommand () const
604{
605 return m_getting_command;
606}
607
608void
609IOChannel::SetGettingCommand (bool new_value)
610{
611 m_getting_command = new_value;
612}
613
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000614IOLocker::IOLocker (pthread_mutex_t &mutex) :
615 m_mutex_ptr (&mutex)
616{
617 if (m_mutex_ptr)
618 ::pthread_mutex_lock (m_mutex_ptr);
619
620}
621
622IOLocker::~IOLocker ()
623{
624 if (m_mutex_ptr)
625 ::pthread_mutex_unlock (m_mutex_ptr);
626}