1 //===-- Editline.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 11 #include "lldb/Host/Editline.h" 12 13 #include "lldb/Core/Error.h" 14 #include "lldb/Core/StreamString.h" 15 #include "lldb/Core/StringList.h" 16 #include "lldb/Host/Host.h" 17 18 #include <limits.h> 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 static const char k_prompt_escape_char = '\1'; 24 25 Editline::Editline (const char *prog, // prog can't be NULL 26 const char *prompt, // can be NULL for no prompt 27 FILE *fin, 28 FILE *fout, 29 FILE *ferr) : 30 m_editline (NULL), 31 m_history (NULL), 32 m_history_event (), 33 m_program (), 34 m_prompt (), 35 m_lines_prompt (), 36 m_getc_buffer (), 37 m_getc_mutex (Mutex::eMutexTypeNormal), 38 m_getc_cond (), 39 // m_gets_mutex (Mutex::eMutexTypeNormal), 40 m_completion_callback (NULL), 41 m_completion_callback_baton (NULL), 42 m_line_complete_callback (NULL), 43 m_line_complete_callback_baton (NULL), 44 m_lines_command (Command::None), 45 m_line_offset (0), 46 m_lines_curr_line (0), 47 m_lines_max_line (0), 48 m_prompt_with_line_numbers (false), 49 m_getting_line (false), 50 m_got_eof (false), 51 m_interrupted (false) 52 { 53 if (prog && prog[0]) 54 { 55 m_program = prog; 56 m_editline = ::el_init(prog, fin, fout, ferr); 57 m_history = ::history_init(); 58 } 59 else 60 { 61 m_editline = ::el_init("lldb-tmp", fin, fout, ferr); 62 } 63 if (prompt && prompt[0]) 64 SetPrompt (prompt); 65 66 //::el_set (m_editline, EL_BIND, "^[[A", NULL); // Print binding for up arrow key 67 //::el_set (m_editline, EL_BIND, "^[[B", NULL); // Print binding for up down key 68 69 assert (m_editline); 70 ::el_set (m_editline, EL_CLIENTDATA, this); 71 72 // only defined for newer versions of editline 73 #ifdef EL_PROMPT_ESC 74 ::el_set (m_editline, EL_PROMPT_ESC, GetPromptCallback, k_prompt_escape_char); 75 #else 76 // fall back on old prompt setting code 77 ::el_set (m_editline, EL_PROMPT, GetPromptCallback); 78 #endif 79 ::el_set (m_editline, EL_EDITOR, "emacs"); 80 if (m_history) 81 { 82 ::el_set (m_editline, EL_HIST, history, m_history); 83 } 84 ::el_set (m_editline, EL_ADDFN, "lldb-complete", "Editline completion function", Editline::CallbackComplete); 85 ::el_set (m_editline, EL_ADDFN, "lldb_complete", "Editline completion function", Editline::CallbackComplete); // Keep old "lldb_complete" mapping for older clients that used this in their .editrc 86 ::el_set (m_editline, EL_ADDFN, "lldb-edit-prev-line", "Editline edit prev line", Editline::CallbackEditPrevLine); 87 ::el_set (m_editline, EL_ADDFN, "lldb-edit-next-line", "Editline edit next line", Editline::CallbackEditNextLine); 88 89 ::el_set (m_editline, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string 90 ::el_set (m_editline, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does. 91 ::el_set (m_editline, EL_BIND, "\033[3~", "ed-delete-next-char", NULL); // Fix the delete key. 92 ::el_set (m_editline, EL_BIND, "\t", "lldb-complete", NULL); // Bind TAB to be auto complete 93 94 // Source $PWD/.editrc then $HOME/.editrc 95 ::el_source (m_editline, NULL); 96 97 if (m_history) 98 { 99 ::history (m_history, &m_history_event, H_SETSIZE, 800); 100 ::history (m_history, &m_history_event, H_SETUNIQUE, 1); 101 } 102 103 // Always read through our callback function so we don't read 104 // stuff we aren't supposed to. This also stops the extra echoing 105 // that can happen when you have more input than editline can handle 106 // at once. 107 SetGetCharCallback(GetCharFromInputFileCallback); 108 109 LoadHistory(); 110 } 111 112 Editline::~Editline() 113 { 114 SaveHistory(); 115 116 if (m_history) 117 { 118 ::history_end (m_history); 119 m_history = NULL; 120 } 121 122 // Disable edit mode to stop the terminal from flushing all input 123 // during the call to el_end() since we expect to have multiple editline 124 // instances in this program. 125 ::el_set (m_editline, EL_EDITMODE, 0); 126 127 ::el_end(m_editline); 128 m_editline = NULL; 129 } 130 131 void 132 Editline::SetGetCharCallback (GetCharCallbackType callback) 133 { 134 ::el_set (m_editline, EL_GETCFN, callback); 135 } 136 137 FileSpec 138 Editline::GetHistoryFile() 139 { 140 char history_path[PATH_MAX]; 141 ::snprintf (history_path, sizeof(history_path), "~/.%s-history", m_program.c_str()); 142 return FileSpec(history_path, true); 143 } 144 145 bool 146 Editline::LoadHistory () 147 { 148 if (m_history) 149 { 150 FileSpec history_file(GetHistoryFile()); 151 if (history_file.Exists()) 152 ::history (m_history, &m_history_event, H_LOAD, history_file.GetPath().c_str()); 153 return true; 154 } 155 return false; 156 } 157 158 bool 159 Editline::SaveHistory () 160 { 161 if (m_history) 162 { 163 std::string history_path = GetHistoryFile().GetPath(); 164 ::history (m_history, &m_history_event, H_SAVE, history_path.c_str()); 165 return true; 166 } 167 return false; 168 } 169 170 171 Error 172 Editline::PrivateGetLine(std::string &line) 173 { 174 Error error; 175 if (m_interrupted) 176 { 177 error.SetErrorString("interrupted"); 178 return error; 179 } 180 181 line.clear(); 182 if (m_editline != NULL) 183 { 184 int line_len = 0; 185 const char *line_cstr = NULL; 186 // Call el_gets to prompt the user and read the user's input. 187 // { 188 // // Make sure we know when we are in el_gets() by using a mutex 189 // Mutex::Locker locker (m_gets_mutex); 190 line_cstr = ::el_gets (m_editline, &line_len); 191 // } 192 193 static int save_errno = (line_len < 0) ? errno : 0; 194 195 if (save_errno != 0) 196 { 197 error.SetError(save_errno, eErrorTypePOSIX); 198 } 199 else if (line_cstr) 200 { 201 // Decrement the length so we don't have newline characters in "line" for when 202 // we assign the cstr into the std::string 203 while (line_len > 0 && 204 (line_cstr[line_len - 1] == '\n' || 205 line_cstr[line_len - 1] == '\r')) 206 --line_len; 207 208 if (line_len > 0) 209 { 210 // We didn't strip the newlines, we just adjusted the length, and 211 // we want to add the history item with the newlines 212 if (m_history) 213 ::history (m_history, &m_history_event, H_ENTER, line_cstr); 214 215 // Copy the part of the c string that we want (removing the newline chars) 216 line.assign(line_cstr, line_len); 217 } 218 } 219 } 220 else 221 { 222 error.SetErrorString("the EditLine instance has been deleted"); 223 } 224 return error; 225 } 226 227 228 Error 229 Editline::GetLine(std::string &line) 230 { 231 Error error; 232 line.clear(); 233 234 // Set arrow key bindings for up and down arrows for single line 235 // mode where up and down arrows do prev/next history 236 ::el_set (m_editline, EL_BIND, "^[[A", "ed-prev-history", NULL); // Map up arrow 237 ::el_set (m_editline, EL_BIND, "^[[B", "ed-next-history", NULL); // Map down arrow 238 m_interrupted = false; 239 240 if (!m_got_eof) 241 { 242 if (m_getting_line) 243 { 244 error.SetErrorString("already getting a line"); 245 return error; 246 } 247 if (m_lines_curr_line > 0) 248 { 249 error.SetErrorString("already getting lines"); 250 return error; 251 } 252 m_getting_line = true; 253 error = PrivateGetLine(line); 254 m_getting_line = false; 255 } 256 257 if (m_got_eof && line.empty()) 258 { 259 // Only set the error if we didn't get an error back from PrivateGetLine() 260 if (error.Success()) 261 error.SetErrorString("end of file"); 262 } 263 264 return error; 265 } 266 267 size_t 268 Editline::Push (const char *bytes, size_t len) 269 { 270 if (m_editline) 271 { 272 // Must NULL terminate the string for el_push() so we stick it 273 // into a std::string first 274 ::el_push(m_editline, 275 const_cast<char*>(std::string (bytes, len).c_str())); 276 return len; 277 } 278 return 0; 279 } 280 281 282 Error 283 Editline::GetLines(const std::string &end_line, StringList &lines) 284 { 285 Error error; 286 if (m_getting_line) 287 { 288 error.SetErrorString("already getting a line"); 289 return error; 290 } 291 if (m_lines_curr_line > 0) 292 { 293 error.SetErrorString("already getting lines"); 294 return error; 295 } 296 297 // Set arrow key bindings for up and down arrows for multiple line 298 // mode where up and down arrows do edit prev/next line 299 ::el_set (m_editline, EL_BIND, "^[[A", "lldb-edit-prev-line", NULL); // Map up arrow 300 ::el_set (m_editline, EL_BIND, "^[[B", "lldb-edit-next-line", NULL); // Map down arrow 301 ::el_set (m_editline, EL_BIND, "^b", "ed-prev-history", NULL); 302 ::el_set (m_editline, EL_BIND, "^n", "ed-next-history", NULL); 303 m_interrupted = false; 304 305 LineStatus line_status = LineStatus::Success; 306 307 lines.Clear(); 308 309 FILE *out_file = GetOutputFile(); 310 FILE *err_file = GetErrorFile(); 311 m_lines_curr_line = 1; 312 while (line_status != LineStatus::Done) 313 { 314 const uint32_t line_idx = m_lines_curr_line-1; 315 if (line_idx >= lines.GetSize()) 316 lines.SetSize(m_lines_curr_line); 317 m_lines_max_line = lines.GetSize(); 318 m_lines_command = Command::None; 319 assert(line_idx < m_lines_max_line); 320 std::string &line = lines[line_idx]; 321 error = PrivateGetLine(line); 322 if (error.Fail()) 323 { 324 line_status = LineStatus::Error; 325 } 326 else 327 { 328 switch (m_lines_command) 329 { 330 case Command::None: 331 if (m_line_complete_callback) 332 { 333 line_status = m_line_complete_callback (this, 334 lines, 335 line_idx, 336 error, 337 m_line_complete_callback_baton); 338 } 339 else if (line == end_line) 340 { 341 line_status = LineStatus::Done; 342 } 343 344 if (line_status == LineStatus::Success) 345 { 346 ++m_lines_curr_line; 347 // If we already have content for the next line because 348 // we were editing previous lines, then populate the line 349 // with the appropriate contents 350 if (line_idx+1 < lines.GetSize() && !lines[line_idx+1].empty()) 351 ::el_push (m_editline, 352 const_cast<char*>(lines[line_idx+1].c_str())); 353 } 354 else if (line_status == LineStatus::Error) 355 { 356 // Clear to end of line ("ESC[K"), then print the error, 357 // then go to the next line ("\n") and then move cursor up 358 // two lines ("ESC[2A"). 359 fprintf (err_file, "\033[Kerror: %s\n\033[2A", error.AsCString()); 360 } 361 break; 362 case Command::EditPrevLine: 363 if (m_lines_curr_line > 1) 364 { 365 //::fprintf (out_file, "\033[1A\033[%uD\033[2K", (uint32_t)(m_lines_prompt.size() + lines[line_idx].size())); // Make cursor go up a line and clear that line 366 ::fprintf (out_file, "\033[1A\033[1000D\033[2K"); 367 if (!lines[line_idx-1].empty()) 368 ::el_push (m_editline, 369 const_cast<char*>(lines[line_idx-1].c_str())); 370 --m_lines_curr_line; 371 } 372 break; 373 case Command::EditNextLine: 374 // Allow the down arrow to create a new line 375 ++m_lines_curr_line; 376 //::fprintf (out_file, "\033[1B\033[%uD\033[2K", (uint32_t)(m_lines_prompt.size() + lines[line_idx].size())); 377 ::fprintf (out_file, "\033[1B\033[1000D\033[2K"); 378 if (line_idx+1 < lines.GetSize() && !lines[line_idx+1].empty()) 379 ::el_push (m_editline, 380 const_cast<char*>(lines[line_idx+1].c_str())); 381 break; 382 } 383 } 384 } 385 m_lines_curr_line = 0; 386 m_lines_command = Command::None; 387 388 // If we have a callback, call it one more time to let the 389 // user know the lines are complete 390 if (m_line_complete_callback) 391 m_line_complete_callback (this, 392 lines, 393 UINT32_MAX, 394 error, 395 m_line_complete_callback_baton); 396 397 return error; 398 } 399 400 unsigned char 401 Editline::HandleCompletion (int ch) 402 { 403 if (m_completion_callback == NULL) 404 return CC_ERROR; 405 406 const LineInfo *line_info = ::el_line(m_editline); 407 StringList completions; 408 int page_size = 40; 409 410 const int num_completions = m_completion_callback (line_info->buffer, 411 line_info->cursor, 412 line_info->lastchar, 413 0, // Don't skip any matches (start at match zero) 414 -1, // Get all the matches 415 completions, 416 m_completion_callback_baton); 417 418 FILE *out_file = GetOutputFile(); 419 420 // if (num_completions == -1) 421 // { 422 // ::el_insertstr (m_editline, m_completion_key); 423 // return CC_REDISPLAY; 424 // } 425 // else 426 if (num_completions == -2) 427 { 428 // Replace the entire line with the first string... 429 ::el_deletestr (m_editline, line_info->cursor - line_info->buffer); 430 ::el_insertstr (m_editline, completions.GetStringAtIndex(0)); 431 return CC_REDISPLAY; 432 } 433 434 // If we get a longer match display that first. 435 const char *completion_str = completions.GetStringAtIndex(0); 436 if (completion_str != NULL && *completion_str != '\0') 437 { 438 el_insertstr (m_editline, completion_str); 439 return CC_REDISPLAY; 440 } 441 442 if (num_completions > 1) 443 { 444 int num_elements = num_completions + 1; 445 ::fprintf (out_file, "\nAvailable completions:"); 446 if (num_completions < page_size) 447 { 448 for (int i = 1; i < num_elements; i++) 449 { 450 completion_str = completions.GetStringAtIndex(i); 451 ::fprintf (out_file, "\n\t%s", completion_str); 452 } 453 ::fprintf (out_file, "\n"); 454 } 455 else 456 { 457 int cur_pos = 1; 458 char reply; 459 int got_char; 460 while (cur_pos < num_elements) 461 { 462 int endpoint = cur_pos + page_size; 463 if (endpoint > num_elements) 464 endpoint = num_elements; 465 for (; cur_pos < endpoint; cur_pos++) 466 { 467 completion_str = completions.GetStringAtIndex(cur_pos); 468 ::fprintf (out_file, "\n\t%s", completion_str); 469 } 470 471 if (cur_pos >= num_elements) 472 { 473 ::fprintf (out_file, "\n"); 474 break; 475 } 476 477 ::fprintf (out_file, "\nMore (Y/n/a): "); 478 reply = 'n'; 479 got_char = el_getc(m_editline, &reply); 480 if (got_char == -1 || reply == 'n') 481 break; 482 if (reply == 'a') 483 page_size = num_elements - cur_pos; 484 } 485 } 486 487 } 488 489 if (num_completions == 0) 490 return CC_REFRESH_BEEP; 491 else 492 return CC_REDISPLAY; 493 } 494 495 Editline * 496 Editline::GetClientData (::EditLine *e) 497 { 498 Editline *editline = NULL; 499 if (e && ::el_get(e, EL_CLIENTDATA, &editline) == 0) 500 return editline; 501 return NULL; 502 } 503 504 FILE * 505 Editline::GetInputFile () 506 { 507 return GetFilePointer (m_editline, 0); 508 } 509 510 FILE * 511 Editline::GetOutputFile () 512 { 513 return GetFilePointer (m_editline, 1); 514 } 515 516 FILE * 517 Editline::GetErrorFile () 518 { 519 return GetFilePointer (m_editline, 2); 520 } 521 522 const char * 523 Editline::GetPrompt() 524 { 525 if (m_prompt_with_line_numbers && m_lines_curr_line > 0) 526 { 527 StreamString strm; 528 strm.Printf("%3u: ", m_lines_curr_line); 529 m_lines_prompt = std::move(strm.GetString()); 530 return m_lines_prompt.c_str(); 531 } 532 else 533 { 534 return m_prompt.c_str(); 535 } 536 } 537 538 void 539 Editline::SetPrompt (const char *p) 540 { 541 if (p && p[0]) 542 m_prompt = p; 543 else 544 m_prompt.clear(); 545 size_t start_pos = 0; 546 size_t escape_pos; 547 while ((escape_pos = m_prompt.find('\033', start_pos)) != std::string::npos) 548 { 549 m_prompt.insert(escape_pos, 1, k_prompt_escape_char); 550 start_pos += 2; 551 } 552 } 553 554 FILE * 555 Editline::GetFilePointer (::EditLine *e, int fd) 556 { 557 FILE *file_ptr = NULL; 558 if (e && ::el_get(e, EL_GETFP, fd, &file_ptr) == 0) 559 return file_ptr; 560 return NULL; 561 } 562 563 unsigned char 564 Editline::CallbackEditPrevLine (::EditLine *e, int ch) 565 { 566 Editline *editline = GetClientData (e); 567 if (editline->m_lines_curr_line > 1) 568 { 569 editline->m_lines_command = Command::EditPrevLine; 570 return CC_NEWLINE; 571 } 572 return CC_ERROR; 573 } 574 unsigned char 575 Editline::CallbackEditNextLine (::EditLine *e, int ch) 576 { 577 Editline *editline = GetClientData (e); 578 if (editline->m_lines_curr_line < editline->m_lines_max_line) 579 { 580 editline->m_lines_command = Command::EditNextLine; 581 return CC_NEWLINE; 582 } 583 return CC_ERROR; 584 } 585 586 unsigned char 587 Editline::CallbackComplete (::EditLine *e, int ch) 588 { 589 Editline *editline = GetClientData (e); 590 if (editline) 591 return editline->HandleCompletion (ch); 592 return CC_ERROR; 593 } 594 595 const char * 596 Editline::GetPromptCallback (::EditLine *e) 597 { 598 Editline *editline = GetClientData (e); 599 if (editline) 600 return editline->GetPrompt(); 601 return ""; 602 } 603 604 size_t 605 Editline::SetInputBuffer (const char *c, size_t len) 606 { 607 if (c && len > 0) 608 { 609 Mutex::Locker locker(m_getc_mutex); 610 SetGetCharCallback(GetCharInputBufferCallback); 611 m_getc_buffer.append(c, len); 612 m_getc_cond.Broadcast(); 613 } 614 return len; 615 } 616 617 int 618 Editline::GetChar (char *c) 619 { 620 Mutex::Locker locker(m_getc_mutex); 621 if (m_getc_buffer.empty()) 622 m_getc_cond.Wait(m_getc_mutex); 623 if (m_getc_buffer.empty()) 624 return 0; 625 *c = m_getc_buffer[0]; 626 m_getc_buffer.erase(0,1); 627 return 1; 628 } 629 630 int 631 Editline::GetCharInputBufferCallback (EditLine *e, char *c) 632 { 633 Editline *editline = GetClientData (e); 634 if (editline) 635 return editline->GetChar(c); 636 return 0; 637 } 638 639 int 640 Editline::GetCharFromInputFileCallback (EditLine *e, char *c) 641 { 642 Editline *editline = GetClientData (e); 643 if (editline && editline->m_got_eof == false) 644 { 645 while (1) 646 { 647 errno = 0; 648 char ch = ::fgetc(editline->GetInputFile()); 649 if (ch == '\x04') 650 { 651 // Only turn a CTRL+D into a EOF if we receive the 652 // CTRL+D an empty line, otherwise it will forward 653 // delete the character at the cursor 654 const LineInfo *line_info = ::el_line(e); 655 if (line_info != NULL && 656 line_info->buffer == line_info->cursor && 657 line_info->cursor == line_info->lastchar) 658 { 659 ch = EOF; 660 errno = 0; 661 } 662 } 663 664 if (ch == EOF) 665 { 666 if (errno == EINTR) 667 continue; 668 else 669 { 670 editline->m_got_eof = true; 671 break; 672 } 673 } 674 else 675 { 676 *c = ch; 677 return 1; 678 } 679 } 680 } 681 return 0; 682 } 683 684 void 685 Editline::Hide () 686 { 687 FILE *out_file = GetOutputFile(); 688 if (out_file) 689 { 690 const LineInfo *line_info = ::el_line(m_editline); 691 if (line_info) 692 ::fprintf (out_file, "\033[%uD\033[K", (uint32_t)(strlen(GetPrompt()) + line_info->cursor - line_info->buffer)); 693 } 694 } 695 696 697 void 698 Editline::Refresh() 699 { 700 ::el_set (m_editline, EL_REFRESH); 701 } 702 703 void 704 Editline::Interrupt () 705 { 706 m_interrupted = true; 707 if (m_getting_line || m_lines_curr_line > 0) 708 el_insertstr(m_editline, "\n"); // True to force the line to complete itself so we get exit from el_gets() 709 } 710