Commit d4fa05b9 by Tobias Schlüter Committed by Tobias Schlüter

re PR fortran/13702 (When preprocessing Fortran files (.F, .F90 and .F95) cpp…

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
parent 39ae2b01
2004-05-15 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de> 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. * Make-lang.in (trans-common.o): Remove redundant dependency.
(data.c): Replace object file name ... (data.c): Replace object file name ...
(data.o): ... by the correct one. (data.o): ... by the correct one.
......
...@@ -118,8 +118,9 @@ error_string (const char *p) ...@@ -118,8 +118,9 @@ error_string (const char *p)
static void error_printf (const char *, ...) ATTRIBUTE_PRINTF_1; static void error_printf (const char *, ...) ATTRIBUTE_PRINTF_1;
static void static void
show_locus (int offset, locus * l) show_locus (int offset, locus * loc)
{ {
gfc_linebuf *lb;
gfc_file *f; gfc_file *f;
char c, *p; char c, *p;
int i, m; int i, m;
...@@ -127,20 +128,25 @@ show_locus (int offset, locus * l) ...@@ -127,20 +128,25 @@ show_locus (int offset, locus * l)
/* TODO: Either limit the total length and number of included files /* TODO: Either limit the total length and number of included files
displayed or add buffering of arbitrary number of characters in displayed or add buffering of arbitrary number of characters in
error messages. */ error messages. */
f = l->file;
error_printf ("In file %s:%d\n", f->filename, l->lp->start_line + l->line);
f = f->included_by; lb = loc->lb;
while (f != NULL) f = lb->file;
error_printf ("In file %s:%d\n", f->filename, lb->linenum);
for (;;)
{ {
error_printf (" Included at %s:%d\n", f->filename, i = f->inclusion_line;
f->loc.lp->start_line + f->loc.line);
f = f->included_by; 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 the line itself, taking care not to print more than what can
show up on the terminal. Tabs are converted to spaces. */ show up on the terminal. Tabs are converted to spaces. */
p = l->lp->line[l->line] + offset;
p = lb->line + offset;
i = strlen (p); i = strlen (p);
if (i > terminal_width) if (i > terminal_width)
i = terminal_width - 1; i = terminal_width - 1;
...@@ -190,12 +196,12 @@ show_loci (locus * l1, locus * l2) ...@@ -190,12 +196,12 @@ show_loci (locus * l1, locus * l2)
return; return;
} }
c1 = l1->nextc - l1->lp->line[l1->line]; c1 = l1->nextc - l1->lb->line;
c2 = 0; c2 = 0;
if (l2 == NULL) if (l2 == NULL)
goto separate; goto separate;
c2 = l2->nextc - l2->lp->line[l2->line]; c2 = l2->nextc - l2->lb->line;
if (c1 < c2) if (c1 < c2)
m = c2 - c1; m = c2 - c1;
...@@ -203,7 +209,7 @@ show_loci (locus * l1, locus * l2) ...@@ -203,7 +209,7 @@ show_loci (locus * l1, locus * l2)
m = c1 - c2; 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; goto separate;
offset = 0; offset = 0;
......
...@@ -413,35 +413,40 @@ typedef struct ...@@ -413,35 +413,40 @@ typedef struct
symbol_attribute; symbol_attribute;
typedef struct /* 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
gfc_linebuf holds a single line of source code and information
which file it resides in
locus point to the sourceline and the character in the source
line.
*/
typedef struct gfc_file
{ {
char *nextc; struct gfc_file *included_by, *next, *up;
int line; /* line within the lp structure */ int inclusion_line, line;
struct linebuf *lp; char *filename;
struct gfc_file *file; } gfc_file;
}
locus;
/* The linebuf structure deserves some explanation. This is the typedef struct gfc_linebuf
primary structure for holding lines. A source file is stored in a {
singly linked list of these structures. Each structure holds an int linenum;
integer number of lines. The line[] member is actually an array of struct gfc_file *file;
pointers that point to the NULL-terminated lines. This list grows struct gfc_linebuf *next;
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. */
/* Chosen so that sizeof(linebuf) = 4096 on most machines */ char line[];
#define LINEBUF_SIZE 4080 } gfc_linebuf;
typedef struct linebuf typedef struct
{ {
int start_line, lines; char *nextc;
struct linebuf *next; gfc_linebuf *lb;
char *line[1]; } locus;
char buf[LINEBUF_SIZE];
}
linebuf;
#include <limits.h> #include <limits.h>
...@@ -451,17 +456,6 @@ linebuf; ...@@ -451,17 +456,6 @@ linebuf;
#endif #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; extern int gfc_suppress_error;
...@@ -1308,7 +1302,9 @@ void gfc_error_recovery (void); ...@@ -1308,7 +1302,9 @@ void gfc_error_recovery (void);
void gfc_gobble_whitespace (void); void gfc_gobble_whitespace (void);
try gfc_new_file (const char *, gfc_source_form); 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 */ /* misc.c */
void *gfc_getmem (size_t) ATTRIBUTE_MALLOC; void *gfc_getmem (size_t) ATTRIBUTE_MALLOC;
......
...@@ -7,29 +7,29 @@ This file is licensed under the GPL. */ ...@@ -7,29 +7,29 @@ This file is licensed under the GPL. */
/* This is the contribution to the `default_compilers' array in gcc.c /* This is the contribution to the `default_compilers' array in gcc.c
for the f95 language. */ for the f95 language. */
{".F", "@f77-cpp-input", 0}, {".F", "@f77-cpp-input", 0, 0, 0},
{".fpp", "@f77-cpp-input", 0}, {".fpp", "@f77-cpp-input", 0, 0, 0},
{".FPP", "@f77-cpp-input", 0}, {".FPP", "@f77-cpp-input", 0, 0, 0},
{"@f77-cpp-input", {"@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)}\ %{E|M|MM:%(cpp_debug_options)}\
%{!M:%{!MM:%{!E: -o %|.f |\n\ %{!M:%{!MM:%{!E: -o %|.f |\n\
f951 %|.f %{!ffree-form:-ffixed-form} %(cc1_options) %{J*} %{I*}\ f951 %|.f %{!ffree-form:-ffixed-form} %(cc1_options) %{J*} %{I*}\
%{!fsyntax-only:%(invoke_as)}}}}", 0}, %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
{".F90", "@f95-cpp-input", 0}, {".F90", "@f95-cpp-input", 0, 0, 0},
{".F95", "@f95-cpp-input", 0}, {".F95", "@f95-cpp-input", 0, 0, 0},
{"@f95-cpp-input", {"@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)}\ %{E|M|MM:%(cpp_debug_options)}\
%{!M:%{!MM:%{!E: -o %|.f95 |\n\ %{!M:%{!MM:%{!E: -o %|.f95 |\n\
f951 %|.f95 %(cc1_options) %{J*} %{I*}\ f951 %|.f95 %(cc1_options) %{J*} %{I*}\
%{!fsyntax-only:%(invoke_as)}}}}", 0}, %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
{".f90", "@f95", 0}, {".f90", "@f95", 0, 0, 0},
{".f95", "@f95", 0}, {".f95", "@f95", 0, 0, 0},
{"@f95", "%{!E:f951 %i %(cc1_options) %{J*} %{I*}\ {"@f95", "%{!E:f951 %i %(cc1_options) %{J*} %{I*}\
%{!fsyntax-only:%(invoke_as)}}", 0}, %{!fsyntax-only:%(invoke_as)}}", 0, 0, 0},
{".f", "@f77", 0}, {".f", "@f77", 0, 0, 0},
{".for", "@f77", 0}, {".for", "@f77", 0, 0, 0},
{".FOR", "@f77", 0}, {".FOR", "@f77", 0, 0, 0},
{"@f77", "%{!E:f951 %i %{!ffree-form:-ffixed-form} %(cc1_options) %{J*} %{I*}\ {"@f77", "%{!E:f951 %i %{!ffree-form:-ffixed-form} %(cc1_options) %{J*} %{I*}\
%{!fsyntax-only:%(invoke_as)}}", 0}, %{!fsyntax-only:%(invoke_as)}}", 0, 0, 0},
...@@ -77,7 +77,7 @@ gfc_match_space (void) ...@@ -77,7 +77,7 @@ gfc_match_space (void)
locus old_loc; locus old_loc;
int c; int c;
if (gfc_current_file->form == FORM_FIXED) if (gfc_current_form == FORM_FIXED)
return MATCH_YES; return MATCH_YES;
old_loc = *gfc_current_locus (); old_loc = *gfc_current_locus ();
...@@ -337,7 +337,7 @@ gfc_match_strings (mstring * a) ...@@ -337,7 +337,7 @@ gfc_match_strings (mstring * a)
if (*p->mp == ' ') if (*p->mp == ' ')
{ {
/* Space matches 1+ whitespace(s). */ /* Space matches 1+ whitespace(s). */
if ((gfc_current_file->form == FORM_FREE) if ((gfc_current_form == FORM_FREE)
&& gfc_is_whitespace (c)) && gfc_is_whitespace (c))
continue; continue;
......
...@@ -3338,7 +3338,6 @@ void ...@@ -3338,7 +3338,6 @@ void
gfc_dump_module (const char *name, int dump_flag) gfc_dump_module (const char *name, int dump_flag)
{ {
char filename[PATH_MAX], *p; char filename[PATH_MAX], *p;
gfc_file *g;
time_t now; time_t now;
filename[0] = '\0'; filename[0] = '\0';
...@@ -3359,17 +3358,13 @@ gfc_dump_module (const char *name, int dump_flag) ...@@ -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", gfc_fatal_error ("Can't open module file '%s' for writing: %s",
filename, strerror (errno)); filename, strerror (errno));
/* Find the top level filename. */
g = gfc_current_file;
while (g->next)
g = g->next;
now = time (NULL); now = time (NULL);
p = ctime (&now); p = ctime (&now);
*strchr (p, '\n') = '\0'; *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); fputs ("If you edit this, you'll get what you deserve.\n\n", module_fp);
iomode = IO_OUTPUT; iomode = IO_OUTPUT;
......
...@@ -483,16 +483,6 @@ next_statement (void) ...@@ -483,16 +483,6 @@ next_statement (void)
gfc_skip_comments (); 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 ()) if (gfc_at_end ())
{ {
st = ST_NONE; st = ST_NONE;
...@@ -500,7 +490,8 @@ next_statement (void) ...@@ -500,7 +490,8 @@ next_statement (void)
} }
st = st =
(gfc_current_file->form == FORM_FIXED) ? next_fixed () : next_free (); (gfc_current_form == FORM_FIXED) ? next_fixed () : next_free ();
if (st != ST_NONE) if (st != ST_NONE)
break; break;
} }
...@@ -1268,7 +1259,7 @@ unexpected_eof (void) ...@@ -1268,7 +1259,7 @@ unexpected_eof (void)
{ {
gfc_state_data *p; 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". */ /* Memory cleanup. Move to "second to last". */
for (p = gfc_state_stack; p && p->previous && p->previous->previous; for (p = gfc_state_stack; p && p->previous && p->previous->previous;
......
...@@ -60,10 +60,15 @@ gfc_directorylist; ...@@ -60,10 +60,15 @@ gfc_directorylist;
/* List of include file search directories. */ /* List of include file search directories. */
static gfc_directorylist *include_dirs; static gfc_directorylist *include_dirs;
static gfc_file *first_file, *first_duplicated_file; static gfc_file *file_head, *current_file;
static int continue_flag, end_flag; static int continue_flag, end_flag;
gfc_file *gfc_current_file; gfc_source_form gfc_current_form;
static gfc_linebuf *line_head, *line_tail;
locus gfc_current_locus1;
char *gfc_source_file;
/* Main scanner initialization. */ /* Main scanner initialization. */
...@@ -71,10 +76,10 @@ gfc_file *gfc_current_file; ...@@ -71,10 +76,10 @@ gfc_file *gfc_current_file;
void void
gfc_scanner_init_1 (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; end_flag = 0;
} }
...@@ -84,36 +89,24 @@ gfc_scanner_init_1 (void) ...@@ -84,36 +89,24 @@ gfc_scanner_init_1 (void)
void void
gfc_scanner_done_1 (void) gfc_scanner_done_1 (void)
{ {
gfc_linebuf *lb;
gfc_file *f;
linebuf *lp, *lp2; while(line_head != NULL)
gfc_file *fp, *fp2;
for (fp = first_file; fp; fp = fp2)
{
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; lb = line_head->next;
gfc_free (lp); gfc_free(line_head);
} line_head = lb;
}
fp2 = fp->next;
gfc_free (fp);
} }
for (fp = first_duplicated_file; fp; fp = fp2) while(file_head != NULL)
{ {
fp2 = fp->next; f = file_head->next;
gfc_free (fp); gfc_free(file_head->filename);
gfc_free(file_head);
file_head = f;
} }
} }
...@@ -168,7 +161,6 @@ gfc_release_include_path (void) ...@@ -168,7 +161,6 @@ gfc_release_include_path (void)
} }
} }
/* Opens file for reading, searching through the include directories /* Opens file for reading, searching through the include directories
given if necessary. */ given if necessary. */
...@@ -206,19 +198,18 @@ locus * ...@@ -206,19 +198,18 @@ locus *
gfc_current_locus (void) gfc_current_locus (void)
{ {
if (gfc_current_file == NULL) return &gfc_current_locus1;
return NULL;
return &gfc_current_file->loc;
} }
/* Let a caller move the current read pointer (backwards). */ /* Let a caller move the current read pointer (backwards). */
void void
gfc_set_locus (locus * lp) gfc_set_locus (locus * lp)
{ {
gfc_current_file->loc = *lp; gfc_current_locus1 = *lp;
} }
...@@ -241,10 +232,10 @@ gfc_at_eof (void) ...@@ -241,10 +232,10 @@ gfc_at_eof (void)
if (gfc_at_end ()) if (gfc_at_end ())
return 1; return 1;
if (gfc_current_file->start->lines == 0) if (line_head == NULL)
return 1; /* Null file */ return 1; /* Null file */
if (gfc_current_file->loc.lp == NULL) if (gfc_current_locus1.lb == NULL)
return 1; return 1;
return 0; return 0;
...@@ -256,14 +247,10 @@ gfc_at_eof (void) ...@@ -256,14 +247,10 @@ gfc_at_eof (void)
int int
gfc_at_bol (void) gfc_at_bol (void)
{ {
int i;
if (gfc_at_eof ()) if (gfc_at_eof ())
return 1; return 1;
i = gfc_current_file->loc.line; return (gfc_current_locus1.nextc == gfc_current_locus1.lb->line);
return gfc_current_file->loc.nextc == gfc_current_file->loc.lp->line[i];
} }
...@@ -276,7 +263,7 @@ gfc_at_eol (void) ...@@ -276,7 +263,7 @@ gfc_at_eol (void)
if (gfc_at_eof ()) if (gfc_at_eof ())
return 1; return 1;
return *gfc_current_file->loc.nextc == '\0'; return (*gfc_current_locus1.nextc == '\0');
} }
...@@ -285,27 +272,24 @@ gfc_at_eol (void) ...@@ -285,27 +272,24 @@ gfc_at_eol (void)
void void
gfc_advance_line (void) gfc_advance_line (void)
{ {
locus *locp;
linebuf *lp;
if (gfc_at_end ()) if (gfc_at_end ())
return; return;
locp = &gfc_current_file->loc; if (gfc_current_locus1.lb == NULL)
lp = locp->lp; {
if (lp == NULL) end_flag = 1;
return; return;
}
if (++locp->line >= lp->lines) gfc_current_locus1.lb = gfc_current_locus1.lb->next;
{
locp->lp = lp = lp->next;
if (lp == NULL)
return; /* End of this file */
locp->line = 0; if (gfc_current_locus1.lb != NULL)
gfc_current_locus1.nextc = gfc_current_locus1.lb->line;
else
{
gfc_current_locus1.nextc = NULL;
end_flag = 1;
} }
locp->nextc = lp->line[locp->line];
} }
...@@ -321,104 +305,21 @@ gfc_advance_line (void) ...@@ -321,104 +305,21 @@ gfc_advance_line (void)
static int static int
next_char (void) next_char (void)
{ {
locus *locp;
int c; int c;
/* End the current include level, but not if we're in the middle if (gfc_current_locus1.nextc == NULL)
of processing a continuation. */
if (gfc_at_eof ())
{
if (continue_flag != 0 || gfc_at_end ())
return '\n'; return '\n';
if (gfc_current_file->included_by == NULL) c = *gfc_current_locus1.nextc++;
end_flag = 1;
return '\n';
}
locp = &gfc_current_file->loc;
if (locp->nextc == NULL)
return '\n';
c = *locp->nextc++;
if (c == '\0') if (c == '\0')
{ {
locp->nextc--; /* Stay stuck on this line */ gfc_current_locus1.nextc--; /* Remain on this line. */
c = '\n'; c = '\n';
} }
return c; 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 /* Skip a comment. When we come here the parse pointer is positioned
immediately after the comment character. If we ever implement immediately after the comment character. If we ever implement
compiler directives withing comments, here is where we parse the compiler directives withing comments, here is where we parse the
...@@ -450,7 +351,7 @@ skip_free_comments (void) ...@@ -450,7 +351,7 @@ skip_free_comments (void)
for (;;) for (;;)
{ {
start = *gfc_current_locus (); start = gfc_current_locus1;
if (gfc_at_eof ()) if (gfc_at_eof ())
break; break;
...@@ -492,7 +393,7 @@ skip_fixed_comments (void) ...@@ -492,7 +393,7 @@ skip_fixed_comments (void)
for (;;) for (;;)
{ {
start = *gfc_current_locus (); start = gfc_current_locus1;
if (gfc_at_eof ()) if (gfc_at_eof ())
break; break;
...@@ -543,7 +444,7 @@ void ...@@ -543,7 +444,7 @@ void
gfc_skip_comments (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 (); skip_free_comments ();
else else
skip_fixed_comments (); skip_fixed_comments ();
...@@ -570,7 +471,7 @@ restart: ...@@ -570,7 +471,7 @@ restart:
if (gfc_at_end ()) if (gfc_at_end ())
return c; return c;
if (gfc_current_file->form == FORM_FREE) if (gfc_current_form == FORM_FREE)
{ {
if (!in_string && c == '!') if (!in_string && c == '!')
...@@ -590,7 +491,7 @@ restart: ...@@ -590,7 +491,7 @@ restart:
/* If the next nonblank character is a ! or \n, we've got a /* If the next nonblank character is a ! or \n, we've got a
continuation line. */ continuation line. */
old_loc = gfc_current_file->loc; old_loc = gfc_current_locus1;
c = next_char (); c = next_char ();
while (gfc_is_whitespace (c)) while (gfc_is_whitespace (c))
...@@ -701,7 +602,7 @@ gfc_next_char (void) ...@@ -701,7 +602,7 @@ gfc_next_char (void)
{ {
c = gfc_next_char_literal (0); 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); return TOLOWER (c);
} }
...@@ -713,7 +614,7 @@ gfc_peek_char (void) ...@@ -713,7 +614,7 @@ gfc_peek_char (void)
locus old_loc; locus old_loc;
int c; int c;
old_loc = *gfc_current_locus (); old_loc = gfc_current_locus1;
c = gfc_next_char (); c = gfc_next_char ();
gfc_set_locus (&old_loc); gfc_set_locus (&old_loc);
...@@ -783,7 +684,7 @@ gfc_gobble_whitespace (void) ...@@ -783,7 +684,7 @@ gfc_gobble_whitespace (void)
do do
{ {
old_loc = *gfc_current_locus (); old_loc = gfc_current_locus1;
c = gfc_next_char_literal (0); c = gfc_next_char_literal (0);
} }
while (gfc_is_whitespace (c)); while (gfc_is_whitespace (c));
...@@ -798,12 +699,13 @@ gfc_gobble_whitespace (void) ...@@ -798,12 +699,13 @@ gfc_gobble_whitespace (void)
character in the source region. */ character in the source region. */
static void static void
load_line (FILE * input, gfc_source_form form, char *buffer, load_line (FILE * input, char *buffer, char *filename, int linenum)
char *filename, int linenum)
{ {
int c, maxlen, i, trunc_flag; 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; i = 0;
...@@ -817,12 +719,19 @@ load_line (FILE * input, gfc_source_form form, char *buffer, ...@@ -817,12 +719,19 @@ load_line (FILE * input, gfc_source_form form, char *buffer,
break; break;
if (c == '\r') if (c == '\r')
continue; /* Gobble characters */ continue; /* Gobble characters. */
if (c == '\0') if (c == '\0')
continue; continue;
if (form == FORM_FIXED && c == '\t' && i <= 6) if (c == '\032')
{ /* Tab expandsion */ {
/* 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) while (i <= 6)
{ {
*buffer++ = ' '; *buffer++ = ' ';
...@@ -836,7 +745,7 @@ load_line (FILE * input, gfc_source_form form, char *buffer, ...@@ -836,7 +745,7 @@ load_line (FILE * input, gfc_source_form form, char *buffer,
i++; i++;
if (i >= maxlen) if (i >= maxlen)
{ /* Truncate the rest of the line */ { /* Truncate the rest of the line. */
trunc_flag = 1; trunc_flag = 1;
for (;;) for (;;)
...@@ -863,51 +772,247 @@ load_line (FILE * input, gfc_source_form form, char *buffer, ...@@ -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 static void
load_file (FILE * input, gfc_file * fp) preprocessor_line (char *c)
{ {
char *linep, line[GFC_MAX_LINE + 1]; bool flag[5];
int len, linenum; int i, line;
linebuf *lp; char *filename;
gfc_file *f;
c++;
while (*c == ' ' || *c == '\t')
c++;
if (*c < '0' || *c > '9')
{
gfc_warning_now ("%s:%d Unknown preprocessor directive",
current_file->filename, current_file->line);
current_file->line++;
return;
}
line = atoi (c);
fp->start = lp = gfc_getmem (sizeof (linebuf)); c = strchr (c, ' ') + 2; /* Skip space and quote. */
filename = c;
linenum = 1; c = strchr (c, '"'); /* Make filename end at quote. */
lp->lines = 0; *c++ = '\0';
lp->start_line = 1;
lp->next = NULL;
linep = (char *) (lp + 1); /* Get flags. */
flag[1] = flag[2] = flag[3] = flag[4] = flag[5] = false;
for (;;)
{
c = strchr (c, ' ');
if (c == NULL)
break;
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. */ /* Load the file. */
f = get_file (filename);
f->up = current_file;
current_file = f;
current_file->line = 1;
for (;;) for (;;)
{ {
load_line (input, fp->form, line, fp->filename, linenum); load_line (input, line, filename, current_file->line);
linenum++;
len = strlen (line); len = strlen (line);
if (feof (input) && len == 0) if (feof (input) && len == 0)
break; break;
/* See if we need another linebuf. */ /* There are three things this line can be: a line of Fortran
if (((char *) &lp->line[lp->lines + 2]) > linep - len - 1) source, an include line or a C preprocessor directive. */
{
lp->next = gfc_getmem (sizeof (linebuf));
lp->next->start_line = lp->start_line + lp->lines; if (line[0] == '#')
lp = lp->next; {
lp->lines = 0; preprocessor_line (line);
continue;
}
linep = (char *) (lp + 1); if (include_line (line))
{
current_file->line++;
continue;
} }
linep = linep - len - 1; /* Add line. */
lp->line[lp->lines++] = linep;
strcpy (linep, 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) ...@@ -982,92 +1087,52 @@ form_from_filename (const char *filename)
} }
/* Open a new file and start scanning from that file. Every new file /* Open a new file and start scanning from that file. Returns SUCCESS
gets a gfc_file node, even if it is a duplicate file. Returns SUCCESS if everything went OK, FAILURE otherwise. If form == FORM_UKNOWN
if everything went OK, FAILURE otherwise. */ it tries to determine the source form from the filename, defaulting
to free form. */
try try
gfc_new_file (const char *filename, gfc_source_form form) gfc_new_file (const char *filename, gfc_source_form form)
{ {
gfc_file *fp, *fp2; try result;
FILE *input;
int len;
len = strlen (filename); if (filename != NULL)
if (len > PATH_MAX)
{ {
gfc_error_now ("Filename '%s' is too long- ignoring it", filename); gfc_source_file = gfc_getmem (strlen (filename) + 1);
return FAILURE; 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 else
input = gfc_open_included_file (filename); gfc_source_file = NULL;
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;
}
/* Decide which form the file will be read in as. */ /* Decide which form the file will be read in as. */
if (form != FORM_UNKNOWN) if (form != FORM_UNKNOWN)
fp->form = form; gfc_current_form = form;
else 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_current_form = FORM_FREE;
gfc_warning_now ("Reading file %s as free form", filename); gfc_warning_now ("Reading file '%s' as free form.",
(filename[0] == '\0') ? "<stdin>" : filename);
} }
} }
fp->next = first_file; result = load_file (gfc_source_file, true);
first_file = fp;
load_file (input, fp); gfc_current_locus1.lb = line_head;
fclose (input); gfc_current_locus1.nextc = (line_head == NULL) ? NULL : line_head->line;
init_fp: #if 0 /* Debugging aid. */
fp->included_by = gfc_current_file; for (; line_head; line_head = line_head->next)
gfc_current_file = fp; gfc_status ("%s:%3d %s\n", line_head->file->filename,
line_head->linenum, line_head->line);
fp->loc.line = 0; exit (0);
fp->loc.lp = fp->start; #endif
fp->loc.nextc = fp->start->line[0];
fp->loc.file = fp;
return SUCCESS; return result;
} }
...@@ -244,8 +244,8 @@ gfc_get_label_decl (gfc_st_label * lp) ...@@ -244,8 +244,8 @@ gfc_get_label_decl (gfc_st_label * lp)
/* Tell the debugger where the label came from. */ /* Tell the debugger where the label came from. */
if (lp->value <= MAX_LABEL_VALUE) /* An internal label */ if (lp->value <= MAX_LABEL_VALUE) /* An internal label */
{ {
DECL_SOURCE_LINE (label_decl) = lp->where.line; DECL_SOURCE_LINE (label_decl) = lp->where.lb->linenum;
DECL_SOURCE_FILE (label_decl) = lp->where.file->filename; DECL_SOURCE_FILE (label_decl) = lp->where.lb->file->filename;
} }
else else
DECL_ARTIFICIAL (label_decl) = 1; DECL_ARTIFICIAL (label_decl) = 1;
......
...@@ -500,13 +500,13 @@ set_error_locus (stmtblock_t * block, locus * where) ...@@ -500,13 +500,13 @@ set_error_locus (stmtblock_t * block, locus * where)
tree tmp; tree tmp;
int line; int line;
f = where->file; f = where->lb->file;
tmp = gfc_build_string_const (strlen (f->filename) + 1, f->filename); tmp = gfc_build_string_const (strlen (f->filename) + 1, f->filename);
tmp = gfc_build_addr_expr (pchar_type_node, tmp); tmp = gfc_build_addr_expr (pchar_type_node, tmp);
gfc_add_modify_expr (block, locus_file, 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)); gfc_add_modify_expr (block, locus_line, build_int_2 (line, 0));
} }
......
...@@ -414,8 +414,9 @@ gfc_add_block_to_block (stmtblock_t * block, stmtblock_t * append) ...@@ -414,8 +414,9 @@ gfc_add_block_to_block (stmtblock_t * block, stmtblock_t * append)
void void
gfc_get_backend_locus (locus * loc) gfc_get_backend_locus (locus * loc)
{ {
loc->line = input_line - 1; loc->lb = gfc_getmem (sizeof (gfc_linebuf));
loc->file = gfc_current_backend_file; loc->lb->linenum = input_line - 1;
loc->lb->file = gfc_current_backend_file;
} }
...@@ -424,9 +425,9 @@ gfc_get_backend_locus (locus * loc) ...@@ -424,9 +425,9 @@ gfc_get_backend_locus (locus * loc)
void void
gfc_set_backend_locus (locus * loc) gfc_set_backend_locus (locus * loc)
{ {
input_line = loc->line + 1; input_line = loc->lb->linenum;
gfc_current_backend_file = loc->file; gfc_current_backend_file = loc->lb->file;
input_filename = loc->file->filename; input_filename = loc->lb->file->filename;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment