Commit f3f751ad by Nathan Sidwell Committed by Nathan Sidwell

cpp.texi: Document #pragma GCC dependency

	* 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.

From-SVN: r34808
parent 34f9943e
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> 2000-06-29 Jason Merrill <jason@redhat.com>
* dwarf2out.c (output_loc_operands): Don't abort on codes that have * dwarf2out.c (output_loc_operands): Don't abort on codes that have
......
...@@ -2664,6 +2664,20 @@ the text is ignored and this directive has no effect. Typically ...@@ -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 @samp{#ident} is only used in header files supplied with those systems
where it is meaningful. 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 @node Output, Invocation, Other Directives, Top
@section C Preprocessor Output @section C Preprocessor Output
......
...@@ -227,6 +227,7 @@ open_include_file (pfile, filename) ...@@ -227,6 +227,7 @@ open_include_file (pfile, filename)
} }
file->fd = fd; file->fd = fd;
file->date = (time_t) -1;
return file; return file;
} }
...@@ -465,6 +466,60 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start) ...@@ -465,6 +466,60 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start)
cpp_error_from_errno (pfile, fname); 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. /* Push an input buffer and load it up with the contents of FNAME.
If FNAME is "" or NULL, read standard input. */ If FNAME is "" or NULL, read standard input. */
int int
...@@ -503,6 +558,8 @@ read_include_file (pfile, inc) ...@@ -503,6 +558,8 @@ read_include_file (pfile, inc)
if (fstat (fd, &st) < 0) if (fstat (fd, &st) < 0)
goto perror_fail; goto perror_fail;
inc->date = st.st_mtime;
/* If fd points to a plain file, we might be able to mmap it; we can /* 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 definitely allocate the buffer all at once. If fd is a pipe or
terminal, we can't do either. If fd is something weird, like a terminal, we can't do either. If fd is something weird, like a
......
...@@ -64,6 +64,7 @@ struct include_file ...@@ -64,6 +64,7 @@ struct include_file
int fd; /* file descriptor possibly open on file */ int fd; /* file descriptor possibly open on file */
unsigned short include_count; /* number of times file has been read */ unsigned short include_count; /* number of times file has been read */
unsigned short sysp; /* file is a system header */ 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 /* 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 *)); ...@@ -193,6 +194,9 @@ extern void _cpp_simplify_pathname PARAMS ((char *));
extern void _cpp_execute_include PARAMS ((cpp_reader *, U_CHAR *, extern void _cpp_execute_include PARAMS ((cpp_reader *, U_CHAR *,
unsigned int, int, unsigned int, int,
struct file_name_list *)); 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 void _cpp_init_include_table PARAMS ((cpp_reader *));
extern const char *_cpp_fake_include PARAMS ((cpp_reader *, const char *)); extern const char *_cpp_fake_include PARAMS ((cpp_reader *, const char *));
......
...@@ -52,7 +52,7 @@ struct if_stack ...@@ -52,7 +52,7 @@ struct if_stack
/* Forward declarations. */ /* Forward declarations. */
static void validate_else PARAMS ((cpp_reader *, const U_CHAR *)); 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, static void push_conditional PARAMS ((cpp_reader *, int, int,
const cpp_hashnode *)); const cpp_hashnode *));
static void pass_thru_directive PARAMS ((const U_CHAR *, size_t, static void pass_thru_directive PARAMS ((const U_CHAR *, size_t,
...@@ -398,9 +398,10 @@ do_define (pfile) ...@@ -398,9 +398,10 @@ do_define (pfile)
/* Handle #include and #import. */ /* Handle #include and #import. */
static unsigned int static unsigned int
parse_include (pfile, name) parse_include (pfile, name, trail)
cpp_reader *pfile; cpp_reader *pfile;
const U_CHAR *name; const U_CHAR *name;
int trail;
{ {
long old_written = CPP_WRITTEN (pfile); long old_written = CPP_WRITTEN (pfile);
enum cpp_ttype token; enum cpp_ttype token;
...@@ -420,7 +421,7 @@ parse_include (pfile, name) ...@@ -420,7 +421,7 @@ parse_include (pfile, name)
return 0; 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_error (pfile, "junk at end of #%s", name);
_cpp_skip_rest_of_line (pfile); _cpp_skip_rest_of_line (pfile);
...@@ -441,7 +442,7 @@ do_include (pfile) ...@@ -441,7 +442,7 @@ do_include (pfile)
unsigned int len; unsigned int len;
U_CHAR *token; U_CHAR *token;
len = parse_include (pfile, dtable[T_INCLUDE].name); len = parse_include (pfile, dtable[T_INCLUDE].name, 0);
if (len == 0) if (len == 0)
return 0; return 0;
token = (U_CHAR *) alloca (len + 1); token = (U_CHAR *) alloca (len + 1);
...@@ -470,7 +471,7 @@ do_import (pfile) ...@@ -470,7 +471,7 @@ do_import (pfile)
"#import is obsolete, use an #ifndef wrapper in the header file"); "#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) if (len == 0)
return 0; return 0;
token = (U_CHAR *) alloca (len + 1); token = (U_CHAR *) alloca (len + 1);
...@@ -492,7 +493,7 @@ do_include_next (pfile) ...@@ -492,7 +493,7 @@ do_include_next (pfile)
U_CHAR *token; U_CHAR *token;
struct file_name_list *search_start = 0; 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) if (len == 0)
return 0; return 0;
token = (U_CHAR *) alloca (len + 1); token = (U_CHAR *) alloca (len + 1);
...@@ -803,6 +804,7 @@ static int do_pragma_poison PARAMS ((cpp_reader *)); ...@@ -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_system_header PARAMS ((cpp_reader *));
static int do_pragma_default PARAMS ((cpp_reader *)); static int do_pragma_default PARAMS ((cpp_reader *));
static int do_pragma_gcc 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 top_pragmas[] =
{ {
...@@ -819,6 +821,7 @@ static const struct pragma_entry gcc_pragmas[] = ...@@ -819,6 +821,7 @@ static const struct pragma_entry gcc_pragmas[] =
{"implementation", do_pragma_implementation}, {"implementation", do_pragma_implementation},
{"poison", do_pragma_poison}, {"poison", do_pragma_poison},
{"system_header", do_pragma_system_header}, {"system_header", do_pragma_system_header},
{"dependency", do_pragma_dependency},
{NULL, do_pragma_default} {NULL, do_pragma_default}
}; };
...@@ -1034,6 +1037,43 @@ do_pragma_system_header (pfile) ...@@ -1034,6 +1037,43 @@ do_pragma_system_header (pfile)
return 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. */ /* Just ignore #sccs, on systems where we define it at all. */
#ifdef SCCS_DIRECTIVE #ifdef SCCS_DIRECTIVE
static int static int
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment