1 /* input_scrub.c - Break up input buffers into whole numbers of lines.
2 Copyright (C) 1987-2024 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
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)
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.
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
22 #include "filenames.h"
23 #include "input-file.h"
29 * O/S independent module to supply buffers of sanitised source code
30 * to rest of assembler. We get sanitised input data of arbitrary length.
31 * We break these buffers on line boundaries, recombine pieces that
32 * were broken across buffers, and return a buffer of full lines to
34 * The last partial line begins the next buffer we build and return to caller.
35 * The buffer returned to caller is preceded by BEFORE_STRING and followed
36 * by AFTER_STRING, as sentinels. The last character before AFTER_STRING
38 * Also looks after line numbers, for e.g. error messages.
42 * We don't care how filthy our buffers are, but our callers assume
43 * that the following sanitation has already been done.
45 * No comments, reduce a comment to a space.
46 * Reduce a tab to a space unless it is 1st char of line.
47 * All multiple tabs and spaces collapsed into 1 char. Tab only
48 * legal if 1st char of line.
49 * # line file statements converted to .line x;.file y; statements.
50 * Escaped newlines at end of line: remove them but add as many newlines
51 * to end of statement as you removed in the middle, to synch line numbers.
54 #define BEFORE_STRING ("\n")
55 #define AFTER_STRING ("\0") /* memcpy of 0 chars might choke. */
56 #define BEFORE_SIZE (1)
57 #define AFTER_SIZE (1)
59 #ifndef TC_EOL_IN_INSN
60 #define TC_EOL_IN_INSN(P) 0
63 static char *buffer_start
; /*->1st char of full buffer area. */
64 static char *partial_where
; /*->after last full line in buffer. */
65 static size_t partial_size
; /* >=0. Number of chars in partial line in buffer. */
67 /* Because we need AFTER_STRING just after last full line, it clobbers
68 1st part of partial line. So we preserve 1st part of partial line
70 static char save_source
[AFTER_SIZE
];
72 /* The size of the input buffer we concatenate
73 input_file_give_next_buffer chunks into. Excludes the BEFORE and
75 static size_t buffer_length
;
77 /* The index into an sb structure we are reading from. -1 if none. */
78 static size_t sb_index
= -1;
80 /* If we are reading from an sb structure, this is it. */
83 /* Should we do a conditional check on from_sb? */
84 static enum expansion from_sb_expansion
= expanding_none
;
86 /* The number of nested sb structures we have included. */
89 /* We can have more than one source file open at once, though the info for all
90 but the latest one are saved off in a struct input_save. These files remain
91 open, so we are limited by the number of open files allowed by the
92 underlying OS. We may also sequentially read more than one source file in an
95 /* We must track the physical file and line number for error messages. We also
96 track a "logical" file and line number corresponding to (C?) compiler
97 source line numbers. Whenever we open a file we must fill in
98 physical_input_file. So if it is NULL we have not opened any files yet. */
100 static const char *physical_input_file
;
101 static const char *logical_input_file
;
103 /* 1-origin line number in a source file. */
104 /* A line ends in '\n' or eof. */
105 static unsigned int physical_input_line
;
106 static unsigned int logical_input_line
;
108 /* Indicator whether the origin of an update was a .linefile directive. */
109 static bool is_linefile
;
111 /* Struct used to save the state of the input handler during include files */
114 char * partial_where
;
116 char save_source
[AFTER_SIZE
];
117 size_t buffer_length
;
118 const char * physical_input_file
;
119 const char * logical_input_file
;
120 unsigned int physical_input_line
;
121 unsigned int logical_input_line
;
125 enum expansion from_sb_expansion
; /* Should we do a conditional check? */
126 struct input_save
* next_saved_file
; /* Chain of input_saves. */
127 char * input_file_save
; /* Saved state of input routines. */
128 char * saved_position
; /* Caller's saved position in buf. */
131 static struct input_save
*input_scrub_push (char *saved_position
);
132 static char *input_scrub_pop (struct input_save
*arg
);
134 /* Saved information about the file that .include'd this one. When we hit EOF,
135 we automatically pop to that file. */
137 static struct input_save
*next_saved_file
;
139 /* Initialize input buffering. */
142 input_scrub_reinit (void)
144 input_file_begin (); /* Reinitialize! */
145 logical_input_line
= -1u;
146 logical_input_file
= NULL
;
149 buffer_length
= input_file_buffer_size () * 2;
150 buffer_start
= XNEWVEC (char, BEFORE_SIZE
+ AFTER_SIZE
+ 1 + buffer_length
);
151 memcpy (buffer_start
, BEFORE_STRING
, (int) BEFORE_SIZE
);
154 /* Push the state of input reading and scrubbing so that we can #include.
155 The return value is a 'void *' (fudged for old compilers) to a save
156 area, which can be restored by passing it to input_scrub_pop(). */
158 static struct input_save
*
159 input_scrub_push (char *saved_position
)
161 struct input_save
*saved
;
163 saved
= XNEW (struct input_save
);
165 saved
->saved_position
= saved_position
;
166 saved
->buffer_start
= buffer_start
;
167 saved
->partial_where
= partial_where
;
168 saved
->partial_size
= partial_size
;
169 saved
->buffer_length
= buffer_length
;
170 saved
->physical_input_file
= physical_input_file
;
171 saved
->logical_input_file
= logical_input_file
;
172 saved
->physical_input_line
= physical_input_line
;
173 saved
->logical_input_line
= logical_input_line
;
174 saved
->is_linefile
= is_linefile
;
175 saved
->sb_index
= sb_index
;
176 saved
->from_sb
= from_sb
;
177 saved
->from_sb_expansion
= from_sb_expansion
;
178 memcpy (saved
->save_source
, save_source
, sizeof (save_source
));
179 saved
->next_saved_file
= next_saved_file
;
180 saved
->input_file_save
= input_file_push ();
182 input_scrub_reinit ();
188 input_scrub_pop (struct input_save
*saved
)
190 char *saved_position
;
192 input_scrub_end (); /* Finish off old buffer */
194 input_file_pop (saved
->input_file_save
);
195 saved_position
= saved
->saved_position
;
196 buffer_start
= saved
->buffer_start
;
197 buffer_length
= saved
->buffer_length
;
199 /* When expanding an #APP / #NO_APP block, original lines are re-
200 processed, so whatever they did to physical file/line needs
201 retaining. If logical file/line weren't changed, the logical
202 line number will want bumping by a corresponding value. */
203 if (from_sb_expansion
!= expanding_app
)
205 if (logical_input_file
== 0 && logical_input_line
== -1u
206 && saved
->logical_input_line
!= -1u)
207 saved
->logical_input_line
208 += physical_input_line
- saved
->physical_input_line
;
209 physical_input_file
= saved
->physical_input_file
;
210 physical_input_line
= saved
->physical_input_line
;
212 logical_input_file
= saved
->logical_input_file
;
213 logical_input_line
= saved
->logical_input_line
;
215 is_linefile
= saved
->is_linefile
;
216 sb_index
= saved
->sb_index
;
217 from_sb
= saved
->from_sb
;
218 from_sb_expansion
= saved
->from_sb_expansion
;
219 partial_where
= saved
->partial_where
;
220 partial_size
= saved
->partial_size
;
221 next_saved_file
= saved
->next_saved_file
;
222 memcpy (save_source
, saved
->save_source
, sizeof (save_source
));
225 return saved_position
;
229 input_scrub_begin (void)
231 know (strlen (BEFORE_STRING
) == BEFORE_SIZE
);
232 know (strlen (AFTER_STRING
) == AFTER_SIZE
233 || (AFTER_STRING
[0] == '\0' && AFTER_SIZE
== 1));
235 physical_input_file
= NULL
; /* No file read yet. */
236 next_saved_file
= NULL
; /* At EOF, don't pop to any other file */
238 input_scrub_reinit ();
239 do_scrub_begin (flag_m68k_mri
);
243 input_scrub_end (void)
253 /* Start reading input from a new file.
254 Return start of caller's part of buffer. */
257 input_scrub_new_file (const char *filename
)
259 input_file_open (filename
, !flag_no_comments
);
260 physical_input_file
= filename
[0] ? filename
: _("{standard input}");
261 physical_input_line
= 0;
264 return (buffer_start
+ BEFORE_SIZE
);
267 /* Include a file from the current file. Save our state, cause it to
268 be restored on EOF, and begin handling a new file. Same result as
269 input_scrub_new_file. */
272 input_scrub_include_file (const char *filename
, char *position
)
274 next_saved_file
= input_scrub_push (position
);
275 from_sb_expansion
= expanding_none
;
276 return input_scrub_new_file (filename
);
279 /* Start getting input from an sb structure. This is used when
280 expanding a macro. */
283 input_scrub_include_sb (sb
*from
, char *position
, enum expansion expansion
)
287 if (expansion
!= expanding_app
)
289 if (macro_nest
> max_macro_nest
)
290 as_fatal (_("macros nested too deeply"));
294 if (expansion
== expanding_macro
)
296 #ifdef md_macro_start
299 increment_macro_nesting_depth ();
302 next_saved_file
= input_scrub_push (position
);
304 /* Allocate sufficient space: from->len plus optional newline
305 plus two ".linefile " directives, plus a little more for other
307 newline
= from
->len
>= 1 && from
->ptr
[0] != '\n';
308 sb_build (&from_sb
, from
->len
+ newline
+ 2 * sizeof (".linefile") + 30);
309 from_sb_expansion
= expansion
;
312 /* Add the sentinel required by read.c. */
313 sb_add_char (&from_sb
, '\n');
315 sb_scrub_and_add_sb (&from_sb
, from
);
317 /* Make sure the parser looks at defined contents when it scans for
318 e.g. end-of-line at the end of a macro. */
319 sb_terminate (&from_sb
);
323 /* These variables are reset by input_scrub_push. Restore them
324 since we are, after all, still at the same point in the file. */
325 logical_input_line
= next_saved_file
->logical_input_line
;
326 logical_input_file
= next_saved_file
->logical_input_file
;
330 input_scrub_close (void)
333 physical_input_line
= 0;
334 logical_input_line
= -1u;
338 input_scrub_next_buffer (char **bufp
)
340 char *limit
; /*->just after last char of buffer. */
342 if (sb_index
!= (size_t) -1)
344 if (sb_index
>= from_sb
.len
)
347 if (from_sb_expansion
== expanding_macro
)
349 cond_finish_check (macro_nest
);
351 /* Allow the target to clean up per-macro expansion
355 decrement_macro_nesting_depth ();
357 if (from_sb_expansion
!= expanding_app
)
359 partial_where
= NULL
;
361 if (next_saved_file
!= NULL
)
362 *bufp
= input_scrub_pop (next_saved_file
);
363 return partial_where
;
366 partial_where
= from_sb
.ptr
+ from_sb
.len
;
368 *bufp
= from_sb
.ptr
+ sb_index
;
369 sb_index
= from_sb
.len
;
370 return partial_where
;
375 memmove (buffer_start
+ BEFORE_SIZE
, partial_where
, partial_size
);
376 memcpy (buffer_start
+ BEFORE_SIZE
, save_source
, AFTER_SIZE
);
382 char *start
= buffer_start
+ BEFORE_SIZE
+ partial_size
;
384 *bufp
= buffer_start
+ BEFORE_SIZE
;
385 limit
= input_file_give_next_buffer (start
);
389 /* End of this file. */
392 as_warn (_("end of file not at end of a line; newline inserted"));
393 p
= buffer_start
+ BEFORE_SIZE
+ partial_size
;
399 /* Terminate the buffer to avoid confusing TC_EOL_IN_INSN. */
402 /* Find last newline. */
403 for (p
= limit
- 1; *p
!= '\n' || TC_EOL_IN_INSN (p
); --p
)
409 /* We found a newline in the newly read chars. */
411 partial_size
= limit
- p
;
413 /* Save the fragment after that last newline. */
414 memcpy (save_source
, partial_where
, (int) AFTER_SIZE
);
415 memcpy (partial_where
, AFTER_STRING
, (int) AFTER_SIZE
);
416 return partial_where
;
419 /* Didn't find a newline. Read more text. */
420 partial_size
= limit
- (buffer_start
+ BEFORE_SIZE
);
421 if (buffer_length
- input_file_buffer_size () < partial_size
)
423 /* Increase the buffer when it doesn't have room for the
424 next block of input. */
426 buffer_start
= XRESIZEVEC (char, buffer_start
,
428 + BEFORE_SIZE
+ AFTER_SIZE
+ 1));
432 /* Tell the listing we've finished the file. */
435 /* If we should pop to another file at EOF, do it. */
436 partial_where
= NULL
;
438 *bufp
= input_scrub_pop (next_saved_file
);
440 return partial_where
;
443 /* The remaining part of this file deals with line numbers, error
444 messages and so on. Return TRUE if we opened any file. */
447 seen_at_least_1_file (void)
449 return (physical_input_file
!= NULL
);
453 bump_line_counters (void)
455 if (sb_index
== (size_t) -1 || from_sb_expansion
== expanding_app
)
456 ++physical_input_line
;
458 if (logical_input_line
!= -1u)
459 ++logical_input_line
;
462 /* Tells us what the new logical line number and file are.
463 If the line_number is -1, we don't change the current logical line
465 If fname is NULL, we don't change the current logical file name, unless
466 bit 3 of flags is set.
467 Returns nonzero if the filename actually changes. */
470 new_logical_line_flags (const char *fname
, /* DON'T destroy it! We point to it! */
479 if (line_number
!= -1)
484 /* FIXME: we could check that include nesting is correct. */
487 if (line_number
< 0 || fname
!= NULL
)
489 if (next_saved_file
== NULL
)
490 fname
= physical_input_file
;
491 else if (next_saved_file
->logical_input_file
)
492 fname
= next_saved_file
->logical_input_file
;
494 fname
= next_saved_file
->physical_input_file
;
500 is_linefile
= flags
!= 1 && (flags
!= 0 || fname
);
502 if (line_number
>= 0)
503 logical_input_line
= line_number
;
504 else if (line_number
== -1 && fname
&& !*fname
&& (flags
& (1 << 2)))
506 logical_input_file
= physical_input_file
;
507 logical_input_line
= physical_input_line
;
512 && (logical_input_file
== NULL
513 || filename_cmp (logical_input_file
, fname
)))
514 logical_input_file
= fname
;
518 new_logical_line (const char *fname
, int line_number
)
520 new_logical_line_flags (fname
, line_number
, 0);
524 as_report_context (void)
526 const struct input_save
*saved
= next_saved_file
;
527 enum expansion expansion
= from_sb_expansion
;
535 if (expansion
!= expanding_macro
)
537 else if (saved
->logical_input_file
!= NULL
538 && saved
->logical_input_line
!= -1u)
539 as_info_where (saved
->logical_input_file
, saved
->logical_input_line
,
540 indent
, _("macro invoked from here"));
542 as_info_where (saved
->physical_input_file
, saved
->physical_input_line
,
543 indent
, _("macro invoked from here"));
545 expansion
= saved
->from_sb_expansion
;
548 while ((saved
= saved
->next_saved_file
) != NULL
);
551 /* Return the current physical input file name and line number, if known */
554 as_where_physical (unsigned int *linep
)
556 if (physical_input_file
!= NULL
)
559 *linep
= physical_input_line
;
560 return physical_input_file
;
568 /* Return the file name and line number at the top most macro
569 invocation, unless .file / .line were used inside a macro. */
572 as_where (unsigned int *linep
)
574 const char *file
= as_where_top (linep
);
576 if (macro_nest
&& is_linefile
)
578 const struct input_save
*saved
= next_saved_file
;
579 enum expansion expansion
= from_sb_expansion
;
583 if (expansion
!= expanding_macro
)
585 else if (saved
->logical_input_file
!= NULL
586 && (linep
== NULL
|| saved
->logical_input_line
!= -1u))
589 *linep
= saved
->logical_input_line
;
590 file
= saved
->logical_input_file
;
592 else if (saved
->physical_input_file
!= NULL
)
595 *linep
= saved
->physical_input_line
;
596 file
= saved
->physical_input_file
;
599 expansion
= saved
->from_sb_expansion
;
601 while ((saved
= saved
->next_saved_file
) != NULL
);
607 /* Return the current file name and line number. */
610 as_where_top (unsigned int *linep
)
612 if (logical_input_file
!= NULL
613 && (linep
== NULL
|| logical_input_line
!= -1u))
616 *linep
= logical_input_line
;
617 return logical_input_file
;
620 return as_where_physical (linep
);