/src/binutils-gdb/gas/input-scrub.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* input_scrub.c - Break up input buffers into whole numbers of lines. |
2 | | Copyright (C) 1987-2025 Free Software Foundation, Inc. |
3 | | |
4 | | This file is part of GAS, the GNU Assembler. |
5 | | |
6 | | GAS 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, or (at your option) |
9 | | any later version. |
10 | | |
11 | | GAS 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. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with GAS; see the file COPYING. If not, write to the Free |
18 | | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA |
19 | | 02110-1301, USA. */ |
20 | | |
21 | | #include "as.h" |
22 | | #include "filenames.h" |
23 | | #include "input-file.h" |
24 | | #include "sb.h" |
25 | | #include "listing.h" |
26 | | |
27 | | /* |
28 | | * O/S independent module to supply buffers of sanitised source code |
29 | | * to rest of assembler. We get sanitised input data of arbitrary length. |
30 | | * We break these buffers on line boundaries, recombine pieces that |
31 | | * were broken across buffers, and return a buffer of full lines to |
32 | | * the caller. |
33 | | * The last partial line begins the next buffer we build and return to caller. |
34 | | * The buffer returned to caller is preceded by BEFORE_STRING and followed |
35 | | * by AFTER_STRING, as sentinels. The last character before AFTER_STRING |
36 | | * is a newline. |
37 | | * Also looks after line numbers, for e.g. error messages. |
38 | | */ |
39 | | |
40 | | /* |
41 | | * We don't care how filthy our buffers are, but our callers assume |
42 | | * that the following sanitation has already been done. |
43 | | * |
44 | | * No comments, reduce a comment to a space. |
45 | | * Reduce a tab to a space unless it is 1st char of line. |
46 | | * All multiple tabs and spaces collapsed into 1 char. Tab only |
47 | | * legal if 1st char of line. |
48 | | * # line file statements converted to .line x;.file y; statements. |
49 | | * Escaped newlines at end of line: remove them but add as many newlines |
50 | | * to end of statement as you removed in the middle, to synch line numbers. |
51 | | */ |
52 | | |
53 | 1.41k | #define BEFORE_STRING ("\n") |
54 | 501 | #define AFTER_STRING ("\0") /* memcpy of 0 chars might choke. */ |
55 | 4.05k | #define BEFORE_SIZE (1) |
56 | 1.45k | #define AFTER_SIZE (1) |
57 | | |
58 | | #ifndef TC_EOL_IN_INSN |
59 | 497 | #define TC_EOL_IN_INSN(P) 0 |
60 | | #endif |
61 | | |
62 | | static char *buffer_start; /*->1st char of full buffer area. */ |
63 | | static char *partial_where; /*->after last full line in buffer. */ |
64 | | static size_t partial_size; /* >=0. Number of chars in partial line in buffer. */ |
65 | | |
66 | | /* Because we need AFTER_STRING just after last full line, it clobbers |
67 | | 1st part of partial line. So we preserve 1st part of partial line |
68 | | here. */ |
69 | | static char save_source[AFTER_SIZE]; |
70 | | |
71 | | /* The size of the input buffer we concatenate |
72 | | input_file_give_next_buffer chunks into. Excludes the BEFORE and |
73 | | AFTER counts. */ |
74 | | static size_t buffer_length; |
75 | | |
76 | | /* The index into an sb structure we are reading from. -1 if none. */ |
77 | | static size_t sb_index = -1; |
78 | | |
79 | | /* If we are reading from an sb structure, this is it. */ |
80 | | static sb from_sb; |
81 | | |
82 | | /* Should we do a conditional check on from_sb? */ |
83 | | static enum expansion from_sb_expansion = expanding_none; |
84 | | |
85 | | /* The number of nested sb structures we have included. */ |
86 | | int macro_nest; |
87 | | |
88 | | /* We can have more than one source file open at once, though the info for all |
89 | | but the latest one are saved off in a struct input_save. These files remain |
90 | | open, so we are limited by the number of open files allowed by the |
91 | | underlying OS. We may also sequentially read more than one source file in an |
92 | | assembly. */ |
93 | | |
94 | | /* We must track the physical file and line number for error messages. We also |
95 | | track a "logical" file and line number corresponding to (C?) compiler |
96 | | source line numbers. Whenever we open a file we must fill in |
97 | | physical_input_file. So if it is NULL we have not opened any files yet. */ |
98 | | |
99 | | static const char *physical_input_file; |
100 | | static const char *logical_input_file; |
101 | | |
102 | | /* 1-origin line number in a source file. */ |
103 | | /* A line ends in '\n' or eof. */ |
104 | | static unsigned int physical_input_line; |
105 | | static unsigned int logical_input_line; |
106 | | |
107 | | /* Indicator whether the origin of an update was a .linefile directive. */ |
108 | | static bool is_linefile; |
109 | | |
110 | | /* Struct used to save the state of the input handler during include files */ |
111 | | struct input_save { |
112 | | char * buffer_start; |
113 | | char * partial_where; |
114 | | size_t partial_size; |
115 | | char save_source[AFTER_SIZE]; |
116 | | size_t buffer_length; |
117 | | const char * physical_input_file; |
118 | | const char * logical_input_file; |
119 | | unsigned int physical_input_line; |
120 | | unsigned int logical_input_line; |
121 | | bool is_linefile; |
122 | | size_t sb_index; |
123 | | sb from_sb; |
124 | | enum expansion from_sb_expansion; /* Should we do a conditional check? */ |
125 | | struct input_save * next_saved_file; /* Chain of input_saves. */ |
126 | | char * input_file_save; /* Saved state of input routines. */ |
127 | | char * saved_position; /* Caller's saved position in buf. */ |
128 | | }; |
129 | | |
130 | | static struct input_save *input_scrub_push (char *saved_position); |
131 | | static char *input_scrub_pop (struct input_save *arg); |
132 | | |
133 | | /* Saved information about the file that .include'd this one. When we hit EOF, |
134 | | we automatically pop to that file. */ |
135 | | |
136 | | static struct input_save *next_saved_file; |
137 | | |
138 | | /* Initialize input buffering. */ |
139 | | |
140 | | static void |
141 | | input_scrub_reinit (void) |
142 | 1.41k | { |
143 | 1.41k | input_file_begin (); /* Reinitialize! */ |
144 | 1.41k | logical_input_line = -1u; |
145 | 1.41k | logical_input_file = NULL; |
146 | 1.41k | sb_index = -1; |
147 | | |
148 | 1.41k | buffer_length = input_file_buffer_size () * 2; |
149 | 1.41k | buffer_start = XNEWVEC (char, BEFORE_SIZE + AFTER_SIZE + 1 + buffer_length); |
150 | 1.41k | memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE); |
151 | 1.41k | } |
152 | | |
153 | | /* Finish off old buffers. */ |
154 | | |
155 | | static void |
156 | | input_scrub_free (void) |
157 | 1.41k | { |
158 | 1.41k | if (sb_index != (size_t) -1) |
159 | 1.38k | { |
160 | 1.38k | sb_kill (&from_sb); |
161 | 1.38k | sb_index = -1; |
162 | 1.38k | } |
163 | 1.41k | free (buffer_start); |
164 | 1.41k | buffer_start = NULL; |
165 | 1.41k | input_file_end (); |
166 | 1.41k | } |
167 | | |
168 | | /* Push the state of input reading and scrubbing so that we can #include. |
169 | | The return value is a 'void *' (fudged for old compilers) to a save |
170 | | area, which can be restored by passing it to input_scrub_pop(). */ |
171 | | |
172 | | static struct input_save * |
173 | | input_scrub_push (char *saved_position) |
174 | 1.38k | { |
175 | 1.38k | struct input_save *saved; |
176 | | |
177 | 1.38k | saved = XNEW (struct input_save); |
178 | | |
179 | 1.38k | saved->saved_position = saved_position; |
180 | 1.38k | saved->buffer_start = buffer_start; |
181 | 1.38k | saved->partial_where = partial_where; |
182 | 1.38k | saved->partial_size = partial_size; |
183 | 1.38k | saved->buffer_length = buffer_length; |
184 | 1.38k | saved->physical_input_file = physical_input_file; |
185 | 1.38k | saved->logical_input_file = logical_input_file; |
186 | 1.38k | saved->physical_input_line = physical_input_line; |
187 | 1.38k | saved->logical_input_line = logical_input_line; |
188 | 1.38k | saved->is_linefile = is_linefile; |
189 | 1.38k | saved->sb_index = sb_index; |
190 | 1.38k | saved->from_sb = from_sb; |
191 | 1.38k | saved->from_sb_expansion = from_sb_expansion; |
192 | 1.38k | memcpy (saved->save_source, save_source, sizeof (save_source)); |
193 | 1.38k | saved->next_saved_file = next_saved_file; |
194 | 1.38k | saved->input_file_save = input_file_push (); |
195 | | |
196 | 1.38k | input_scrub_reinit (); |
197 | | |
198 | 1.38k | return saved; |
199 | 1.38k | } |
200 | | |
201 | | static char * |
202 | | input_scrub_pop (struct input_save *saved) |
203 | 1.38k | { |
204 | 1.38k | char *saved_position; |
205 | | |
206 | 1.38k | input_scrub_free (); |
207 | | |
208 | 1.38k | input_file_pop (saved->input_file_save); |
209 | 1.38k | saved_position = saved->saved_position; |
210 | 1.38k | buffer_start = saved->buffer_start; |
211 | 1.38k | buffer_length = saved->buffer_length; |
212 | | |
213 | | /* When expanding an #APP / #NO_APP block, original lines are re- |
214 | | processed, so whatever they did to physical file/line needs |
215 | | retaining. If logical file/line weren't changed, the logical |
216 | | line number will want bumping by a corresponding value. */ |
217 | 1.38k | if (from_sb_expansion != expanding_app) |
218 | 1.28k | { |
219 | 1.28k | if (logical_input_file == 0 && logical_input_line == -1u |
220 | 1.28k | && saved->logical_input_line != -1u) |
221 | 0 | saved->logical_input_line |
222 | 0 | += physical_input_line - saved->physical_input_line; |
223 | 1.28k | physical_input_file = saved->physical_input_file; |
224 | 1.28k | physical_input_line = saved->physical_input_line; |
225 | 1.28k | } |
226 | 1.38k | logical_input_file = saved->logical_input_file; |
227 | 1.38k | logical_input_line = saved->logical_input_line; |
228 | | |
229 | 1.38k | is_linefile = saved->is_linefile; |
230 | 1.38k | sb_index = saved->sb_index; |
231 | 1.38k | from_sb = saved->from_sb; |
232 | 1.38k | from_sb_expansion = saved->from_sb_expansion; |
233 | 1.38k | partial_where = saved->partial_where; |
234 | 1.38k | partial_size = saved->partial_size; |
235 | 1.38k | next_saved_file = saved->next_saved_file; |
236 | 1.38k | memcpy (save_source, saved->save_source, sizeof (save_source)); |
237 | | |
238 | 1.38k | free (saved); |
239 | 1.38k | return saved_position; |
240 | 1.38k | } |
241 | | |
242 | | void |
243 | | input_scrub_begin (void) |
244 | 28 | { |
245 | 28 | know (strlen (BEFORE_STRING) == BEFORE_SIZE); |
246 | 28 | know (strlen (AFTER_STRING) == AFTER_SIZE |
247 | 28 | || (AFTER_STRING[0] == '\0' && AFTER_SIZE == 1)); |
248 | | |
249 | 28 | physical_input_file = NULL; /* No file read yet. */ |
250 | 28 | next_saved_file = NULL; /* At EOF, don't pop to any other file */ |
251 | 28 | macro_nest = 0; |
252 | 28 | input_scrub_reinit (); |
253 | 28 | do_scrub_begin (flag_m68k_mri); |
254 | 28 | } |
255 | | |
256 | | void |
257 | | input_scrub_end (void) |
258 | 28 | { |
259 | 28 | while (next_saved_file != NULL) |
260 | 0 | input_scrub_pop (next_saved_file); |
261 | 28 | input_scrub_free (); |
262 | 28 | } |
263 | | |
264 | | /* Start reading input from a new file. |
265 | | Return start of caller's part of buffer. */ |
266 | | |
267 | | char * |
268 | | input_scrub_new_file (const char *filename) |
269 | 28 | { |
270 | 28 | input_file_open (filename, !flag_no_comments); |
271 | 28 | physical_input_file = filename[0] ? filename : _("{standard input}"); |
272 | 28 | physical_input_line = 0; |
273 | | |
274 | 28 | partial_size = 0; |
275 | 28 | return (buffer_start + BEFORE_SIZE); |
276 | 28 | } |
277 | | |
278 | | /* Include a file from the current file. Save our state, cause it to |
279 | | be restored on EOF, and begin handling a new file. Same result as |
280 | | input_scrub_new_file. */ |
281 | | |
282 | | char * |
283 | | input_scrub_include_file (const char *filename, char *position) |
284 | 0 | { |
285 | 0 | next_saved_file = input_scrub_push (position); |
286 | 0 | from_sb_expansion = expanding_none; |
287 | 0 | return input_scrub_new_file (filename); |
288 | 0 | } |
289 | | |
290 | | /* Start getting input from an sb structure. This is used when |
291 | | expanding a macro. */ |
292 | | |
293 | | void |
294 | | input_scrub_include_sb (sb *from, char *position, enum expansion expansion) |
295 | 1.38k | { |
296 | 1.38k | int newline; |
297 | | |
298 | 1.38k | if (expansion != expanding_app) |
299 | 1.28k | { |
300 | 1.28k | if (macro_nest > max_macro_nest) |
301 | 0 | as_fatal (_("macros nested too deeply")); |
302 | 1.28k | ++macro_nest; |
303 | 1.28k | } |
304 | | |
305 | | #ifdef md_macro_start |
306 | | if (expansion == expanding_macro) |
307 | | { |
308 | | md_macro_start (); |
309 | | } |
310 | | #endif |
311 | | |
312 | 1.38k | next_saved_file = input_scrub_push (position); |
313 | | |
314 | | /* Allocate sufficient space: from->len plus optional newline |
315 | | plus two ".linefile " directives, plus a little more for other |
316 | | expansion. */ |
317 | 1.38k | newline = from->len >= 1 && from->ptr[0] != '\n'; |
318 | 1.38k | sb_build (&from_sb, from->len + newline + 2 * sizeof (".linefile") + 30); |
319 | 1.38k | from_sb_expansion = expansion; |
320 | 1.38k | if (newline) |
321 | 1.09k | { |
322 | | /* Add the sentinel required by read.c. */ |
323 | 1.09k | sb_add_char (&from_sb, '\n'); |
324 | 1.09k | } |
325 | 1.38k | sb_scrub_and_add_sb (&from_sb, from); |
326 | | |
327 | | /* Make sure the parser looks at defined contents when it scans for |
328 | | e.g. end-of-line at the end of a macro. */ |
329 | 1.38k | sb_terminate (&from_sb); |
330 | | |
331 | 1.38k | sb_index = 1; |
332 | | |
333 | | /* These variables are reset by input_scrub_push. Restore them |
334 | | since we are, after all, still at the same point in the file. */ |
335 | 1.38k | logical_input_line = next_saved_file->logical_input_line; |
336 | 1.38k | logical_input_file = next_saved_file->logical_input_file; |
337 | 1.38k | } |
338 | | |
339 | | void |
340 | | input_scrub_close (void) |
341 | 28 | { |
342 | 28 | input_file_close (); |
343 | 28 | physical_input_line = 0; |
344 | 28 | logical_input_line = -1u; |
345 | 28 | } |
346 | | |
347 | | char * |
348 | | input_scrub_next_buffer (char **bufp) |
349 | 3.01k | { |
350 | 3.01k | char *limit; /*->just after last char of buffer. */ |
351 | | |
352 | 3.01k | if (sb_index != (size_t) -1) |
353 | 2.48k | { |
354 | 2.48k | if (sb_index >= from_sb.len) |
355 | 1.38k | { |
356 | 1.38k | if (from_sb_expansion == expanding_macro) |
357 | 1.18k | { |
358 | 1.18k | cond_finish_check (macro_nest); |
359 | | #ifdef md_macro_end |
360 | | /* Allow the target to clean up per-macro expansion |
361 | | data. */ |
362 | | md_macro_end (); |
363 | | #endif |
364 | 1.18k | } |
365 | 1.38k | if (from_sb_expansion != expanding_app) |
366 | 1.28k | --macro_nest; |
367 | 1.38k | partial_where = NULL; |
368 | 1.38k | partial_size = 0; |
369 | 1.38k | if (next_saved_file != NULL) |
370 | 1.38k | *bufp = input_scrub_pop (next_saved_file); |
371 | 1.38k | return partial_where; |
372 | 1.38k | } |
373 | | |
374 | 1.09k | partial_where = from_sb.ptr + from_sb.len; |
375 | 1.09k | partial_size = 0; |
376 | 1.09k | *bufp = from_sb.ptr + sb_index; |
377 | 1.09k | sb_index = from_sb.len; |
378 | 1.09k | return partial_where; |
379 | 2.48k | } |
380 | | |
381 | 529 | if (partial_size) |
382 | 452 | { |
383 | 452 | memmove (buffer_start + BEFORE_SIZE, partial_where, partial_size); |
384 | 452 | memcpy (buffer_start + BEFORE_SIZE, save_source, AFTER_SIZE); |
385 | 452 | } |
386 | | |
387 | 744 | while (1) |
388 | 744 | { |
389 | 744 | char *p; |
390 | 744 | char *start = buffer_start + BEFORE_SIZE + partial_size; |
391 | | |
392 | 744 | *bufp = buffer_start + BEFORE_SIZE; |
393 | 744 | limit = input_file_give_next_buffer (start); |
394 | 744 | if (!limit) |
395 | 32 | { |
396 | 32 | if (!partial_size) |
397 | | /* End of this file. */ |
398 | 28 | break; |
399 | | |
400 | 4 | as_warn (_("end of file not at end of a line; newline inserted")); |
401 | 4 | p = buffer_start + BEFORE_SIZE + partial_size; |
402 | 4 | *p++ = '\n'; |
403 | 4 | limit = p; |
404 | 4 | } |
405 | 712 | else |
406 | 712 | { |
407 | | /* Terminate the buffer to avoid confusing TC_EOL_IN_INSN. */ |
408 | 712 | *limit = '\0'; |
409 | | |
410 | | /* Find last newline. */ |
411 | 8.27M | for (p = limit - 1; *p != '\n' || TC_EOL_IN_INSN (p); --p) |
412 | 8.27M | if (p < start) |
413 | 215 | goto read_more; |
414 | 497 | ++p; |
415 | 497 | } |
416 | | |
417 | | /* We found a newline in the newly read chars. */ |
418 | 501 | partial_where = p; |
419 | 501 | partial_size = limit - p; |
420 | | |
421 | | /* Save the fragment after that last newline. */ |
422 | 501 | memcpy (save_source, partial_where, (int) AFTER_SIZE); |
423 | 501 | memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE); |
424 | 501 | return partial_where; |
425 | | |
426 | 215 | read_more: |
427 | | /* Didn't find a newline. Read more text. */ |
428 | 215 | partial_size = limit - (buffer_start + BEFORE_SIZE); |
429 | 215 | if (buffer_length - input_file_buffer_size () < partial_size) |
430 | 40 | { |
431 | | /* Increase the buffer when it doesn't have room for the |
432 | | next block of input. */ |
433 | 40 | buffer_length *= 2; |
434 | 40 | buffer_start = XRESIZEVEC (char, buffer_start, |
435 | 40 | (buffer_length |
436 | 40 | + BEFORE_SIZE + AFTER_SIZE + 1)); |
437 | 40 | } |
438 | 215 | } |
439 | | |
440 | | /* Tell the listing we've finished the file. */ |
441 | 28 | LISTING_EOF (); |
442 | | |
443 | | /* If we should pop to another file at EOF, do it. */ |
444 | 28 | partial_where = NULL; |
445 | 28 | if (next_saved_file) |
446 | 0 | *bufp = input_scrub_pop (next_saved_file); |
447 | | |
448 | 28 | return partial_where; |
449 | 529 | } |
450 | | |
451 | | /* The remaining part of this file deals with line numbers, error |
452 | | messages and so on. Return TRUE if we opened any file. */ |
453 | | |
454 | | int |
455 | | seen_at_least_1_file (void) |
456 | 0 | { |
457 | 0 | return (physical_input_file != NULL); |
458 | 0 | } |
459 | | |
460 | | void |
461 | | bump_line_counters (void) |
462 | 762k | { |
463 | 762k | if (sb_index == (size_t) -1 || from_sb_expansion == expanding_app) |
464 | 483k | ++physical_input_line; |
465 | | |
466 | 762k | if (logical_input_line != -1u) |
467 | 340k | ++logical_input_line; |
468 | 762k | } |
469 | | |
470 | | /* Tells us what the new logical line number and file are. |
471 | | If the line_number is -1, we don't change the current logical line |
472 | | number. |
473 | | If fname is NULL, we don't change the current logical file name, unless |
474 | | bit 3 of flags is set. |
475 | | Returns nonzero if the filename actually changes. */ |
476 | | |
477 | | void |
478 | | new_logical_line_flags (const char *fname, /* DON'T destroy it! We point to it! */ |
479 | | int line_number, |
480 | | int flags) |
481 | 39.6k | { |
482 | 39.6k | switch (flags) |
483 | 39.6k | { |
484 | 1.10k | case 0: |
485 | 1.10k | break; |
486 | 432 | case 1: |
487 | 432 | if (line_number != -1) |
488 | 0 | abort (); |
489 | 432 | break; |
490 | 432 | case 1 << 1: |
491 | 9 | case 1 << 2: |
492 | | /* FIXME: we could check that include nesting is correct. */ |
493 | 9 | break; |
494 | 38.1k | case 1 << 3: |
495 | 38.1k | if (line_number < 0 || fname != NULL) |
496 | 0 | abort (); |
497 | 38.1k | if (next_saved_file == NULL) |
498 | 0 | fname = physical_input_file; |
499 | 38.1k | else if (next_saved_file->logical_input_file) |
500 | 4.46k | fname = next_saved_file->logical_input_file; |
501 | 33.6k | else |
502 | 33.6k | fname = next_saved_file->physical_input_file; |
503 | 38.1k | break; |
504 | 0 | default: |
505 | 0 | abort (); |
506 | 39.6k | } |
507 | | |
508 | 39.6k | is_linefile = flags != 1 && (flags != 0 || fname); |
509 | | |
510 | 39.6k | if (line_number >= 0) |
511 | 39.2k | logical_input_line = line_number; |
512 | 456 | else if (line_number == -1 && fname && !*fname && (flags & (1 << 2))) |
513 | 0 | { |
514 | 0 | logical_input_file = physical_input_file; |
515 | 0 | logical_input_line = physical_input_line; |
516 | 0 | fname = NULL; |
517 | 0 | } |
518 | | |
519 | 39.6k | if (fname |
520 | 39.6k | && (logical_input_file == NULL |
521 | 39.5k | || filename_cmp (logical_input_file, fname))) |
522 | 1.07k | logical_input_file = fname; |
523 | 39.6k | } |
524 | | |
525 | | void |
526 | | new_logical_line (const char *fname, int line_number) |
527 | 137 | { |
528 | 137 | new_logical_line_flags (fname, line_number, 0); |
529 | 137 | } |
530 | | |
531 | | void |
532 | | as_report_context (void) |
533 | 986k | { |
534 | 986k | const struct input_save *saved = next_saved_file; |
535 | 986k | enum expansion expansion = from_sb_expansion; |
536 | 986k | int indent = 1; |
537 | | |
538 | 986k | if (!macro_nest) |
539 | 708k | return; |
540 | | |
541 | 278k | do |
542 | 314k | { |
543 | 314k | if (expansion != expanding_macro) |
544 | 311k | /* Nothing. */; |
545 | 2.73k | else if (saved->logical_input_file != NULL |
546 | 2.73k | && saved->logical_input_line != -1u) |
547 | 2.65k | as_info_where (saved->logical_input_file, saved->logical_input_line, |
548 | 2.65k | indent, _("macro invoked from here")); |
549 | 76 | else |
550 | 76 | as_info_where (saved->physical_input_file, saved->physical_input_line, |
551 | 76 | indent, _("macro invoked from here")); |
552 | | |
553 | 314k | expansion = saved->from_sb_expansion; |
554 | 314k | ++indent; |
555 | 314k | } |
556 | 314k | while ((saved = saved->next_saved_file) != NULL); |
557 | 278k | } |
558 | | |
559 | | /* Return the current physical input file name and line number, if known */ |
560 | | |
561 | | const char * |
562 | | as_where_physical (unsigned int *linep) |
563 | 584k | { |
564 | 584k | if (physical_input_file != NULL) |
565 | 584k | { |
566 | 584k | if (linep != NULL) |
567 | 584k | *linep = physical_input_line; |
568 | 584k | return physical_input_file; |
569 | 584k | } |
570 | | |
571 | 0 | if (linep != NULL) |
572 | 0 | *linep = 0; |
573 | 0 | return NULL; |
574 | 584k | } |
575 | | |
576 | | /* Return the file name and line number at the top most macro |
577 | | invocation, unless .file / .line were used inside a macro. */ |
578 | | |
579 | | const char * |
580 | | as_where (unsigned int *linep) |
581 | 57.1k | { |
582 | 57.1k | const char *file = as_where_top (linep); |
583 | | |
584 | 57.1k | if (macro_nest && is_linefile) |
585 | 22.2k | { |
586 | 22.2k | const struct input_save *saved = next_saved_file; |
587 | 22.2k | enum expansion expansion = from_sb_expansion; |
588 | | |
589 | 22.2k | do |
590 | 41.1k | { |
591 | 41.1k | if (expansion != expanding_macro) |
592 | 40.8k | /* Nothing. */; |
593 | 340 | else if (saved->logical_input_file != NULL |
594 | 340 | && (linep == NULL || saved->logical_input_line != -1u)) |
595 | 332 | { |
596 | 332 | if (linep != NULL) |
597 | 332 | *linep = saved->logical_input_line; |
598 | 332 | file = saved->logical_input_file; |
599 | 332 | } |
600 | 8 | else if (saved->physical_input_file != NULL) |
601 | 8 | { |
602 | 8 | if (linep != NULL) |
603 | 8 | *linep = saved->physical_input_line; |
604 | 8 | file = saved->physical_input_file; |
605 | 8 | } |
606 | | |
607 | 41.1k | expansion = saved->from_sb_expansion; |
608 | 41.1k | } |
609 | 41.1k | while ((saved = saved->next_saved_file) != NULL); |
610 | 22.2k | } |
611 | | |
612 | 57.1k | return file; |
613 | 57.1k | } |
614 | | |
615 | | /* Return the current file name and line number. */ |
616 | | |
617 | | const char * |
618 | | as_where_top (unsigned int *linep) |
619 | 1.04M | { |
620 | 1.04M | if (logical_input_file != NULL |
621 | 1.04M | && (linep == NULL || logical_input_line != -1u)) |
622 | 461k | { |
623 | 461k | if (linep != NULL) |
624 | 461k | *linep = logical_input_line; |
625 | 461k | return logical_input_file; |
626 | 461k | } |
627 | | |
628 | 584k | return as_where_physical (linep); |
629 | 1.04M | } |