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
This commit is contained in:
parent
39ae2b013a
commit
d4fa05b90d
|
@ -1,3 +1,53 @@
|
|||
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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -413,35 +413,40 @@ typedef struct
|
|||
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
|
||||
{
|
||||
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;
|
||||
int line; /* line within the lp structure */
|
||||
struct linebuf *lp;
|
||||
struct gfc_file *file;
|
||||
}
|
||||
locus;
|
||||
|
||||
/* 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. */
|
||||
|
||||
/* Chosen so that sizeof(linebuf) = 4096 on most machines */
|
||||
#define LINEBUF_SIZE 4080
|
||||
|
||||
typedef struct linebuf
|
||||
{
|
||||
int start_line, lines;
|
||||
struct linebuf *next;
|
||||
char *line[1];
|
||||
char buf[LINEBUF_SIZE];
|
||||
}
|
||||
linebuf;
|
||||
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;
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 gfc_file *file_head, *current_file;
|
||||
|
||||
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. */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
while(file_head != NULL)
|
||||
{
|
||||
f = file_head->next;
|
||||
gfc_free(file_head->filename);
|
||||
gfc_free(file_head);
|
||||
file_head = f;
|
||||
}
|
||||
|
||||
for (fp = first_duplicated_file; fp; fp = fp2)
|
||||
{
|
||||
fp2 = fp->next;
|
||||
gfc_free (fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
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)
|
||||
/* There are three things this line can be: a line of Fortran
|
||||
source, an include line or a C preprocessor directive. */
|
||||
|
||||
if (line[0] == '#')
|
||||
{
|
||||
lp->next = gfc_getmem (sizeof (linebuf));
|
||||
|
||||
lp->next->start_line = lp->start_line + lp->lines;
|
||||
lp = lp->next;
|
||||
lp->lines = 0;
|
||||
|
||||
linep = (char *) (lp + 1);
|
||||
preprocessor_line (line);
|
||||
continue;
|
||||
}
|
||||
|
||||
linep = linep - len - 1;
|
||||
lp->line[lp->lines++] = linep;
|
||||
strcpy (linep, line);
|
||||
if (include_line (line))
|
||||
{
|
||||
current_file->line++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue