This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [cpplib] implement pragma dependancy


Zack Weinberg wrote:
> I like the general idea.  Unfortunately I just rewrote
> find_include_file() and friends to fix Jakub's bug with "" vs <>
> includes - so if you can update your patch, after I commit the
> changes, and resubmit, that would be nice.
Ok, attached is a modified patch + documentation

I modified the error messages to be either boilerplate, or the trailing
text, not a mixture. Thus we get,

foo.c:3:62: warning: rerun fixincludes
foo.c:4:44: warning: out of date with dependency on "/usr/include/time.h"

from
	#pragma GCC dependency "/usr/include/time.h" rerun fixincludes
	#pragma GCC dependency "/usr/include/time.h"

built & tested on i686-pc-linux-gnu

ok?

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2000-06-23  Nathan Sidwell  <nathan@codesourcery.com>

	* cpp.texi: Document #pragma GCC dependency
	* cppfiles.c (open_include_file): Set date to unknown.
	(_cpp_compare_file_date): New function.
	(read_include_file): Set file date.
	* cpphash.h (struct include_file): Add date member.
	(_cpp_compare_file_date): Prototype.
	* cpplib.c (parse_include): Add trail parameter. Adjust.
	(do_include): Adjust parse_include call.
	(do_import): Likewise.
	(do_include_next): Likewise.
	(gcc_pragmas): Add dependency pragma.
	(do_pragma_dependancy): New pragma.

Index: cpp.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cpp.texi,v
retrieving revision 1.22
diff -c -3 -p -r1.22 cpp.texi
*** cpp.texi	2000/06/23 10:56:09	1.22
--- cpp.texi	2000/06/23 11:19:17
*************** the text is ignored and this directive h
*** 2659,2664 ****
--- 2659,2678 ----
  @samp{#ident} is only used in header files supplied with those systems
  where it is meaningful.
  
+ @findex #pragma GCC dependency
+ The @samp{#pragma GCC dependency} allows you to check the relative dates
+ of the current include file and another file. If the other file is more
+ recent than the current file, a warning is issued. This is useful if the
+ include file is derived from the other file, and should be regenerated.
+ The other file is searched for using the normal include search path.
+ Optional trailing text can be used to give more information in the
+ warning message.
+ 
+ @smallexample
+ #pragma GCC dependency "foo.h.def"
+ #pragma GCC dependency "/usr/include/time.h" rerun fixincludes
+ @end smallexample
+ 
  @node Output, Invocation, Other Directives, Top
  @section C Preprocessor Output
  
Index: cppfiles.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cppfiles.c,v
retrieving revision 1.67
diff -c -3 -p -r1.67 cppfiles.c
*** cppfiles.c	2000/06/21 23:08:17	1.67
--- cppfiles.c	2000/06/23 11:19:19
*************** open_include_file (pfile, filename)
*** 195,200 ****
--- 195,201 ----
      }
  
    file->fd = fd;
+   file->date = (time_t) -1;
    return file;
  }
  
*************** _cpp_execute_include (pfile, f, len, no_
*** 433,438 ****
--- 434,493 ----
      cpp_error_from_errno (pfile, fname);
  }
  
+ /* Locate file F, and determine whether it is newer than PFILE. Return -1,
+    if F cannot be located or dated, 1, if it is newer and 0 if older.  */
+ 
+ int
+ _cpp_compare_file_date (pfile, f, len, search_start)
+      cpp_reader *pfile;
+      U_CHAR *f;
+      unsigned int len;
+      struct file_name_list *search_start;
+ {
+   char *fname = (char *)f;
+   int angle_brackets = fname[0] == '<';
+   struct include_file *inc;
+   struct include_file *current_include = cpp_file_buffer (pfile)->inc;
+ 
+   if (!search_start)
+     {
+       if (angle_brackets)
+ 	search_start = CPP_OPTION (pfile, bracket_include);
+       else if (CPP_OPTION (pfile, ignore_srcdir))
+ 	search_start = CPP_OPTION (pfile, quote_include);
+       else
+ 	search_start = CPP_BUFFER (pfile)->actual_dir;
+     }
+ 
+   /* Remove quote marks.  */
+   fname++;
+   len -= 2;
+   fname[len] = '\0';
+   
+   inc = find_include_file (pfile, fname, search_start);
+   
+   if (!inc)
+     return -1;
+   if (inc->fd >= 0)
+     {
+       struct stat source;
+       
+       if (fstat (inc->fd, &source) < 0)
+         {
+           close (inc->fd);
+           inc->fd = -1;
+           return -1;
+         }
+       inc->date = source.st_mtime;
+       close (inc->fd);
+       inc->fd = -1;
+     }
+   if (inc->date == (time_t)-1 || current_include->date == (time_t)-1)
+     return -1;
+   return inc->date > current_include->date;
+ }
+ 
+ 
  /* Push an input buffer and load it up with the contents of FNAME.
     If FNAME is "" or NULL, read standard input.  */
  int
