Branch data Line data Source code
1 : : /* m2linemap.cc provides an interface to GCC linemaps.
2 : :
3 : : Copyright (C) 2012-2024 Free Software Foundation, Inc.
4 : : Contributed by Gaius Mulley <gaius@glam.ac.uk>.
5 : :
6 : : This file is part of GNU Modula-2.
7 : :
8 : : GNU Modula-2 is free software; you can redistribute it and/or modify
9 : : it under the terms of the GNU General Public License as published by
10 : : the Free Software Foundation; either version 3, or (at your option)
11 : : any later version.
12 : :
13 : : GNU Modula-2 is distributed in the hope that it will be useful, but
14 : : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : : General Public License for more details.
17 : :
18 : : You should have received a copy of the GNU General Public License
19 : : along with GNU Modula-2; see the file COPYING3. If not see
20 : : <http://www.gnu.org/licenses/>. */
21 : :
22 : : #define INCLUDE_STRING
23 : : #include "gcc-consolidation.h"
24 : :
25 : : /* Utilize some of the C build routines */
26 : :
27 : : #include "../gm2-lang.h"
28 : : #include "../m2-tree.h"
29 : :
30 : : #include "m2assert.h"
31 : : #include "m2block.h"
32 : : #include "m2decl.h"
33 : : #include "m2expr.h"
34 : : #include "m2options.h"
35 : : #include "m2tree.h"
36 : : #include "m2type.h"
37 : : #define m2linemap_c
38 : : #include "m2linemap.h"
39 : : #include "m2color.h"
40 : :
41 : : static int inFile = FALSE;
42 : :
43 : : #if defined(__cplusplus)
44 : : #define EXTERN extern "C"
45 : : #else
46 : : #define EXTERN
47 : : #endif
48 : :
49 : : /* Start getting locations from a new file. */
50 : :
51 : : EXTERN
52 : : void
53 : 275910 : m2linemap_StartFile (void *filename, unsigned int linebegin)
54 : : {
55 : 275910 : if (inFile)
56 : 253643 : m2linemap_EndFile ();
57 : 275910 : linemap_add (line_table, LC_ENTER, false,
58 : 275910 : xstrdup (reinterpret_cast<char *> (filename)), linebegin);
59 : 275910 : inFile = TRUE;
60 : 275910 : }
61 : :
62 : : /* Tell the line table the file has ended. */
63 : :
64 : : EXTERN
65 : : void
66 : 253643 : m2linemap_EndFile (void)
67 : : {
68 : 253643 : linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
69 : 253643 : inFile = FALSE;
70 : 253643 : }
71 : :
72 : : /* Indicate that there is a new source file line number with a
73 : : maximum width. */
74 : :
75 : : EXTERN
76 : : void
77 : 47549046 : m2linemap_StartLine (unsigned int linenumber, unsigned int linesize)
78 : : {
79 : 47549046 : linemap_line_start (line_table, linenumber, linesize);
80 : 47549046 : }
81 : :
82 : : /* GetLocationColumn, returns a location_t based on the current line
83 : : number and column. */
84 : :
85 : : EXTERN
86 : : location_t
87 : 1547280220 : m2linemap_GetLocationColumn (unsigned int column)
88 : : {
89 : 1547280220 : return linemap_position_for_column (line_table, column);
90 : : }
91 : :
92 : : /* GetLocationRange, returns a location based on the start column
93 : : and end column. */
94 : :
95 : : EXTERN
96 : : location_t
97 : 1547280220 : m2linemap_GetLocationRange (unsigned int start, unsigned int end)
98 : : {
99 : 1547280220 : location_t caret = m2linemap_GetLocationColumn (start);
100 : :
101 : 1547280220 : source_range where;
102 : 1547280220 : where.m_start = linemap_position_for_column (line_table, start);
103 : 1547280220 : where.m_finish = linemap_position_for_column (line_table, end);
104 : 1547280220 : return make_location (caret, where);
105 : : }
106 : :
107 : :
108 : : static
109 : : int
110 : 0 : isSrcLocation (location_t location)
111 : : {
112 : 0 : return (location != BUILTINS_LOCATION) && (location != UNKNOWN_LOCATION);
113 : : }
114 : :
115 : :
116 : : /* GetLocationBinary, returns a location based on the expression
117 : : start caret finish locations. */
118 : :
119 : : EXTERN
120 : : location_t
121 : 1941635 : m2linemap_GetLocationBinary (location_t caret, location_t start, location_t finish)
122 : : {
123 : 1941635 : if (isSrcLocation (start) && isSrcLocation (finish) && isSrcLocation (caret)
124 : 3883270 : && (m2linemap_GetFilenameFromLocation (start) != NULL))
125 : : {
126 : 1930085 : linemap_add (line_table, LC_ENTER, false, xstrdup (m2linemap_GetFilenameFromLocation (start)), 1);
127 : 1930085 : gcc_assert (inFile);
128 : 1930085 : location_t location = make_location (caret, start, finish);
129 : 1930085 : return location;
130 : : }
131 : : return caret;
132 : : }
133 : :
134 : : /* GetLineNoFromLocation - returns the lineno given a location. */
135 : :
136 : : EXTERN
137 : : int
138 : 3688 : m2linemap_GetLineNoFromLocation (location_t location)
139 : : {
140 : 3688 : if (isSrcLocation (location) && (!M2Options_GetCpp ()))
141 : : {
142 : 1588 : expanded_location xl = expand_location (location);
143 : 1588 : return xl.line;
144 : : }
145 : : return 0;
146 : : }
147 : :
148 : : /* GetColumnNoFromLocation - returns the columnno given a location. */
149 : :
150 : : EXTERN
151 : : int
152 : 3688 : m2linemap_GetColumnNoFromLocation (location_t location)
153 : : {
154 : 3688 : if (isSrcLocation (location) && (!M2Options_GetCpp ()))
155 : : {
156 : 1588 : expanded_location xl = expand_location (location);
157 : 1588 : return xl.column;
158 : : }
159 : : return 0;
160 : : }
161 : :
162 : : /* GetFilenameFromLocation - returns the filename given a location. */
163 : :
164 : : EXTERN
165 : : const char *
166 : 3875408 : m2linemap_GetFilenameFromLocation (location_t location)
167 : : {
168 : 3875408 : if (isSrcLocation (location) && (!M2Options_GetCpp ()))
169 : : {
170 : 3861758 : expanded_location xl = expand_location (location);
171 : 3861758 : return xl.file;
172 : : }
173 : : return NULL;
174 : : }
175 : :
176 : : /* ErrorAt - issue an error message. */
177 : :
178 : : EXTERN
179 : : void
180 : 0 : m2linemap_ErrorAt (location_t location, char *message)
181 : : {
182 : 0 : error_at (location, "%s", message);
183 : 0 : }
184 : :
185 : : /* m2linemap_ErrorAtf - wraps up an error message. */
186 : :
187 : : static void
188 : 2606 : m2linemap_ErrorAtf_1 (location_t location, const char *message, ...)
189 : : {
190 : 2606 : diagnostic_info diagnostic;
191 : 2606 : va_list ap;
192 : 2606 : rich_location richloc (line_table, location);
193 : :
194 : 2606 : va_start (ap, message);
195 : 2606 : diagnostic_set_info (&diagnostic, message, &ap, &richloc, DK_ERROR);
196 : 2606 : diagnostic_report_diagnostic (global_dc, &diagnostic);
197 : 2606 : va_end (ap);
198 : 2606 : }
199 : :
200 : : void
201 : 2606 : m2linemap_ErrorAtf (location_t location, const char *message)
202 : : {
203 : 2606 : m2linemap_ErrorAtf_1 (location, "%s", message);
204 : 2606 : }
205 : :
206 : : /* m2linemap_WarningAtf - wraps up a warning message. */
207 : :
208 : : static void
209 : 594 : m2linemap_WarningAtf_1 (location_t location, const char *message, ...)
210 : : {
211 : 594 : diagnostic_info diagnostic;
212 : 594 : va_list ap;
213 : 594 : rich_location richloc (line_table, location);
214 : :
215 : 594 : va_start (ap, message);
216 : 594 : diagnostic_set_info (&diagnostic, message, &ap, &richloc, DK_WARNING);
217 : 594 : diagnostic_report_diagnostic (global_dc, &diagnostic);
218 : 594 : va_end (ap);
219 : 594 : }
220 : :
221 : : void
222 : 594 : m2linemap_WarningAtf (location_t location, const char *message)
223 : : {
224 : 594 : m2linemap_WarningAtf_1 (location, "%s", message);
225 : 594 : }
226 : :
227 : : /* m2linemap_NoteAtf - wraps up a note message. */
228 : :
229 : : static void
230 : 15 : m2linemap_NoteAtf_1 (location_t location, const char *message, ...)
231 : : {
232 : 15 : diagnostic_info diagnostic;
233 : 15 : va_list ap;
234 : 15 : rich_location richloc (line_table, location);
235 : :
236 : 15 : va_start (ap, message);
237 : 15 : diagnostic_set_info (&diagnostic, message, &ap, &richloc, DK_NOTE);
238 : 15 : diagnostic_report_diagnostic (global_dc, &diagnostic);
239 : 15 : va_end (ap);
240 : 15 : }
241 : :
242 : : void
243 : 15 : m2linemap_NoteAtf (location_t location, const char *message)
244 : : {
245 : 15 : m2linemap_NoteAtf_1 (location, "%s", message);
246 : 15 : }
247 : :
248 : : /* m2linemap_internal_error - allow Modula-2 to use the GCC internal error. */
249 : :
250 : : void
251 : 0 : m2linemap_internal_error (const char *message)
252 : : {
253 : 0 : internal_error ("%s", message);
254 : : }
255 : :
256 : :
257 : : /* Code derived from rust. */
258 : :
259 : : static std::string
260 : 0 : mformat_value ()
261 : : {
262 : 0 : return std::string (xstrerror (errno));
263 : : }
264 : :
265 : :
266 : : static std::string
267 : 0 : expand_format (const char *fmt)
268 : : {
269 : 0 : std::string result;
270 : 0 : for (const char *c = fmt; *c; ++c)
271 : : {
272 : 0 : if (*c != '%')
273 : : {
274 : 0 : result += *c;
275 : 0 : continue;
276 : : }
277 : 0 : c++;
278 : 0 : switch (*c)
279 : : {
280 : 0 : case '\0': {
281 : : // malformed format string
282 : 0 : gcc_unreachable ();
283 : : }
284 : 0 : case '%': {
285 : 0 : result += '%';
286 : 0 : break;
287 : : }
288 : 0 : case 'm': {
289 : 0 : result += mformat_value ();
290 : 0 : break;
291 : : }
292 : 0 : case '<': {
293 : 0 : result += m2color_open_quote ();
294 : 0 : break;
295 : : }
296 : 0 : case '>': {
297 : 0 : result += m2color_close_quote ();
298 : 0 : break;
299 : : }
300 : 0 : case 'q': {
301 : 0 : result += m2color_open_quote ();
302 : 0 : c++;
303 : 0 : if (*c == 'm')
304 : 0 : result += mformat_value ();
305 : : else
306 : : {
307 : 0 : result += '%';
308 : 0 : result += *c;
309 : : }
310 : 0 : result += m2color_close_quote ();
311 : 0 : break;
312 : : }
313 : 0 : default: {
314 : 0 : result += '%';
315 : 0 : result += *c;
316 : : }
317 : : }
318 : : }
319 : 0 : return result;
320 : : }
321 : :
322 : : static std::string
323 : 0 : expand_message (const char *fmt, va_list ap)
324 : : {
325 : 0 : char *mbuf = 0;
326 : 0 : std::string expanded_fmt = expand_format (fmt);
327 : 0 : int nwr = vasprintf (&mbuf, expanded_fmt.c_str (), ap);
328 : 0 : if (nwr == -1)
329 : : {
330 : : // memory allocation failed
331 : 0 : error_at (UNKNOWN_LOCATION,
332 : : "memory allocation failed in vasprintf");
333 : 0 : gcc_assert (0);
334 : : }
335 : 0 : std::string rval = std::string (mbuf);
336 : 0 : free (mbuf);
337 : 0 : return rval;
338 : 0 : }
339 : :
340 : :
341 : : static void
342 : 0 : gm2_internal_error_at (location_t location, const std::string &errmsg)
343 : : {
344 : 0 : expanded_location exp_loc = expand_location (location);
345 : 0 : std::string loc_str;
346 : 0 : std::string file_str;
347 : :
348 : 0 : if (exp_loc.file == NULL)
349 : : file_str.clear ();
350 : : else
351 : 0 : file_str = std::string (exp_loc.file);
352 : :
353 : 0 : if (! file_str.empty ())
354 : : {
355 : 0 : loc_str += file_str;
356 : 0 : loc_str += ':';
357 : 0 : loc_str += std::to_string (exp_loc.line);
358 : 0 : loc_str += ':';
359 : 0 : loc_str += std::to_string (exp_loc.column);
360 : : }
361 : 0 : if (loc_str.empty ())
362 : 0 : internal_error ("%s", errmsg.c_str ());
363 : : else
364 : 0 : internal_error ("at %s, %s", loc_str.c_str (), errmsg.c_str ());
365 : : }
366 : :
367 : :
368 : : void
369 : 0 : m2linemap_internal_error_at (location_t location, const char *fmt, ...)
370 : : {
371 : 0 : va_list ap;
372 : :
373 : 0 : va_start (ap, fmt);
374 : 0 : gm2_internal_error_at (location, expand_message (fmt, ap));
375 : : va_end (ap);
376 : : }
377 : :
378 : : /* UnknownLocation - return the predefined location representing an
379 : : unknown location. */
380 : :
381 : : EXTERN
382 : : location_t
383 : 128694069 : m2linemap_UnknownLocation (void)
384 : : {
385 : 128694069 : return UNKNOWN_LOCATION;
386 : : }
387 : :
388 : : /* BuiltinsLocation - return the predefined location representing a
389 : : builtin. */
390 : :
391 : : EXTERN
392 : : location_t
393 : 5069900 : m2linemap_BuiltinsLocation (void)
394 : : {
395 : 5069900 : return BUILTINS_LOCATION;
396 : : }
|