This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [cpplib] implement pragma dependancy
- To: Zack Weinberg <zack at wolery dot cumb dot org>
- Subject: Re: [cpplib] implement pragma dependancy
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Fri, 23 Jun 2000 14:06:04 +0100
- CC: gcc-patches at gcc dot gnu dot org
- Organization: Codesourcery LLC
- References: <3950B4F9.49FD2493@codesourcery.com> <20000621110602.T5412@wolery.cumb.org>
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