line-map.c: New.

* 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.
testsuite:
	* gcc.dg/cpp/19951025-1.c: Update.

From-SVN: r44584
This commit is contained in:
Neil Booth 2001-08-02 23:03:31 +00:00
parent 6ff02a9579
commit d82fc1085f
16 changed files with 387 additions and 117 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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 ();

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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 *));

View File

@ -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;

View File

@ -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

118
gcc/line-map.c Normal file
View File

@ -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];
}

80
gcc/line-map.h Normal file
View File

@ -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 */

View File

@ -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,

View File

@ -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 /\