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
28 #include <srchilite/sourcehighlight.h>
29 #include <srchilite/langmap.h>
32 /* The number of source files we'll cache. */
36 /* See source-cache.h. */
38 source_cache g_source_cache
;
40 /* See source-cache.h. */
43 source_cache::get_plain_source_lines (struct symtab
*s
, int first_line
,
44 int last_line
, std::string
*lines
)
46 scoped_fd
desc (open_source_file (s
));
50 if (s
->line_charpos
== 0)
51 find_source_lines (s
, desc
.get ());
53 if (first_line
< 1 || first_line
> s
->nlines
|| last_line
< 1)
56 if (lseek (desc
.get (), s
->line_charpos
[first_line
- 1], SEEK_SET
) < 0)
57 perror_with_name (symtab_to_filename_for_display (s
));
60 if (last_line
>= s
->nlines
)
64 if (fstat (desc
.get (), &st
) < 0)
65 perror_with_name (symtab_to_filename_for_display (s
));
66 /* We could cache this in line_charpos... */
67 last_charpos
= st
.st_size
;
70 last_charpos
= s
->line_charpos
[last_line
];
72 lines
->resize (last_charpos
- s
->line_charpos
[first_line
- 1]);
73 if (myread (desc
.get (), &(*lines
)[0], lines
->size ()) < 0)
74 perror_with_name (symtab_to_filename_for_display (s
));
79 /* See source-cache.h. */
82 source_cache::extract_lines (const struct source_text
&text
, int first_line
,
83 int last_line
, std::string
*lines
)
86 std::string::size_type pos
= 0;
87 std::string::size_type first_pos
= std::string::npos
;
89 while (pos
!= std::string::npos
&& lineno
<= last_line
)
91 std::string::size_type new_pos
= text
.contents
.find ('\n', pos
);
93 if (lineno
== first_line
)
97 if (lineno
== last_line
|| pos
== std::string::npos
)
99 if (pos
== std::string::npos
)
100 pos
= text
.contents
.size ();
101 *lines
= text
.contents
.substr (first_pos
, pos
- first_pos
);
111 #ifdef HAVE_SOURCE_HIGHLIGHT
113 /* Return the Source Highlight language name, given a gdb language
114 LANG. Returns NULL if the language is not known. */
117 get_language_name (enum language lang
)
134 case language_fortran
:
135 return "fortran.lang";
138 /* Not handled by Source Highlight. */
144 case language_pascal
:
145 return "pascal.lang";
147 case language_opencl
:
148 /* Not handled by Source Highlight. */
152 /* Not handled by Source Highlight. */
165 #endif /* HAVE_SOURCE_HIGHLIGHT */
167 /* See source-cache.h. */
170 source_cache::get_source_lines (struct symtab
*s
, int first_line
,
171 int last_line
, std::string
*lines
)
173 if (first_line
< 1 || last_line
< 1 || first_line
> last_line
)
176 #ifdef HAVE_SOURCE_HIGHLIGHT
177 if (can_emit_style_escape (gdb_stdout
))
179 const char *fullname
= symtab_to_fullname (s
);
181 for (const auto &item
: m_source_map
)
183 if (item
.fullname
== fullname
)
184 return extract_lines (item
, first_line
, last_line
, lines
);
187 const char *lang_name
= get_language_name (SYMTAB_LANGUAGE (s
));
188 if (lang_name
!= nullptr)
190 std::ifstream
input (fullname
);
191 if (input
.is_open ())
193 srchilite::SourceHighlight
highlighter ("esc.outlang");
194 highlighter
.setStyleFile("esc.style");
196 std::ostringstream output
;
197 highlighter
.highlight (input
, output
, lang_name
, fullname
);
199 source_text result
= { fullname
, output
.str () };
200 m_source_map
.push_back (std::move (result
));
202 if (m_source_map
.size () > MAX_ENTRIES
)
203 m_source_map
.erase (m_source_map
.begin ());
205 return extract_lines (m_source_map
.back (), first_line
,
210 #endif /* HAVE_SOURCE_HIGHLIGHT */
212 return get_plain_source_lines (s
, first_line
, last_line
, lines
);