Branch data Line data Source code
1 : : /* m2linemap.cc provides an interface to GCC linemaps.
2 : :
3 : : Copyright (C) 2012-2025 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 : 232996 : m2linemap_StartFile (void *filename, unsigned int linebegin)
54 : : {
55 : 232996 : if (inFile)
56 : 217112 : m2linemap_EndFile ();
57 : 232996 : linemap_add (line_table, LC_ENTER, false,
58 : 232996 : xstrdup (reinterpret_cast<char *> (filename)), linebegin);
59 : 232996 : inFile = TRUE;
60 : 232996 : }
61 : :
62 : : /* Tell the line table the file has ended. */
63 : :
64 : : EXTERN
65 : : void
66 : 217112 : m2linemap_EndFile (void)
67 : : {
68 : 217112 : linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
69 : 217112 : inFile = FALSE;
70 : 217112 : }
71 : :
72 : : /* Indicate that there is a new source file line number with a
73 : : maximum width. */
74 : :
75 : : EXTERN
76 : : void
77 : 42938021 : m2linemap_StartLine (unsigned int linenumber, unsigned int linesize)
78 : : {
79 : 42938021 : linemap_line_start (line_table, linenumber, linesize);
80 : 42938021 : }
81 : :
82 : : /* GetLocationColumn, returns a location_t based on the current line
83 : : number and column. */
84 : :
85 : : EXTERN
86 : : location_t
87 : 1340193332 : m2linemap_GetLocationColumn (unsigned int column)
88 : : {
89 : 1340193332 : 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 : 1340193332 : m2linemap_GetLocationRange (unsigned int start, unsigned int end)
98 : : {
99 : 1340193332 : location_t caret = m2linemap_GetLocationColumn (start);
100 : :
101 : 1340193332 : source_range where;
102 : 1340193332 : where.m_start = linemap_position_for_column (line_table, start);
103 : 1340193332 : where.m_finish = linemap_position_for_column (line_table, end);
104 : 1340193332 : 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 : 1843986 : m2linemap_GetLocationBinary (location_t caret, location_t start, location_t finish)
122 : : {
123 : 1843986 : if (isSrcLocation (start) && isSrcLocation (finish) && isSrcLocation (caret)
124 : 3687972 : && (m2linemap_GetFilenameFromLocation (start) != NULL))
125 : : {
126 : 1831506 : linemap_add (line_table, LC_ENTER, false, xstrdup (m2linemap_GetFilenameFromLocation (start)), 1);
127 : 1831506 : gcc_assert (inFile);
128 : 1831506 : location_t location = make_location (caret, start, finish);
129 : 1831506 : linemap_add (line_table, LC_LEAVE, false, NULL, 0);
130 : 1831506 : return location;
131 : : }
132 : : return caret;
133 : : }
134 : :
135 : : /* GetLineNoFromLocation - returns the lineno given a location. */
136 : :
137 : : EXTERN
138 : : int
139 : 3712 : m2linemap_GetLineNoFromLocation (location_t location)
140 : : {
141 : 3712 : if (isSrcLocation (location) && (!M2Options_GetCpp ()))
142 : : {
143 : 3100 : expanded_location xl = expand_location (location);
144 : 3100 : return xl.line;
145 : : }
146 : : return 0;
147 : : }
148 : :
149 : : /* GetColumnNoFromLocation - returns the columnno given a location. */
150 : :
151 : : EXTERN
152 : : int
153 : 3712 : m2linemap_GetColumnNoFromLocation (location_t location)
154 : : {
155 : 3712 : if (isSrcLocation (location) && (!M2Options_GetCpp ()))
156 : : {
157 : 3100 : expanded_location xl = expand_location (location);
158 : 3100 : return xl.column;
159 : : }
160 : : return 0;
161 : : }
162 : :
163 : : /* GetFilenameFromLocation - returns the filename given a location. */
164 : :
165 : : EXTERN
166 : : const char *
167 : 3679204 : m2linemap_GetFilenameFromLocation (location_t location)
168 : : {
169 : 3679204 : if (isSrcLocation (location) && (!M2Options_GetCpp ()))
170 : : {
171 : 3666112 : expanded_location xl = expand_location (location);
172 : 3666112 : return xl.file;
173 : : }
174 : : return NULL;
175 : : }
176 : :
177 : : /* ErrorAt - issue an error message. */
178 : :
179 : : EXTERN
180 : : void
181 : 0 : m2linemap_ErrorAt (location_t location, char *message)
182 : : {
183 : 0 : error_at (location, "%s", message);
184 : 0 : }
185 : :
186 : : /* m2linemap_ErrorAtf - wraps up an error message. */
187 : :
188 : : static void
189 : 3216 : m2linemap_ErrorAtf_1 (location_t location, const char *message, ...)
190 : : {
191 : 3216 : diagnostic_info diagnostic;
192 : 3216 : va_list ap;
193 : 3216 : rich_location richloc (line_table, location);
194 : :
195 : 3216 : va_start (ap, message);
196 : 3216 : diagnostic_set_info (&diagnostic, message, &ap, &richloc, DK_ERROR);
197 : 3216 : diagnostic_report_diagnostic (global_dc, &diagnostic);
198 : 3216 : va_end (ap);
199 : 3216 : }
200 : :
201 : : void
202 : 3216 : m2linemap_ErrorAtf (location_t location, const char *message)
203 : : {
204 : 3216 : m2linemap_ErrorAtf_1 (location, "%s", message);
205 : 3216 : }
206 : :
207 : : /* m2linemap_WarningAtf - wraps up a warning message. */
208 : :
209 : : static void
210 : 594 : m2linemap_WarningAtf_1 (location_t location, const char *message, ...)
211 : : {
212 : 594 : diagnostic_info diagnostic;
213 : 594 : va_list ap;
214 : 594 : rich_location richloc (line_table, location);
215 : :
216 : 594 : va_start (ap, message);
217 : 594 : diagnostic_set_info (&diagnostic, message, &ap, &richloc, DK_WARNING);
218 : 594 : diagnostic_report_diagnostic (global_dc, &diagnostic);
219 : 594 : va_end (ap);
220 : 594 : }
221 : :
222 : : void
223 : 594 : m2linemap_WarningAtf (location_t location, const char *message)
224 : : {
225 : 594 : m2linemap_WarningAtf_1 (location, "%s", message);
226 : 594 : }
227 : :
228 : : /* m2linemap_NoteAtf - wraps up a note message. */
229 : :
230 : : static void
231 : 16 : m2linemap_NoteAtf_1 (location_t location, const char *message, ...)
232 : : {
233 : 16 : diagnostic_info diagnostic;
234 : 16 : va_list ap;
235 : 16 : rich_location richloc (line_table, location);
236 : :
237 : 16 : va_start (ap, message);
238 : 16 : diagnostic_set_info (&diagnostic, message, &ap, &richloc, DK_NOTE);
239 : 16 : diagnostic_report_diagnostic (global_dc, &diagnostic);
240 : 16 : va_end (ap);
241 : 16 : }
242 : :
243 : : void
244 : 16 : m2linemap_NoteAtf (location_t location, const char *message)
245 : : {
246 : 16 : m2linemap_NoteAtf_1 (location, "%s", message);
247 : 16 : }
248 : :
249 : : /* m2linemap_internal_error - allow Modula-2 to use the GCC internal error. */
250 : :
251 : : void
252 : 0 : m2linemap_internal_error (const char *message)
253 : : {
254 : 0 : internal_error ("%s", message);
255 : : }
256 : :
257 : :
258 : : /* Code derived from rust. */
259 : :
260 : : static std::string
261 : 0 : mformat_value ()
262 : : {
263 : 0 : return std::string (xstrerror (errno));
264 : : }
265 : :
266 : :
267 : : static std::string
268 : 0 : expand_format (const char *fmt)
269 : : {
270 : 0 : std::string result;
271 : 0 : for (const char *c = fmt; *c; ++c)
272 : : {
273 : 0 : if (*c != '%')
274 : : {
275 : 0 : result += *c;
276 : 0 : continue;
277 : : }
278 : 0 : c++;
279 : 0 : switch (*c)
280 : : {
281 : 0 : case '\0': {
282 : : // malformed format string
283 : 0 : gcc_unreachable ();
284 : : }
285 : 0 : case '%': {
286 : 0 : result += '%';
287 : 0 : break;
288 : : }
289 : 0 : case 'm': {
290 : 0 : result += mformat_value ();
291 : 0 : break;
292 : : }
293 : 0 : case '<': {
294 : 0 : result += m2color_open_quote ();
295 : 0 : break;
296 : : }
297 : 0 : case '>': {
298 : 0 : result += m2color_close_quote ();
299 : 0 : break;
300 : : }
301 : 0 : case 'q': {
302 : 0 : result += m2color_open_quote ();
303 : 0 : c++;
304 : 0 : if (*c == 'm')
305 : 0 : result += mformat_value ();
306 : : else
307 : : {
308 : 0 : result += '%';
309 : 0 : result += *c;
310 : : }
311 : 0 : result += m2color_close_quote ();
312 : 0 : break;
313 : : }
314 : 0 : default: {
315 : 0 : result += '%';
316 : 0 : result += *c;
317 : : }
318 : : }
319 : : }
320 : 0 : return result;
321 : : }
322 : :
323 : : static std::string
324 : 0 : expand_message (const char *fmt, va_list ap)
325 : : {
326 : 0 : char *mbuf = 0;
327 : 0 : std::string expanded_fmt = expand_format (fmt);
328 : 0 : int nwr = vasprintf (&mbuf, expanded_fmt.c_str (), ap);
329 : 0 : if (nwr == -1)
330 : : {
331 : : // memory allocation failed
332 : 0 : error_at (UNKNOWN_LOCATION,
333 : : "memory allocation failed in vasprintf");
334 : 0 : gcc_assert (0);
335 : : }
336 : 0 : std::string rval = std::string (mbuf);
337 : 0 : free (mbuf);
338 : 0 : return rval;
339 : 0 : }
340 : :
341 : :
342 : : static void
343 : 0 : gm2_internal_error_at (location_t location, const std::string &errmsg)
344 : : {
345 : 0 : expanded_location exp_loc = expand_location (location);
346 : 0 : std::string loc_str;
347 : 0 : std::string file_str;
348 : :
349 : 0 : if (exp_loc.file == NULL)
350 : : file_str.clear ();
351 : : else
352 : 0 : file_str = std::string (exp_loc.file);
353 : :
354 : 0 : if (! file_str.empty ())
355 : : {
356 : 0 : loc_str += file_str;
357 : 0 : loc_str += ':';
358 : 0 : loc_str += std::to_string (exp_loc.line);
359 : 0 : loc_str += ':';
360 : 0 : loc_str += std::to_string (exp_loc.column);
361 : : }
362 : 0 : if (loc_str.empty ())
363 : 0 : internal_error ("%s", errmsg.c_str ());
364 : : else
365 : 0 : internal_error ("at %s, %s", loc_str.c_str (), errmsg.c_str ());
366 : : }
367 : :
368 : :
369 : : void
370 : 0 : m2linemap_internal_error_at (location_t location, const char *fmt, ...)
371 : : {
372 : 0 : va_list ap;
373 : :
374 : 0 : va_start (ap, fmt);
375 : 0 : gm2_internal_error_at (location, expand_message (fmt, ap));
376 : : va_end (ap);
377 : : }
378 : :
379 : : /* UnknownLocation - return the predefined location representing an
380 : : unknown location. */
381 : :
382 : : EXTERN
383 : : location_t
384 : 111229756 : m2linemap_UnknownLocation (void)
385 : : {
386 : 111229756 : return UNKNOWN_LOCATION;
387 : : }
388 : :
389 : : /* BuiltinsLocation - return the predefined location representing a
390 : : builtin. */
391 : :
392 : : EXTERN
393 : : location_t
394 : 3643132 : m2linemap_BuiltinsLocation (void)
395 : : {
396 : 3643132 : return BUILTINS_LOCATION;
397 : : }
|