aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorTobias Schlüter <tobias.schlueter@physik.uni-muenchen.de>2004-05-15 19:31:32 +0200
committerTobias Schlüter <tobi@gcc.gnu.org>2004-05-15 19:31:32 +0200
commitd4fa05b90d6647ceaf50b5f1b8504fc0e01fae9c (patch)
tree78eca888e2f4be9f6b0c5e4db6a69c5180d050c6 /gcc/fortran
parent39ae2b013af4a6a8fbdd8bc2ee72cdda174e0d95 (diff)
downloadgcc-d4fa05b90d6647ceaf50b5f1b8504fc0e01fae9c.zip
gcc-d4fa05b90d6647ceaf50b5f1b8504fc0e01fae9c.tar.gz
gcc-d4fa05b90d6647ceaf50b5f1b8504fc0e01fae9c.tar.bz2
re PR fortran/13702 (When preprocessing Fortran files (.F, .F90 and .F95) cpp should emit line numbers.)
PR fortran/13702 (Port from g95) * gfortran.h (gfc_linebuf): New typedef. (linebuf): Remove. (gfc_file): Revamped, use new gfc_linebuf. (locus): Revamped, use new types. (gfc_current_file): Remove. (gfc_current_form, gfc_source_file): New global variables. * match.c (gfc_match_space, gfc_match_strings): Use gfc_current_form to find source form. * module.c (gfc_dump_module): Use gfc_source_file when printing module header. * error.c (show_locus, show_loci) Use new data structures to print locus. * scanner.c (first_file, first_duplicated_file, gfc_current_file): Remove. (file_head, current_file, gfc_current_form, line_head, line_tail, gfc_current_locus1, gfc_source_file): New global variables. (gfc_scanner_init1): Set new global variables. (gfc_scanner_done1): Free new data structures. (gfc_current_locus): Return pointer to gfc_current_locus1. (gfc_set_locus): Set gfc_current_locus1. (gfc_at_eof): Set new variables. (gfc_at_bol, gfc_at_eol, gfc_advance_line, gfc_next_char): Adapt to new locus structure. (gfc_check_include): Remove. (skip_free_comments, skip_fixed_comments): Use gfc_current_locus1. (gfc_skip_comments): Use gfc_current_form, find locus with gfc_current_locus1. (gfc_next_char): Use gfc_current_form. (gfc_peek_char, gfc_gobble_whitespace): Use gfc_current_locus1. (load_line): Use gfc_current_form. Recognize ^Z as EOF. Fix comment formatting. (get_file): New function. (preprocessor_line, include_line): New functions. (load_file): Move down, rewrite to match new data structures. (gfc_new_file): Rewrite to match new data structures. * parse.c (next_statement): Remove code which is now useless. Use gfc_source_form and gfc_source_file where appropriate. * trans-decl.c (gfc_get_label_decl): adapt to new data structures when determining locus of frontend code. * trans-io.c (set_error_locus): Same. * trans.c (gfc_get_backend_locus, gfc_set_backend_locus): Likewise. * lang-specs.h (@f77-cpp-input, @f95-cpp-input): Remove '-P' from preprocessor flags. (all): Add missing initializers. From-SVN: r81888
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog50
-rw-r--r--gcc/fortran/error.c28
-rw-r--r--gcc/fortran/gfortran.h70
-rw-r--r--gcc/fortran/lang-specs.h32
-rw-r--r--gcc/fortran/match.c4
-rw-r--r--gcc/fortran/module.c9
-rw-r--r--gcc/fortran/parse.c15
-rw-r--r--gcc/fortran/scanner.c571
-rw-r--r--gcc/fortran/trans-decl.c4
-rw-r--r--gcc/fortran/trans-io.c4
-rw-r--r--gcc/fortran/trans.c11
11 files changed, 451 insertions, 347 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 586ddb6..a1542b5 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,5 +1,55 @@
2004-05-15 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
+ PR fortran/13702
+ (Port from g95)
+ * gfortran.h (gfc_linebuf): New typedef.
+ (linebuf): Remove.
+ (gfc_file): Revamped, use new gfc_linebuf.
+ (locus): Revamped, use new types.
+ (gfc_current_file): Remove.
+ (gfc_current_form, gfc_source_file): New global variables.
+ * match.c (gfc_match_space, gfc_match_strings): Use
+ gfc_current_form to find source form.
+ * module.c (gfc_dump_module): Use gfc_source_file when printing
+ module header.
+ * error.c (show_locus, show_loci) Use new data structures to print
+ locus.
+ * scanner.c (first_file, first_duplicated_file, gfc_current_file):
+ Remove.
+ (file_head, current_file, gfc_current_form, line_head, line_tail,
+ gfc_current_locus1, gfc_source_file): New global variables.
+ (gfc_scanner_init1): Set new global variables.
+ (gfc_scanner_done1): Free new data structures.
+ (gfc_current_locus): Return pointer to gfc_current_locus1.
+ (gfc_set_locus): Set gfc_current_locus1.
+ (gfc_at_eof): Set new variables.
+ (gfc_at_bol, gfc_at_eol, gfc_advance_line, gfc_next_char): Adapt
+ to new locus structure.
+ (gfc_check_include): Remove.
+ (skip_free_comments, skip_fixed_comments): Use gfc_current_locus1.
+ (gfc_skip_comments): Use gfc_current_form, find locus with
+ gfc_current_locus1.
+ (gfc_next_char): Use gfc_current_form.
+ (gfc_peek_char, gfc_gobble_whitespace): Use gfc_current_locus1.
+ (load_line): Use gfc_current_form. Recognize ^Z as EOF. Fix
+ comment formatting.
+ (get_file): New function.
+ (preprocessor_line, include_line): New functions.
+ (load_file): Move down, rewrite to match new data structures.
+ (gfc_new_file): Rewrite to match new data structures.
+ * parse.c (next_statement): Remove code which is now useless. Use
+ gfc_source_form and gfc_source_file where appropriate.
+ * trans-decl.c (gfc_get_label_decl): adapt to new data structures
+ when determining locus of frontend code.
+ * trans-io.c (set_error_locus): Same.
+ * trans.c (gfc_get_backend_locus, gfc_set_backend_locus): Likewise.
+ * lang-specs.h (@f77-cpp-input, @f95-cpp-input): Remove '-P' from
+ preprocessor flags.
+ (all): Add missing initializers.
+
+
+2004-05-15 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
+
* Make-lang.in (trans-common.o): Remove redundant dependency.
(data.c): Replace object file name ...
(data.o): ... by the correct one.
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index 260733c..b7b0fdb 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -118,8 +118,9 @@ error_string (const char *p)
static void error_printf (const char *, ...) ATTRIBUTE_PRINTF_1;
static void
-show_locus (int offset, locus * l)
+show_locus (int offset, locus * loc)
{
+ gfc_linebuf *lb;
gfc_file *f;
char c, *p;
int i, m;
@@ -127,20 +128,25 @@ show_locus (int offset, locus * l)
/* TODO: Either limit the total length and number of included files
displayed or add buffering of arbitrary number of characters in
error messages. */
- f = l->file;
- error_printf ("In file %s:%d\n", f->filename, l->lp->start_line + l->line);
- f = f->included_by;
- while (f != NULL)
+ lb = loc->lb;
+ f = lb->file;
+ error_printf ("In file %s:%d\n", f->filename, lb->linenum);
+
+ for (;;)
{
- error_printf (" Included at %s:%d\n", f->filename,
- f->loc.lp->start_line + f->loc.line);
+ i = f->inclusion_line;
+
f = f->included_by;
+ if (f == NULL) break;
+
+ error_printf (" Included at %s:%d\n", f->filename, i);
}
/* Show the line itself, taking care not to print more than what can
show up on the terminal. Tabs are converted to spaces. */
- p = l->lp->line[l->line] + offset;
+
+ p = lb->line + offset;
i = strlen (p);
if (i > terminal_width)
i = terminal_width - 1;
@@ -190,12 +196,12 @@ show_loci (locus * l1, locus * l2)
return;
}
- c1 = l1->nextc - l1->lp->line[l1->line];
+ c1 = l1->nextc - l1->lb->line;
c2 = 0;
if (l2 == NULL)
goto separate;
- c2 = l2->nextc - l2->lp->line[l2->line];
+ c2 = l2->nextc - l2->lb->line;
if (c1 < c2)
m = c2 - c1;
@@ -203,7 +209,7 @@ show_loci (locus * l1, locus * l2)
m = c1 - c2;
- if (l1->lp != l2->lp || l1->line != l2->line || m > terminal_width - 10)
+ if (l1->lb != l2->lb || m > terminal_width - 10)
goto separate;
offset = 0;
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 627eb8d..498e63b 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -413,35 +413,40 @@ typedef struct
symbol_attribute;
-typedef struct
-{
- char *nextc;
- int line; /* line within the lp structure */
- struct linebuf *lp;
- struct gfc_file *file;
-}
-locus;
+/* The following three structures are used to identify a location in
+ the sources.
+
+ gfc_file is used to maintain a tree of the source files and how
+ they include each other
-/* The linebuf structure deserves some explanation. This is the
- primary structure for holding lines. A source file is stored in a
- singly linked list of these structures. Each structure holds an
- integer number of lines. The line[] member is actually an array of
- pointers that point to the NULL-terminated lines. This list grows
- upwards, and the actual lines are stored at the top of the
- structure and grow downward. Each structure is packed with as many
- lines as it can hold, then another linebuf is allocated. */
+ gfc_linebuf holds a single line of source code and information
+ which file it resides in
-/* Chosen so that sizeof(linebuf) = 4096 on most machines */
-#define LINEBUF_SIZE 4080
+ locus point to the sourceline and the character in the source
+ line.
+*/
-typedef struct linebuf
+typedef struct gfc_file
{
- int start_line, lines;
- struct linebuf *next;
- char *line[1];
- char buf[LINEBUF_SIZE];
-}
-linebuf;
+ struct gfc_file *included_by, *next, *up;
+ int inclusion_line, line;
+ char *filename;
+} gfc_file;
+
+typedef struct gfc_linebuf
+{
+ int linenum;
+ struct gfc_file *file;
+ struct gfc_linebuf *next;
+
+ char line[];
+} gfc_linebuf;
+
+typedef struct
+{
+ char *nextc;
+ gfc_linebuf *lb;
+} locus;
#include <limits.h>
@@ -451,17 +456,6 @@ linebuf;
#endif
-typedef struct gfc_file
-{
- char filename[PATH_MAX + 1];
- gfc_source_form form;
- struct gfc_file *included_by, *next;
- locus loc;
- struct linebuf *start;
-}
-gfc_file;
-
-
extern int gfc_suppress_error;
@@ -1308,7 +1302,9 @@ void gfc_error_recovery (void);
void gfc_gobble_whitespace (void);
try gfc_new_file (const char *, gfc_source_form);
-extern gfc_file *gfc_current_file;
+extern gfc_source_form gfc_current_form;
+extern char *gfc_source_file;
+/* extern locus gfc_current_locus; */
/* misc.c */
void *gfc_getmem (size_t) ATTRIBUTE_MALLOC;
diff --git a/gcc/fortran/lang-specs.h b/gcc/fortran/lang-specs.h
index f1828e2..b18483f 100644
--- a/gcc/fortran/lang-specs.h
+++ b/gcc/fortran/lang-specs.h
@@ -7,29 +7,29 @@ This file is licensed under the GPL. */
/* This is the contribution to the `default_compilers' array in gcc.c
for the f95 language. */
-{".F", "@f77-cpp-input", 0},
-{".fpp", "@f77-cpp-input", 0},
-{".FPP", "@f77-cpp-input", 0},
+{".F", "@f77-cpp-input", 0, 0, 0},
+{".fpp", "@f77-cpp-input", 0, 0, 0},
+{".FPP", "@f77-cpp-input", 0, 0, 0},
{"@f77-cpp-input",
- "cc1 -P -E -traditional-cpp -D_LANGUAGE_FORTRAN %(cpp_options) \
+ "cc1 -E -traditional-cpp -D_LANGUAGE_FORTRAN %(cpp_options) \
%{E|M|MM:%(cpp_debug_options)}\
%{!M:%{!MM:%{!E: -o %|.f |\n\
f951 %|.f %{!ffree-form:-ffixed-form} %(cc1_options) %{J*} %{I*}\
- %{!fsyntax-only:%(invoke_as)}}}}", 0},
-{".F90", "@f95-cpp-input", 0},
-{".F95", "@f95-cpp-input", 0},
+ %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+{".F90", "@f95-cpp-input", 0, 0, 0},
+{".F95", "@f95-cpp-input", 0, 0, 0},
{"@f95-cpp-input",
- "cc1 -P -E -traditional-cpp -D_LANGUAGE_FORTRAN %(cpp_options) \
+ "cc1 -E -traditional-cpp -D_LANGUAGE_FORTRAN %(cpp_options) \
%{E|M|MM:%(cpp_debug_options)}\
%{!M:%{!MM:%{!E: -o %|.f95 |\n\
f951 %|.f95 %(cc1_options) %{J*} %{I*}\
- %{!fsyntax-only:%(invoke_as)}}}}", 0},
-{".f90", "@f95", 0},
-{".f95", "@f95", 0},
+ %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+{".f90", "@f95", 0, 0, 0},
+{".f95", "@f95", 0, 0, 0},
{"@f95", "%{!E:f951 %i %(cc1_options) %{J*} %{I*}\
- %{!fsyntax-only:%(invoke_as)}}", 0},
-{".f", "@f77", 0},
-{".for", "@f77", 0},
-{".FOR", "@f77", 0},
+ %{!fsyntax-only:%(invoke_as)}}", 0, 0, 0},
+{".f", "@f77", 0, 0, 0},
+{".for", "@f77", 0, 0, 0},
+{".FOR", "@f77", 0, 0, 0},
{"@f77", "%{!E:f951 %i %{!ffree-form:-ffixed-form} %(cc1_options) %{J*} %{I*}\
- %{!fsyntax-only:%(invoke_as)}}", 0},
+ %{!fsyntax-only:%(invoke_as)}}", 0, 0, 0},
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index c13e057..dc8dc3e 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -77,7 +77,7 @@ gfc_match_space (void)
locus old_loc;
int c;
- if (gfc_current_file->form == FORM_FIXED)
+ if (gfc_current_form == FORM_FIXED)
return MATCH_YES;
old_loc = *gfc_current_locus ();
@@ -337,7 +337,7 @@ gfc_match_strings (mstring * a)
if (*p->mp == ' ')
{
/* Space matches 1+ whitespace(s). */
- if ((gfc_current_file->form == FORM_FREE)
+ if ((gfc_current_form == FORM_FREE)
&& gfc_is_whitespace (c))
continue;
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 566e3f3..1143705 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -3338,7 +3338,6 @@ void
gfc_dump_module (const char *name, int dump_flag)
{
char filename[PATH_MAX], *p;
- gfc_file *g;
time_t now;
filename[0] = '\0';
@@ -3359,17 +3358,13 @@ gfc_dump_module (const char *name, int dump_flag)
gfc_fatal_error ("Can't open module file '%s' for writing: %s",
filename, strerror (errno));
- /* Find the top level filename. */
- g = gfc_current_file;
- while (g->next)
- g = g->next;
-
now = time (NULL);
p = ctime (&now);
*strchr (p, '\n') = '\0';
- fprintf (module_fp, "GFORTRAN module created from %s on %s\n", g->filename, p);
+ fprintf (module_fp, "GFORTRAN module created from %s on %s\n",
+ gfc_source_file, p);
fputs ("If you edit this, you'll get what you deserve.\n\n", module_fp);
iomode = IO_OUTPUT;
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index beec9d6..dea613b 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -483,16 +483,6 @@ next_statement (void)
gfc_skip_comments ();
- if (gfc_at_bol () && gfc_check_include ())
- continue;
-
- if (gfc_at_eof () && gfc_current_file->included_by != NULL)
- {
- gfc_current_file = gfc_current_file->included_by;
- gfc_advance_line ();
- continue;
- }
-
if (gfc_at_end ())
{
st = ST_NONE;
@@ -500,7 +490,8 @@ next_statement (void)
}
st =
- (gfc_current_file->form == FORM_FIXED) ? next_fixed () : next_free ();
+ (gfc_current_form == FORM_FIXED) ? next_fixed () : next_free ();
+
if (st != ST_NONE)
break;
}
@@ -1268,7 +1259,7 @@ unexpected_eof (void)
{
gfc_state_data *p;
- gfc_error ("Unexpected end of file in '%s'", gfc_current_file->filename);
+ gfc_error ("Unexpected end of file in '%s'", gfc_source_file);
/* Memory cleanup. Move to "second to last". */
for (p = gfc_state_stack; p && p->previous && p->previous->previous;
diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c
index 34959ab..a16c274 100644
--- a/gcc/fortran/scanner.c
+++ b/gcc/fortran/scanner.c
@@ -60,21 +60,26 @@ gfc_directorylist;
/* List of include file search directories. */
static gfc_directorylist *include_dirs;
-static gfc_file *first_file, *first_duplicated_file;
-static int continue_flag, end_flag;
+static gfc_file *file_head, *current_file;
-gfc_file *gfc_current_file;
+static int continue_flag, end_flag;
+gfc_source_form gfc_current_form;
+static gfc_linebuf *line_head, *line_tail;
+
+locus gfc_current_locus1;
+char *gfc_source_file;
+
/* Main scanner initialization. */
void
gfc_scanner_init_1 (void)
{
+ file_head = NULL;
+ line_head = NULL;
+ line_tail = NULL;
- gfc_current_file = NULL;
- first_file = NULL;
- first_duplicated_file = NULL;
end_flag = 0;
}
@@ -84,36 +89,24 @@ gfc_scanner_init_1 (void)
void
gfc_scanner_done_1 (void)
{
+ gfc_linebuf *lb;
+ gfc_file *f;
- linebuf *lp, *lp2;
- gfc_file *fp, *fp2;
-
- for (fp = first_file; fp; fp = fp2)
+ while(line_head != NULL)
{
-
- if (fp->start != NULL)
- {
- /* Free linebuf blocks */
- for (fp2 = fp->next; fp2; fp2 = fp2->next)
- if (fp->start == fp2->start)
- fp2->start = NULL;
-
- for (lp = fp->start; lp; lp = lp2)
- {
- lp2 = lp->next;
- gfc_free (lp);
- }
- }
-
- fp2 = fp->next;
- gfc_free (fp);
+ lb = line_head->next;
+ gfc_free(line_head);
+ line_head = lb;
}
-
- for (fp = first_duplicated_file; fp; fp = fp2)
+
+ while(file_head != NULL)
{
- fp2 = fp->next;
- gfc_free (fp);
+ f = file_head->next;
+ gfc_free(file_head->filename);
+ gfc_free(file_head);
+ file_head = f;
}
+
}
@@ -168,7 +161,6 @@ gfc_release_include_path (void)
}
}
-
/* Opens file for reading, searching through the include directories
given if necessary. */
@@ -206,19 +198,18 @@ locus *
gfc_current_locus (void)
{
- if (gfc_current_file == NULL)
- return NULL;
- return &gfc_current_file->loc;
+ return &gfc_current_locus1;
}
+
/* Let a caller move the current read pointer (backwards). */
void
gfc_set_locus (locus * lp)
{
- gfc_current_file->loc = *lp;
+ gfc_current_locus1 = *lp;
}
@@ -241,10 +232,10 @@ gfc_at_eof (void)
if (gfc_at_end ())
return 1;
- if (gfc_current_file->start->lines == 0)
+ if (line_head == NULL)
return 1; /* Null file */
- if (gfc_current_file->loc.lp == NULL)
+ if (gfc_current_locus1.lb == NULL)
return 1;
return 0;
@@ -256,14 +247,10 @@ gfc_at_eof (void)
int
gfc_at_bol (void)
{
- int i;
-
if (gfc_at_eof ())
return 1;
- i = gfc_current_file->loc.line;
-
- return gfc_current_file->loc.nextc == gfc_current_file->loc.lp->line[i];
+ return (gfc_current_locus1.nextc == gfc_current_locus1.lb->line);
}
@@ -276,7 +263,7 @@ gfc_at_eol (void)
if (gfc_at_eof ())
return 1;
- return *gfc_current_file->loc.nextc == '\0';
+ return (*gfc_current_locus1.nextc == '\0');
}
@@ -285,27 +272,24 @@ gfc_at_eol (void)
void
gfc_advance_line (void)
{
- locus *locp;
- linebuf *lp;
-
if (gfc_at_end ())
return;
- locp = &gfc_current_file->loc;
- lp = locp->lp;
- if (lp == NULL)
- return;
-
- if (++locp->line >= lp->lines)
+ if (gfc_current_locus1.lb == NULL)
{
- locp->lp = lp = lp->next;
- if (lp == NULL)
- return; /* End of this file */
+ end_flag = 1;
+ return;
+ }
- locp->line = 0;
- }
+ gfc_current_locus1.lb = gfc_current_locus1.lb->next;
- locp->nextc = lp->line[locp->line];
+ if (gfc_current_locus1.lb != NULL)
+ gfc_current_locus1.nextc = gfc_current_locus1.lb->line;
+ else
+ {
+ gfc_current_locus1.nextc = NULL;
+ end_flag = 1;
+ }
}
@@ -321,104 +305,21 @@ gfc_advance_line (void)
static int
next_char (void)
{
- locus *locp;
int c;
-
- /* End the current include level, but not if we're in the middle
- of processing a continuation. */
- if (gfc_at_eof ())
- {
- if (continue_flag != 0 || gfc_at_end ())
- return '\n';
-
- if (gfc_current_file->included_by == NULL)
- end_flag = 1;
-
- return '\n';
- }
-
- locp = &gfc_current_file->loc;
- if (locp->nextc == NULL)
+
+ if (gfc_current_locus1.nextc == NULL)
return '\n';
- c = *locp->nextc++;
+ c = *gfc_current_locus1.nextc++;
if (c == '\0')
{
- locp->nextc--; /* Stay stuck on this line */
+ gfc_current_locus1.nextc--; /* Remain on this line. */
c = '\n';
}
return c;
}
-
-/* Checks the current line buffer to see if it is an include line. If
- so, we load the new file and prepare to read from it. Include
- lines happen at a lower level than regular parsing because the
- string-matching subroutine is far simpler than the normal one.
-
- We never return a syntax error because a statement like "include = 5"
- is perfectly legal. We return zero if no include was processed or
- nonzero if we matched an include. */
-
-int
-gfc_check_include (void)
-{
- char c, quote, path[PATH_MAX + 1];
- const char *include;
- locus start;
- int i;
-
- include = "include";
-
- start = *gfc_current_locus ();
- gfc_gobble_whitespace ();
-
- /* Match the 'include' */
- while (*include != '\0')
- if (*include++ != gfc_next_char ())
- goto no_include;
-
- gfc_gobble_whitespace ();
-
- quote = next_char ();
- if (quote != '"' && quote != '\'')
- goto no_include;
-
- /* Copy the filename */
- for (i = 0;;)
- {
- c = next_char ();
- if (c == '\n')
- goto no_include; /* No close quote */
- if (c == quote)
- break;
-
- /* This shouldn't happen-- PATH_MAX should be way longer than the
- max line length. */
-
- if (i >= PATH_MAX)
- gfc_internal_error ("Pathname of include file is too long at %C");
-
- path[i++] = c;
- }
-
- path[i] = '\0';
- if (i == 0)
- goto no_include; /* No filename! */
-
- /* At this point, we've got a filename to be included. The rest
- of the include line is ignored */
-
- gfc_new_file (path, gfc_current_file->form);
- return 1;
-
-no_include:
- gfc_set_locus (&start);
- return 0;
-}
-
-
/* Skip a comment. When we come here the parse pointer is positioned
immediately after the comment character. If we ever implement
compiler directives withing comments, here is where we parse the
@@ -450,7 +351,7 @@ skip_free_comments (void)
for (;;)
{
- start = *gfc_current_locus ();
+ start = gfc_current_locus1;
if (gfc_at_eof ())
break;
@@ -492,7 +393,7 @@ skip_fixed_comments (void)
for (;;)
{
- start = *gfc_current_locus ();
+ start = gfc_current_locus1;
if (gfc_at_eof ())
break;
@@ -543,7 +444,7 @@ void
gfc_skip_comments (void)
{
- if (!gfc_at_bol () || gfc_current_file->form == FORM_FREE)
+ if (!gfc_at_bol () || gfc_current_form == FORM_FREE)
skip_free_comments ();
else
skip_fixed_comments ();
@@ -570,7 +471,7 @@ restart:
if (gfc_at_end ())
return c;
- if (gfc_current_file->form == FORM_FREE)
+ if (gfc_current_form == FORM_FREE)
{
if (!in_string && c == '!')
@@ -590,7 +491,7 @@ restart:
/* If the next nonblank character is a ! or \n, we've got a
continuation line. */
- old_loc = gfc_current_file->loc;
+ old_loc = gfc_current_locus1;
c = next_char ();
while (gfc_is_whitespace (c))
@@ -701,7 +602,7 @@ gfc_next_char (void)
{
c = gfc_next_char_literal (0);
}
- while (gfc_current_file->form == FORM_FIXED && gfc_is_whitespace (c));
+ while (gfc_current_form == FORM_FIXED && gfc_is_whitespace (c));
return TOLOWER (c);
}
@@ -713,7 +614,7 @@ gfc_peek_char (void)
locus old_loc;
int c;
- old_loc = *gfc_current_locus ();
+ old_loc = gfc_current_locus1;
c = gfc_next_char ();
gfc_set_locus (&old_loc);
@@ -783,7 +684,7 @@ gfc_gobble_whitespace (void)
do
{
- old_loc = *gfc_current_locus ();
+ old_loc = gfc_current_locus1;
c = gfc_next_char_literal (0);
}
while (gfc_is_whitespace (c));
@@ -798,12 +699,13 @@ gfc_gobble_whitespace (void)
character in the source region. */
static void
-load_line (FILE * input, gfc_source_form form, char *buffer,
- char *filename, int linenum)
+load_line (FILE * input, char *buffer, char *filename, int linenum)
{
int c, maxlen, i, trunc_flag;
- maxlen = (form == FORM_FREE) ? 132 : gfc_option.fixed_line_length;
+ maxlen = (gfc_current_form == FORM_FREE)
+ ? 132
+ : gfc_option.fixed_line_length;
i = 0;
@@ -817,12 +719,19 @@ load_line (FILE * input, gfc_source_form form, char *buffer,
break;
if (c == '\r')
- continue; /* Gobble characters */
+ continue; /* Gobble characters. */
if (c == '\0')
continue;
- if (form == FORM_FIXED && c == '\t' && i <= 6)
- { /* Tab expandsion */
+ if (c == '\032')
+ {
+ /* Ctrl-Z ends the file. */
+ while (fgetc (input) != EOF);
+ break;
+ }
+
+ if (gfc_current_form == FORM_FIXED && c == '\t' && i <= 6)
+ { /* Tab expandsion. */
while (i <= 6)
{
*buffer++ = ' ';
@@ -836,7 +745,7 @@ load_line (FILE * input, gfc_source_form form, char *buffer,
i++;
if (i >= maxlen)
- { /* Truncate the rest of the line */
+ { /* Truncate the rest of the line. */
trunc_flag = 1;
for (;;)
@@ -863,51 +772,247 @@ load_line (FILE * input, gfc_source_form form, char *buffer,
}
-/* Load a file into memory by calling load_line until the file ends. */
+/* Get a gfc_file structure, initialize it and add it to
+ the file stack. */
+
+static gfc_file *
+get_file (char *name)
+{
+ gfc_file *f;
+
+ f = gfc_getmem (sizeof (gfc_file));
+
+ f->filename = gfc_getmem (strlen (name) + 1);
+ strcpy (f->filename, name);
+
+ f->next = file_head;
+ file_head = f;
+
+ f->included_by = current_file;
+ if (current_file != NULL)
+ f->inclusion_line = current_file->line;
+
+ return f;
+}
+
+/* Deal with a line from the C preprocessor. The
+ initial octothorp has already been seen. */
static void
-load_file (FILE * input, gfc_file * fp)
+preprocessor_line (char *c)
{
- char *linep, line[GFC_MAX_LINE + 1];
- int len, linenum;
- linebuf *lp;
+ bool flag[5];
+ int i, line;
+ char *filename;
+ gfc_file *f;
- fp->start = lp = gfc_getmem (sizeof (linebuf));
+ c++;
+ while (*c == ' ' || *c == '\t')
+ c++;
- linenum = 1;
- lp->lines = 0;
- lp->start_line = 1;
- lp->next = NULL;
+ if (*c < '0' || *c > '9')
+ {
+ gfc_warning_now ("%s:%d Unknown preprocessor directive",
+ current_file->filename, current_file->line);
+ current_file->line++;
+ return;
+ }
- linep = (char *) (lp + 1);
+ line = atoi (c);
+
+ c = strchr (c, ' ') + 2; /* Skip space and quote. */
+ filename = c;
+
+ c = strchr (c, '"'); /* Make filename end at quote. */
+ *c++ = '\0';
+
+ /* Get flags. */
+
+ flag[1] = flag[2] = flag[3] = flag[4] = flag[5] = false;
- /* Load the file. */
for (;;)
{
- load_line (input, fp->form, line, fp->filename, linenum);
- linenum++;
+ c = strchr (c, ' ');
+ if (c == NULL)
+ break;
- len = strlen (line);
+ c++;
+ i = atoi (c);
+ if (1 <= i && i <= 4)
+ flag[i] = true;
+ }
+
+ /* Interpret flags. */
+
+ if (flag[1] || flag[3]) /* Starting new file. */
+ {
+ f = get_file (filename);
+ f->up = current_file;
+ current_file = f;
+ }
+
+ if (flag[2]) /* Ending current file. */
+ {
+ 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. */
+
+ if (strcmp (current_file->filename, filename) != 0)
+ {
+ gfc_free (current_file->filename);
+ current_file->filename = gfc_getmem (strlen (filename) + 1);
+ strcpy (current_file->filename, filename);
+ }
+}
+
+
+static try load_file (char *, bool);
+
+/* include_line()-- Checks a line buffer to see if it is an include
+ line. If so, we call load_file() recursively to load the included
+ file. We never return a syntax error because a statement like
+ "include = 5" is perfectly legal. We return false if no include was
+ processed or true if we matched an include. */
+
+static bool
+include_line (char *line)
+{
+ char quote, *c, *begin, *stop;
+
+ c = line;
+ while (*c == ' ' || *c == '\t')
+ c++;
+
+ if (strncasecmp (c, "include", 7))
+ return false;
+
+ c += 7;
+ while (*c == ' ' || *c == '\t')
+ c++;
+
+ /* Find filename between quotes. */
+
+ quote = *c++;
+ if (quote != '"' && quote != '\'')
+ return false;
+
+ begin = c;
+
+ while (*c != quote && *c != '\0')
+ c++;
+
+ if (*c == '\0')
+ return false;
+
+ stop = c++;
+
+ while (*c == ' ' || *c == '\t')
+ c++;
+
+ if (*c != '\0' && *c != '!')
+ return false;
+
+ /* 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. */
+
+ load_file (begin, false);
+ return true;
+}
+
+/* Load a file into memory by calling load_line until the file ends. */
+
+static try
+load_file (char *filename, bool initial)
+{
+ char line[GFC_MAX_LINE+1];
+ gfc_linebuf *b;
+ gfc_file *f;
+ FILE *input;
+ int len;
+
+ for (f = current_file; f; f = f->up)
+ if (strcmp (filename, f->filename) == 0)
+ {
+ gfc_error_now ("File '%s' is being included recursively", filename);
+ return FAILURE;
+ }
+
+ if (initial)
+ {
+ input = gfc_open_file (filename);
+ if (input == NULL)
+ {
+ gfc_error_now ("Can't open file '%s'", filename);
+ return FAILURE;
+ }
+ }
+ else
+ {
+ input = gfc_open_included_file (filename);
+ if (input == NULL)
+ {
+ gfc_error_now ("Can't open included file '%s'", filename);
+ return FAILURE;
+ }
+ }
+
+ /* Load the file. */
+
+ f = get_file (filename);
+ f->up = current_file;
+ current_file = f;
+ current_file->line = 1;
+
+ for (;;)
+ {
+ load_line (input, line, filename, current_file->line);
+
+ len = strlen (line);
if (feof (input) && len == 0)
break;
- /* See if we need another linebuf. */
- if (((char *) &lp->line[lp->lines + 2]) > linep - len - 1)
- {
- lp->next = gfc_getmem (sizeof (linebuf));
+ /* There are three things this line can be: a line of Fortran
+ source, an include line or a C preprocessor directive. */
- lp->next->start_line = lp->start_line + lp->lines;
- lp = lp->next;
- lp->lines = 0;
+ if (line[0] == '#')
+ {
+ preprocessor_line (line);
+ continue;
+ }
- linep = (char *) (lp + 1);
+ if (include_line (line))
+ {
+ current_file->line++;
+ continue;
}
- linep = linep - len - 1;
- lp->line[lp->lines++] = linep;
- strcpy (linep, line);
+ /* Add line. */
+
+ b = gfc_getmem (sizeof (gfc_linebuf) + len + 1);
+
+ b->linenum = current_file->line++;
+ b->file = current_file;
+ strcpy (b->line, line);
+
+ if (line_head == NULL)
+ line_head = b;
+ else
+ line_tail->next = b;
+
+ line_tail = b;
}
+
+ fclose (input);
+
+ current_file = current_file->up;
+ return SUCCESS;
}
@@ -982,92 +1087,52 @@ form_from_filename (const char *filename)
}
-/* Open a new file and start scanning from that file. Every new file
- gets a gfc_file node, even if it is a duplicate file. Returns SUCCESS
- if everything went OK, FAILURE otherwise. */
+/* Open a new file and start scanning from that file. Returns SUCCESS
+ if everything went OK, FAILURE otherwise. If form == FORM_UKNOWN
+ it tries to determine the source form from the filename, defaulting
+ to free form. */
try
gfc_new_file (const char *filename, gfc_source_form form)
{
- gfc_file *fp, *fp2;
- FILE *input;
- int len;
+ try result;
- len = strlen (filename);
- if (len > PATH_MAX)
+ if (filename != NULL)
{
- gfc_error_now ("Filename '%s' is too long- ignoring it", filename);
- return FAILURE;
+ gfc_source_file = gfc_getmem (strlen (filename) + 1);
+ strcpy (gfc_source_file, filename);
}
-
- fp = gfc_getmem (sizeof (gfc_file));
-
- /* Make sure this file isn't being included recursively. */
- for (fp2 = gfc_current_file; fp2; fp2 = fp2->included_by)
- if (strcmp (filename, fp2->filename) == 0)
- {
- gfc_error_now ("Recursive inclusion of file '%s' at %C- ignoring it",
- filename);
- gfc_free (fp);
- return FAILURE;
- }
-
- /* See if the file has already been included. */
- for (fp2 = first_file; fp2; fp2 = fp2->next)
- if (strcmp (filename, fp2->filename) == 0)
- {
- *fp = *fp2;
- fp->next = first_duplicated_file;
- first_duplicated_file = fp;
- goto init_fp;
- }
-
- strcpy (fp->filename, filename);
-
- if (gfc_current_file == NULL)
- input = gfc_open_file (filename);
else
- input = gfc_open_included_file (filename);
-
- if (input == NULL)
- {
- if (gfc_current_file == NULL)
- gfc_error_now ("Can't open file '%s'", filename);
- else
- gfc_error_now ("Can't open file '%s' included at %C", filename);
-
- gfc_free (fp);
- return FAILURE;
- }
+ gfc_source_file = NULL;
/* Decide which form the file will be read in as. */
+
if (form != FORM_UNKNOWN)
- fp->form = form;
+ gfc_current_form = form;
else
{
- fp->form = form_from_filename (filename);
+ gfc_current_form = form_from_filename (filename);
- if (fp->form == FORM_UNKNOWN)
+ if (gfc_current_form == FORM_UNKNOWN)
{
- fp->form = FORM_FREE;
- gfc_warning_now ("Reading file %s as free form", filename);
+ gfc_current_form = FORM_FREE;
+ gfc_warning_now ("Reading file '%s' as free form.",
+ (filename[0] == '\0') ? "<stdin>" : filename);
}
}
- fp->next = first_file;
- first_file = fp;
+ result = load_file (gfc_source_file, true);
- load_file (input, fp);
- fclose (input);
+ gfc_current_locus1.lb = line_head;
+ gfc_current_locus1.nextc = (line_head == NULL) ? NULL : line_head->line;
-init_fp:
- fp->included_by = gfc_current_file;
- gfc_current_file = fp;
+#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);
- fp->loc.line = 0;
- fp->loc.lp = fp->start;
- fp->loc.nextc = fp->start->line[0];
- fp->loc.file = fp;
+ exit (0);
+#endif
- return SUCCESS;
+ return result;
}
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index b345ed9..e4f564c 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -244,8 +244,8 @@ gfc_get_label_decl (gfc_st_label * lp)
/* Tell the debugger where the label came from. */
if (lp->value <= MAX_LABEL_VALUE) /* An internal label */
{
- DECL_SOURCE_LINE (label_decl) = lp->where.line;
- DECL_SOURCE_FILE (label_decl) = lp->where.file->filename;
+ DECL_SOURCE_LINE (label_decl) = lp->where.lb->linenum;
+ DECL_SOURCE_FILE (label_decl) = lp->where.lb->file->filename;
}
else
DECL_ARTIFICIAL (label_decl) = 1;
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index 24f403d..c0570fc 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -500,13 +500,13 @@ set_error_locus (stmtblock_t * block, locus * where)
tree tmp;
int line;
- f = where->file;
+ f = where->lb->file;
tmp = gfc_build_string_const (strlen (f->filename) + 1, f->filename);
tmp = gfc_build_addr_expr (pchar_type_node, tmp);
gfc_add_modify_expr (block, locus_file, tmp);
- line = where->lp->start_line + where->line;
+ line = where->lb->linenum;
gfc_add_modify_expr (block, locus_line, build_int_2 (line, 0));
}
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 39a6341..267391c 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -414,8 +414,9 @@ gfc_add_block_to_block (stmtblock_t * block, stmtblock_t * append)
void
gfc_get_backend_locus (locus * loc)
{
- loc->line = input_line - 1;
- loc->file = gfc_current_backend_file;
+ loc->lb = gfc_getmem (sizeof (gfc_linebuf));
+ loc->lb->linenum = input_line - 1;
+ loc->lb->file = gfc_current_backend_file;
}
@@ -424,9 +425,9 @@ gfc_get_backend_locus (locus * loc)
void
gfc_set_backend_locus (locus * loc)
{
- input_line = loc->line + 1;
- gfc_current_backend_file = loc->file;
- input_filename = loc->file->filename;
+ input_line = loc->lb->linenum;
+ gfc_current_backend_file = loc->lb->file;
+ input_filename = loc->lb->file->filename;
}