+
+2004-02-11 Per Bothner <per@bothner.com>
+
+ Represent column numbers using line-map's source_location.
+ The "next available source_location" is now managed internally by
+ line-maps.c rather than by clients.
+ * line-map.h (struct line_map): New field column_bits.
+ <from_line>: Rename field to start_location.
+ (struct line_maps): New fields highest_location and max_column_hint.
+ (linemap_check_files_exited): New declaration.
+ (linemap_line_start): New declaration.
+ (linemap_add): Remove from_line parameter; use highest_location field.
+ (SOURCE_LINE, LAST_SOURCE_LINE): Modify to use column_bits.
+ (SOURCE_COLUMN, LAST_SOURCE_LINE_LOCATION): New macros.
+ (CURRENT_LINE_MAP): Remove macro.
+ (linemap_position_for_column): New inline function.
+ * line-map.c (linemap_init): Clear new fields.
+ (linemap_check_files_exited): New function, extracted from ...
+ (linemap_free): Use linemap_check_files_exited.
+ (linemap_add): Remove from_line parameter. Various updates.
+ (linemap_line_start): New function.
+ (linemap_lookeup): Update for new field names.
+ * cpphash.h (struct cpp_reader) <map>: Field removed. Because
+ linemap_position_for_column may unpredictably change the current map,
+ it is cleaner and simpler for us to not cache it in cpp_reader.
+ (struct cpp_buffer): New sysp field.
+ Changed warned_cplusplus_comments and from_stage3 to bitfields.
+ * cppinit.c (cpp_read_min_file): pfile->map no longer exists.
+ * cpplib.c (do_line, do_linemarker, _cpp_do_file_change): Get
+ current map using linemap_lookup.
+ (do_linemarker): Also set buffer's sysp field.
+ (destringize_and_run): No longer need to decrement current line.
+ * cppfiles.c (_cpp_stack_file): Set sysp from and in buffer.
+ (search_path_head, open_file_failed): Use buffer's sysp.
+ (cpp_make_system_header): Get current map using linemap_lookup.
+ Also set buffer's sysp flag.
+ * cppmacro.c (_cpp_builtin_macro_text): Likewise use linemap_lookup.
+ * cpphash.h (CPP_INCREMENT_LINE): New macro.
+ (struct cpp_buffer): Moved fields saved_cur, saved_rlimit to ...
+ (struct cpp_reader): ... and adding saved_line_base field.
+ * cpptrad.c (_cpp_overlay_buffer, _cpp_remove_overlay):
+ Update accordingly. Don't adjust line.
+ (_cpp_scan_out_logical_line): Use CPP_INCREMENT_LINE.
+ * cpphash.c (CPP_IN_SYSTEM_HEADER): Replaced macro by ...
+ (cpp_in_system_header): ... new inline function, using buffer's sysp.
+ * cpperror.c (_cpp_begin_message): Update to use cpp_in_system_header.
+ * cpplex.c (_cpp_lex_direct): Likewise.
+ * cppmacro.c (_cpp_builtin_macro_text): Likewise.
+ * cppmacro.c (_cpp_create_definition): Use buffer's sysp field.
+ * cpplib.h (struct cpp_token): Rename line field to src_loc.
+ Remove col field as it is now subsumed by src_loc.
+ * cpperror.c: Update various field, parameter, and macro names.
+ (print_location): If col==0, try SOURCE_COLUMN of line.
+ (cpp_error): Use cur_token's src_loc field, rather than line+col.
+ * cpplib.c (do_diagnostic): Token's src_loc fields replaces line+col.
+ * cpplex.c (_cpp_process_line_notes, _cpp_lex_direct,
+ _cpp_skip_block_comment): Use CPP_INCREMENT_LINE.
+ (_cpp_temp_token): Replace cpp_token's line+col fields by src_loc.
+ (_cpp_get_fresh_line): Don't need to adjust line for missing newline.
+ (_cpp_lex_direct): Use linemap_position_for_column.
+ * c-ppoutput.c (maybe_print_line, print_line): Don't take map
+ parameter. Instead get it from the line_table global. Adjust callers.
+ (print): Remove map field. Replace line field to src_line.
+ (init_pp_output, account_for_newlines, maybe_print_line): Adjust.
+ (cb_line_change): Use SOURCE_COLUMN. Minor optimizations.
+ (pp_file_change): Use MAIN_FILE_P since we cannot checked print.map.
+ Use LAST_SOURCE_LINE_LOCATION to "catch up" after #include.
+ * cpptrad.c (copy_comment): Rename variable.
+ * c-lex.c (map): Remove static variable, for same reason we removed
+ cpp_reader's map field.
+ (cb_line_change, cb_def_pragma, cb_define, cb_undef): Hence we need
+ to call linemap_lookup.
+ (cb_line_change): Token's line field replaced by src_loc.
+ (fe_file_change): Use MAINFILE_P and LAST_SOURCE_LINE macros.
+ Don't save new_map.
+
+ * cpphash.h, cpperror.c, cpplib.h: Some renames of fileline to
+ source_location.
+
2004-02-11 Hartmut Penner <hpenner@de.ibm.com>
* config/rs6000/altivec.md (*movv4si_internal): At least one
#include "splay-tree.h"
#include "debug.h"
-/* The current line map. */
-static const struct line_map *map;
-
/* We may keep statistics about how long which files took to compile. */
static int header_time, body_time;
static splay_tree file_info_tree;
cb_line_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const cpp_token *token,
int parsing_args)
{
- if (token->type == CPP_EOF || parsing_args)
- return;
-
- input_line = SOURCE_LINE (map, token->line);
+ if (token->type != CPP_EOF && !parsing_args)
+ {
+ source_location loc = token->src_loc;
+ const struct line_map *map = linemap_lookup (&line_table, loc);
+ input_line = SOURCE_LINE (map, loc);
+ }
}
void
fe_file_change (const struct line_map *new_map)
{
if (new_map == NULL)
- {
- map = NULL;
- return;
- }
+ return;
if (new_map->reason == LC_ENTER)
{
/* Don't stack the main buffer on the input stack;
we already did in compile_file. */
- if (map != NULL)
+ if (! MAIN_FILE_P (new_map))
{
- int included_at = SOURCE_LINE (new_map - 1, new_map->from_line - 1);
+ int included_at = LAST_SOURCE_LINE (new_map - 1);
input_line = included_at;
push_srcloc (new_map->to_file, 1);
in_system_header = new_map->sysp != 0;
input_filename = new_map->to_file;
input_line = new_map->to_line;
- map = new_map;
/* Hook for C++. */
extract_interface_info ();
}
static void
-cb_def_pragma (cpp_reader *pfile, unsigned int line)
+cb_def_pragma (cpp_reader *pfile, source_location loc)
{
/* Issue a warning message if we have been asked to do so. Ignore
unknown pragmas in system headers unless an explicit
-Wunknown-pragmas has been given. */
if (warn_unknown_pragmas > in_system_header)
{
+ const struct line_map *map = linemap_lookup (&line_table, loc);
const unsigned char *space, *name;
const cpp_token *s;
name = cpp_token_as_text (pfile, s);
}
- input_line = SOURCE_LINE (map, line);
+ input_line = SOURCE_LINE (map, loc);
warning ("ignoring #pragma %s %s", space, name);
}
}
/* #define callback for DWARF and DWARF2 debug info. */
static void
-cb_define (cpp_reader *pfile, unsigned int line, cpp_hashnode *node)
+cb_define (cpp_reader *pfile, source_location loc, cpp_hashnode *node)
{
- (*debug_hooks->define) (SOURCE_LINE (map, line),
+ const struct line_map *map = linemap_lookup (&line_table, loc);
+ (*debug_hooks->define) (SOURCE_LINE (map, loc),
(const char *) cpp_macro_definition (pfile, node));
}
/* #undef callback for DWARF and DWARF2 debug info. */
static void
-cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, unsigned int line,
+cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location loc,
cpp_hashnode *node)
{
- (*debug_hooks->undef) (SOURCE_LINE (map, line),
+ const struct line_map *map = linemap_lookup (&line_table, loc);
+ (*debug_hooks->undef) (SOURCE_LINE (map, loc),
(const char *) NODE_NAME (node));
}
\f
static struct
{
FILE *outf; /* Stream to write to. */
- const struct line_map *map; /* Logical to physical line mappings. */
const cpp_token *prev; /* Previous token. */
const cpp_token *source; /* Source token for spacing. */
- fileline line; /* Line currently being written. */
+ int src_line; /* Line number currently being written. */
unsigned char printed; /* Nonzero if something output at line. */
} print;
static void account_for_newlines (const unsigned char *, size_t);
static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
-static void print_line (const struct line_map *, fileline, const char *);
-static void maybe_print_line (const struct line_map *, fileline);
+static void print_line (source_location, const char *);
+static void maybe_print_line (source_location);
/* Callback routines for the parser. Most of these are active only
in specific modes. */
cb->undef = cb_undef;
}
- /* Initialize the print structure. Setting print.line to -1 here is
+ /* Initialize the print structure. Setting print.src_line to -1 here is
a trick to guarantee that the first token of the file will cause
a linemarker to be output by maybe_print_line. */
- print.line = (fileline) -1;
+ print.src_line = -1;
print.printed = 0;
print.prev = 0;
- print.map = 0;
print.outf = out_stream;
}
}
}
-/* Adjust print.line for newlines embedded in output. */
+/* Adjust print.src_line for newlines embedded in output. */
static void
account_for_newlines (const unsigned char *str, size_t len)
{
while (len--)
if (*str++ == '\n')
- print.line++;
+ print.src_line++;
}
/* Writes out a traditionally preprocessed file. */
while (_cpp_read_logical_line_trad (pfile))
{
size_t len = pfile->out.cur - pfile->out.base;
- maybe_print_line (print.map, pfile->out.first_line);
+ maybe_print_line (pfile->out.first_line);
fwrite (pfile->out.base, 1, len, print.outf);
print.printed = 1;
if (!CPP_OPTION (pfile, discard_comments))
different line to the current one, output the required newlines or
a line marker, and return 1. Otherwise return 0. */
static void
-maybe_print_line (const struct line_map *map, fileline line)
+maybe_print_line (source_location src_loc)
{
+ const struct line_map *map = linemap_lookup (&line_table, src_loc);
+ int src_line = SOURCE_LINE (map, src_loc);
/* End the previous line of text. */
if (print.printed)
{
putc ('\n', print.outf);
- print.line++;
+ print.src_line++;
print.printed = 0;
}
- if (line >= print.line && line < print.line + 8)
+ if (src_line >= print.src_line && src_line < print.src_line + 8)
{
- while (line > print.line)
+ while (src_line > print.src_line)
{
putc ('\n', print.outf);
- print.line++;
+ print.src_line++;
}
}
else
- print_line (map, line, "");
+ print_line (src_loc, "");
}
/* Output a line marker for logical line LINE. Special flags are "1"
or "2" indicating entering or leaving a file. */
static void
-print_line (const struct line_map *map, fileline line, const char *special_flags)
+print_line (source_location src_loc, const char *special_flags)
{
/* End any previous line of text. */
if (print.printed)
putc ('\n', print.outf);
print.printed = 0;
- print.line = line;
if (!flag_no_line_commands)
{
+ const struct line_map *map = linemap_lookup (&line_table, src_loc);
+
size_t to_file_len = strlen (map->to_file);
unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1);
unsigned char *p;
+ print.src_line = SOURCE_LINE (map, src_loc);
+
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
p = cpp_quote_string (to_file_quoted,
(unsigned char *)map->to_file, to_file_len);
*p = '\0';
- fprintf (print.outf, "# %u \"%s\"%s",
- SOURCE_LINE (map, print.line),
+ fprintf (print.outf, "# %u \"%s\"%s", print.src_line,
to_file_quoted, special_flags);
if (map->sysp == 2)
cb_line_change (cpp_reader *pfile, const cpp_token *token,
int parsing_args)
{
+ source_location src_loc = token->src_loc;
+
if (token->type == CPP_EOF || parsing_args)
return;
- maybe_print_line (print.map, token->line);
+ maybe_print_line (src_loc);
print.prev = 0;
print.source = 0;
ought to care. Some things do care; the fault lies with them. */
if (!CPP_OPTION (pfile, traditional))
{
+ const struct line_map *map = linemap_lookup (&line_table, src_loc);
+ int spaces = SOURCE_COLUMN (map, src_loc) - 2;
print.printed = 1;
- if (token->col > 2)
- {
- unsigned int spaces = token->col - 2;
- while (spaces--)
- putc (' ', print.outf);
- }
+ while (-- spaces >= 0)
+ putc (' ', print.outf);
}
}
cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line,
const cpp_string *str)
{
- maybe_print_line (print.map, line);
+ maybe_print_line (line);
fprintf (print.outf, "#ident \"%s\"\n", str->text);
- print.line++;
+ print.src_line++;
}
static void
cb_define (cpp_reader *pfile, fileline line, cpp_hashnode *node)
{
- maybe_print_line (print.map, line);
+ maybe_print_line (line);
fputs ("#define ", print.outf);
/* 'D' is whole definition; 'N' is name only. */
fputs ((const char *) NODE_NAME (node), print.outf);
putc ('\n', print.outf);
- print.line++;
+ print.src_line++;
}
static void
-cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line,
+cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
cpp_hashnode *node)
{
- maybe_print_line (print.map, line);
+ maybe_print_line (line);
fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
- print.line++;
+ print.src_line++;
}
static void
-cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line,
+cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
const unsigned char *dir, const char *header, int angle_brackets)
{
- maybe_print_line (print.map, line);
+ maybe_print_line (line);
if (angle_brackets)
fprintf (print.outf, "#%s <%s>\n", dir, header);
else
fprintf (print.outf, "#%s \"%s\"\n", dir, header);
- print.line++;
+ print.src_line++;
}
/* Callback called when -fworking-director and -E to emit working
}
/* The file name, line number or system header flags have changed, as
- described in MAP. From this point on, the old print.map might be
- pointing to freed memory, and so must not be dereferenced. */
+ described in MAP. */
void
pp_file_change (const struct line_map *map)
if (map != NULL)
{
/* First time? */
- if (print.map == NULL)
+ if (MAIN_FILE_P (map))
{
/* Avoid printing foo.i when the main file is foo.c. */
if (!cpp_get_options (parse_in)->preprocessed)
- print_line (map, map->from_line, flags);
+ print_line (map->start_location, flags);
}
else
{
/* Bring current file to correct line when entering a new file. */
if (map->reason == LC_ENTER)
- maybe_print_line (map - 1, map->from_line - 1);
-
+ {
+ const struct line_map *from = INCLUDED_FROM (&line_table, map);
+ maybe_print_line (LAST_SOURCE_LINE_LOCATION (from));
+ }
if (map->reason == LC_ENTER)
flags = " 1";
else if (map->reason == LC_LEAVE)
flags = " 2";
- print_line (map, map->from_line, flags);
+ print_line (map->start_location, flags);
}
}
-
- print.map = map;
}
/* Copy a #pragma directive to the preprocessed output. */
static void
cb_def_pragma (cpp_reader *pfile, fileline line)
{
- maybe_print_line (print.map, line);
+ maybe_print_line (line);
fputs ("#pragma ", print.outf);
cpp_output_line (pfile, print.outf);
- print.line++;
+ print.src_line++;
}
/* Dump out the hash table. */
fputs ((const char *) cpp_macro_definition (pfile, node),
print.outf);
putc ('\n', print.outf);
- print.line++;
+ print.src_line++;
}
return 1;
#include "cpphash.h"
#include "intl.h"
-static void print_location (cpp_reader *, fileline, unsigned int);
+static void print_location (cpp_reader *, source_location, unsigned int);
/* Print the logical file location (LINE, COL) in preparation for a
diagnostic. Outputs the #include chain if it has changed. A line
of zero suppresses the include stack, and outputs the program name
instead. */
static void
-print_location (cpp_reader *pfile, fileline line, unsigned int col)
+print_location (cpp_reader *pfile, source_location line, unsigned int col)
{
if (line == 0)
fprintf (stderr, "%s: ", progname);
lin = SOURCE_LINE (map, line);
if (col == 0)
- col = 1;
+ {
+ col = SOURCE_COLUMN (map, line);
+ if (col == 0)
+ col = 1;
+ }
if (lin == 0)
fprintf (stderr, "%s:", map->to_file);
}
/* Set up for a diagnostic: print the file and line, bump the error
- counter, etc. LINE is the logical line number; zero means to print
+ counter, etc. SRC_LOC is the logical line number; zero means to print
at the location of the previously lexed token, which tends to be
- the correct place by default. Returns 0 if the error has been
- suppressed. */
+ the correct place by default. The column number can be specified either
+ using COLUMN or (if COLUMN==0) extracting SOURCE_COLUMN from SRC_LOC.
+ (This may seem redundant, but is useful when pre-scanning (cleaning) a line,
+ when we haven't yet verified whether the current line_map has a
+ big enough max_column_hint.)
+
+ Returns 0 if the error has been suppressed. */
int
-_cpp_begin_message (cpp_reader *pfile, int code, fileline line,
- unsigned int column)
+_cpp_begin_message (cpp_reader *pfile, int code,
+ source_location src_loc, unsigned int column)
{
int level = CPP_DL_EXTRACT (code);
{
case CPP_DL_WARNING:
case CPP_DL_PEDWARN:
- if (CPP_IN_SYSTEM_HEADER (pfile)
+ if (cpp_in_system_header (pfile)
&& ! CPP_OPTION (pfile, warn_system_headers))
return 0;
/* Fall through. */
break;
}
- print_location (pfile, line, column);
+ print_location (pfile, src_loc, column);
if (CPP_DL_WARNING_P (level))
fputs (_("warning: "), stderr);
else if (level == CPP_DL_ICE)
void
cpp_error (cpp_reader * pfile, int level, const char *msgid, ...)
{
- fileline line;
- unsigned int column;
+ source_location src_loc;
va_list ap;
va_start (ap, msgid);
if (CPP_OPTION (pfile, traditional))
{
if (pfile->state.in_directive)
- line = pfile->directive_line;
+ src_loc = pfile->directive_line;
else
- line = pfile->line;
- column = 0;
+ src_loc = pfile->line;
}
else
{
- line = pfile->cur_token[-1].line;
- column = pfile->cur_token[-1].col;
+ src_loc = pfile->cur_token[-1].src_loc;
}
- if (_cpp_begin_message (pfile, level, line, column))
+ if (_cpp_begin_message (pfile, level, src_loc, 0))
v_message (msgid, ap);
va_end (ap);
/* Print an error at a specific location. */
void
cpp_error_with_line (cpp_reader *pfile, int level,
- fileline line, unsigned int column,
+ source_location src_loc, unsigned int column,
const char *msgid, ...)
{
va_list ap;
va_start (ap, msgid);
- if (_cpp_begin_message (pfile, level, line, column))
+ if (_cpp_begin_message (pfile, level, src_loc, column))
v_message (msgid, ap);
va_end (ap);
if (!should_stack_file (pfile, file, import))
return false;
- sysp = MAX ((pfile->map ? pfile->map->sysp : 0),
- (file->dir ? file->dir->sysp : 0));
+ if (pfile->buffer == NULL || file->dir == NULL)
+ sysp = 0;
+ else
+ sysp = MAX (pfile->buffer->sysp, file->dir->sysp);
/* Add the file to the dependencies on its first inclusion. */
if (CPP_OPTION (pfile, deps.style) > !!sysp && !file->stack_count)
buffer = cpp_push_buffer (pfile, file->buffer, file->st.st_size,
CPP_OPTION (pfile, preprocessed));
buffer->file = file;
+ buffer->sysp = sysp;
/* Initialize controlling macro state. */
pfile->mi_valid = true;
else if (pfile->quote_ignores_source_dir)
dir = pfile->quote_include;
else
- return make_cpp_dir (pfile, dir_name_of_file (file), pfile->map->sysp);
+ return make_cpp_dir (pfile, dir_name_of_file (file),
+ pfile->buffer ? pfile->buffer->sysp : 0);
if (dir == NULL)
cpp_error (pfile, CPP_DL_ERROR,
static void
open_file_failed (cpp_reader *pfile, _cpp_file *file)
{
- int sysp = pfile->map ? pfile->map->sysp: 0;
+ int sysp = pfile->line > 1 && pfile->buffer ? pfile->buffer->sysp : 0;
bool print_dep = CPP_OPTION (pfile, deps.style) > !!sysp;
errno = file->err_no;
cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc)
{
int flags = 0;
+ const struct line_map *map = linemap_lookup (pfile->line_table, pfile->line);
/* 1 = system header, 2 = system header to be treated as C. */
if (syshdr)
flags = 1 + (externc != 0);
- _cpp_do_file_change (pfile, LC_RENAME, pfile->map->to_file,
- SOURCE_LINE (pfile->map, pfile->line), flags);
+ pfile->buffer->sysp = flags;
+ _cpp_do_file_change (pfile, LC_RENAME, map->to_file,
+ SOURCE_LINE (map, pfile->line), flags);
}
/* Allow the client to change the current file. Used by the front end
#define CPP_BUF_COLUMN(BUF, CUR) ((CUR) - (BUF)->line_base)
#define CPP_BUF_COL(BUF) CPP_BUF_COLUMN(BUF, (BUF)->cur)
+#define CPP_INCREMENT_LINE(PFILE, COLS_HINT) do { \
+ const struct line_map *map \
+ = linemap_lookup (PFILE->line_table, PFILE->line); \
+ unsigned int line = SOURCE_LINE (map, PFILE->line) + 1; \
+ PFILE->line = linemap_line_start (PFILE->line_table, line, COLS_HINT); \
+ } while (0)
+
/* Maximum nesting of cpp_buffers. We use a static limit, partly for
efficiency, and partly to limit runaway recursion. */
#define CPP_STACK_MAX 200
The warning happens only for C89 extended mode with -pedantic on,
or for -Wtraditional, and only once per file (otherwise it would
be far too noisy). */
- unsigned char warned_cplusplus_comments;
+ unsigned int warned_cplusplus_comments : 1;
/* True if we don't process trigraphs and escaped newlines. True
for preprocessed input, command line directives, and _Pragma
buffers. */
- unsigned char from_stage3;
+ unsigned int from_stage3 : 1;
/* Nonzero means that the directory to start searching for ""
include files has been calculated and stored in "dir" below. */
unsigned char search_cached;
+ /* One for a system header, two for a C system header file that therefore
+ needs to be extern "C" protected in C++, and zero otherwise. */
+ unsigned char sysp;
+
/* The directory of the this buffer's file. Its NAME member is not
allocated, so we don't need to worry about freeing it. */
struct cpp_dir dir;
- /* Used for buffer overlays by cpptrad.c. */
- const uchar *saved_cur, *saved_rlimit;
-
/* Descriptor for converting from the input character set to the
source character set. */
struct cset_converter input_cset_desc;
/* Source line tracking. */
struct line_maps *line_table;
- const struct line_map *map;
fileline line;
/* The line of the '#' of the current directive. */
fileline first_line;
} out;
+ /* Used for buffer overlays by cpptrad.c. */
+ const uchar *saved_cur, *saved_rlimit, *saved_line_base;
+
/* Used to save the original line number during traditional
preprocessing. */
unsigned int saved_line;
/* Macros. */
-#define CPP_IN_SYSTEM_HEADER(PFILE) ((PFILE)->map && (PFILE)->map->sysp)
+static inline int cpp_in_system_header (cpp_reader *);
+static inline int
+cpp_in_system_header (cpp_reader *pfile)
+{
+ return pfile->buffer ? pfile->buffer->sysp : 0;
+}
#define CPP_PEDANTIC(PF) CPP_OPTION (PF, pedantic)
#define CPP_WTRADITIONAL(PF) CPP_OPTION (PF, warn_traditional)
/* In cpperror.c */
-extern int _cpp_begin_message (cpp_reader *, int, fileline, unsigned int);
+extern int _cpp_begin_message (cpp_reader *, int,
+ source_location, unsigned int);
/* In cppmacro.c */
extern void _cpp_free_definition (cpp_hashnode *);
if (CPP_OPTION (pfile, preprocessed))
{
read_original_filename (pfile);
- fname = pfile->map->to_file;
+ fname = pfile->line_table->maps[pfile->line_table->used-1].to_file;
}
return fname;
}
}
buffer->line_base = note->pos;
- pfile->line++;
+ CPP_INCREMENT_LINE (pfile, 0);
}
else if (_cpp_trigraph_map[note->type])
{
}
else if (c == '\n')
{
+ unsigned int cols;
buffer->cur = cur - 1;
_cpp_process_line_notes (pfile, true);
if (buffer->next_line >= buffer->rlimit)
return true;
_cpp_clean_line (pfile);
- pfile->line++;
+
+ cols = buffer->next_line - buffer->line_base;
+ CPP_INCREMENT_LINE (pfile, cols);
+
cur = buffer->cur;
}
}
}
result = pfile->cur_token++;
- result->line = old->line;
- result->col = old->col;
+ result->src_loc = old->src_loc;
return result;
}
{
/* Only warn once. */
buffer->next_line = buffer->rlimit;
- cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line - 1,
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line,
CPP_BUF_COLUMN (buffer, buffer->cur),
"no newline at end of file");
}
if (!pfile->state.in_directive)
{
/* Tell the compiler the line number of the EOF token. */
- result->line = pfile->line;
+ result->src_loc = pfile->line;
result->flags = BOL;
}
return result;
}
buffer = pfile->buffer;
update_tokens_line:
- result->line = pfile->line;
+ result->src_loc = pfile->line;
skipped_white:
if (buffer->cur >= buffer->notes[buffer->cur_note].pos
&& !pfile->overlaid_buffer)
{
_cpp_process_line_notes (pfile, false);
- result->line = pfile->line;
+ result->src_loc = pfile->line;
}
c = *buffer->cur++;
- result->col = CPP_BUF_COLUMN (buffer, buffer->cur);
+
+ result->src_loc = linemap_position_for_column (pfile->line_table,
+ CPP_BUF_COLUMN (buffer, buffer->cur));
switch (c)
{
goto skipped_white;
case '\n':
- pfile->line++;
+ if (buffer->cur < buffer->rlimit)
+ CPP_INCREMENT_LINE (pfile, 0);
buffer->need_line = true;
goto fresh_line;
cpp_error (pfile, CPP_DL_ERROR, "unterminated comment");
}
else if (c == '/' && (CPP_OPTION (pfile, cplusplus_comments)
- || CPP_IN_SYSTEM_HEADER (pfile)))
+ || cpp_in_system_header (pfile)))
{
/* Warn about comments only if pedantically GNUC89, and not
in system headers. */
static void
do_line (cpp_reader *pfile)
{
+ const struct line_map *map = linemap_lookup (pfile->line_table, pfile->line);
const cpp_token *token;
- const char *new_file = pfile->map->to_file;
+ const char *new_file = map->to_file;
unsigned long new_lineno;
/* C99 raised the minimum limit on #line numbers. */
skip_rest_of_line (pfile);
_cpp_do_file_change (pfile, LC_RENAME, new_file, new_lineno,
- pfile->map->sysp);
+ map->sysp);
}
/* Interpret the # 44 "file" [flags] notation, which has slightly
static void
do_linemarker (cpp_reader *pfile)
{
+ const struct line_map *map = linemap_lookup (pfile->line_table, pfile->line);
const cpp_token *token;
- const char *new_file = pfile->map->to_file;
+ const char *new_file = map->to_file;
unsigned long new_lineno;
- unsigned int new_sysp = pfile->map->sysp;
+ unsigned int new_sysp = map->sysp;
enum lc_reason reason = LC_RENAME;
int flag;
flag = read_flag (pfile, flag);
if (flag == 4)
new_sysp = 2;
+ pfile->buffer->sysp = new_sysp;
}
check_eol (pfile);
const char *to_file, unsigned int file_line,
unsigned int sysp)
{
- pfile->map = linemap_add (pfile->line_table, reason, sysp,
- pfile->line, to_file, file_line);
+ const struct line_map *map = linemap_add (pfile->line_table, reason, sysp,
+ to_file, file_line);
+ if (map == NULL)
+ pfile->line = 0;
+ else
+ pfile->line = linemap_line_start (pfile->line_table, map->to_line, 127);
if (pfile->cb.file_change)
- pfile->cb.file_change (pfile, pfile->map);
+ pfile->cb.file_change (pfile, map);
}
/* Report a warning or error detected by the program we are
static void
do_diagnostic (cpp_reader *pfile, int code, int print_dir)
{
- if (_cpp_begin_message (pfile, code,
- pfile->cur_token[-1].line,
- pfile->cur_token[-1].col))
+ if (_cpp_begin_message (pfile, code, pfile->cur_token[-1].src_loc, 0))
{
if (print_dir)
fprintf (stderr, "#%s ", pfile->directive->name);
pfile->context = saved_context;
pfile->cur_token = saved_cur_token;
pfile->cur_run = saved_cur_run;
- pfile->line--;
}
/* See above comment. For the moment, we'd like
return &pfile->cb;
}
-/* The line map set. */
-const struct line_maps *
-cpp_get_line_maps (cpp_reader *pfile)
-{
- return pfile->line_table;
-}
-
/* Copy the given callbacks structure to our own. */
void
cpp_set_callbacks (cpp_reader *pfile, cpp_callbacks *cb)
occupy 16 bytes on 32-bit hosts and 24 bytes on 64-bit hosts. */
struct cpp_token
{
- fileline line; /* Logical line of first char of token. */
- unsigned short col; /* Column of first char of token. */
+ source_location src_loc; /* Location of first char of token. */
ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* token type */
unsigned char flags; /* flags - see above */
through the pointer returned from cpp_get_callbacks, or set them
with cpp_set_callbacks. */
extern cpp_options *cpp_get_options (cpp_reader *);
-extern const struct line_maps *cpp_get_line_maps (cpp_reader *);
extern cpp_callbacks *cpp_get_callbacks (cpp_reader *);
extern void cpp_set_callbacks (cpp_reader *, cpp_callbacks *);
/* Same as cpp_error, except additionally specifies a position as a
(translation unit) physical line and physical column. If the line is
zero, then no location is printed. */
-extern void cpp_error_with_line (cpp_reader *, int, fileline, unsigned,
+extern void cpp_error_with_line (cpp_reader *, int, source_location, unsigned,
const char *msgid, ...) ATTRIBUTE_PRINTF_5;
/* In cpplex.c */
const uchar *
_cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
{
+ const struct line_map *map;
const uchar *result = NULL;
unsigned int number = 1;
unsigned int len;
const char *name;
uchar *buf;
- const struct line_map *map = pfile->map;
+ map = linemap_lookup (pfile->line_table, pfile->line);
if (node->value.builtin == BT_BASE_FILE)
while (! MAIN_FILE_P (map))
break;
case BT_SPECLINE:
+ map = linemap_lookup (pfile->line_table, pfile->line);
/* If __LINE__ is embedded in a macro, it must expand to the
line of the macro's invocation, not its definition.
Otherwise things like assert() will not work properly. */
if (CPP_OPTION (pfile, traditional))
number = pfile->line;
else
- number = pfile->cur_token[-1].line;
- number = SOURCE_LINE (pfile->map, number);
+ number = pfile->cur_token[-1].src_loc;
+ number = SOURCE_LINE (map, number);
break;
/* __STDC__ has the value 1 under normal circumstances.
value 0. */
case BT_STDC:
{
- if (CPP_IN_SYSTEM_HEADER (pfile)
+ if (cpp_in_system_header (pfile)
&& CPP_OPTION (pfile, stdc_0_in_system_headers)
&& !CPP_OPTION (pfile,std))
number = 0;
macro->count = 0;
macro->fun_like = 0;
/* To suppress some diagnostics. */
- macro->syshdr = pfile->map->sysp != 0;
+ macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0;
if (CPP_OPTION (pfile, traditional))
ok = _cpp_create_trad_definition (pfile, macro);
copy_comment (cpp_reader *pfile, const uchar *cur, int in_define)
{
bool unterminated, copy = false;
- unsigned int from_line = pfile->line;
+ source_location src_loc = pfile->line;
cpp_buffer *buffer = pfile->buffer;
buffer->cur = cur;
unterminated = _cpp_skip_block_comment (pfile);
if (unterminated)
- cpp_error_with_line (pfile, CPP_DL_ERROR, from_line, 0,
+ cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
"unterminated comment");
/* Comments in directives become spaces so that tokens are properly
cpp_buffer *buffer = pfile->buffer;
pfile->overlaid_buffer = buffer;
- buffer->saved_cur = buffer->cur;
- buffer->saved_rlimit = buffer->rlimit;
- /* Prevent the ISO lexer from scanning a fresh line. */
- pfile->saved_line = pfile->line--;
+ pfile->saved_cur = buffer->cur;
+ pfile->saved_rlimit = buffer->rlimit;
+ pfile->saved_line_base = buffer->next_line;
+ pfile->saved_line = pfile->line;
buffer->need_line = false;
buffer->cur = start;
+ buffer->line_base = start;
buffer->rlimit = start + len;
}
{
cpp_buffer *buffer = pfile->overlaid_buffer;
- buffer->cur = buffer->saved_cur;
- buffer->rlimit = buffer->saved_rlimit;
+ buffer->cur = pfile->saved_cur;
+ buffer->rlimit = pfile->saved_rlimit;
+ buffer->line_base = pfile->saved_line_base;
buffer->need_line = true;
pfile->overlaid_buffer = NULL;
- pfile->line = pfile->saved_line;
}
/* Reads a logical line into the output buffer. Returns TRUE if there
pfile->out.cur = out - 1;
pfile->buffer->cur = cur;
pfile->buffer->need_line = true;
- pfile->line++;
+ CPP_INCREMENT_LINE (pfile, 0);
if ((lex_state == ls_fun_open || lex_state == ls_fun_close)
&& !pfile->state.in_directive
/* Null directive. Ignore it and don't invalidate
the MI optimization. */
pfile->buffer->need_line = true;
- pfile->line++;
+ CPP_INCREMENT_LINE (pfile, 0);
result = false;
goto done;
}
set->trace_includes = false;
set->depth = 0;
set->cache = 0;
+ set->highest_location = 0;
+ set->max_column_hint = 0;
}
+/* Check for and warn about line_maps entered but not exited. */
+
+void
+linemap_check_files_exited (struct line_maps *set)
+{
+ struct line_map *map;
+ /* Depending upon whether we are handling preprocessed input or
+ not, this can be a user error or an ICE. */
+ for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
+ map = INCLUDED_FROM (set, map))
+ fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
+ map->to_file);
+}
+
/* Free a line map set. */
void
{
if (set->maps)
{
- struct line_map *map;
-
- /* Depending upon whether we are handling preprocessed input or
- not, this can be a user error or an ICE. */
- for (map = CURRENT_LINE_MAP (set); ! MAIN_FILE_P (map);
- map = INCLUDED_FROM (set, map))
- fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
- map->to_file);
+ linemap_check_files_exited (set);
free (set->maps);
}
FROM_LINE should be monotonic increasing across calls to this
function. A call to this function can relocate the previous set of
+ A call to this function can relocate the previous set of
maps, so any stored line_map pointers should not be used. */
const struct line_map *
linemap_add (struct line_maps *set, enum lc_reason reason,
- unsigned int sysp, source_location from_line,
- const char *to_file, unsigned int to_line)
+ unsigned int sysp, const char *to_file, unsigned int to_line)
{
struct line_map *map;
+ source_location start_location = set->highest_location + 1;
- if (set->used && from_line < set->maps[set->used - 1].from_line)
+ if (set->used && start_location < set->maps[set->used - 1].start_location)
abort ();
if (set->used == set->allocated)
if (error || to_file == NULL)
{
to_file = from->to_file;
- to_line = LAST_SOURCE_LINE (from) + 1;
+ to_line = SOURCE_LINE (from, from[1].start_location);
sysp = from->sysp;
}
}
map->reason = reason;
map->sysp = sysp;
- map->from_line = from_line;
+ map->start_location = start_location;
map->to_file = to_file;
map->to_line = to_line;
set->cache = set->used++;
+ map->column_bits = 0;
+ set->highest_location = start_location;
+ set->max_column_hint = 0;
if (reason == LC_ENTER)
{
return map;
}
+source_location
+linemap_line_start (struct line_maps *set, unsigned int to_line,
+ unsigned int max_column_hint)
+{
+ struct line_map *map = &set->maps[set->used - 1];
+ source_location highest = set->highest_location;
+ source_location r;
+ unsigned int last_line = SOURCE_LINE (map, highest);
+ int line_delta = to_line - last_line;
+ bool add_map = false;
+ if (line_delta < 0
+ || (line_delta > 10 && line_delta * map->column_bits > 1000)
+ || (max_column_hint >= (1U << map->column_bits))
+ || (max_column_hint <= 80 && map->column_bits >= 10))
+ {
+ add_map = true;
+ }
+ else
+ max_column_hint = set->max_column_hint;
+ if (add_map)
+ {
+ int column_bits;
+ if (max_column_hint > 1000000 || highest > 0xC0000000)
+ {
+ max_column_hint = 0;
+ if (highest >0xF0000000)
+ return 0;
+ column_bits = 0;
+ }
+ else
+ {
+ column_bits = 7;
+ while (max_column_hint >= (1U << column_bits))
+ column_bits++;
+ max_column_hint = 1U << column_bits;
+ }
+ if (line_delta < 0
+ || last_line != map->to_line
+ || SOURCE_COLUMN (map, highest) >= (1U << column_bits))
+ map = (struct line_map*) linemap_add (set, LC_RENAME, map->sysp,
+ map->to_file, to_line);
+ map->column_bits = column_bits;
+ r = map->start_location;
+ }
+ else
+ r = highest - SOURCE_COLUMN (map, highest)
+ + (line_delta << map->column_bits);
+ if (r > set->highest_location)
+ set->highest_location = r;
+ set->max_column_hint = max_column_hint;
+ return r;
+}
+
/* Given a logical line, returns the map from which the corresponding
(source file, line) pair can be deduced. Since the set is built
chronologically, the logical lines are monotonic increasing, and so
cached = &set->maps[mn];
/* We should get a segfault if no line_maps have been added yet. */
- if (line >= cached->from_line)
+ if (line >= cached->start_location)
{
- if (mn + 1 == mx || line < cached[1].from_line)
+ if (mn + 1 == mx || line < cached[1].start_location)
return cached;
}
else
while (mx - mn > 1)
{
md = (mn + mx) / 2;
- if (set->maps[md].from_line > line)
+ if (set->maps[md].start_location > line)
mx = md;
else
mn = md;
(e.g. a #line directive in C). */
enum lc_reason {LC_ENTER = 0, LC_LEAVE, LC_RENAME};
-/* A logical line number, i,e, an "index" into a line_map. */
+/* A logical line/column number, i.e. an "index" into a line_map. */
/* Long-term, we want to use this to replace struct location_s (in input.h),
and effectively typedef source_location location_t. */
typedef unsigned int source_location;
typedef source_location fileline; /* deprecated name */
-/* 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. INCLUDED_FROM is an index into the set that
- gives the line mapping at whose end the current one was included.
- File(s) at the bottom of the include stack have this set to -1.
- REASON is the reason for creation of this line map, SYSP is one for
- a system header, two for a C system header file that therefore
- needs to be extern "C" protected in C++, and zero otherwise. */
+/* Physical source file TO_FILE at line TO_LINE at column 0 is represented
+ by the logical START_LOCATION. TO_LINE+L at column C is represented by
+ START_LOCATION+(L*(1<<column_bits))+C, as long as C<(1<<column_bits),
+ and the result_location is less than the next line_map's start_location.
+ (The top line is line 1 and the leftmost column is column 1; line/column 0
+ means "entire file/line" or "unknown line/column" or "not applicable".)
+ INCLUDED_FROM is an index into the set that gives the line mapping
+ at whose end the current one was included. File(s) at the bottom
+ of the include stack have this set to -1. REASON is the reason for
+ creation of this line map, SYSP is one for a system header, two for
+ a C system header file that therefore needs to be extern "C"
+ protected in C++, and zero otherwise. */
struct line_map
{
const char *to_file;
unsigned int to_line;
- source_location from_line;
+ source_location start_location;
int included_from;
ENUM_BITFIELD (lc_reason) reason : CHAR_BIT;
+ /* The sysp field isn't really needed now that it's in cpp_buffer. */
unsigned char sysp;
+ /* Number of the low-order source_location bits used for a column number. */
+ unsigned int column_bits : 8;
};
/* A set of chronological line_map structures. */
/* If true, prints an include trace a la -H. */
bool trace_includes;
+
+ /* Highest source_location "given out". */
+ source_location highest_location;
+
+ /* The maximum column number we can quickly allocate. Higher numbers
+ may require allocating a new line_map. */
+ unsigned int max_column_hint;
};
/* Initialize a line map set. */
/* Free a line map set. */
extern void linemap_free (struct line_maps *);
+/* Check for and warn about line_maps entered but not exited. */
+
+extern void linemap_check_files_exited (struct line_maps *);
+
+/* Return a source_location for the start (i.e. column==0) of
+ (physical) line TO_LINE in the current source file (as in the
+ most recent linemap_add). MAX_COLUMN_HINT is the highest column
+ number we expect to use in this line (but it does not change
+ the highest_location). */
+
+extern source_location linemap_line_start
+(struct line_maps *, unsigned int, unsigned int);
+
/* Add a mapping of logical source line to physical source file and
line number.
TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
natural values considering the file we are returning to.
- FROM_LINE should be monotonic increasing across calls to this
+ START_LOCATION should be monotonic increasing across calls to this
function. A call to this function can relocate the previous set of
maps, so any stored line_map pointers should not be used. */
extern const struct line_map *linemap_add
(struct line_maps *, enum lc_reason, unsigned int sysp,
- source_location from_line, const char *to_file, unsigned int to_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 void linemap_print_containing_files (struct line_maps *,
const struct line_map *);
-/* Converts a map and logical line to source line. */
-#define SOURCE_LINE(MAP, LINE) ((LINE) + (MAP)->to_line - (MAP)->from_line)
+/* Converts a map and a source_location to source line. */
+#define SOURCE_LINE(MAP, LINE) \
+ ((((LINE) - (MAP)->start_location) >> (MAP)->column_bits) + (MAP)->to_line)
+
+#define SOURCE_COLUMN(MAP, LINE) \
+ (((LINE) - (MAP)->start_location) & ((1 << (MAP)->column_bits) - 1))
/* 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 LAST_SOURCE_LINE(MAP) \
+ SOURCE_LINE (MAP, LAST_SOURCE_LINE_LOCATION (MAP))
+#define LAST_SOURCE_LINE_LOCATION(MAP) \
+ ((((MAP)[1].start_location - 2 - (MAP)->start_location) \
+ & ~((1 << (MAP)->column_bits) - 1)) \
+ + (MAP)->start_location)
/* Returns the map a given map was included from. */
#define INCLUDED_FROM(SET, MAP) (&(SET)->maps[(MAP)->included_from])
/* Nonzero if the map is at the bottom of the include stack. */
#define MAIN_FILE_P(MAP) ((MAP)->included_from < 0)
-/* The current line map. Saves a call to lookup_line if the caller is
- sure he is in the scope of the current map. */
-#define CURRENT_LINE_MAP(MAPS) ((MAPS)->maps + (MAPS)->used - 1)
+/* Get a source position that for the same line as the most recent
+ linemap_line_start, but with the specified TO_COLUMN column number. */
+static inline source_location
+linemap_position_for_column (struct line_maps *set, unsigned int to_column)
+{
+ struct line_map *map = &set->maps[set->used - 1];
+ source_location r = set->highest_location;
+ if (__builtin_expect (to_column > set->max_column_hint, 0))
+ {
+ if (r >= 0xC000000 || to_column > 1000000) /* FIXME */
+ {
+ /* Running low on source_locations - disable column numbers. */
+ return r - SOURCE_COLUMN (map, r);
+ }
+ else
+ {
+ r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
+ map = &set->maps[set->used - 1];
+ r = set->highest_location;
+ }
+ }
+ r = r - SOURCE_COLUMN (map, r) + to_column;
+ if (r >= set->highest_location)
+ set->highest_location = r;
+ return r;
+}
+
#endif /* !GCC_LINE_MAP_H */