Home | History | Annotate | Download | only in driver
      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