IOChannel.cpp revision bedc667c905c55de911d8b9195039d82e6cf0121
124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- IOChannel.cpp -------------------------------------------*- C++ -*-===//
224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//                     The LLVM Compiler Infrastructure
424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source
624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details.
724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===//
924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "IOChannel.h"
1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <map>
1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
14f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBCommandInterpreter.h"
15f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBDebugger.h"
16f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBError.h"
17f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBEvent.h"
18f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBFileSpec.h"
19f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBHostOS.h"
20f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBListener.h"
21f2f321d826c21c674ca5787b18e8b3e0edaa214bEli Friedman#include "lldb/API/SBStringList.h"
2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23d6e167d0fe8666347554226424bb39e36686e0d6Eli Friedman#include <string.h>
24d6e167d0fe8666347554226424bb39e36686e0d6Eli Friedman#include <limits.h>
25d6e167d0fe8666347554226424bb39e36686e0d6Eli Friedman
2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb;
2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnertypedef std::map<EditLine *, std::string> PromptMap;
2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst char *g_default_prompt = "(lldb) ";
3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerPromptMap g_prompt_map;
3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
32c5f0b99c2c2e40dca22cf11208da70ae979a37e8Caroline Tice// Printing the following string causes libedit to back up to the beginning of the line & blank it out.
33c5f0b99c2c2e40dca22cf11208da70ae979a37e8Caroline Ticeconst char undo_prompt_string[4] = { (char) 13, (char) 27, (char) 91, (char) 75};
34c5f0b99c2c2e40dca22cf11208da70ae979a37e8Caroline Tice
3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic const char*
3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerel_prompt(EditLine *el)
3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    PromptMap::const_iterator pos = g_prompt_map.find (el);
3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (pos == g_prompt_map.end())
4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return g_default_prompt;
4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return pos->second.c_str();
4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst char *
4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::GetPrompt ()
4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    PromptMap::const_iterator pos = g_prompt_map.find (m_edit_line);
4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (pos == g_prompt_map.end())
4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return g_default_prompt;
5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return pos->second.c_str();
5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerunsigned char
5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::ElCompletionFn (EditLine *e, int ch)
5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    IOChannel *io_channel;
5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (el_get(e, EL_CLIENTDATA, &io_channel) == 0)
5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return io_channel->HandleCompletion (e, ch);
6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return CC_ERROR;
6424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
6624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
6724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerunsigned char
6824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::HandleCompletion (EditLine *e, int ch)
6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    assert (e == m_edit_line);
7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const LineInfo *line_info  = el_line(m_edit_line);
7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    SBStringList completions;
7454e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton    int page_size = 40;
7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7663094e0bb161580564954dee512955c1c79d3476Greg Clayton    int num_completions = m_driver->GetDebugger().GetCommandInterpreter().HandleCompletion (line_info->buffer,
7763094e0bb161580564954dee512955c1c79d3476Greg Clayton                                                                                            line_info->cursor,
7863094e0bb161580564954dee512955c1c79d3476Greg Clayton                                                                                            line_info->lastchar,
7963094e0bb161580564954dee512955c1c79d3476Greg Clayton                                                                                            0,
8063094e0bb161580564954dee512955c1c79d3476Greg Clayton                                                                                            -1,
8163094e0bb161580564954dee512955c1c79d3476Greg Clayton                                                                                            completions);
8224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (num_completions == -1)
8424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
8524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        el_insertstr (m_edit_line, m_completion_key);
8624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return CC_REDISPLAY;
8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
886247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham    else if (num_completions == -2)
896247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham    {
906247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham        el_deletestr (m_edit_line, line_info->cursor - line_info->buffer);
916247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham        el_insertstr (m_edit_line, completions.GetStringAtIndex(0));
926247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham        return CC_REDISPLAY;
936247dbee41ec51e9a082df7e86269c0f47f28160Jim Ingham    }
9424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
9524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If we get a longer match display that first.
9624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const char *completion_str = completions.GetStringAtIndex(0);
9724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (completion_str != NULL && *completion_str != '\0')
9824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
9924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        el_insertstr (m_edit_line, completion_str);
10024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return CC_REDISPLAY;
10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
10224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (num_completions > 1)
10424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
10524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        const char *comment = "\nAvailable completions:";
10624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
10724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        int num_elements = num_completions + 1;
1084a348081030cdd2af758fddc869518357d9befd3Caroline Tice        OutWrite(comment,  strlen (comment), NO_ASYNC);
10924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (num_completions < page_size)
11024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
11124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            for (int i = 1; i < num_elements; i++)
11224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
113bef1583b89e73de77c8b0897fcf42b5b1fcabe4cGreg Clayton                completion_str = completions.GetStringAtIndex(i);
1144a348081030cdd2af758fddc869518357d9befd3Caroline Tice                OutWrite("\n\t", 2, NO_ASYNC);
1154a348081030cdd2af758fddc869518357d9befd3Caroline Tice                OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
1174a348081030cdd2af758fddc869518357d9befd3Caroline Tice            OutWrite ("\n", 1, NO_ASYNC);
11824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
11924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
12024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
12124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            int cur_pos = 1;
12224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            char reply;
12324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            int got_char;
12424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            while (cur_pos < num_elements)
12524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
12624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                int endpoint = cur_pos + page_size;
12724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (endpoint > num_elements)
12824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    endpoint = num_elements;
12924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                for (; cur_pos < endpoint; cur_pos++)
13024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
131bef1583b89e73de77c8b0897fcf42b5b1fcabe4cGreg Clayton                    completion_str = completions.GetStringAtIndex(cur_pos);
1324a348081030cdd2af758fddc869518357d9befd3Caroline Tice                    OutWrite("\n\t", 2, NO_ASYNC);
1334a348081030cdd2af758fddc869518357d9befd3Caroline Tice                    OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
13624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (cur_pos >= num_elements)
13724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
1384a348081030cdd2af758fddc869518357d9befd3Caroline Tice                    OutWrite("\n", 1, NO_ASYNC);
13924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    break;
14024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
14124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1424a348081030cdd2af758fddc869518357d9befd3Caroline Tice                OutWrite("\nMore (Y/n/a): ", strlen ("\nMore (Y/n/a): "), NO_ASYNC);
14324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                reply = 'n';
14424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                got_char = el_getc(m_edit_line, &reply);
14524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (got_char == -1 || reply == 'n')
14624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    break;
14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (reply == 'a')
14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    page_size = num_elements - cur_pos;
14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
15124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
15424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (num_completions == 0)
15524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return CC_REFRESH_BEEP;
15624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return CC_REDISPLAY;
15824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
16024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::IOChannel
16124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
1624a348081030cdd2af758fddc869518357d9befd3Caroline Tice    FILE *editline_in,
1634a348081030cdd2af758fddc869518357d9befd3Caroline Tice    FILE *editline_out,
1644a348081030cdd2af758fddc869518357d9befd3Caroline Tice    FILE *out,
16524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FILE *err,
16624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Driver *driver
16724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner) :
16824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    SBBroadcaster ("IOChannel"),
169757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    m_output_mutex (),
170757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    m_enter_elgets_time (),
17124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_driver (driver),
17224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_read_thread (LLDB_INVALID_HOST_THREAD),
17324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_read_thread_should_exit (false),
17424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_out_file (out),
17524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_err_file (err),
17654e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton    m_command_queue (),
17754e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton    m_completion_key ("\t"),
1784a348081030cdd2af758fddc869518357d9befd3Caroline Tice    m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), editline_in, editline_out,  editline_out)),
17924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_history (history_init()),
18054e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton    m_history_event(),
1814a348081030cdd2af758fddc869518357d9befd3Caroline Tice    m_getting_command (false),
1824a348081030cdd2af758fddc869518357d9befd3Caroline Tice    m_expecting_prompt (false),
183388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice	m_prompt_str (),
184388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice    m_refresh_request_pending (false)
18524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    assert (m_edit_line);
18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ::el_set (m_edit_line, EL_PROMPT, el_prompt);
18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ::el_set (m_edit_line, EL_EDITOR, "emacs");
18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ::el_set (m_edit_line, EL_HIST, history, m_history);
19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
19124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Source $PWD/.editrc then $HOME/.editrc
19224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ::el_source (m_edit_line, NULL);
19324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
194882c554207e94f66ba8d652302a9d817f275dc4eCaroline Tice    el_set (m_edit_line, EL_ADDFN, "lldb_complete",
19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            "LLDB completion function",
19624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            IOChannel::ElCompletionFn);
197882c554207e94f66ba8d652302a9d817f275dc4eCaroline Tice    el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
198882c554207e94f66ba8d652302a9d817f275dc4eCaroline Tice    el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL);  // Cycle through backwards search, entering string
19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    el_set (m_edit_line, EL_CLIENTDATA, this);
20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    assert (m_history);
20224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ::history (m_history, &m_history_event, H_SETSIZE, 800);
20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ::history (m_history, &m_history_event, H_SETUNIQUE, 1);
20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Load history
20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    HistorySaveLoad (false);
206757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
207757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    // Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere
208757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    // with each other when writing.
209757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
210757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    int error;
211757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    ::pthread_mutexattr_t attr;
212757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    error = ::pthread_mutexattr_init (&attr);
213757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    assert (error == 0);
214757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
215757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    assert (error == 0);
216757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    error = ::pthread_mutex_init (&m_output_mutex, &attr);
217757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    assert (error == 0);
218757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    error = ::pthread_mutexattr_destroy (&attr);
219757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    assert (error == 0);
220757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
221757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    // Initialize time that ::el_gets was last called.
222757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
223757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    m_enter_elgets_time.tv_sec = 0;
224757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    m_enter_elgets_time.tv_usec = 0;
22524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
22624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
22724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::~IOChannel ()
22824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
22924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Save history
23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    HistorySaveLoad (true);
23124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (m_history != NULL)
23324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
23424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ::history_end (m_history);
23524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_history = NULL;
23624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
23724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (m_edit_line != NULL)
23924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
24024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ::el_end (m_edit_line);
24124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_edit_line = NULL;
24224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
243757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
244757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    ::pthread_mutex_destroy (&m_output_mutex);
24524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
24624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
24724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
24824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::HistorySaveLoad (bool save)
24924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
25024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (m_history != NULL)
25124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
25224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        char history_path[PATH_MAX];
2534ead2e9a5a74f465d00b0301c165fbebf4ee4ff3Johnny Chen        ::snprintf (history_path, sizeof(history_path), "~/.%s-history", SBHostOS::GetProgramFileSpec().GetFilename());
25454e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton        if ((size_t)SBFileSpec::ResolvePath (history_path, history_path, sizeof(history_path)) < sizeof(history_path) - 1)
25524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
25624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            const char *path_ptr = history_path;
25724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (save)
25824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                ::history (m_history, &m_history_event, H_SAVE, path_ptr);
25924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            else
26024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                ::history (m_history, &m_history_event, H_LOAD, path_ptr);
26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
26224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2654a348081030cdd2af758fddc869518357d9befd3Caroline Ticevoid
2664a348081030cdd2af758fddc869518357d9befd3Caroline TiceIOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
2674a348081030cdd2af758fddc869518357d9befd3Caroline Tice{
2684a348081030cdd2af758fddc869518357d9befd3Caroline Tice	// Make this a member variable.
2694a348081030cdd2af758fddc869518357d9befd3Caroline Tice    // static std::string prompt_str;
2704a348081030cdd2af758fddc869518357d9befd3Caroline Tice    IOChannel *io_channel = (IOChannel *) baton;
271388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice    IOLocker locker (io_channel->m_output_mutex);
2724a348081030cdd2af758fddc869518357d9befd3Caroline Tice    const char *bytes = (const char *) src;
2734a348081030cdd2af758fddc869518357d9befd3Caroline Tice
2744a348081030cdd2af758fddc869518357d9befd3Caroline Tice    if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt)
2754a348081030cdd2af758fddc869518357d9befd3Caroline Tice    {
2764a348081030cdd2af758fddc869518357d9befd3Caroline Tice        io_channel->m_prompt_str.append (bytes, src_len);
2774a348081030cdd2af758fddc869518357d9befd3Caroline Tice		// Log this to make sure the prompt is really what you think it is.
2784a348081030cdd2af758fddc869518357d9befd3Caroline Tice        if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0)
2794a348081030cdd2af758fddc869518357d9befd3Caroline Tice        {
2804a348081030cdd2af758fddc869518357d9befd3Caroline Tice            io_channel->m_expecting_prompt = false;
281388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice            io_channel->m_refresh_request_pending = false;
2824a348081030cdd2af758fddc869518357d9befd3Caroline Tice            io_channel->OutWrite (io_channel->m_prompt_str.c_str(),
2834a348081030cdd2af758fddc869518357d9befd3Caroline Tice                                  io_channel->m_prompt_str.size(), NO_ASYNC);
2844a348081030cdd2af758fddc869518357d9befd3Caroline Tice            io_channel->m_prompt_str.clear();
2854a348081030cdd2af758fddc869518357d9befd3Caroline Tice        }
2864a348081030cdd2af758fddc869518357d9befd3Caroline Tice    }
2874a348081030cdd2af758fddc869518357d9befd3Caroline Tice    else
2884a348081030cdd2af758fddc869518357d9befd3Caroline Tice    {
2894a348081030cdd2af758fddc869518357d9befd3Caroline Tice        if (io_channel->m_prompt_str.size() > 0)
2904a348081030cdd2af758fddc869518357d9befd3Caroline Tice            io_channel->m_prompt_str.clear();
291388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice        std::string tmp_str (bytes, src_len);
292388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice        if (tmp_str.find (el_prompt (io_channel->m_edit_line)) == 0)
293388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice            io_channel->m_refresh_request_pending = false;
2944a348081030cdd2af758fddc869518357d9befd3Caroline Tice        io_channel->OutWrite (bytes, src_len, NO_ASYNC);
2954a348081030cdd2af758fddc869518357d9befd3Caroline Tice    }
2964a348081030cdd2af758fddc869518357d9befd3Caroline Tice}
2974a348081030cdd2af758fddc869518357d9befd3Caroline Tice
29824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
29924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::LibeditGetInput (std::string &new_line)
30024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
30124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (m_edit_line != NULL)
30224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
30324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        int line_len = 0;
304757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
305757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice        // Set boolean indicating whether or not el_gets is trying to get input (i.e. whether or not to attempt
306757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice        // to refresh the prompt after writing data).
307757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice        SetGettingCommand (true);
3084a348081030cdd2af758fddc869518357d9befd3Caroline Tice        m_expecting_prompt = true;
309757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
310757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice        // Call el_gets to prompt the user and read the user's input.
31124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        const char *line = ::el_gets (m_edit_line, &line_len);
312757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
313757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice        // Re-set the boolean indicating whether or not el_gets is trying to get input.
314757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice        SetGettingCommand (false);
315757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
31624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (line)
31724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
31824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // strip any newlines off the end of the string...
31924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            while (line_len > 0 && (line[line_len - 1] == '\n' || line[line_len - 1] == '\r'))
32024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                --line_len;
32124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (line_len > 0)
32224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
32324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                ::history (m_history, &m_history_event, H_ENTER, line);
32424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                new_line.assign (line, line_len);   // Omit the newline
32524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
32624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            else
32724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
32824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Someone just hit ENTER, return the empty string
32924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                new_line.clear();
33024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
33124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Return true to indicate success even if a string is empty
33224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return true;
33324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
33424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
33524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Return false to indicate failure. This can happen when the file handle
33624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // is closed (EOF).
33724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    new_line.clear();
33824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
33924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
34024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
34124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid *
34224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::IOReadThread (void *ptr)
34324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
34424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    IOChannel *myself = static_cast<IOChannel *> (ptr);
34524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    myself->Run();
34624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return NULL;
34724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
34824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
34924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
35024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::Run ()
35124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
35224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    SBListener listener("IOChannel::Run");
35324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    std::string new_line;
35424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
35563094e0bb161580564954dee512955c1c79d3476Greg Clayton    SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster());
35624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    listener.StartListeningForEvents (interpreter_broadcaster,
35724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                      SBCommandInterpreter::eBroadcastBitResetPrompt |
35824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                      SBCommandInterpreter::eBroadcastBitThreadShouldExit |
359388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice                                      SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
36024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
36124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    listener.StartListeningForEvents (*this,
36224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                      IOChannel::eBroadcastBitThreadShouldExit);
36324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
36424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    listener.StartListeningForEvents (*m_driver,
36524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                      Driver::eBroadcastBitReadyForInput |
36624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                      Driver::eBroadcastBitThreadShouldExit);
36724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
36824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Let anyone know that the IO channel is up and listening and ready for events
36924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    BroadcastEventByType (eBroadcastBitThreadDidStart);
37024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool done = false;
37124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    while (!done)
37224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
37324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        SBEvent event;
37424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
37524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        listener.WaitForEvent (UINT32_MAX, event);
37624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (!event.IsValid())
37724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            continue;
37824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
37924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        const uint32_t event_type = event.GetType();
38024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
38124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (event.GetBroadcaster().IsValid())
38224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
38324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (event.BroadcasterMatchesPtr (m_driver))
38424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
38524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (event_type & Driver::eBroadcastBitReadyForInput)
38624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
38724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    std::string line;
38824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
38924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (CommandQueueIsEmpty())
39024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
39124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (LibeditGetInput(line) == false)
39224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
39324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            // EOF or some other file error occurred
39424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            done = true;
39524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            continue;
39624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
39724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
39824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else
39924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
40024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        GetCommandFromQueue (line);
40124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
40224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
40324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN'
40424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // AND TAKE CARE OF THAT HERE.
40524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
40624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    SBEvent line_event(IOChannel::eBroadcastBitHasUserInput,
40724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                             line.c_str(),
40824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                             line.size());
40924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    BroadcastEvent (line_event);
41024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
41124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else if (event_type & Driver::eBroadcastBitThreadShouldExit)
41224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
41324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    done = true;
414ee6e790171b9a04023d0ea22603f0ac0ecb9a2c6Johnny Chen                    continue;
41524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
41624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
41724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            else if (event.BroadcasterMatchesRef (interpreter_broadcaster))
41824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
41924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                switch (event_type)
42024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
42124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                case SBCommandInterpreter::eBroadcastBitResetPrompt:
42224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
42324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        const char *new_prompt = SBEvent::GetCStringFromEvent (event);
42424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (new_prompt)
42524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            g_prompt_map[m_edit_line] = new_prompt;
42624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
42724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    break;
42824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
42924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                case SBCommandInterpreter::eBroadcastBitThreadShouldExit:
43024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                case SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
43124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    done = true;
43224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    break;
43324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
43424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
43524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            else if (event.BroadcasterMatchesPtr (this))
43624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
43724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (event_type & IOChannel::eBroadcastBitThreadShouldExit)
43824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
43924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    done = true;
440ee6e790171b9a04023d0ea22603f0ac0ecb9a2c6Johnny Chen                    continue;
44124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
44224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
44324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
44424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
44524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit);
44624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_driver = NULL;
44724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_read_thread = NULL;
44824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
44924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
45024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
45124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::Start ()
45224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
45309c81efd010d1c9ac8821bad00cdfc9747fcae79Greg Clayton    if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
45424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return true;
45524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
45624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this,
45724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                            NULL);
45824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
45909c81efd010d1c9ac8821bad00cdfc9747fcae79Greg Clayton    return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
46024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
46124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
46224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
46324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::Stop ()
46424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
46509c81efd010d1c9ac8821bad00cdfc9747fcae79Greg Clayton    if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
46624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return true;
46724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
46824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    BroadcastEventByType (eBroadcastBitThreadShouldExit);
46924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
47024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Don't call Host::ThreadCancel since el_gets won't respond to this
47124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // function call -- the thread will just die and all local variables in
47224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // IOChannel::Run() won't get destructed down which is bad since there is
47324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // a local listener holding onto broadcasters... To ensure proper shutdown,
47424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // a ^D (control-D) sequence (0x04) should be written to other end of the
47524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // the "in" file handle that was passed into the contructor as closing the
47624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // file handle doesn't seem to make el_gets() exit....
47724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return SBHostOS::ThreadJoin (m_read_thread, NULL, NULL);
47824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
47924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
48024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
48124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::RefreshPrompt ()
48224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
483757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    // If we are not in the middle of getting input from the user, there is no need to
484757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    // refresh the prompt.
485388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice    IOLocker locker (m_output_mutex);
486757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    if (! IsGettingCommand())
487757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice        return;
488757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
4894a348081030cdd2af758fddc869518357d9befd3Caroline Tice	// If we haven't finished writing the prompt, there's no need to refresh it.
4904a348081030cdd2af758fddc869518357d9befd3Caroline Tice    if (m_expecting_prompt)
4914a348081030cdd2af758fddc869518357d9befd3Caroline Tice        return;
492757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
493388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice    if (m_refresh_request_pending)
494388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice        return;
495388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice
49624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ::el_set (m_edit_line, EL_REFRESH);
497388ca8fef002edf49d66126efa8f4dff7176edc1Caroline Tice    m_refresh_request_pending = true;
49824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
49924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
50024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
5014a348081030cdd2af758fddc869518357d9befd3Caroline TiceIOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous)
50224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
50324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (len == 0)
50424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return;
505757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
506bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda    // We're in the process of exiting -- IOChannel::Run() has already completed
507bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda    // and set m_driver to NULL - it is time for us to leave now.  We might not
508bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda    // print the final ^D to stdout in this case.  We need to do some re-work on
509bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda    // how the I/O streams are managed at some point.
510bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda    if (m_driver == NULL)
511bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda    {
512bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda        return;
513bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda    }
514bedc667c905c55de911d8b9195039d82e6cf0121Jason Molenda
5154a348081030cdd2af758fddc869518357d9befd3Caroline Tice    // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
5164a348081030cdd2af758fddc869518357d9befd3Caroline Tice    IOLocker locker (m_output_mutex);
517b38df1e945846a5d956974ec157902a6ad748868Caroline Tice    if (m_driver->EditlineReaderIsTop() && asynchronous)
518c5f0b99c2c2e40dca22cf11208da70ae979a37e8Caroline Tice        ::fwrite (undo_prompt_string, 1, 4, m_out_file);
5194a348081030cdd2af758fddc869518357d9befd3Caroline Tice    ::fwrite (buffer, 1, len, m_out_file);
5204a348081030cdd2af758fddc869518357d9befd3Caroline Tice    if (asynchronous)
5214a348081030cdd2af758fddc869518357d9befd3Caroline Tice        m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
5254a348081030cdd2af758fddc869518357d9befd3Caroline TiceIOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous)
52624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
52724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (len == 0)
52824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return;
529757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
5304a348081030cdd2af758fddc869518357d9befd3Caroline Tice    // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
5314a348081030cdd2af758fddc869518357d9befd3Caroline Tice    IOLocker locker (m_output_mutex);
5324a348081030cdd2af758fddc869518357d9befd3Caroline Tice    if (asynchronous)
533c5f0b99c2c2e40dca22cf11208da70ae979a37e8Caroline Tice        ::fwrite (undo_prompt_string, 1, 4, m_err_file);
5344a348081030cdd2af758fddc869518357d9befd3Caroline Tice    ::fwrite (buffer, 1, len, m_err_file);
5354a348081030cdd2af758fddc869518357d9befd3Caroline Tice    if (asynchronous)
5364a348081030cdd2af758fddc869518357d9befd3Caroline Tice        m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
53724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
53824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
53924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::AddCommandToQueue (const char *command)
54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_command_queue.push (std::string(command));
54324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
54424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
54524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
54624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::GetCommandFromQueue (std::string &cmd)
54724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
54824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (m_command_queue.empty())
54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return false;
55024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    cmd.swap(m_command_queue.front());
55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_command_queue.pop ();
55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return true;
55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
55524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint
55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::CommandQueueSize () const
55724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
55824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_command_queue.size();
55924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
56024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
56224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::ClearCommandQueue ()
56324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
56424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    while (!m_command_queue.empty())
56524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_command_queue.pop();
56624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
56724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
56824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
56924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerIOChannel::CommandQueueIsEmpty () const
57024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_command_queue.empty();
57224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
573757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
574757500e29b7856823f2f4aedd30f206ec009147eCaroline Ticebool
575757500e29b7856823f2f4aedd30f206ec009147eCaroline TiceIOChannel::IsGettingCommand () const
576757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice{
577757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    return m_getting_command;
578757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice}
579757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
580757500e29b7856823f2f4aedd30f206ec009147eCaroline Ticevoid
581757500e29b7856823f2f4aedd30f206ec009147eCaroline TiceIOChannel::SetGettingCommand (bool new_value)
582757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice{
583757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    m_getting_command = new_value;
584757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice}
585757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
586757500e29b7856823f2f4aedd30f206ec009147eCaroline TiceIOLocker::IOLocker (pthread_mutex_t &mutex) :
587757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    m_mutex_ptr (&mutex)
588757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice{
589757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    if (m_mutex_ptr)
590757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice        ::pthread_mutex_lock (m_mutex_ptr);
591757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
592757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice}
593757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice
594757500e29b7856823f2f4aedd30f206ec009147eCaroline TiceIOLocker::~IOLocker ()
595757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice{
596757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice    if (m_mutex_ptr)
597757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice        ::pthread_mutex_unlock (m_mutex_ptr);
598757500e29b7856823f2f4aedd30f206ec009147eCaroline Tice}
599