This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [cpplib] implement pragma dependancy
Zack Weinberg wrote:
> This depends on the other patch for pragma namespaces, right?
correct.
> "warning: rerun fixincludes" is not a good error message. It does not
> say why, or what the actual problem is. I think we should always
> generate the boilerplate text:
> and if there's trailing text, emit that as a separate warning:
Good idea.
foo.c:3:62: warning: current file is older than "/usr/include/time.h"
foo.c:3:62: warning: rerun fixincludes
> Finally, should this pragma be rejected in the primary source file? I
> suppose it could be useful for Yacc output files and the like, too.
yes.
is this patch ok? It adjusts the warning message.
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-24 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.23
diff -c -3 -p -r1.23 cpp.texi
*** cpp.texi 2000/06/24 09:21:22 1.23
--- cpp.texi 2000/06/24 09:26:32
*************** the text is ignored and this directive h
*** 2664,2669 ****
--- 2664,2683 ----
@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 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 "parse.y"
+ #pragma GCC dependency "/usr/include/time.h" rerun /path/to/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/24 09:26:33
*************** 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/24 09:26:33
*************** 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/24 09:26:33
*************** 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)
*** 1032,1039 ****
cpp_make_system_header (pfile, ip, 1);
return 1;
}
!
/* Just ignore #sccs, on systems where we define it at all. */
#ifdef SCCS_DIRECTIVE
static int
--- 1035,1079 ----
cpp_make_system_header (pfile, ip, 1);
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;
+
+ cpp_warning (pfile, "current file is older than %s", original_name);
+ if (limit != text)
+ 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