From d4fa05b90d6647ceaf50b5f1b8504fc0e01fae9c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tobias=20Schl=C3=BCter?= Date: Sat, 15 May 2004 19:31:32 +0200 Subject: [PATCH] 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 --- gcc/fortran/ChangeLog | 50 ++++ gcc/fortran/error.c | 28 +- gcc/fortran/gfortran.h | 70 +++-- gcc/fortran/lang-specs.h | 32 +-- gcc/fortran/match.c | 4 +- gcc/fortran/module.c | 9 +- gcc/fortran/parse.c | 15 +- gcc/fortran/scanner.c | 571 ++++++++++++++++++++++----------------- gcc/fortran/trans-decl.c | 4 +- gcc/fortran/trans-io.c | 4 +- gcc/fortran/trans.c | 11 +- 11 files changed, 451 insertions(+), 347 deletions(-) diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 586ddb61104..a1542b5db3e 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,53 @@ +2004-05-15 Tobias Schlueter + + 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 * Make-lang.in (trans-common.o): Remove redundant dependency. diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c index 260733c8af4..b7b0fdb1bf6 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 627eb8df96b..498e63b6c9b 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 @@ -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 f1828e2ad19..b18483f5c23 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 c13e0579585..dc8dc3e7333 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 566e3f330c7..1143705a1d9 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 beec9d622ba..dea613bce77 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 34959ab92fe..a16c2749ce8 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') ? "" : 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 b345ed99c8e..e4f564cbf67 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 24f403d90b3..c0570fc8575 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 39a63415539..267391c1c38 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; } -- 2.30.2