]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
line-map.c: New.
authorNeil Booth <neil@gcc.gnu.org>
Thu, 2 Aug 2001 23:03:31 +0000 (23:03 +0000)
committerNeil Booth <neil@gcc.gnu.org>
Thu, 2 Aug 2001 23:03:31 +0000 (23:03 +0000)
* 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

16 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/c-lex.c
gcc/cpperror.c
gcc/cppfiles.c
gcc/cpphash.h
gcc/cppinit.c
gcc/cpplex.c
gcc/cpplib.c
gcc/cpplib.h
gcc/cppmain.c
gcc/fix-header.c
gcc/line-map.c [new file with mode: 0644]
gcc/line-map.h [new file with mode: 0644]
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cpp/19951025-1.c

index d97e946a0e15db482d60a41ba7e0260a0cfc1a60..d7aa23c787e1196b90d147a118e4e2419785f423 100644 (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.
index 90de1a0867c575470b8889f8669f8005be976adf..c465c9c3b0824e2fb94367f4e1fe1468064f9cbe 100644 (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.
index cf958f56c30eed6bb25eab22e4ec2f436d5f4d79..ffd3b7441726df5e5b16b5d86adb9a1d7fc84c26 100644 (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 ();
index 063489dae63072b3458d544ea26a3fe0eac87bdc..f10198288f097da13ef4ce41f59dfeaf9d51fffa 100644 (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);
     }
 }
 
index 2592d4dc1fd4798ab3bf02d9414eb2dc16575aa0..b939b405c889d659ab0512661138f8f497604c92 100644 (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);
index 12b64a80afa8d102be8e5262e538f1bd8bc8f4d6..0c1695c1d09328ba9d81cf1ba8afcbf7bb452e1b 100644 (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
index 9c194109266446a697bd4fd8ab1d0be1bd18799f..fa01b347055bb4a7344df436bf411511f5dc9d9a 100644 (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
index af2b9e93006e0457c7ecba986b91c83f0ac3e87e..fa32bd51561a108ac87c2b41b65cdc5a3452641a 100644 (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;
        }
index 06bf6744ef693db241dba77bee8a6177c42184ff..b3d1c701794a6a7485bdbf3f20ea4752c64976f8 100644 (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;
 
index fb7fac276db6c68df1e5ddf0b0079f9598f509df..bb91adb33eb36583aa6086d87c6098a0686f15e4 100644 (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 *));
 
index 8f1982f53892544b82b4b714312ca4ebd0398c51..cc3b81d10bd89ace35e61713802c157d4e66c251 100644 (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;
index 8d801281d456fa2085d2da2dc9d7d3b2d2ebf34e..3124196e7b07b1b6c92652d21f894c97035ef292 100644 (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
diff --git a/gcc/line-map.c b/gcc/line-map.c
new file mode 100644 (file)
index 0000000..a67191d
--- /dev/null
@@ -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 (file)
index 0000000..fe5e3cc
--- /dev/null
@@ -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  */
index 2b9b8e1008754d6132af5b3676aa26b770ada73d..c03e7e3948e1942e24aa2406d6a3d796f2a945fc 100644 (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,
index 283b5f53f1abaaee40c164ebcdc31aee6f6ecf9b..ca21a227c13b16c7ca61f6031e94b1cc7673b01d 100644 (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 /\