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