*************** read_include_file (pfile, inc)
*** 470,475 ****
--- 525,532 ----
  
    if (fstat (fd, &st) < 0)
      goto perror_fail;
+   
+   inc->date = st.st_mtime;
  
    /* If fd points to a plain file, we might be able to mmap it; we can
       definitely allocate the buffer all at once.  If fd is a pipe or
Index: cpphash.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cpphash.h,v
retrieving revision 1.54
diff -c -3 -p -r1.54 cpphash.h
*** cpphash.h	2000/06/21 18:33:51	1.54
--- cpphash.h	2000/06/23 11:19:19
*************** struct include_file
*** 62,67 ****
--- 62,68 ----
  				/* location in search path where file was
  				   found, for #include_next */
    int fd;			/* file descriptor possibly open on file */
+   time_t  date;                 /* modification date of file, if known */
    unsigned char before;		/* file has been included before */
    unsigned char sysp;		/* file is a system header */
  };
*************** extern void _cpp_simplify_pathname	PARAM
*** 193,198 ****
--- 194,202 ----
  extern void _cpp_execute_include	PARAMS ((cpp_reader *, U_CHAR *,
  						 unsigned int, int,
  						 struct file_name_list *));
+ extern int _cpp_compare_file_date       PARAMS ((cpp_reader *, U_CHAR *,
+                                                  unsigned int,
+                                                  struct file_name_list *));
  extern void _cpp_init_include_table	PARAMS ((cpp_reader *));
  extern const char *_cpp_fake_include	PARAMS ((cpp_reader *, const char *));
  
Index: cpplib.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cpplib.c,v
retrieving revision 1.178
diff -c -3 -p -r1.178 cpplib.c
*** cpplib.c	2000/06/23 10:56:09	1.178
--- cpplib.c	2000/06/23 11:19:26
*************** struct if_stack
*** 52,58 ****
  /* Forward declarations.  */
  
  static void validate_else		PARAMS ((cpp_reader *, const U_CHAR *));
