/* Character scanner.
- Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by Andy Vaught
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* Set of subroutines to (ultimately) return the next character to the
various matching subroutines. This file's job is to read files and
new characters and do a lot of jumping backwards. */
#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-
+#include "system.h"
#include "gfortran.h"
/* Structure for holding module and include file search path. */
/* Skip comment lines in fixed source mode. We have the same rules as
in skip_free_comment(), except that we can have a 'c', 'C' or '*'
- in column 1. and a '!' cannot be in* column 6. */
+ in column 1, and a '!' cannot be in column 6. */
static void
skip_fixed_comments (void)
}
while (c != '\n');
+ /* Avoid truncation warnings for comment ending lines. */
+ gfc_current_locus.lb->truncated = 0;
+
goto done;
}
goto done;
/* If the next nonblank character is a ! or \n, we've got a
- continuation line. */
+ continuation line. */
old_loc = gfc_current_locus;
c = next_char ();
c = next_char ();
}
while (c != '\n');
+
+ /* Avoid truncation warnings for comment ending lines. */
+ gfc_current_locus.lb->truncated = 0;
}
if (c != '\n')
if (c == delim)
break;
if (c == '\n')
- goto done;
+ return;
if (c == '\\')
{
c = next_char ();
if (c == '\n')
- goto done;
+ return;
}
}
if (gfc_at_eof ())
break;
}
-
-done:
- if (c == '\n')
- gfc_advance_line ();
}
}
-/* Load a single line into the buffer. We truncate lines that are too
- long. In fixed mode, we expand a tab that occurs within the
- statement label region to expand to spaces that leave the next
- character in the source region. */
+/* Load a single line into pbuf.
-static void
-load_line (FILE * input, char *buffer, char *filename, int linenum)
+ If pbuf points to a NULL pointer, it is allocated.
+ We truncate lines that are too long, unless we're dealing with
+ preprocessor lines or if the option -ffixed-line-length-none is set,
+ in which case we reallocate the buffer to fit the entire line, if
+ need be.
+ In fixed mode, we expand a tab that occurs within the statement
+ label region to expand to spaces that leave the next character in
+ the source region.
+ load_line returns wether the line was truncated. */
+
+static int
+load_line (FILE * input, char **pbuf)
{
- int c, maxlen, i, trunc_flag, preprocessor_flag;
+ int c, maxlen, i, preprocessor_flag;
+ int trunc_flag = 0;
+ static int buflen = 0;
+ char *buffer;
- maxlen = (gfc_current_form == FORM_FREE)
- ? 132
- : gfc_option.fixed_line_length;
+ /* Determine the maximum allowed line length. */
+ if (gfc_current_form == FORM_FREE)
+ maxlen = GFC_MAX_LINE;
+ else
+ maxlen = gfc_option.fixed_line_length;
+
+ if (*pbuf == NULL)
+ {
+ /* Allocate the line buffer, storing its length into buflen. */
+ if (maxlen > 0)
+ buflen = maxlen;
+ else
+ buflen = GFC_MAX_LINE;
+
+ *pbuf = gfc_getmem (buflen + 1);
+ }
i = 0;
+ buffer = *pbuf;
preprocessor_flag = 0;
c = fgetc (input);
if (c == '#')
- /* Don't truncate preprocessor lines. */
+ /* In order to not truncate preprocessor lines, we have to
+ remember that this is one. */
preprocessor_flag = 1;
ungetc (c, input);
}
if (gfc_current_form == FORM_FIXED && c == '\t' && i <= 6)
- { /* Tab expandsion. */
+ { /* Tab expansion. */
while (i <= 6)
{
*buffer++ = ' ';
*buffer++ = c;
i++;
- if (i >= maxlen && !preprocessor_flag)
- { /* Truncate the rest of the line. */
- trunc_flag = 1;
-
+ if (i >= buflen && (maxlen == 0 || preprocessor_flag))
+ {
+ /* Reallocate line buffer to double size to hold the
+ overlong line. */
+ buflen = buflen * 2;
+ *pbuf = xrealloc (*pbuf, buflen);
+ buffer = (*pbuf)+i;
+ }
+ else if (i >= buflen)
+ {
+ /* Truncate the rest of the line. */
for (;;)
{
c = fgetc (input);
if (c == '\n' || c == EOF)
break;
- if (gfc_option.warn_line_truncation
- && trunc_flag
- && !gfc_is_whitespace (c))
- {
- gfc_warning_now ("%s:%d: Line is being truncated",
- filename, linenum);
- trunc_flag = 0;
- }
+ trunc_flag = 1;
}
ungetc ('\n', input);
}
}
+ /* Pad lines to the selected line length in fixed form. */
+ if (gfc_current_form == FORM_FIXED
+ && gfc_option.fixed_line_length > 0
+ && !preprocessor_flag
+ && c != EOF)
+ while (i++ < buflen)
+ *buffer++ = ' ';
+
*buffer = '\0';
+
+ return trunc_flag;
}
the file stack. */
static gfc_file *
-get_file (char *name)
+get_file (char *name, enum lc_reason reason ATTRIBUTE_UNUSED)
{
gfc_file *f;
if (current_file != NULL)
f->inclusion_line = current_file->line;
+#ifdef USE_MAPPED_LOCATION
+ linemap_add (&line_table, reason, false, f->filename, 1);
+#endif
+
return f;
}
int i, line;
char *filename;
gfc_file *f;
+ int escaped;
c++;
while (*c == ' ' || *c == '\t')
line = atoi (c);
+ /* Set new line number. */
+ current_file->line = line;
+
c = strchr (c, ' ');
if (c == NULL)
- /* Something we don't understand has happened. */
+ /* No file name given. */
+ return;
+
+
+
+ /* Skip spaces. */
+ while (*c == ' ' || *c == '\t')
+ c++;
+
+ /* Skip quote. */
+ if (*c != '"')
goto bad_cpp_line;
- c += 2; /* Skip space and quote. */
+ ++c;
+
filename = c;
- c = strchr (c, '"'); /* Make filename end at quote. */
- if (c == NULL)
+ /* Make filename end at quote. */
+ escaped = false;
+ while (*c && ! (! escaped && *c == '"'))
+ {
+ if (escaped)
+ escaped = false;
+ else
+ escaped = *c == '\\';
+ ++c;
+ }
+
+ if (! *c)
/* Preprocessor line has no closing quote. */
goto bad_cpp_line;
+
*c++ = '\0';
+
+
/* Get flags. */
flag[1] = flag[2] = flag[3] = flag[4] = flag[5] = false;
if (flag[1] || flag[3]) /* Starting new file. */
{
- f = get_file (filename);
+ f = get_file (filename, LC_RENAME);
f->up = current_file;
current_file = f;
}
current_file = current_file->up;
}
- current_file->line = line;
-
/* The name of the file can be a temporary file produced by
cpp. Replace the name if it is different. */
return;
bad_cpp_line:
- gfc_warning_now ("%s:%d: Unknown preprocessor directive",
+ gfc_warning_now ("%s:%d: Illegal preprocessor directive",
current_file->filename, current_file->line);
current_file->line++;
}
if (*c != '\0' && *c != '!')
return false;
- /* We have an include line at this point. */
+ /* We have an include line at this point. */
*stop = '\0'; /* It's ok to trash the buffer, as this line won't be
read by anything else. */
static try
load_file (char *filename, bool initial)
{
- char line[GFC_MAX_LINE+1];
+ char *line;
gfc_linebuf *b;
gfc_file *f;
FILE *input;
/* Load the file. */
- f = get_file (filename);
+ f = get_file (filename, initial ? LC_RENAME : LC_ENTER);
f->up = current_file;
current_file = f;
current_file->line = 1;
+ line = NULL;
for (;;)
{
- load_line (input, line, filename, current_file->line);
+ int trunc = load_line (input, &line);
len = strlen (line);
if (feof (input) && len == 0)
/* Add line. */
- b = gfc_getmem (sizeof (gfc_linebuf) + len + 1);
+ b = gfc_getmem (gfc_linebuf_header_size + len + 1);
+#ifdef USE_MAPPED_LOCATION
+ b->location
+ = linemap_line_start (&line_table, current_file->line++, 120);
+#else
b->linenum = current_file->line++;
+#endif
b->file = current_file;
+ b->truncated = trunc;
strcpy (b->line, line);
if (line_head == NULL)
line_tail = b;
}
+ /* Release the line buffer allocated in load_line. */
+ gfc_free (line);
+
fclose (input);
current_file = current_file->up;
+#ifdef USE_MAPPED_LOCATION
+ linemap_add (&line_table, LC_LEAVE, 0, NULL, 0);
+#endif
return SUCCESS;
}
/* Determine the source form from the filename extension. We assume
- case insensitivity. */
+ case insensitivity. */
static gfc_source_form
form_from_filename (const char *filename)
#if 0 /* Debugging aid. */
for (; line_head; line_head = line_head->next)
gfc_status ("%s:%3d %s\n", line_head->file->filename,
- line_head->linenum, line_head->line);
+#ifdef USE_MAPPED_LOCATION
+ LOCATION_LINE (line_head->location),
+#else
+ line_head->linenum,
+#endif
+ line_head->line);
exit (0);
#endif