/* input_scrub.c - Break up input buffers into whole numbers of lines.
- Copyright (C) 1987-2021 Free Software Foundation, Inc.
+ Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
static sb from_sb;
/* Should we do a conditional check on from_sb? */
-static int from_sb_is_expansion = 1;
+static enum expansion from_sb_expansion = expanding_none;
/* The number of nested sb structures we have included. */
int macro_nest;
/* 1-origin line number in a source file. */
/* A line ends in '\n' or eof. */
static unsigned int physical_input_line;
-static int logical_input_line;
+static unsigned int logical_input_line;
+
+/* Indicator whether the origin of an update was a .linefile directive. */
+static bool is_linefile;
/* Struct used to save the state of the input handler during include files */
struct input_save {
size_t partial_size;
char save_source[AFTER_SIZE];
size_t buffer_length;
- const char * physical_input_file;
- const char * logical_input_file;
+ const char * physical_input_file;
+ const char * logical_input_file;
unsigned int physical_input_line;
- int logical_input_line;
+ unsigned int logical_input_line;
+ bool is_linefile;
size_t sb_index;
sb from_sb;
- int from_sb_is_expansion; /* Should we do a conditional check? */
+ enum expansion from_sb_expansion; /* Should we do a conditional check? */
struct input_save * next_saved_file; /* Chain of input_saves. */
char * input_file_save; /* Saved state of input routines. */
char * saved_position; /* Caller's saved position in buf. */
input_scrub_reinit (void)
{
input_file_begin (); /* Reinitialize! */
- logical_input_line = -1;
+ logical_input_line = -1u;
logical_input_file = NULL;
+ sb_index = -1;
buffer_length = input_file_buffer_size () * 2;
buffer_start = XNEWVEC (char, BEFORE_SIZE + AFTER_SIZE + 1 + buffer_length);
saved->logical_input_file = logical_input_file;
saved->physical_input_line = physical_input_line;
saved->logical_input_line = logical_input_line;
+ saved->is_linefile = is_linefile;
saved->sb_index = sb_index;
saved->from_sb = from_sb;
- saved->from_sb_is_expansion = from_sb_is_expansion;
+ saved->from_sb_expansion = from_sb_expansion;
memcpy (saved->save_source, save_source, sizeof (save_source));
saved->next_saved_file = next_saved_file;
saved->input_file_save = input_file_push ();
- sb_index = -1;
-
input_scrub_reinit ();
return saved;
logical_input_file = saved->logical_input_file;
physical_input_line = saved->physical_input_line;
logical_input_line = saved->logical_input_line;
+ is_linefile = saved->is_linefile;
sb_index = saved->sb_index;
from_sb = saved->from_sb;
- from_sb_is_expansion = saved->from_sb_is_expansion;
+ from_sb_expansion = saved->from_sb_expansion;
partial_where = saved->partial_where;
partial_size = saved->partial_size;
next_saved_file = saved->next_saved_file;
physical_input_file = NULL; /* No file read yet. */
next_saved_file = NULL; /* At EOF, don't pop to any other file */
+ macro_nest = 0;
input_scrub_reinit ();
do_scrub_begin (flag_m68k_mri);
}
input_scrub_include_file (const char *filename, char *position)
{
next_saved_file = input_scrub_push (position);
+ from_sb_expansion = expanding_none;
return input_scrub_new_file (filename);
}
expanding a macro. */
void
-input_scrub_include_sb (sb *from, char *position, int is_expansion)
+input_scrub_include_sb (sb *from, char *position, enum expansion expansion)
{
int newline;
++macro_nest;
#ifdef md_macro_start
- if (is_expansion)
+ if (expansion == expanding_macro)
{
md_macro_start ();
}
next_saved_file = input_scrub_push (position);
- /* Allocate sufficient space: from->len + optional newline. */
+ /* Allocate sufficient space: from->len plus optional newline
+ plus two ".linefile " directives, plus a little more for other
+ expansion. */
newline = from->len >= 1 && from->ptr[0] != '\n';
- sb_build (&from_sb, from->len + newline);
- from_sb_is_expansion = is_expansion;
+ sb_build (&from_sb, from->len + newline + 2 * sizeof (".linefile") + 30);
+ from_sb_expansion = expansion;
if (newline)
{
/* Add the sentinel required by read.c. */
{
input_file_close ();
physical_input_line = 0;
- logical_input_line = -1;
+ logical_input_line = -1u;
}
char *
if (sb_index >= from_sb.len)
{
sb_kill (&from_sb);
- if (from_sb_is_expansion)
+ if (from_sb_expansion == expanding_macro)
{
cond_finish_check (macro_nest);
#ifdef md_macro_end
bump_line_counters (void)
{
if (sb_index == (size_t) -1)
- {
- ++physical_input_line;
- if (logical_input_line >= 0)
- ++logical_input_line;
- }
+ ++physical_input_line;
+
+ if (logical_input_line != -1u)
+ ++logical_input_line;
}
\f
/* Tells us what the new logical line number and file are.
If the line_number is -1, we don't change the current logical line
- number. If it is -2, we decrement the logical line number (this is
- to support the .appfile pseudo-op inserted into the stream by
- do_scrub_chars).
- If the fname is NULL, we don't change the current logical file name.
+ number.
+ If fname is NULL, we don't change the current logical file name, unless
+ bit 3 of flags is set.
Returns nonzero if the filename actually changes. */
-int
+void
new_logical_line_flags (const char *fname, /* DON'T destroy it! We point to it! */
int line_number,
int flags)
case 1 << 2:
/* FIXME: we could check that include nesting is correct. */
break;
+ case 1 << 3:
+ if (line_number < 0 || fname != NULL)
+ abort ();
+ if (next_saved_file == NULL)
+ fname = physical_input_file;
+ else if (next_saved_file->logical_input_file)
+ fname = next_saved_file->logical_input_file;
+ else
+ fname = next_saved_file->physical_input_file;
+ break;
default:
abort ();
}
+ is_linefile = flags != 1 && (flags != 0 || fname);
+
if (line_number >= 0)
logical_input_line = line_number;
else if (line_number == -1 && fname && !*fname && (flags & (1 << 2)))
if (fname
&& (logical_input_file == NULL
|| filename_cmp (logical_input_file, fname)))
- {
- logical_input_file = fname;
- return 1;
- }
- else
- return 0;
+ logical_input_file = fname;
}
-int
+void
new_logical_line (const char *fname, int line_number)
{
- return new_logical_line_flags (fname, line_number, 0);
+ new_logical_line_flags (fname, line_number, 0);
}
+void
+as_report_context (void)
+{
+ const struct input_save *saved = next_saved_file;
+ enum expansion expansion = from_sb_expansion;
+ int indent = 1;
+
+ if (!macro_nest)
+ return;
+
+ do
+ {
+ if (expansion != expanding_macro)
+ /* Nothing. */;
+ else if (saved->logical_input_file != NULL
+ && saved->logical_input_line != -1u)
+ as_info_where (saved->logical_input_file, saved->logical_input_line,
+ indent, _("macro invoked from here"));
+ else
+ as_info_where (saved->physical_input_file, saved->physical_input_line,
+ indent, _("macro invoked from here"));
+
+ expansion = saved->from_sb_expansion;
+ ++indent;
+ }
+ while ((saved = saved->next_saved_file) != NULL);
+}
\f
/* Return the current physical input file name and line number, if known */
return NULL;
}
-/* Return the current file name and line number. */
+/* Return the file name and line number at the top most macro
+ invocation, unless .file / .line were used inside a macro. */
const char *
as_where (unsigned int *linep)
+{
+ const char *file = as_where_top (linep);
+
+ if (macro_nest && is_linefile)
+ {
+ const struct input_save *saved = next_saved_file;
+ enum expansion expansion = from_sb_expansion;
+
+ do
+ {
+ if (expansion != expanding_macro)
+ /* Nothing. */;
+ else if (saved->logical_input_file != NULL
+ && (linep == NULL || saved->logical_input_line != -1u))
+ {
+ if (linep != NULL)
+ *linep = saved->logical_input_line;
+ file = saved->logical_input_file;
+ }
+ else if (saved->physical_input_file != NULL)
+ {
+ if (linep != NULL)
+ *linep = saved->physical_input_line;
+ file = saved->physical_input_file;
+ }
+
+ expansion = saved->from_sb_expansion;
+ }
+ while ((saved = saved->next_saved_file) != NULL);
+ }
+
+ return file;
+}
+
+/* Return the current file name and line number. */
+
+const char *
+as_where_top (unsigned int *linep)
{
if (logical_input_file != NULL
- && (linep == NULL || logical_input_line >= 0))
+ && (linep == NULL || logical_input_line != -1u))
{
if (linep != NULL)
*linep = logical_input_line;
return as_where_physical (linep);
}
-