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