diff options
-rw-r--r-- | gcc/ChangeLog | 40 | ||||
-rw-r--r-- | gcc/Makefile.in | 7 | ||||
-rw-r--r-- | gcc/c-lex.c | 26 | ||||
-rw-r--r-- | gcc/cpperror.c | 48 | ||||
-rw-r--r-- | gcc/cppfiles.c | 6 | ||||
-rw-r--r-- | gcc/cpphash.h | 4 | ||||
-rw-r--r-- | gcc/cppinit.c | 10 | ||||
-rw-r--r-- | gcc/cpplex.c | 19 | ||||
-rw-r--r-- | gcc/cpplib.c | 103 | ||||
-rw-r--r-- | gcc/cpplib.h | 17 | ||||
-rw-r--r-- | gcc/cppmain.c | 16 | ||||
-rw-r--r-- | gcc/fix-header.c | 2 | ||||
-rw-r--r-- | gcc/line-map.c | 118 | ||||
-rw-r--r-- | gcc/line-map.h | 80 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/19951025-1.c | 4 |
16 files changed, 387 insertions, 117 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d97e946a0e1..d7aa23c787e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,43 @@ +2001-08-03 Neil Booth <neil@cat.daikokuya.demon.co.uk> + + * line-map.c: New. + * line-map.h: New. + * Makefile.in (line-map.o): New. + (LIBCPP_OBJS, LIBCPP_DEPS): Update. + * c-lex.c (cb_file_change): Update for new cpp_file_change structure. + * cpperror.c (print_containing_files): Similarly. + (print_location): Update. Don't output a space before _Pragma. + * cppfiles.c (stack_include_file): Set to line 1 immediately. + (stack_include_filee, cpp_make_system_header): Update. + (_cpp_execute_include): Get logical line number right for calling + as-yet-unterminated #include. + * cpphash.h (struct cpp_reader): Add line_maps. + (_cpp_do_file_change): Update. + * cppinit.c (cpp_create_reader): Initialize line maps. + (cpp_destroy): Destroy line maps. + (cpp_start_read): Get logical line number right. + * cpplex.c (parse_string): Only warn once for multi-line strings. + Use boolean variable for null warning. + * cpplib.c (_cpp_handle_directive): End the directive if it isn't + already. + (do_include_common): End the directive early. + (do_line): Don't warn about out-of-range lines in preprocessed + source. Update. Remove unused variables. + (_cpp_do_file_change): Update for new line mapping. + (pragma_cb): New typedef. + (cpp_register_pragma): Stop looking ahead before calling the + handler. Clean up. + (do_pragma_system_header): End directive early. + (cpp_get_line_maps): New. + (cpp_pop_buffer): Fudge logical line. Update. + * cpplib.h: Include line-map.h + (enum cpp_fc_reason): Remove. + (struct cpp_file_change): Update. + (cpp_get_line_maps): New. + * cppmain.c (struct_printer): New member map. + (cb_file_change): Update for new mappings. + * fix-header.c (cb_file_change): Similarly. + 2001-08-02 Nick Clifton <nickc@cambridge.redhat.com> * Makefile.in (libgcc.mk): Define mkinstalldirs. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 90de1a0867c..c465c9c3b08 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1324,6 +1324,8 @@ stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) \ hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H) +line-map.o: line-map.c line-map.h $(CONFIG_H) $(SYSTEM_H) + ggc-none.o: ggc-none.c $(GCONFIG_H) $(SYSTEM_H) $(GGC_H) $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) @@ -1933,9 +1935,10 @@ PREPROCESSOR_DEFINES = \ LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o \ cpphash.o cpperror.o cppinit.o cppdefault.o \ - hashtable.o mkdeps.o prefix.o version.o mbchar.o + hashtable.o line-map.o mkdeps.o prefix.o version.o mbchar.o -LIBCPP_DEPS = cpplib.h cpphash.h hashtable.h intl.h $(OBSTACK_H) $(SYSTEM_H) +LIBCPP_DEPS = cpplib.h cpphash.h line-map.h hashtable.h intl.h \ + $(OBSTACK_H) $(SYSTEM_H) # Most of the other archives built/used by this makefile are for # targets. This one is strictly for the host. diff --git a/gcc/c-lex.c b/gcc/c-lex.c index cf958f56c30..ffd3b744172 100644 --- a/gcc/c-lex.c +++ b/gcc/c-lex.c @@ -241,16 +241,20 @@ cb_file_change (pfile, fc) cpp_reader *pfile ATTRIBUTE_UNUSED; const cpp_file_change *fc; { - if (fc->reason == FC_ENTER) + unsigned int from_line = SOURCE_LINE (fc->map - 1, fc->line - 1); + + if (fc->reason == LC_ENTER) { /* Don't stack the main buffer on the input stack; we already did in compile_file. */ - if (fc->from.filename) + if (MAIN_FILE_P (fc->map)) + main_input_filename = fc->map->to_file; + else { - lineno = fc->from.lineno; - push_srcloc (fc->to.filename, 1); + lineno = from_line; + push_srcloc (fc->map->to_file, 1); input_file_stack->indent_level = indent_level; - (*debug_hooks->start_source_file) (fc->from.lineno, fc->to.filename); + (*debug_hooks->start_source_file) (lineno, fc->map->to_file); #ifndef NO_IMPLICIT_EXTERN_C if (c_header_level) ++c_header_level; @@ -261,10 +265,8 @@ cb_file_change (pfile, fc) } #endif } - else - main_input_filename = fc->to.filename; } - else if (fc->reason == FC_LEAVE) + else if (fc->reason == LC_LEAVE) { /* Popping out of a file. */ if (input_file_stack->next) @@ -288,16 +290,16 @@ cb_file_change (pfile, fc) } #endif pop_srcloc (); - (*debug_hooks->end_source_file) (input_file_stack->line); + (*debug_hooks->end_source_file) (from_line); } else error ("leaving more files than we entered"); } - update_header_times (fc->to.filename); + update_header_times (fc->map->to_file); in_system_header = fc->sysp != 0; - input_filename = fc->to.filename; - lineno = fc->to.lineno; /* Do we need this? */ + input_filename = fc->map->to_file; + lineno = SOURCE_LINE (fc->map, fc->line); /* Do we need this? */ /* Hook for C++. */ extract_interface_info (); diff --git a/gcc/cpperror.c b/gcc/cpperror.c index 063489dae63..f10198288f0 100644 --- a/gcc/cpperror.c +++ b/gcc/cpperror.c @@ -29,7 +29,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "cpphash.h" #include "intl.h" -static void print_containing_files PARAMS ((cpp_buffer *)); +static void print_containing_files PARAMS ((struct line_map *, + struct line_map *)); static void print_location PARAMS ((cpp_reader *, const char *, const cpp_lexer_pos *)); @@ -42,21 +43,25 @@ static void print_location PARAMS ((cpp_reader *, /* Print the file names and line numbers of the #include commands which led to the current file. */ static void -print_containing_files (ip) - cpp_buffer *ip; +print_containing_files (map_array, map) + struct line_map *map_array; + struct line_map *map; { int first = 1; - /* Find the other, outer source files. */ - for (ip = ip->prev; ip; ip = ip->prev) + for (;;) { + if (MAIN_FILE_P (map)) + break; + map = &map_array[map->included_from]; + if (first) { first = 0; /* The current line in each outer source file is now the same as the line of the #include. */ fprintf (stderr, _("In file included from %s:%u"), - ip->nominal_fname, CPP_BUF_LINE (ip)); + map->to_file, LAST_SOURCE_LINE (map)); } else /* Translators note: this message is used in conjunction @@ -72,8 +77,9 @@ print_containing_files (ip) The trailing comma is at the beginning of this message, and the trailing colon is not translated. */ fprintf (stderr, _(",\n from %s:%u"), - ip->nominal_fname, CPP_BUF_LINE (ip)); + map->to_file, LAST_SOURCE_LINE (map)); } + fputs (":\n", stderr); } @@ -100,19 +106,24 @@ print_location (pfile, filename, pos) line = 0; else { + struct line_map *map; + + line = pfile->line; if (type == BUF_PRAGMA) { buffer = buffer->prev; - line = CPP_BUF_LINE (buffer); col = CPP_BUF_COL (buffer); } - else + + map = lookup_line (&pfile->line_maps, line); + if (pos == 0) { - if (pos == 0) - pos = cpp_get_line (pfile); - line = pos->line; - col = pos->col; + pos = cpp_get_line (pfile); + line = SOURCE_LINE (map, line); } + else + line = pos->line; + col = pos->col; if (col == 0) col = 1; @@ -121,7 +132,7 @@ print_location (pfile, filename, pos) if (buffer->prev && ! buffer->include_stack_listed) { buffer->include_stack_listed = 1; - print_containing_files (buffer); + print_containing_files (pfile->line_maps.maps, map); } } @@ -129,14 +140,15 @@ print_location (pfile, filename, pos) filename = buffer->nominal_fname; if (line == 0) - fprintf (stderr, "%s: ", filename); + fprintf (stderr, "%s:", filename); else if (CPP_OPTION (pfile, show_column) == 0) - fprintf (stderr, "%s:%u: ", filename, line); + fprintf (stderr, "%s:%u:", filename, line); else - fprintf (stderr, "%s:%u:%u: ", filename, line, col); + fprintf (stderr, "%s:%u:%u:", filename, line, col); if (type == BUF_PRAGMA) - fprintf (stderr, "_Pragma: "); + fprintf (stderr, "_Pragma:"); + fputc (' ', stderr); } } diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index 2592d4dc1fd..b939b405c88 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -338,7 +338,7 @@ stack_include_file (pfile, inc) /* Generate the call back. */ fp->lineno = 0; - _cpp_do_file_change (pfile, FC_ENTER, 0, 0); + _cpp_do_file_change (pfile, LC_ENTER); fp->lineno = 1; } @@ -579,8 +579,7 @@ cpp_make_system_header (pfile, syshdr, externc) if (syshdr) flags = 1 + (externc != 0); pfile->buffer->sysp = flags; - _cpp_do_file_change (pfile, FC_RENAME, pfile->buffer->nominal_fname, - pfile->buffer->lineno); + _cpp_do_file_change (pfile, LC_RENAME); } /* Report on all files that might benefit from a multiple include guard. @@ -681,6 +680,7 @@ _cpp_execute_include (pfile, header, type) pfile->system_include_depth++; stack_include_file (pfile, inc); + pfile->line++; /* Fake the '\n' at the end of #include. */ if (type == IT_IMPORT) _cpp_never_reread (inc); diff --git a/gcc/cpphash.h b/gcc/cpphash.h index 12b64a80afa..0c1695c1d09 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -249,6 +249,7 @@ struct cpp_reader /* Source line tracking. Subtract pseudo_newlines from the actual line number to get the line number of preprocessed output. Used for escaped newlines and macro args that cross multiple lines. */ + struct line_maps line_maps; unsigned int line; unsigned int pseudo_newlines; @@ -439,8 +440,7 @@ extern void _cpp_define_builtin PARAMS ((cpp_reader *, const char *)); extern void _cpp_do__Pragma PARAMS ((cpp_reader *)); extern void _cpp_init_directives PARAMS ((cpp_reader *)); extern void _cpp_init_internal_pragmas PARAMS ((cpp_reader *)); -extern void _cpp_do_file_change PARAMS ((cpp_reader *, enum cpp_fc_reason, - const char *, unsigned int)); +extern void _cpp_do_file_change PARAMS ((cpp_reader *, enum lc_reason)); /* Utility routines and macros. */ #define DSC(str) (const U_CHAR *)str, sizeof str - 1 diff --git a/gcc/cppinit.c b/gcc/cppinit.c index 9c194109266..fa01b347055 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -496,6 +496,9 @@ cpp_create_reader (table, lang) be needed. */ pfile->deps = deps_init (); + /* Initialise the line map. */ + init_line_maps (&pfile->line_maps); + /* Initialize lexer state. */ pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); @@ -585,6 +588,8 @@ cpp_destroy (pfile) free (context); } + free_line_maps (&pfile->line_maps); + result = pfile->errors; free (pfile); @@ -941,6 +946,11 @@ cpp_start_read (pfile, fname) p = q; } + /* This was zero when the initial buffer was stacked; so we must + make up for a non-existent new line, as well as the intervening + macro definitions, by setting it to 1. */ + pfile->line = 1; + /* The -imacros files can be scanned now, but the -include files have to be pushed onto the buffer stack and processed later, otherwise cppmain.c won't see the tokens. include_head was built diff --git a/gcc/cpplex.c b/gcc/cpplex.c index af2b9e93006..fa32bd51561 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -657,7 +657,7 @@ parse_string (pfile, token, terminator) cpp_pool *pool = &pfile->ident_pool; unsigned char *dest, *limit; cppchar_t c; - unsigned int nulls = 0; + bool warned_nulls = false, warned_multi = false; dest = POOL_FRONT (pool); limit = POOL_LIMIT (pool); @@ -707,7 +707,12 @@ parse_string (pfile, token, terminator) break; } - cpp_pedwarn (pfile, "multi-line string literals are deprecated"); + if (!warned_multi) + { + warned_multi = true; + cpp_pedwarn (pfile, "multi-line string literals are deprecated"); + } + if (pfile->mlstring_pos.line == 0) pfile->mlstring_pos = pfile->lexer_pos; @@ -715,10 +720,10 @@ parse_string (pfile, token, terminator) *dest++ = '\n'; goto have_char; } - else if (c == '\0') + else if (c == '\0' && !warned_nulls) { - if (nulls++ == 0) - cpp_warning (pfile, "null character(s) preserved in literal"); + warned_nulls = true; + cpp_warning (pfile, "null character(s) preserved in literal"); } *dest++ = c; @@ -914,8 +919,8 @@ _cpp_lex_token (pfile, result) bol = 1; pfile->lexer_pos.output_line = buffer->lineno; /* This is a new line, so clear any white space flag. - Newlines in arguments are white space (6.10.3.10); - parse_arg takes care of that. */ + Newlines in arguments are white space (6.10.3.10); + parse_arg takes care of that. */ result->flags &= ~(PREV_WHITE | AVOID_LPASTE); goto next_char; } diff --git a/gcc/cpplib.c b/gcc/cpplib.c index 06bf6744ef6..b3d1c701794 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -379,7 +379,8 @@ _cpp_handle_directive (pfile, indented) cpp_token_as_text (pfile, &dname)); } - end_directive (pfile, skip); + if (pfile->state.in_directive) + end_directive (pfile, skip); return skip; } @@ -623,7 +624,7 @@ do_include_common (pfile, type) { check_eol (pfile); /* Get out of macro context, if we are. */ - skip_rest_of_line (pfile); + end_directive (pfile, 1); if (pfile->cb.include) (*pfile->cb.include) (pfile, pfile->directive->name, &header); @@ -713,9 +714,7 @@ do_line (pfile) cpp_reader *pfile; { cpp_buffer *buffer = pfile->buffer; - const char *filename = buffer->nominal_fname; - unsigned int lineno = buffer->lineno; - enum cpp_fc_reason reason = FC_RENAME; + enum lc_reason reason = LC_RENAME; unsigned long new_lineno; unsigned int cap; cpp_token token; @@ -733,7 +732,8 @@ do_line (pfile) return; } - if (CPP_PEDANTIC (pfile) && (new_lineno == 0 || new_lineno > cap)) + if (CPP_PEDANTIC (pfile) && ! pfile->state.line_extension + && (new_lineno == 0 || new_lineno > cap)) cpp_pedwarn (pfile, "line number out of range"); cpp_get_token (pfile, &token); @@ -751,12 +751,12 @@ do_line (pfile) flag = read_flag (pfile, flag); if (flag == 1) { - reason = FC_ENTER; + reason = LC_ENTER; flag = read_flag (pfile, flag); } else if (flag == 2) { - reason = FC_LEAVE; + reason = LC_LEAVE; flag = read_flag (pfile, flag); } if (flag == 3) @@ -767,7 +767,7 @@ do_line (pfile) sysp = 2, read_flag (pfile, flag); } - if (reason == FC_ENTER) + if (reason == LC_ENTER) { /* Fake a buffer stack for diagnostics. */ cpp_push_buffer (pfile, 0, 0, BUF_FAKE, fname); @@ -775,7 +775,7 @@ do_line (pfile) _cpp_fake_include (pfile, fname); buffer = pfile->buffer; } - else if (reason == FC_LEAVE) + else if (reason == LC_LEAVE) { if (buffer->type != BUF_FAKE) cpp_warning (pfile, "file \"%s\" left but not entered", @@ -808,49 +808,36 @@ do_line (pfile) return; } - /* Our line number is incremented after the directive is processed. */ + end_directive (pfile, 1); buffer->lineno = new_lineno - 1; - _cpp_do_file_change (pfile, reason, filename, lineno); + _cpp_do_file_change (pfile, reason); } -/* Arrange the file_change callback. */ +/* Arrange the file_change callback. It is assumed that the next line + is given by incrementing buffer->lineno and pfile->line. */ void -_cpp_do_file_change (pfile, reason, from_file, from_lineno) +_cpp_do_file_change (pfile, reason) cpp_reader *pfile; - enum cpp_fc_reason reason; - const char *from_file; - unsigned int from_lineno; + enum lc_reason reason; { + cpp_buffer *buffer; + struct line_map *map; + + buffer = pfile->buffer; + map = add_line_map (&pfile->line_maps, reason, + pfile->line + 1, buffer->nominal_fname, buffer->lineno + 1); + if (pfile->cb.file_change) { cpp_file_change fc; - cpp_buffer *buffer = pfile->buffer; - + + fc.map = map; + fc.line = pfile->line + 1; fc.reason = reason; - fc.to.filename = buffer->nominal_fname; - fc.to.lineno = buffer->lineno + 1; fc.sysp = buffer->sysp; fc.externc = CPP_OPTION (pfile, cplusplus) && buffer->sysp == 2; - /* Caller doesn't need to handle FC_ENTER. */ - if (reason == FC_ENTER) - { - if (buffer->prev) - { - from_file = buffer->prev->nominal_fname; - from_lineno = buffer->prev->lineno; - } - else - from_file = 0; - } - /* Special case for file "foo.i" with "# 1 foo.c" on first line. */ - else if (reason == FC_RENAME && ! buffer->prev - && pfile->directive_pos.line == 1) - from_file = 0; - - fc.from.filename = from_file; - fc.from.lineno = from_lineno; - pfile->cb.file_change (pfile, &fc); + (*pfile->cb.file_change) (pfile, &fc); } } @@ -915,6 +902,7 @@ do_ident (pfile) /* Sub-handlers for the pragmas needing treatment here. They return 1 if the token buffer is to be popped, 0 if not. */ +typedef void (*pragma_cb) PARAMS ((cpp_reader *)); struct pragma_entry { struct pragma_entry *next; @@ -922,7 +910,7 @@ struct pragma_entry size_t len; int isnspace; union { - void (*handler) PARAMS ((cpp_reader *)); + pragma_cb handler; struct pragma_entry *space; } u; }; @@ -932,7 +920,7 @@ cpp_register_pragma (pfile, space, name, handler) cpp_reader *pfile; const char *space; const char *name; - void (*handler) PARAMS ((cpp_reader *)); + pragma_cb handler; { struct pragma_entry **x, *new; size_t len; @@ -1014,9 +1002,9 @@ static void do_pragma (pfile) cpp_reader *pfile; { + pragma_cb handler = NULL; const struct pragma_entry *p; cpp_token tok; - int drop = 0; p = pfile->pragmas; pfile->state.prevent_expansion++; @@ -1041,8 +1029,7 @@ do_pragma (pfile) } else { - (*p->u.handler) (pfile); - drop = 1; + handler = p->u.handler; break; } } @@ -1050,10 +1037,12 @@ do_pragma (pfile) } } - cpp_stop_lookahead (pfile, drop); + cpp_stop_lookahead (pfile, handler != NULL); pfile->state.prevent_expansion--; - if (!drop && pfile->cb.def_pragma) + if (handler) + (*handler) (pfile); + else if (pfile->cb.def_pragma) (*pfile->cb.def_pragma) (pfile); } @@ -1119,9 +1108,11 @@ do_pragma_system_header (pfile) if (buffer->prev == 0) cpp_warning (pfile, "#pragma system_header ignored outside include file"); else - cpp_make_system_header (pfile, 1, 0); - - check_eol (pfile); + { + check_eol (pfile); + end_directive (pfile, 1); + cpp_make_system_header (pfile, 1, 0); + } } /* Check the modified date of the current include file against a specified @@ -1763,6 +1754,14 @@ cpp_get_callbacks (pfile) return &pfile->cb; } +/* The line map set. */ +struct line_maps * +cpp_get_line_maps (pfile) + cpp_reader *pfile; +{ + return &pfile->line_maps; +} + /* Copy the given callbacks structure to our own. */ void cpp_set_callbacks (pfile, cb) @@ -1875,8 +1874,8 @@ cpp_pop_buffer (pfile) if (pfile->directive == &dtable[T_LINE]) break; - _cpp_do_file_change (pfile, FC_LEAVE, buffer->nominal_fname, - buffer->lineno); + pfile->line--; /* We have a '\n' at the end of #include. */ + _cpp_do_file_change (pfile, LC_LEAVE); if (pfile->buffer->type == BUF_FILE) break; diff --git a/gcc/cpplib.h b/gcc/cpplib.h index fb7fac276db..bb91adb33eb 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -25,6 +25,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <sys/types.h> #include "hashtable.h" +#include "line-map.h" #ifdef __cplusplus extern "C" { @@ -386,21 +387,12 @@ struct cpp_options unsigned char help_only; }; -/* This structure is passed to the call back when changing file. */ -enum cpp_fc_reason {FC_ENTER = 0, FC_LEAVE, FC_RENAME}; - -struct cpp_file_loc -{ - const char *filename; - unsigned int lineno; -}; - typedef struct cpp_file_change cpp_file_change; struct cpp_file_change { - struct cpp_file_loc from; /* Line of #include or #line. */ - struct cpp_file_loc to; /* Line after #include or #line, or start. */ - enum cpp_fc_reason reason; /* Reason for change. */ + struct line_map *map; /* Line map to use until next callback. */ + unsigned int line; /* Logical line number of next line. */ + enum lc_reason reason; /* Reason for change. */ unsigned char sysp; /* Nonzero if system header. */ unsigned char externc; /* Nonzero if wrapper needed. */ }; @@ -510,6 +502,7 @@ extern int cpp_destroy PARAMS ((cpp_reader *)); through the pointer returned from cpp_get_callbacks, or set them with cpp_set_callbacks. */ extern cpp_options *cpp_get_options PARAMS ((cpp_reader *)); +extern struct line_maps *cpp_get_line_maps PARAMS ((cpp_reader *)); extern cpp_callbacks *cpp_get_callbacks PARAMS ((cpp_reader *)); extern void cpp_set_callbacks PARAMS ((cpp_reader *, cpp_callbacks *)); diff --git a/gcc/cppmain.c b/gcc/cppmain.c index 8f1982f5389..cc3b81d10bd 100644 --- a/gcc/cppmain.c +++ b/gcc/cppmain.c @@ -35,6 +35,7 @@ struct printer const char *syshdr_flags; /* system header flags, if any. */ unsigned int lineno; /* line currently being written. */ unsigned char printed; /* nonzero if something output at lineno. */ + struct line_map *map; /* logical to physical line mappings. */ }; int main PARAMS ((int, char **)); @@ -402,10 +403,11 @@ cb_file_change (pfile, fc) const cpp_file_change *fc; { /* Bring current file to correct line (except first file). */ - if (fc->reason == FC_ENTER && fc->from.filename) - maybe_print_line (fc->from.lineno); + if (fc->reason == LC_ENTER && !MAIN_FILE_P (fc->map)) + maybe_print_line (SOURCE_LINE (fc->map - 1, fc->line - 1)); - print.last_fname = fc->to.filename; + print.map = fc->map; + print.last_fname = fc->map->to_file; if (fc->externc) print.syshdr_flags = " 3 4"; else if (fc->sysp) @@ -417,10 +419,10 @@ cb_file_change (pfile, fc) { const char *flags = ""; - print.lineno = fc->to.lineno; - if (fc->reason == FC_ENTER) + print.lineno = SOURCE_LINE (fc->map, fc->line); + if (fc->reason == LC_ENTER) flags = " 1"; - else if (fc->reason == FC_LEAVE) + else if (fc->reason == LC_LEAVE) flags = " 2"; if (! options->no_line_commands) @@ -428,6 +430,8 @@ cb_file_change (pfile, fc) } } +/* Copy a #pragma directive to the preprocessed output. LINE is the + line of the current source file, not the logical line. */ static void cb_def_pragma (pfile) cpp_reader *pfile; diff --git a/gcc/fix-header.c b/gcc/fix-header.c index 8d801281d45..3124196e7b0 100644 --- a/gcc/fix-header.c +++ b/gcc/fix-header.c @@ -603,7 +603,7 @@ cb_file_change (pfile, fc) const cpp_file_change *fc; { /* Just keep track of current file name. */ - cur_file = fc->to.filename; + cur_file = fc->map->to_file; } static void diff --git a/gcc/line-map.c b/gcc/line-map.c new file mode 100644 index 00000000000..a67191d3aed --- /dev/null +++ b/gcc/line-map.c @@ -0,0 +1,118 @@ +/* Map logical line numbers to (source file, line number) pairs. + Copyright (C) 2001 + Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + +#include "config.h" +#include "system.h" +#include "line-map.h" + +/* Initialize a line map set. */ + +void +init_line_maps (set) + struct line_maps *set; +{ + set->maps = 0; + set->allocated = 0; + set->used = 0; +} + +/* Free a line map set. */ + +void free_line_maps (set) + struct line_maps *set; +{ + if (set->maps) + free (set->maps); +} + +/* Add a mapping of logical source line to physical source file and + line number. Ther text pointed to by TO_FILE must have a lifetime + at least as long as the final call to lookup_line (). + + FROM_LINE should be monotonic increasing across calls to this + function. */ + +struct line_map * +add_line_map (set, reason, from_line, to_file, to_line) + struct line_maps *set; + enum lc_reason reason; + unsigned int from_line; + const char *to_file; + unsigned int to_line; +{ + struct line_map *map; + + if (set->used && from_line < set->maps[set->used - 1].from_line) + abort (); + + if (set->used == set->allocated) + { + set->allocated = 2 * set->allocated + 256; + set->maps = (struct line_map *) + xrealloc (set->maps, set->allocated * sizeof (struct line_map)); + } + + map = &set->maps[set->used]; + map->from_line = from_line; + map->to_file = to_file; + map->to_line = to_line; + + if (set->used == 0) + map->included_from = -1; + else if (reason == LC_ENTER) + map->included_from = set->used - 1; + else if (reason == LC_RENAME) + map->included_from = map[-1].included_from; + else if (reason == LC_LEAVE) + { + if (map[-1].included_from < 0) + abort (); + map->included_from = set->maps[map[-1].included_from].included_from; + } + + set->used++; + return map; +} + +/* Translate a logical line number into a (source file, line) pair. */ + +struct line_map * +lookup_line (set, line) + struct line_maps *set; + unsigned int line; +{ + unsigned int md, mn = 0, mx = set->used; + + if (mx == 0) + abort (); + + while (mx - mn > 1) + { + md = (mn + mx) / 2; + if (set->maps[md].from_line > line) + mx = md; + else + mn = md; + } + + return &set->maps[mn]; +} diff --git a/gcc/line-map.h b/gcc/line-map.h new file mode 100644 index 00000000000..fe5e3cc6c9d --- /dev/null +++ b/gcc/line-map.h @@ -0,0 +1,80 @@ +/* Map logical line numbers to (source file, line number) pairs. + Copyright (C) 2001 + Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + +#ifndef GCC_LINE_MAP_H +#define GCC_LINE_MAP_H + +/* The logical line FROM_LINE maps to physical source file TO_FILE at + line TO_LINE, and subsequently one-to-one until the next line_map + structure in the set. */ +struct line_map +{ + const char *to_file; + unsigned int to_line; + unsigned int from_line; + int included_from; +}; + +/* Contains a sequence of chronological line_map structures. */ +struct line_maps +{ + struct line_map *maps; + unsigned int allocated; + unsigned int used; +}; + +/* Reason for adding a line change with add_line_map (). */ +enum lc_reason {LC_ENTER = 0, LC_LEAVE, LC_RENAME}; + +/* Initialize a line map set. */ +extern void init_line_maps + PARAMS ((struct line_maps *)); + +/* Free a line map set. */ +extern void free_line_maps + PARAMS ((struct line_maps *)); + +/* Add a mapping of logical source line to physical source file and + line number. Ther text pointed to by TO_FILE must have a lifetime + at least as long as the final call to lookup_line (). + + FROM_LINE should be monotonic increasing across calls to this + function. */ +extern struct line_map *add_line_map + PARAMS ((struct line_maps *, enum lc_reason, + unsigned int from_line, const char *to_file, unsigned int to_line)); + +/* Given a logical line, returns the map from which the corresponding + (source file, line) pair can be deduced. */ +extern struct line_map *lookup_line + PARAMS ((struct line_maps *, unsigned int)); + +/* Converts a map and logical line to source line. */ +#define SOURCE_LINE(MAP, LINE) ((LINE) + (MAP)->to_line - (MAP)->from_line) + +/* Returns the last source line within a map. This is the (last) line + of the #include, or other directive, that caused a map change. */ +#define LAST_SOURCE_LINE(MAP) SOURCE_LINE (MAP, (MAP)[1].from_line - 1) + +#define MAIN_FILE_P(MAP) ((MAP)->included_from < 0) + +#endif /* !GCC_LINE_MAP_H */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2b9b8e10087..c03e7e3948e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-08-02 Neil Booth <neil@daikokuya.demon.co.uk> + + * gcc.dg/cpp/19951025-1.c: Update. + 2001-08-02 Jeffrey Oldham <oldham@codesourcery.com> * g77.dg/ff90-1.f (s): Fix reference of variable z, diff --git a/gcc/testsuite/gcc.dg/cpp/19951025-1.c b/gcc/testsuite/gcc.dg/cpp/19951025-1.c index 283b5f53f1a..ca21a227c13 100644 --- a/gcc/testsuite/gcc.dg/cpp/19951025-1.c +++ b/gcc/testsuite/gcc.dg/cpp/19951025-1.c @@ -1,4 +1,4 @@ /* { dg-do preprocess } */ -/* { dg-error "include expects" "" { target *-*-* } 4 } */ -/* { dg-error "newline at end" "" { target *-*-* } 4 } */ +/* { dg-error "include expects" "" { target *-*-* } 5 } */ +/* { dg-error "newline at end" "" { target *-*-* } 5 } */ #include /\ |