Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Core/Statusline.cpp
213765 views
1
//===-- Statusline.cpp ---------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "lldb/Core/Statusline.h"
10
#include "lldb/Core/Debugger.h"
11
#include "lldb/Core/FormatEntity.h"
12
#include "lldb/Host/StreamFile.h"
13
#include "lldb/Interpreter/CommandInterpreter.h"
14
#include "lldb/Symbol/SymbolContext.h"
15
#include "lldb/Target/Process.h"
16
#include "lldb/Target/StackFrame.h"
17
#include "lldb/Utility/AnsiTerminal.h"
18
#include "lldb/Utility/StreamString.h"
19
#include "llvm/ADT/StringRef.h"
20
#include "llvm/Support/Locale.h"
21
22
#define ESCAPE "\x1b"
23
#define ANSI_NORMAL ESCAPE "[0m"
24
#define ANSI_SAVE_CURSOR ESCAPE "7"
25
#define ANSI_RESTORE_CURSOR ESCAPE "8"
26
#define ANSI_CLEAR_BELOW ESCAPE "[J"
27
#define ANSI_CLEAR_SCREEN ESCAPE "[2J"
28
#define ANSI_SET_SCROLL_ROWS ESCAPE "[1;%ur"
29
#define ANSI_TO_START_OF_ROW ESCAPE "[%u;1f"
30
#define ANSI_REVERSE_VIDEO ESCAPE "[7m"
31
#define ANSI_UP_ROWS ESCAPE "[%dA"
32
33
using namespace lldb;
34
using namespace lldb_private;
35
36
Statusline::Statusline(Debugger &debugger)
37
: m_debugger(debugger), m_terminal_width(m_debugger.GetTerminalWidth()),
38
m_terminal_height(m_debugger.GetTerminalHeight()) {
39
Enable();
40
}
41
42
Statusline::~Statusline() { Disable(); }
43
44
void Statusline::TerminalSizeChanged() {
45
m_terminal_width = m_debugger.GetTerminalWidth();
46
m_terminal_height = m_debugger.GetTerminalHeight();
47
48
UpdateScrollWindow(ResizeStatusline);
49
50
// Draw the old statusline.
51
Redraw(/*update=*/false);
52
}
53
54
void Statusline::Enable() {
55
// Reduce the scroll window to make space for the status bar below.
56
UpdateScrollWindow(EnableStatusline);
57
58
// Draw the statusline.
59
Redraw(/*update=*/true);
60
}
61
62
void Statusline::Disable() {
63
// Extend the scroll window to cover the status bar.
64
UpdateScrollWindow(DisableStatusline);
65
}
66
67
void Statusline::Draw(std::string str) {
68
lldb::LockableStreamFileSP stream_sp = m_debugger.GetOutputStreamSP();
69
if (!stream_sp)
70
return;
71
72
m_last_str = str;
73
74
str = ansi::TrimAndPad(str, m_terminal_width);
75
76
LockedStreamFile locked_stream = stream_sp->Lock();
77
locked_stream << ANSI_SAVE_CURSOR;
78
locked_stream.Printf(ANSI_TO_START_OF_ROW,
79
static_cast<unsigned>(m_terminal_height));
80
81
// Use "reverse video" to make sure the statusline has a background. Only do
82
// this when colors are disabled, and rely on the statusline format otherwise.
83
if (!m_debugger.GetUseColor())
84
locked_stream << ANSI_REVERSE_VIDEO;
85
86
locked_stream << str;
87
locked_stream << ANSI_NORMAL;
88
locked_stream << ANSI_RESTORE_CURSOR;
89
}
90
91
void Statusline::UpdateScrollWindow(ScrollWindowMode mode) {
92
assert(m_terminal_width != 0 && m_terminal_height != 0);
93
94
lldb::LockableStreamFileSP stream_sp = m_debugger.GetOutputStreamSP();
95
if (!stream_sp)
96
return;
97
98
const unsigned reduced_scroll_window = m_terminal_height - 1;
99
LockedStreamFile locked_stream = stream_sp->Lock();
100
101
switch (mode) {
102
case EnableStatusline:
103
// Move everything on the screen up.
104
locked_stream << '\n';
105
locked_stream.Printf(ANSI_UP_ROWS, 1);
106
// Reduce the scroll window.
107
locked_stream << ANSI_SAVE_CURSOR;
108
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_window);
109
locked_stream << ANSI_RESTORE_CURSOR;
110
break;
111
case DisableStatusline:
112
// Reset the scroll window.
113
locked_stream << ANSI_SAVE_CURSOR;
114
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, 0);
115
locked_stream << ANSI_RESTORE_CURSOR;
116
// Clear the screen below to hide the old statusline.
117
locked_stream << ANSI_CLEAR_BELOW;
118
break;
119
case ResizeStatusline:
120
// Clear the screen and update the scroll window.
121
// FIXME: Find a better solution (#146919).
122
locked_stream << ANSI_CLEAR_SCREEN;
123
locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_window);
124
break;
125
}
126
127
m_debugger.RefreshIOHandler();
128
}
129
130
void Statusline::Redraw(bool update) {
131
if (!update) {
132
Draw(m_last_str);
133
return;
134
}
135
136
ExecutionContext exe_ctx = m_debugger.GetSelectedExecutionContext();
137
138
// For colors and progress events, the format entity needs access to the
139
// debugger, which requires a target in the execution context.
140
if (!exe_ctx.HasTargetScope())
141
exe_ctx.SetTargetPtr(&m_debugger.GetSelectedOrDummyTarget());
142
143
SymbolContext symbol_ctx;
144
if (ProcessSP process_sp = exe_ctx.GetProcessSP()) {
145
// Check if the process is stopped, and if it is, make sure it remains
146
// stopped until we've computed the symbol context.
147
Process::StopLocker stop_locker;
148
if (stop_locker.TryLock(&process_sp->GetRunLock())) {
149
if (auto frame_sp = exe_ctx.GetFrameSP())
150
symbol_ctx = frame_sp->GetSymbolContext(eSymbolContextEverything);
151
}
152
}
153
154
StreamString stream;
155
FormatEntity::Entry format = m_debugger.GetStatuslineFormat();
156
FormatEntity::Format(format, stream, &symbol_ctx, &exe_ctx, nullptr, nullptr,
157
false, false);
158
159
Draw(stream.GetString().str());
160
}
161
162