1 //===-- 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 14 #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" 22 23 #include <string.h> 24 #include <limits.h> 25 26 using namespace lldb; 27 28 typedef std::map<EditLine *, std::string> PromptMap; 29 const char *g_default_prompt = "(lldb) "; 30 PromptMap g_prompt_map; 31 32 // Printing the following string causes libedit to back up to the beginning of the line & blank it out. 33 const char undo_prompt_string[4] = { (char) 13, (char) 27, (char) 91, (char) 75}; 34 35 static const char* 36 el_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 44 const char * 45 IOChannel::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 53 bool 54 IOChannel::EditLineHasCharacters () 55 { 56 const LineInfo *line_info = el_line(m_edit_line); 57 if (line_info) 58 { 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 } 67 else 68 return false; 69 } 70 71 72 void 73 IOChannel::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 79 unsigned char 80 IOChannel::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 93 void 94 IOChannel::ElResize() 95 { 96 el_resize(m_edit_line); 97 } 98 99 unsigned char 100 IOChannel::HandleCompletion (EditLine *e, int ch) 101 { 102 assert (e == m_edit_line); 103 104 const LineInfo *line_info = el_line(m_edit_line); 105 SBStringList completions; 106 int page_size = 40; 107 108 int num_completions = m_driver->GetDebugger().GetCommandInterpreter().HandleCompletion (line_info->buffer, 109 line_info->cursor, 110 line_info->lastchar, 111 0, 112 -1, 113 completions); 114 115 if (num_completions == -1) 116 { 117 el_insertstr (m_edit_line, m_completion_key); 118 return CC_REDISPLAY; 119 } 120 else if (num_completions == -2) 121 { 122 el_deletestr (m_edit_line, line_info->cursor - line_info->buffer); 123 el_insertstr (m_edit_line, completions.GetStringAtIndex(0)); 124 return CC_REDISPLAY; 125 } 126 127 // If we get a longer match display that first. 128 const char *completion_str = completions.GetStringAtIndex(0); 129 if (completion_str != NULL && *completion_str != '\0') 130 { 131 el_insertstr (m_edit_line, completion_str); 132 return CC_REDISPLAY; 133 } 134 135 if (num_completions > 1) 136 { 137 const char *comment = "\nAvailable completions:"; 138 139 int num_elements = num_completions + 1; 140 OutWrite(comment, strlen (comment), NO_ASYNC); 141 if (num_completions < page_size) 142 { 143 for (int i = 1; i < num_elements; i++) 144 { 145 completion_str = completions.GetStringAtIndex(i); 146 OutWrite("\n\t", 2, NO_ASYNC); 147 OutWrite(completion_str, strlen (completion_str), NO_ASYNC); 148 } 149 OutWrite ("\n", 1, NO_ASYNC); 150 } 151 else 152 { 153 int cur_pos = 1; 154 char reply; 155 int got_char; 156 while (cur_pos < num_elements) 157 { 158 int endpoint = cur_pos + page_size; 159 if (endpoint > num_elements) 160 endpoint = num_elements; 161 for (; cur_pos < endpoint; cur_pos++) 162 { 163 completion_str = completions.GetStringAtIndex(cur_pos); 164 OutWrite("\n\t", 2, NO_ASYNC); 165 OutWrite(completion_str, strlen (completion_str), NO_ASYNC); 166 } 167 168 if (cur_pos >= num_elements) 169 { 170 OutWrite("\n", 1, NO_ASYNC); 171 break; 172 } 173 174 OutWrite("\nMore (Y/n/a): ", strlen ("\nMore (Y/n/a): "), NO_ASYNC); 175 reply = 'n'; 176 got_char = el_getc(m_edit_line, &reply); 177 if (got_char == -1 || reply == 'n') 178 break; 179 if (reply == 'a') 180 page_size = num_elements - cur_pos; 181 } 182 } 183 184 } 185 186 if (num_completions == 0) 187 return CC_REFRESH_BEEP; 188 else 189 return CC_REDISPLAY; 190 } 191 192 IOChannel::IOChannel 193 ( 194 FILE *editline_in, 195 FILE *editline_out, 196 FILE *out, 197 FILE *err, 198 Driver *driver 199 ) : 200 SBBroadcaster ("IOChannel"), 201 m_output_mutex (), 202 m_enter_elgets_time (), 203 m_driver (driver), 204 m_read_thread (LLDB_INVALID_HOST_THREAD), 205 m_read_thread_should_exit (false), 206 m_out_file (out), 207 m_err_file (err), 208 m_command_queue (), 209 m_completion_key ("\t"), 210 m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), editline_in, editline_out, editline_out)), 211 m_history (history_init()), 212 m_history_event(), 213 m_getting_command (false), 214 m_expecting_prompt (false), 215 m_prompt_str (), 216 m_refresh_request_pending (false) 217 { 218 assert (m_edit_line); 219 ::el_set (m_edit_line, EL_PROMPT, el_prompt); 220 ::el_set (m_edit_line, EL_EDITOR, "emacs"); 221 ::el_set (m_edit_line, EL_HIST, history, m_history); 222 223 el_set (m_edit_line, EL_ADDFN, "lldb_complete", 224 "LLDB completion function", 225 IOChannel::ElCompletionFn); 226 el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL); 227 el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string 228 el_set (m_edit_line, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does. 229 el_set (m_edit_line, EL_BIND, "\e[3~", "ed-delete-next-char", NULL); // Fix the delete key. 230 el_set (m_edit_line, EL_CLIENTDATA, this); 231 232 // Source $PWD/.editrc then $HOME/.editrc 233 ::el_source (m_edit_line, NULL); 234 235 assert (m_history); 236 ::history (m_history, &m_history_event, H_SETSIZE, 800); 237 ::history (m_history, &m_history_event, H_SETUNIQUE, 1); 238 // Load history 239 HistorySaveLoad (false); 240 241 // Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere 242 // with each other when writing. 243 244 int error; 245 ::pthread_mutexattr_t attr; 246 error = ::pthread_mutexattr_init (&attr); 247 assert (error == 0); 248 error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); 249 assert (error == 0); 250 error = ::pthread_mutex_init (&m_output_mutex, &attr); 251 assert (error == 0); 252 error = ::pthread_mutexattr_destroy (&attr); 253 assert (error == 0); 254 255 // Initialize time that ::el_gets was last called. 256 257 m_enter_elgets_time.tv_sec = 0; 258 m_enter_elgets_time.tv_usec = 0; 259 } 260 261 IOChannel::~IOChannel () 262 { 263 // Save history 264 HistorySaveLoad (true); 265 266 if (m_history != NULL) 267 { 268 ::history_end (m_history); 269 m_history = NULL; 270 } 271 272 if (m_edit_line != NULL) 273 { 274 ::el_end (m_edit_line); 275 m_edit_line = NULL; 276 } 277 278 ::pthread_mutex_destroy (&m_output_mutex); 279 } 280 281 void 282 IOChannel::HistorySaveLoad (bool save) 283 { 284 if (m_history != NULL) 285 { 286 char history_path[PATH_MAX]; 287 ::snprintf (history_path, sizeof(history_path), "~/.%s-history", SBHostOS::GetProgramFileSpec().GetFilename()); 288 if ((size_t)SBFileSpec::ResolvePath (history_path, history_path, sizeof(history_path)) < sizeof(history_path) - 1) 289 { 290 const char *path_ptr = history_path; 291 if (save) 292 ::history (m_history, &m_history_event, H_SAVE, path_ptr); 293 else 294 ::history (m_history, &m_history_event, H_LOAD, path_ptr); 295 } 296 } 297 } 298 299 void 300 IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len) 301 { 302 // Make this a member variable. 303 // static std::string prompt_str; 304 IOChannel *io_channel = (IOChannel *) baton; 305 IOLocker locker (io_channel->m_output_mutex); 306 const char *bytes = (const char *) src; 307 308 if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt) 309 { 310 io_channel->m_prompt_str.append (bytes, src_len); 311 // Log this to make sure the prompt is really what you think it is. 312 if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0) 313 { 314 io_channel->m_expecting_prompt = false; 315 io_channel->m_refresh_request_pending = false; 316 io_channel->OutWrite (io_channel->m_prompt_str.c_str(), 317 io_channel->m_prompt_str.size(), NO_ASYNC); 318 io_channel->m_prompt_str.clear(); 319 } 320 } 321 else 322 { 323 if (io_channel->m_prompt_str.size() > 0) 324 io_channel->m_prompt_str.clear(); 325 std::string tmp_str (bytes, src_len); 326 if (tmp_str.find (el_prompt (io_channel->m_edit_line)) == 0) 327 io_channel->m_refresh_request_pending = false; 328 io_channel->OutWrite (bytes, src_len, NO_ASYNC); 329 } 330 } 331 332 IOChannel::LibeditGetInputResult 333 IOChannel::LibeditGetInput (std::string &new_line) 334 { 335 IOChannel::LibeditGetInputResult retval = IOChannel::eLibeditGetInputResultUnknown; 336 if (m_edit_line != NULL) 337 { 338 int line_len = 0; 339 340 // Set boolean indicating whether or not el_gets is trying to get input (i.e. whether or not to attempt 341 // to refresh the prompt after writing data). 342 SetGettingCommand (true); 343 m_expecting_prompt = true; 344 345 // Call el_gets to prompt the user and read the user's input. 346 const char *line = ::el_gets (m_edit_line, &line_len); 347 348 // Re-set the boolean indicating whether or not el_gets is trying to get input. 349 SetGettingCommand (false); 350 351 if (line) 352 { 353 retval = IOChannel::eLibeditGetInputValid; 354 // strip any newlines off the end of the string... 355 while (line_len > 0 && (line[line_len - 1] == '\n' || line[line_len - 1] == '\r')) 356 --line_len; 357 if (line_len > 0) 358 { 359 ::history (m_history, &m_history_event, H_ENTER, line); 360 new_line.assign (line, line_len); // Omit the newline 361 } 362 else 363 { 364 retval = IOChannel::eLibeditGetInputEmpty; 365 // Someone just hit ENTER, return the empty string 366 new_line.clear(); 367 } 368 // Return true to indicate success even if a string is empty 369 return retval; 370 } 371 else 372 { 373 retval = (line_len == 0 ? IOChannel::eLibeditGetInputEOF : IOChannel::eLibeditGetInputResultError); 374 } 375 } 376 // Return false to indicate failure. This can happen when the file handle 377 // is closed (EOF). 378 new_line.clear(); 379 return retval; 380 } 381 382 void * 383 IOChannel::IOReadThread (void *ptr) 384 { 385 IOChannel *myself = static_cast<IOChannel *> (ptr); 386 myself->Run(); 387 return NULL; 388 } 389 390 void 391 IOChannel::Run () 392 { 393 SBListener listener("IOChannel::Run"); 394 std::string new_line; 395 396 SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster()); 397 listener.StartListeningForEvents (interpreter_broadcaster, 398 SBCommandInterpreter::eBroadcastBitResetPrompt | 399 SBCommandInterpreter::eBroadcastBitThreadShouldExit | 400 SBCommandInterpreter::eBroadcastBitQuitCommandReceived); 401 402 listener.StartListeningForEvents (*this, 403 IOChannel::eBroadcastBitThreadShouldExit); 404 405 listener.StartListeningForEvents (*m_driver, 406 Driver::eBroadcastBitReadyForInput | 407 Driver::eBroadcastBitThreadShouldExit); 408 409 // Let anyone know that the IO channel is up and listening and ready for events 410 BroadcastEventByType (eBroadcastBitThreadDidStart); 411 bool done = false; 412 while (!done) 413 { 414 SBEvent event; 415 416 listener.WaitForEvent (UINT32_MAX, event); 417 if (!event.IsValid()) 418 continue; 419 420 const uint32_t event_type = event.GetType(); 421 422 if (event.GetBroadcaster().IsValid()) 423 { 424 if (event.BroadcasterMatchesPtr (m_driver)) 425 { 426 if (event_type & Driver::eBroadcastBitReadyForInput) 427 { 428 std::string line; 429 430 if (CommandQueueIsEmpty()) 431 { 432 IOChannel::LibeditGetInputResult getline_result = LibeditGetInput(line); 433 if (getline_result == IOChannel::eLibeditGetInputEOF) 434 { 435 // EOF occurred 436 // pretend that a quit was typed so the user gets a potential 437 // chance to confirm 438 line.assign("quit"); 439 } 440 else if (getline_result == IOChannel::eLibeditGetInputResultError || getline_result == IOChannel::eLibeditGetInputResultUnknown) 441 { 442 // some random error occurred, exit and don't ask because the state might be corrupt 443 done = true; 444 continue; 445 } 446 } 447 else 448 { 449 GetCommandFromQueue (line); 450 } 451 452 // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN' 453 // AND TAKE CARE OF THAT HERE. 454 455 SBEvent line_event(IOChannel::eBroadcastBitHasUserInput, 456 line.c_str(), 457 line.size()); 458 BroadcastEvent (line_event); 459 } 460 else if (event_type & Driver::eBroadcastBitThreadShouldExit) 461 { 462 done = true; 463 continue; 464 } 465 } 466 else if (event.BroadcasterMatchesRef (interpreter_broadcaster)) 467 { 468 switch (event_type) 469 { 470 case SBCommandInterpreter::eBroadcastBitResetPrompt: 471 { 472 const char *new_prompt = SBEvent::GetCStringFromEvent (event); 473 if (new_prompt) 474 g_prompt_map[m_edit_line] = new_prompt; 475 } 476 break; 477 478 case SBCommandInterpreter::eBroadcastBitThreadShouldExit: 479 case SBCommandInterpreter::eBroadcastBitQuitCommandReceived: 480 done = true; 481 break; 482 } 483 } 484 else if (event.BroadcasterMatchesPtr (this)) 485 { 486 if (event_type & IOChannel::eBroadcastBitThreadShouldExit) 487 { 488 done = true; 489 continue; 490 } 491 } 492 } 493 } 494 BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit); 495 m_driver = NULL; 496 m_read_thread = 0; 497 } 498 499 bool 500 IOChannel::Start () 501 { 502 if (IS_VALID_LLDB_HOST_THREAD(m_read_thread)) 503 return true; 504 505 m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this, 506 NULL); 507 508 return (IS_VALID_LLDB_HOST_THREAD(m_read_thread)); 509 } 510 511 bool 512 IOChannel::Stop () 513 { 514 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread)) 515 return true; 516 517 BroadcastEventByType (eBroadcastBitThreadShouldExit); 518 519 // Don't call Host::ThreadCancel since el_gets won't respond to this 520 // function call -- the thread will just die and all local variables in 521 // IOChannel::Run() won't get destructed down which is bad since there is 522 // a local listener holding onto broadcasters... To ensure proper shutdown, 523 // a ^D (control-D) sequence (0x04) should be written to other end of the 524 // the "in" file handle that was passed into the contructor as closing the 525 // file handle doesn't seem to make el_gets() exit.... 526 return SBHostOS::ThreadJoin (m_read_thread, NULL, NULL); 527 } 528 529 void 530 IOChannel::RefreshPrompt () 531 { 532 // If we are not in the middle of getting input from the user, there is no need to 533 // refresh the prompt. 534 IOLocker locker (m_output_mutex); 535 if (! IsGettingCommand()) 536 return; 537 538 // If we haven't finished writing the prompt, there's no need to refresh it. 539 if (m_expecting_prompt) 540 return; 541 542 if (m_refresh_request_pending) 543 return; 544 545 ::el_set (m_edit_line, EL_REFRESH); 546 m_refresh_request_pending = true; 547 } 548 549 void 550 IOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous) 551 { 552 if (len == 0 || buffer == NULL) 553 return; 554 555 // We're in the process of exiting -- IOChannel::Run() has already completed 556 // and set m_driver to NULL - it is time for us to leave now. We might not 557 // print the final ^D to stdout in this case. We need to do some re-work on 558 // how the I/O streams are managed at some point. 559 if (m_driver == NULL) 560 { 561 return; 562 } 563 564 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output. 565 IOLocker locker (m_output_mutex); 566 if (m_driver->EditlineReaderIsTop() && asynchronous) 567 ::fwrite (undo_prompt_string, 1, 4, m_out_file); 568 ::fwrite (buffer, 1, len, m_out_file); 569 if (asynchronous) 570 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten); 571 } 572 573 void 574 IOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous) 575 { 576 if (len == 0 || buffer == NULL) 577 return; 578 579 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output. 580 IOLocker locker (m_output_mutex); 581 if (asynchronous) 582 ::fwrite (undo_prompt_string, 1, 4, m_err_file); 583 ::fwrite (buffer, 1, len, m_err_file); 584 if (asynchronous) 585 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten); 586 } 587 588 void 589 IOChannel::AddCommandToQueue (const char *command) 590 { 591 m_command_queue.push (std::string(command)); 592 } 593 594 bool 595 IOChannel::GetCommandFromQueue (std::string &cmd) 596 { 597 if (m_command_queue.empty()) 598 return false; 599 cmd.swap(m_command_queue.front()); 600 m_command_queue.pop (); 601 return true; 602 } 603 604 int 605 IOChannel::CommandQueueSize () const 606 { 607 return m_command_queue.size(); 608 } 609 610 void 611 IOChannel::ClearCommandQueue () 612 { 613 while (!m_command_queue.empty()) 614 m_command_queue.pop(); 615 } 616 617 bool 618 IOChannel::CommandQueueIsEmpty () const 619 { 620 return m_command_queue.empty(); 621 } 622 623 bool 624 IOChannel::IsGettingCommand () const 625 { 626 return m_getting_command; 627 } 628 629 void 630 IOChannel::SetGettingCommand (bool new_value) 631 { 632 m_getting_command = new_value; 633 } 634 635 IOLocker::IOLocker (pthread_mutex_t &mutex) : 636 m_mutex_ptr (&mutex) 637 { 638 if (m_mutex_ptr) 639 ::pthread_mutex_lock (m_mutex_ptr); 640 641 } 642 643 IOLocker::~IOLocker () 644 { 645 if (m_mutex_ptr) 646 ::pthread_mutex_unlock (m_mutex_ptr); 647 } 648