Require GNU make 3.82
[deliverable/binutils-gdb.git] / gdb / source-cache.c
CommitLineData
62f29fda 1/* Cache of styled source file text
42a4f53d 2 Copyright (C) 2018-2019 Free Software Foundation, Inc.
62f29fda
TT
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"
268a13a5 21#include "gdbsupport/scoped_fd.h"
62f29fda
TT
22#include "source.h"
23#include "cli/cli-style.h"
0d12e84c 24#include "symtab.h"
62f29fda
TT
25
26#ifdef HAVE_SOURCE_HIGHLIGHT
3a350822
EZ
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
62f29fda
TT
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
45source_cache g_source_cache;
46
47/* See source-cache.h. */
48
49bool
50source_cache::get_plain_source_lines (struct symtab *s, int first_line,
51 int last_line, std::string *lines)
52{
00df30ae 53 scoped_fd desc (open_source_file_with_line_charpos (s));
62f29fda
TT
54 if (desc.get () < 0)
55 return false;
56
62f29fda
TT
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
3b336828 85std::string
62f29fda 86source_cache::extract_lines (const struct source_text &text, int first_line,
3b336828 87 int last_line)
62f29fda
TT
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 {
3b336828
TT
103 if (first_pos == std::string::npos)
104 return {};
62f29fda
TT
105 if (pos == std::string::npos)
106 pos = text.contents.size ();
3b336828 107 return text.contents.substr (first_pos, pos - first_pos);
62f29fda
TT
108 }
109 ++lineno;
110 ++pos;
111 }
112
3b336828 113 return {};
62f29fda
TT
114}
115
64c45143
TT
116#ifdef HAVE_SOURCE_HIGHLIGHT
117
62f29fda
TT
118/* Return the Source Highlight language name, given a gdb language
119 LANG. Returns NULL if the language is not known. */
120
121static const char *
122get_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
64c45143
TT
170#endif /* HAVE_SOURCE_HIGHLIGHT */
171
62f29fda
TT
172/* See source-cache.h. */
173
174bool
175source_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
8a522c6c 182 if (source_styling && gdb_stdout->can_emit_style_escape ())
62f29fda
TT
183 {
184 const char *fullname = symtab_to_fullname (s);
185
186 for (const auto &item : m_source_map)
187 {
188 if (item.fullname == fullname)
3b336828
TT
189 {
190 *lines = extract_lines (item, first_line, last_line);
191 return true;
192 }
62f29fda
TT
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 {
dcf37923
TT
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
ab42892f
EZ
208 if (s->line_charpos == 0)
209 {
00df30ae 210 scoped_fd desc (open_source_file_with_line_charpos (s));
ab42892f
EZ
211 if (desc.get () < 0)
212 return false;
068ef30e
SM
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);
ab42892f 219 }
dcf37923
TT
220
221 if (highlighter == nullptr)
222 {
223 highlighter = new srchilite::SourceHighlight ("esc.outlang");
224 highlighter->setStyleFile ("esc.style");
225 }
62f29fda
TT
226
227 std::ostringstream output;
dcf37923 228 highlighter->highlight (input, output, lang_name, fullname);
62f29fda
TT
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
3b336828
TT
236 *lines = extract_lines (m_source_map.back (), first_line,
237 last_line);
238 return true;
62f29fda
TT
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.107915 seconds and 4 git commands to generate.