cpu,opcodes,gas: fix explicit arguments to eBPF ldabs instructions
[deliverable/binutils-gdb.git] / gdb / source-cache.c
1 /* Cache of styled source file text
2 Copyright (C) 2018-2019 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19 #include "defs.h"
20 #include "source-cache.h"
21 #include "gdbsupport/scoped_fd.h"
22 #include "source.h"
23 #include "cli/cli-style.h"
24 #include "symtab.h"
25
26 #ifdef HAVE_SOURCE_HIGHLIGHT
27 /* If Gnulib redirects 'open' and 'close' to its replacements
28 'rpl_open' and 'rpl_close' via cpp macros, including <fstream>
29 below with those macros in effect will cause unresolved externals
30 when GDB is linked. Happens, e.g., in the MinGW build. */
31 #undef open
32 #undef close
33 #include <fstream>
34 #include <sstream>
35 #include <srchilite/sourcehighlight.h>
36 #include <srchilite/langmap.h>
37 #endif
38
39 /* The number of source files we'll cache. */
40
41 #define MAX_ENTRIES 5
42
43 /* See source-cache.h. */
44
45 source_cache g_source_cache;
46
47 /* See source-cache.h. */
48
49 bool
50 source_cache::get_plain_source_lines (struct symtab *s, int first_line,
51 int last_line, std::string *lines)
52 {
53 scoped_fd desc (open_source_file_with_line_charpos (s));
54 if (desc.get () < 0)
55 return false;
56
57 if (first_line < 1 || first_line > s->nlines || last_line < 1)
58 return false;
59
60 if (lseek (desc.get (), s->line_charpos[first_line - 1], SEEK_SET) < 0)
61 perror_with_name (symtab_to_filename_for_display (s));
62
63 int last_charpos;
64 if (last_line >= s->nlines)
65 {
66 struct stat st;
67
68 if (fstat (desc.get (), &st) < 0)
69 perror_with_name (symtab_to_filename_for_display (s));
70 /* We could cache this in line_charpos... */
71 last_charpos = st.st_size;
72 }
73 else
74 last_charpos = s->line_charpos[last_line];
75
76 lines->resize (last_charpos - s->line_charpos[first_line - 1]);
77 if (myread (desc.get (), &(*lines)[0], lines->size ()) < 0)
78 perror_with_name (symtab_to_filename_for_display (s));
79
80 return true;
81 }
82
83 /* See source-cache.h. */
84
85 std::string
86 source_cache::extract_lines (const struct source_text &text, int first_line,
87 int last_line)
88 {
89 int lineno = 1;
90 std::string::size_type pos = 0;
91 std::string::size_type first_pos = std::string::npos;
92
93 while (pos != std::string::npos && lineno <= last_line)
94 {
95 std::string::size_type new_pos = text.contents.find ('\n', pos);
96
97 if (lineno == first_line)
98 first_pos = pos;
99
100 pos = new_pos;
101 if (lineno == last_line || pos == std::string::npos)
102 {
103 if (first_pos == std::string::npos)
104 return {};
105 if (pos == std::string::npos)
106 pos = text.contents.size ();
107 return text.contents.substr (first_pos, pos - first_pos);
108 }
109 ++lineno;
110 ++pos;
111 }
112
113 return {};
114 }
115
116 #ifdef HAVE_SOURCE_HIGHLIGHT
117
118 /* Return the Source Highlight language name, given a gdb language
119 LANG. Returns NULL if the language is not known. */
120
121 static const char *
122 get_language_name (enum language lang)
123 {
124 switch (lang)
125 {
126 case language_c:
127 case language_objc:
128 return "c.lang";
129
130 case language_cplus:
131 return "cpp.lang";
132
133 case language_d:
134 return "d.lang";
135
136 case language_go:
137 return "go.lang";
138
139 case language_fortran:
140 return "fortran.lang";
141
142 case language_m2:
143 /* Not handled by Source Highlight. */
144 break;
145
146 case language_asm:
147 return "asm.lang";
148
149 case language_pascal:
150 return "pascal.lang";
151
152 case language_opencl:
153 /* Not handled by Source Highlight. */
154 break;
155
156 case language_rust:
157 /* Not handled by Source Highlight. */
158 break;
159
160 case language_ada:
161 return "ada.lang";
162
163 default:
164 break;
165 }
166
167 return nullptr;
168 }
169
170 #endif /* HAVE_SOURCE_HIGHLIGHT */
171
172 /* See source-cache.h. */
173
174 bool
175 source_cache::get_source_lines (struct symtab *s, int first_line,
176 int last_line, std::string *lines)
177 {
178 if (first_line < 1 || last_line < 1 || first_line > last_line)
179 return false;
180
181 #ifdef HAVE_SOURCE_HIGHLIGHT
182 if (source_styling && gdb_stdout->can_emit_style_escape ())
183 {
184 const char *fullname = symtab_to_fullname (s);
185
186 for (const auto &item : m_source_map)
187 {
188 if (item.fullname == fullname)
189 {
190 *lines = extract_lines (item, first_line, last_line);
191 return true;
192 }
193 }
194
195 const char *lang_name = get_language_name (SYMTAB_LANGUAGE (s));
196 if (lang_name != nullptr)
197 {
198 std::ifstream input (fullname);
199 if (input.is_open ())
200 {
201 /* The global source highlight object, or null if one
202 was never constructed. This is stored here rather
203 than in the class so that we don't need to include
204 anything or do conditional compilation in
205 source-cache.h. */
206 static srchilite::SourceHighlight *highlighter;
207
208 if (s->line_charpos == 0)
209 {
210 scoped_fd desc (open_source_file_with_line_charpos (s));
211 if (desc.get () < 0)
212 return false;
213
214 /* FULLNAME points to a value owned by the symtab
215 (symtab::fullname). Calling open_source_file reallocates
216 that value, so we must refresh FULLNAME to avoid a
217 use-after-free. */
218 fullname = symtab_to_fullname (s);
219 }
220
221 if (highlighter == nullptr)
222 {
223 highlighter = new srchilite::SourceHighlight ("esc.outlang");
224 highlighter->setStyleFile ("esc.style");
225 }
226
227 std::ostringstream output;
228 highlighter->highlight (input, output, lang_name, fullname);
229
230 source_text result = { fullname, output.str () };
231 m_source_map.push_back (std::move (result));
232
233 if (m_source_map.size () > MAX_ENTRIES)
234 m_source_map.erase (m_source_map.begin ());
235
236 *lines = extract_lines (m_source_map.back (), first_line,
237 last_line);
238 return true;
239 }
240 }
241 }
242 #endif /* HAVE_SOURCE_HIGHLIGHT */
243
244 return get_plain_source_lines (s, first_line, last_line, lines);
245 }
This page took 0.034071 seconds and 4 git commands to generate.