! static unsigned int parse_include	PARAMS ((cpp_reader *, const U_CHAR *));
  static void push_conditional		PARAMS ((cpp_reader *, int, int,
  						 const cpp_hashnode *));
  static void pass_thru_directive		PARAMS ((const U_CHAR *, size_t,
--- 52,58 ----
  /* Forward declarations.  */
  
  static void validate_else		PARAMS ((cpp_reader *, const U_CHAR *));
! static unsigned int parse_include	PARAMS ((cpp_reader *, const U_CHAR *, int));
  static void push_conditional		PARAMS ((cpp_reader *, int, int,
  						 const cpp_hashnode *));
  static void pass_thru_directive		PARAMS ((const U_CHAR *, size_t,
*************** do_define (pfile)
*** 398,406 ****
  /* Handle #include and #import.  */
  
  static unsigned int
! parse_include (pfile, name)
       cpp_reader *pfile;
       const U_CHAR *name;
  {
    long old_written = CPP_WRITTEN (pfile);
    enum cpp_ttype token;
--- 398,407 ----
  /* Handle #include and #import.  */
  
  static unsigned int
! parse_include (pfile, name, trail)
       cpp_reader *pfile;
       const U_CHAR *name;
+      int trail;
  {
    long old_written = CPP_WRITTEN (pfile);
    enum cpp_ttype token;
*************** parse_include (pfile, name)
*** 420,426 ****
        return 0;
      }
  
!   if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
      {
        cpp_error (pfile, "junk at end of #%s", name);
        _cpp_skip_rest_of_line (pfile);
--- 421,427 ----
        return 0;
      }
  
!   if (!trail && _cpp_get_directive_token (pfile) != CPP_VSPACE)
      {
        cpp_error (pfile, "junk at end of #%s", name);
        _cpp_skip_rest_of_line (pfile);
*************** do_include (pfile)
*** 441,447 ****
    unsigned int len;
    U_CHAR *token;
  
!   len = parse_include (pfile, dtable[T_INCLUDE].name);
    if (len == 0)
      return 0;
    token = (U_CHAR *) alloca (len + 1);
--- 442,448 ----
    unsigned int len;
    U_CHAR *token;
  
!   len = parse_include (pfile, dtable[T_INCLUDE].name, 0);
    if (len == 0)
      return 0;
    token = (U_CHAR *) alloca (len + 1);
*************** do_import (pfile)
*** 470,476 ****
  	   "#import is obsolete, use an #ifndef wrapper in the header file");
      }
  
!   len = parse_include (pfile, dtable[T_IMPORT].name);
    if (len == 0)
      return 0;
    token = (U_CHAR *) alloca (len + 1);
--- 471,477 ----
  	   "#import is obsolete, use an #ifndef wrapper in the header file");
      }
  
!   len = parse_include (pfile, dtable[T_IMPORT].name, 0);
    if (len == 0)
      return 0;
    token = (U_CHAR *) alloca (len + 1);
*************** do_include_next (pfile)
*** 492,498 ****
    U_CHAR *token;
    struct file_name_list *search_start = 0;
  
!   len = parse_include (pfile, dtable[T_INCLUDE_NEXT].name);
    if (len == 0)
      return 0;
    token = (U_CHAR *) alloca (len + 1);
--- 493,499 ----
    U_CHAR *token;
    struct file_name_list *search_start = 0;
  
!   len = parse_include (pfile, dtable[T_INCLUDE_NEXT].name, 0);
    if (len == 0)
      return 0;
    token = (U_CHAR *) alloca (len + 1);
*************** static int do_pragma_poison		PARAMS ((cp
*** 803,808 ****
--- 804,810 ----
  static int do_pragma_system_header	PARAMS ((cpp_reader *));
  static int do_pragma_default		PARAMS ((cpp_reader *));
  static int do_pragma_gcc                PARAMS ((cpp_reader *));
+ static int do_pragma_dependency         PARAMS ((cpp_reader *));
  
  static const struct pragma_entry top_pragmas[] =
  {
*************** static const struct pragma_entry gcc_pra
*** 819,824 ****
--- 821,827 ----
    {"implementation", do_pragma_implementation},
    {"poison", do_pragma_poison},
    {"system_header", do_pragma_system_header},
+   {"dependency", do_pragma_dependency},
    {NULL, do_pragma_default}
  };
  
*************** do_pragma_system_header (pfile)
*** 1033,1039 ****
  
    return 1;
  }
!  
  /* Just ignore #sccs, on systems where we define it at all.  */
  #ifdef SCCS_DIRECTIVE
  static int
--- 1036,1080 ----
  
    return 1;
  }
! 
! /* Check the modified date of the current include file against a specified
!    file. Issue a diagnostic, if the specified file is newer. We use this to
!    determine if a fixed header should be refixed.  */
! static int
! do_pragma_dependency (pfile)
!      cpp_reader *pfile;
! {
!   U_CHAR *original_name, *name;
!   unsigned len;
!   int ordering;
!   
!   len = parse_include (pfile, (const U_CHAR *)"pragma dependency", 1);
!   original_name = (U_CHAR *) alloca (len + 1);
!   name = (U_CHAR *) alloca (len + 1);
!   memcpy (original_name, CPP_PWRITTEN (pfile), len);
!   memcpy (name, CPP_PWRITTEN (pfile), len);
!   original_name[len] = name[len] = 0;
!   
!   ordering = _cpp_compare_file_date (pfile, name, len, 0);
!   if (ordering < 0)
!     cpp_warning (pfile, "cannot find source %s", original_name);
!   else if (ordering > 0)
!     {
!       const U_CHAR *text, *limit;
!       _cpp_skip_hspace (pfile);
!       text = CPP_BUFFER (pfile)->cur;
!       _cpp_skip_rest_of_line (pfile);
!       limit = CPP_BUFFER (pfile)->cur;
!       
!       if (limit == text)
!         cpp_warning (pfile, "out of date with dependency on %s", original_name);
!       else
!         cpp_warning (pfile, "%.*s", (int)(limit - text), text);
!     }
!   _cpp_skip_rest_of_line (pfile);
!   return 1;
! }
! 
  /* Just ignore #sccs, on systems where we define it at all.  */
  #ifdef SCCS_DIRECTIVE
  static int

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]