PR gas/15295

* listing.c (rebuffer_line): Rewrite to avoid seeking back to the
	start of the file each time.
This commit is contained in:
Nick Clifton 2013-03-26 14:16:59 +00:00
parent c5d685bf3a
commit 9b97828214
2 changed files with 72 additions and 32 deletions

View file

@ -1,5 +1,9 @@
2013-03-26 Nick Clifton <nickc@redhat.com> 2013-03-26 Nick Clifton <nickc@redhat.com>
PR gas/15295
* listing.c (rebuffer_line): Rewrite to avoid seeking back to the
start of the file each time.
PR gas/15178 PR gas/15178
* config/tc-sparc.h (ELF_TARGET_FORMAT): Set to elf32-sparc for * config/tc-sparc.h (ELF_TARGET_FORMAT): Set to elf32-sparc for
FreeBSD targets. FreeBSD targets.

View file

@ -553,7 +553,8 @@ buffer_line (file_info_type *file, char *line, unsigned int size)
/* This function rewinds the requested file back to the line requested, /* This function rewinds the requested file back to the line requested,
reads it in again into the buffer provided and then restores the file reads it in again into the buffer provided and then restores the file
back to its original location. */ back to its original location. Returns the buffer pointer upon success
or an empty string if an error occurs. */
static char * static char *
rebuffer_line (file_info_type * file, rebuffer_line (file_info_type * file,
@ -562,13 +563,15 @@ rebuffer_line (file_info_type * file,
unsigned int size) unsigned int size)
{ {
unsigned int count = 0; unsigned int count = 0;
unsigned int current_line = 1; unsigned int current_line;
char * p = buffer; char * p = buffer;
long pos; long pos;
long pos2;
int c; int c;
bfd_boolean found = FALSE;
/* Sanity checks. */ /* Sanity checks. */
if (file == NULL || buffer == NULL || size == 0 || file->linenum <= linenum) if (file == NULL || buffer == NULL || size <= 1 || file->linenum <= linenum)
return ""; return "";
/* Check the cache and see if we last used this file. */ /* Check the cache and see if we last used this file. */
@ -596,38 +599,71 @@ rebuffer_line (file_info_type * file,
} }
/* Remember where we are in the current file. */ /* Remember where we are in the current file. */
pos = ftell (last_open_file); pos2 = pos = ftell (last_open_file);
if (pos < 3)
/* Go back to the beginning. */ return "";
fseek (last_open_file, 0, SEEK_SET); current_line = file->linenum;
/* Skip lines prior to the one we are interested in. */
while (current_line < linenum)
{
/* fgets only stops on newlines and has a size limit,
so we read one character at a time instead. */
do
{
c = fgetc (last_open_file);
}
while (c != EOF && c != '\n' && c != '\r');
++ current_line;
if (c == '\r' || c == '\n')
{
int next = fgetc (last_open_file);
/* If '\r' is followed by '\n', swallow that. Likewise, if '\n'
is followed by '\r', swallow that as well. */
if ((c == '\r' && next != '\n')
|| (c == '\n' && next != '\r'))
ungetc (next, last_open_file);
}
}
/* Leave room for the nul at the end of the buffer. */ /* Leave room for the nul at the end of the buffer. */
size -= 1; size -= 1;
buffer[size] = 0;
/* Increment the current line count by one.
This is to allow for the fact that we are searching for the
start of a previous line, but we do this by detecting end-of-line
character(s) not start-of-line characters. */
++ current_line;
while (pos2 > 0 && ! found)
{
char * ptr;
/* Move backwards through the file, looking for earlier lines. */
pos2 = (long) size > pos2 ? 0 : pos2 - size;
fseek (last_open_file, pos2, SEEK_SET);
/* Our caller has kindly provided us with a buffer, so we use it. */
if (fread (buffer, 1, size, last_open_file) != size)
{
as_warn (_("unable to rebuffer file: %s\n"), file->filename);
return "";
}
for (ptr = buffer + size; ptr >= buffer; -- ptr)
{
if (*ptr == '\n')
{
-- current_line;
if (current_line == linenum)
{
/* We have found the start of the line we seek. */
found = TRUE;
/* FIXME: We could skip the read-in-the-line code
below if we know that we already have the whole
line in the buffer. */
/* Advance pos2 to the newline character we have just located. */
pos2 += (ptr - buffer);
/* Skip the newline and, if present, the carriage return. */
if (ptr + 1 == buffer + size)
{
++pos2;
if (fgetc (last_open_file) == '\r')
++ pos2;
}
else
pos2 += (ptr[1] == '\r' ? 2 : 1);
/* Move the file pointer to this location. */
fseek (last_open_file, pos2, SEEK_SET);
break;
}
}
}
}
/* Read in the line. */ /* Read in the line. */
c = fgetc (last_open_file); c = fgetc (last_open_file);