1 /* Cache of styled source file text
2 Copyright (C) 2018-2019 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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/>. */
20 #include "source-cache.h"
21 #include "common/scoped_fd.h"
23 #include "cli/cli-style.h"
25 #ifdef HAVE_SOURCE_HIGHLIGHT
26 /* If Gnulib redirects 'open' and 'close' to its replacements
27 'rpl_open' and 'rpl_close' via cpp macros, including <fstream>
28 below with those macros in effect will cause unresolved externals
29 when GDB is linked. Happens, e.g., in the MinGW build. */
34 #include <srchilite/sourcehighlight.h>
35 #include <srchilite/langmap.h>
38 /* The number of source files we'll cache. */
42 /* See source-cache.h. */
44 source_cache g_source_cache
;
46 /* See source-cache.h. */
49 source_cache::get_plain_source_lines (struct symtab
*s
, int first_line
,
50 int last_line
, std::string
*lines
)
52 scoped_fd
desc (open_source_file_with_line_charpos (s
));
56 if (first_line
< 1 || first_line
> s
->nlines
|| last_line
< 1)
59 if (lseek (desc
.get (), s
->line_charpos
[first_line
- 1], SEEK_SET
) < 0)
60 perror_with_name (symtab_to_filename_for_display (s
));
63 if (last_line
>= s
->nlines
)
67 if (fstat (desc
.get (), &st
) < 0)
68 perror_with_name (symtab_to_filename_for_display (s
));
69 /* We could cache this in line_charpos... */
70 last_charpos
= st
.st_size
;
73 last_charpos
= s
->line_charpos
[last_line
];
75 lines
->resize (last_charpos
- s
->line_charpos
[first_line
- 1]);
76 if (myread (desc
.get (), &(*lines
)[0], lines
->size ()) < 0)
77 perror_with_name (symtab_to_filename_for_display (s
));
82 /* See source-cache.h. */
85 source_cache::extract_lines (const struct source_text
&text
, int first_line
,
89 std::string::size_type pos
= 0;
90 std::string::size_type first_pos
= std::string::npos
;
92 while (pos
!= std::string::npos
&& lineno
<= last_line
)
94 std::string::size_type new_pos
= text
.contents
.find ('\n', pos
);
96 if (lineno
== first_line
)
100 if (lineno
== last_line
|| pos
== std::string::npos
)
102 if (first_pos
== std::string::npos
)
104 if (pos
== std::string::npos
)
105 pos
= text
.contents
.size ();
106 return text
.contents
.substr (first_pos
, pos
- first_pos
);
115 #ifdef HAVE_SOURCE_HIGHLIGHT
117 /* Return the Source Highlight language name, given a gdb language
118 LANG. Returns NULL if the language is not known. */
121 get_language_name (enum language lang
)
138 case language_fortran
:
139 return "fortran.lang";
142 /* Not handled by Source Highlight. */
148 case language_pascal
:
149 return "pascal.lang";
151 case language_opencl
:
152 /* Not handled by Source Highlight. */
156 /* Not handled by Source Highlight. */
169 #endif /* HAVE_SOURCE_HIGHLIGHT */
171 /* See source-cache.h. */
174 source_cache::get_source_lines (struct symtab
*s
, int first_line
,
175 int last_line
, std::string
*lines
)
177 if (first_line
< 1 || last_line
< 1 || first_line
> last_line
)
180 #ifdef HAVE_SOURCE_HIGHLIGHT
181 if (source_styling
&& gdb_stdout
->can_emit_style_escape ())
183 const char *fullname
= symtab_to_fullname (s
);
185 for (const auto &item
: m_source_map
)
187 if (item
.fullname
== fullname
)
189 *lines
= extract_lines (item
, first_line
, last_line
);
194 const char *lang_name
= get_language_name (SYMTAB_LANGUAGE (s
));
195 if (lang_name
!= nullptr)
197 std::ifstream
input (fullname
);
198 if (input
.is_open ())
200 if (s
->line_charpos
== 0)
202 scoped_fd
desc (open_source_file_with_line_charpos (s
));
206 /* FULLNAME points to a value owned by the symtab
207 (symtab::fullname). Calling open_source_file reallocates
208 that value, so we must refresh FULLNAME to avoid a
210 fullname
= symtab_to_fullname (s
);
212 srchilite::SourceHighlight
highlighter ("esc.outlang");
213 highlighter
.setStyleFile("esc.style");
215 std::ostringstream output
;
216 highlighter
.highlight (input
, output
, lang_name
, fullname
);
218 source_text result
= { fullname
, output
.str () };
219 m_source_map
.push_back (std::move (result
));
221 if (m_source_map
.size () > MAX_ENTRIES
)
222 m_source_map
.erase (m_source_map
.begin ());
224 *lines
= extract_lines (m_source_map
.back (), first_line
,
230 #endif /* HAVE_SOURCE_HIGHLIGHT */
232 return get_plain_source_lines (s
, first_line
, last_line
, lines
);