aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/cpp.texi14
-rw-r--r--gcc/cppfiles.c57
-rw-r--r--gcc/cpphash.h4
-rw-r--r--gcc/cpplib.c54
5 files changed, 137 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a0dd12a..3ee3b40 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2000-06-30 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.
+
2000-06-29 Jason Merrill <jason@redhat.com>
* dwarf2out.c (output_loc_operands): Don't abort on codes that have
diff --git a/gcc/cpp.texi b/gcc/cpp.texi
index 6413eec..4764702 100644
--- a/gcc/cpp.texi
+++ b/gcc/cpp.texi
@@ -2664,6 +2664,20 @@ the text is ignored and this directive has no effect. Typically
@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
diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c
index 35d1aa6..4e14aae 100644
--- a/gcc/cppfiles.c
+++ b/gcc/cppfiles.c
@@ -227,6 +227,7 @@ open_include_file (pfile, filename)
}
file->fd = fd;
+ file->date = (time_t) -1;
return file;
}
@@ -465,6 +466,60 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start)
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
@@ -502,6 +557,8 @@ read_include_file (pfile, inc)
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
diff --git a/gcc/cpphash.h b/gcc/cpphash.h
index f3e19d3e..ec9204a 100644
--- a/gcc/cpphash.h
+++ b/gcc/cpphash.h
@@ -64,6 +64,7 @@ struct include_file
int fd; /* file descriptor possibly open on file */
unsigned short include_count; /* number of times file has been read */
unsigned short sysp; /* file is a system header */
+ time_t date; /* modification date of file, if known */
};
/* The cmacro works like this: If it's NULL, the file is to be
@@ -193,6 +194,9 @@ extern void _cpp_simplify_pathname PARAMS ((char *));
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 *));
diff --git a/gcc/cpplib.c b/gcc/cpplib.c
index f6cbd90..26396df 100644
--- a/gcc/cpplib.c
+++ b/gcc/cpplib.c
@@ -52,7 +52,7 @@ struct if_stack
/* Forward declarations. */
static void validate_else PARAMS ((cpp_reader *, const U_CHAR *));
-static unsigned int parse_include 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,
@@ -398,9 +398,10 @@ do_define (pfile)
/* Handle #include and #import. */
static unsigned int
-parse_include (pfile, name)
+parse_include (pfile, name, trail)
cpp_reader *pfile;
const U_CHAR *name;
+ int trail;
{
long old_written = CPP_WRITTEN (pfile);
enum cpp_ttype token;
@@ -420,7 +421,7 @@ parse_include (pfile, name)
return 0;
}
- if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
+ if (!trail && _cpp_get_directive_token (pfile) != CPP_VSPACE)
{
cpp_error (pfile, "junk at end of #%s", name);
_cpp_skip_rest_of_line (pfile);
@@ -441,7 +442,7 @@ do_include (pfile)
unsigned int len;
U_CHAR *token;
- len = parse_include (pfile, dtable[T_INCLUDE].name);
+ len = parse_include (pfile, dtable[T_INCLUDE].name, 0);
if (len == 0)
return 0;
token = (U_CHAR *) alloca (len + 1);
@@ -470,7 +471,7 @@ do_import (pfile)
"#import is obsolete, use an #ifndef wrapper in the header file");
}
- len = parse_include (pfile, dtable[T_IMPORT].name);
+ len = parse_include (pfile, dtable[T_IMPORT].name, 0);
if (len == 0)
return 0;
token = (U_CHAR *) alloca (len + 1);
@@ -492,7 +493,7 @@ do_include_next (pfile)
U_CHAR *token;
struct file_name_list *search_start = 0;
- len = parse_include (pfile, dtable[T_INCLUDE_NEXT].name);
+ len = parse_include (pfile, dtable[T_INCLUDE_NEXT].name, 0);
if (len == 0)
return 0;
token = (U_CHAR *) alloca (len + 1);
@@ -803,6 +804,7 @@ static int do_pragma_poison PARAMS ((cpp_reader *));
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[] =
{
@@ -819,6 +821,7 @@ static const struct pragma_entry gcc_pragmas[] =
{"implementation", do_pragma_implementation},
{"poison", do_pragma_poison},
{"system_header", do_pragma_system_header},
+ {"dependency", do_pragma_dependency},
{NULL, do_pragma_default}
};
@@ -1033,7 +1036,44 @@ do_pragma_system_header (pfile)
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