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 (s
));
56 if (s
->line_charpos
== 0)
57 find_source_lines (s
, desc
.get ());
59 if (first_line
< 1 || first_line
> s
->nlines
|| last_line
< 1)
62 if (lseek (desc
.get (), s
->line_charpos
[first_line
- 1], SEEK_SET
) < 0)
63 perror_with_name (symtab_to_filename_for_display (s
));
66 if (last_line
>= s
->nlines
)
70 if (fstat (desc
.get (), &st
) < 0)
71 perror_with_name (symtab_to_filename_for_display (s
));
72 /* We could cache this in line_charpos... */
73 last_charpos
= st
.st_size
;
76 last_charpos
= s
->line_charpos
[last_line
];
78 lines
->resize (last_charpos
- s
->line_charpos
[first_line
- 1]);
79 if (myread (desc
.get (), &(*lines
)[0], lines
->size ()) < 0)
80 perror_with_name (symtab_to_filename_for_display (s
));
85 /* See source-cache.h. */
88 source_cache::extract_lines (const struct source_text
&text
, int first_line
,
89 int last_line
, std::string
*lines
)
92 std::string::size_type pos
= 0;
93 std::string::size_type first_pos
= std::string::npos
;
95 while (pos
!= std::string::npos
&& lineno
<= last_line
)
97 std::string::size_type new_pos
= text
.contents
.find ('\n', pos
);
99 if (lineno
== first_line
)
103 if (lineno
== last_line
|| pos
== std::string::npos
)
105 if (pos
== std::string::npos
)
106 pos
= text
.contents
.size ();
107 *lines
= text
.contents
.substr (first_pos
, pos
- first_pos
);
117 #ifdef HAVE_SOURCE_HIGHLIGHT
119 /* Return the Source Highlight language name, given a gdb language
120 LANG. Returns NULL if the language is not known. */
123 get_language_name (enum language lang
)
140 case language_fortran
:
141 return "fortran.lang";
144 /* Not handled by Source Highlight. */
150 case language_pascal
:
151 return "pascal.lang";
153 case language_opencl
:
154 /* Not handled by Source Highlight. */
158 /* Not handled by Source Highlight. */
171 #endif /* HAVE_SOURCE_HIGHLIGHT */
173 /* See source-cache.h. */
176 source_cache::get_source_lines (struct symtab
*s
, int first_line
,
177 int last_line
, std::string
*lines
)
179 if (first_line
< 1 || last_line
< 1 || first_line
> last_line
)
182 #ifdef HAVE_SOURCE_HIGHLIGHT
183 if (source_styling
&& can_emit_style_escape (gdb_stdout
))
185 const char *fullname
= symtab_to_fullname (s
);
187 for (const auto &item
: m_source_map
)
189 if (item
.fullname
== fullname
)
190 return extract_lines (item
, first_line
, last_line
, lines
);
193 const char *lang_name
= get_language_name (SYMTAB_LANGUAGE (s
));
194 if (lang_name
!= nullptr)
196 std::ifstream
input (fullname
);
197 if (input
.is_open ())
199 srchilite::SourceHighlight
highlighter ("esc.outlang");
200 highlighter
.setStyleFile("esc.style");
202 std::ostringstream output
;
203 highlighter
.highlight (input
, output
, lang_name
, fullname
);
205 source_text result
= { fullname
, output
.str () };
206 m_source_map
.push_back (std::move (result
));
208 if (m_source_map
.size () > MAX_ENTRIES
)
209 m_source_map
.erase (m_source_map
.begin ());
211 return extract_lines (m_source_map
.back (), first_line
,
216 #endif /* HAVE_SOURCE_HIGHLIGHT */
218 return get_plain_source_lines (s
, first_line
, last_line
, lines
);