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