summaryrefslogtreecommitdiff
path: root/file.c
diff options
context:
space:
mode:
authorKévin THIERRY <kevin.thierry@open.eurogiciel.org>2014-11-05 08:27:15 +0100
committerKévin THIERRY <kevin.thierry@open.eurogiciel.org>2014-11-05 08:27:15 +0100
commite15597c3e85dedc015ff923a88febd46a1551f71 (patch)
tree467fdb092d1fa76bcb63d4db653e8176dae24e62 /file.c
parent9789b4dba120180760ec948089fc98ebab6eb28b (diff)
downloadmake-e15597c3e85dedc015ff923a88febd46a1551f71.tar.gz
make-e15597c3e85dedc015ff923a88febd46a1551f71.tar.bz2
make-e15597c3e85dedc015ff923a88febd46a1551f71.zip
Imported Upstream version 4.0upstream/4.0sandbox/kevinthierry/upstream
Diffstat (limited to 'file.c')
-rw-r--r--file.c278
1 files changed, 150 insertions, 128 deletions
diff --git a/file.c b/file.c
index 0a4edb2..b209d88 100644
--- a/file.c
+++ b/file.c
@@ -1,7 +1,5 @@
/* Target file management for GNU Make.
-Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-2010 Free Software Foundation, Inc.
+Copyright (C) 1988-2013 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@@ -16,12 +14,12 @@ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>. */
-#include "make.h"
+#include "makeint.h"
#include <assert.h>
-#include "dep.h"
#include "filedef.h"
+#include "dep.h"
#include "job.h"
#include "commands.h"
#include "variable.h"
@@ -56,11 +54,11 @@ static int
file_hash_cmp (const void *x, const void *y)
{
return_ISTRING_COMPARE (((struct file const *) x)->hname,
- ((struct file const *) y)->hname);
+ ((struct file const *) y)->hname);
}
-#ifndef FILE_BUCKETS
-#define FILE_BUCKETS 1007
+#ifndef FILE_BUCKETS
+#define FILE_BUCKETS 1007
#endif
static struct hash_table files;
@@ -105,20 +103,20 @@ lookup_file (const char *name)
#endif
while (name[0] == '.'
#ifdef HAVE_DOS_PATHS
- && (name[1] == '/' || name[1] == '\\')
+ && (name[1] == '/' || name[1] == '\\')
#else
- && name[1] == '/'
+ && name[1] == '/'
#endif
- && name[2] != '\0')
+ && name[2] != '\0')
{
name += 2;
while (*name == '/'
#ifdef HAVE_DOS_PATHS
- || *name == '\\'
+ || *name == '\\'
#endif
- )
- /* Skip following slashes: ".//foo" is "foo", not "/foo". */
- ++name;
+ )
+ /* Skip following slashes: ".//foo" is "foo", not "/foo". */
+ ++name;
}
if (*name == '\0')
@@ -155,7 +153,7 @@ enter_file (const char *name)
struct file file_key;
assert (*name != '\0');
- assert (strcache_iscached (name));
+ assert (! verify_flag || strcache_iscached (name));
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
if (*name != '.')
@@ -179,11 +177,14 @@ enter_file (const char *name)
file_slot = (struct file **) hash_find_slot (&files, &file_key);
f = *file_slot;
if (! HASH_VACANT (f) && !f->double_colon)
- return f;
+ {
+ f->builtin = 0;
+ return f;
+ }
new = xcalloc (sizeof (struct file));
new->name = new->hname = name;
- new->update_status = -1;
+ new->update_status = us_none;
if (HASH_VACANT (f))
{
@@ -202,7 +203,7 @@ enter_file (const char *name)
}
/* Rehash FILE to NAME. This is not as simple as resetting
- the `hname' member, since it must be put in a new hash bucket,
+ the 'hname' member, since it must be put in a new hash bucket,
and possibly merged with an existing file called NAME. */
void
@@ -215,6 +216,7 @@ rehash_file (struct file *from_file, const char *to_hname)
struct file *f;
/* If it's already that name, we're done. */
+ from_file->builtin = 0;
file_key.hname = to_hname;
if (! file_hash_cmp (from_file, &file_key))
return;
@@ -264,18 +266,18 @@ rehash_file (struct file *from_file, const char *to_hname)
but give a message to let the user know what's going on. */
if (to_file->cmds->fileinfo.filenm != 0)
error (&from_file->cmds->fileinfo,
- _("Recipe was specified for file `%s' at %s:%lu,"),
+ _("Recipe was specified for file '%s' at %s:%lu,"),
from_file->name, to_file->cmds->fileinfo.filenm,
to_file->cmds->fileinfo.lineno);
else
error (&from_file->cmds->fileinfo,
- _("Recipe for file `%s' was found by implicit rule search,"),
+ _("Recipe for file '%s' was found by implicit rule search,"),
from_file->name);
error (&from_file->cmds->fileinfo,
- _("but `%s' is now considered the same file as `%s'."),
+ _("but '%s' is now considered the same file as '%s'."),
from_file->name, to_hname);
error (&from_file->cmds->fileinfo,
- _("Recipe for `%s' will be ignored in favor of the one for `%s'."),
+ _("Recipe for '%s' will be ignored in favor of the one for '%s'."),
to_hname, from_file->name);
}
}
@@ -295,12 +297,12 @@ rehash_file (struct file *from_file, const char *to_hname)
merge_variable_set_lists (&to_file->variables, from_file->variables);
if (to_file->double_colon && from_file->is_target && !from_file->double_colon)
- fatal (NILF, _("can't rename single-colon `%s' to double-colon `%s'"),
+ fatal (NILF, _("can't rename single-colon '%s' to double-colon '%s'"),
from_file->name, to_hname);
if (!to_file->double_colon && from_file->double_colon)
{
if (to_file->is_target)
- fatal (NILF, _("can't rename double-colon `%s' to single-colon `%s'"),
+ fatal (NILF, _("can't rename double-colon '%s' to single-colon '%s'"),
from_file->name, to_hname);
else
to_file->double_colon = from_file->double_colon;
@@ -320,14 +322,16 @@ rehash_file (struct file *from_file, const char *to_hname)
MERGE (is_target);
MERGE (cmd_target);
MERGE (phony);
+ MERGE (loaded);
MERGE (ignore_vpath);
#undef MERGE
+ to_file->builtin = 0;
from_file->renamed = to_file;
}
/* Rename FILE to NAME. This is not as simple as resetting
- the `name' member, since it must be put in a new hash bucket,
+ the 'name' member, since it must be put in a new hash bucket,
and possibly merged with an existing file called NAME. */
void
@@ -365,52 +369,52 @@ remove_intermediates (int sig)
for ( ; file_slot < file_end; file_slot++)
if (! HASH_VACANT (*file_slot))
{
- struct file *f = *file_slot;
+ struct file *f = *file_slot;
/* Is this file eligible for automatic deletion?
Yes, IFF: it's marked intermediate, it's not secondary, it wasn't
given on the command line, and it's either a -include makefile or
it's not precious. */
- if (f->intermediate && (f->dontcare || !f->precious)
- && !f->secondary && !f->cmd_target)
- {
- int status;
- if (f->update_status == -1)
- /* If nothing would have created this file yet,
- don't print an "rm" command for it. */
- continue;
- if (just_print_flag)
- status = 0;
- else
- {
- status = unlink (f->name);
- if (status < 0 && errno == ENOENT)
- continue;
- }
- if (!f->dontcare)
- {
- if (sig)
- error (NILF, _("*** Deleting intermediate file `%s'"), f->name);
- else
- {
- if (! doneany)
- DB (DB_BASIC, (_("Removing intermediate files...\n")));
- if (!silent_flag)
- {
- if (! doneany)
- {
- fputs ("rm ", stdout);
- doneany = 1;
- }
- else
- putchar (' ');
- fputs (f->name, stdout);
- fflush (stdout);
- }
- }
- if (status < 0)
- perror_with_name ("unlink: ", f->name);
- }
- }
+ if (f->intermediate && (f->dontcare || !f->precious)
+ && !f->secondary && !f->cmd_target)
+ {
+ int status;
+ if (f->update_status == us_none)
+ /* If nothing would have created this file yet,
+ don't print an "rm" command for it. */
+ continue;
+ if (just_print_flag)
+ status = 0;
+ else
+ {
+ status = unlink (f->name);
+ if (status < 0 && errno == ENOENT)
+ continue;
+ }
+ if (!f->dontcare)
+ {
+ if (sig)
+ error (NILF, _("*** Deleting intermediate file '%s'"), f->name);
+ else
+ {
+ if (! doneany)
+ DB (DB_BASIC, (_("Removing intermediate files...\n")));
+ if (!silent_flag)
+ {
+ if (! doneany)
+ {
+ fputs ("rm ", stdout);
+ doneany = 1;
+ }
+ else
+ putchar (' ');
+ fputs (f->name, stdout);
+ fflush (stdout);
+ }
+ }
+ if (status < 0)
+ perror_with_name ("unlink: ", f->name);
+ }
+ }
}
if (doneany && !sig)
@@ -426,7 +430,8 @@ remove_intermediates (int sig)
struct dep *
split_prereqs (char *p)
{
- struct dep *new = PARSE_FILE_SEQ (&p, struct dep, '|', NULL, 0);
+ struct dep *new = PARSE_FILE_SEQ (&p, struct dep, MAP_PIPE, NULL,
+ PARSEFS_NONE);
if (*p)
{
@@ -435,7 +440,7 @@ split_prereqs (char *p)
struct dep *ood;
++p;
- ood = PARSE_FILE_SEQ (&p, struct dep, '\0', NULL, 0);
+ ood = PARSE_SIMPLE_SEQ (&p, struct dep);
if (! new)
new = ood;
@@ -575,12 +580,11 @@ expand_deps (struct file *f)
"$*" so they'll expand properly. */
if (d->staticpattern)
{
- char *o;
- d->name = o = variable_expand ("");
+ char *o = variable_expand ("");
o = subst_expand (o, name, "%", "$*", 1, 2, 0);
*o = '\0';
free (name);
- d->name = name = xstrdup (d->name);
+ d->name = name = xstrdup (variable_buffer);
d->staticpattern = 0;
}
@@ -637,8 +641,8 @@ reset_updating (const void *item)
f->updating = 0;
}
-/* For each dependency of each file, make the `struct dep' point
- at the appropriate `struct file' (which may have to be created).
+/* For each dependency of each file, make the 'struct dep' point
+ at the appropriate 'struct file' (which may have to be created).
Also mark the files depended on by .PRECIOUS, .PHONY, .SILENT,
and various other special targets. */
@@ -693,23 +697,23 @@ snap_deps (void)
for (f = lookup_file (".PRECIOUS"); f != 0; f = f->prev)
for (d = f->deps; d != 0; d = d->next)
for (f2 = d->file; f2 != 0; f2 = f2->prev)
- f2->precious = 1;
+ f2->precious = 1;
for (f = lookup_file (".LOW_RESOLUTION_TIME"); f != 0; f = f->prev)
for (d = f->deps; d != 0; d = d->next)
for (f2 = d->file; f2 != 0; f2 = f2->prev)
- f2->low_resolution_time = 1;
+ f2->low_resolution_time = 1;
for (f = lookup_file (".PHONY"); f != 0; f = f->prev)
for (d = f->deps; d != 0; d = d->next)
for (f2 = d->file; f2 != 0; f2 = f2->prev)
- {
- /* Mark this file as phony nonexistent target. */
- f2->phony = 1;
+ {
+ /* Mark this file as phony nonexistent target. */
+ f2->phony = 1;
f2->is_target = 1;
- f2->last_mtime = NONEXISTENT_MTIME;
- f2->mtime_before_update = NONEXISTENT_MTIME;
- }
+ f2->last_mtime = NONEXISTENT_MTIME;
+ f2->mtime_before_update = NONEXISTENT_MTIME;
+ }
for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev)
/* Mark .INTERMEDIATE deps as intermediate files. */
@@ -741,22 +745,22 @@ snap_deps (void)
if (f != 0 && f->is_target)
{
if (f->deps == 0)
- ignore_errors_flag = 1;
+ ignore_errors_flag = 1;
else
- for (d = f->deps; d != 0; d = d->next)
- for (f2 = d->file; f2 != 0; f2 = f2->prev)
- f2->command_flags |= COMMANDS_NOERROR;
+ for (d = f->deps; d != 0; d = d->next)
+ for (f2 = d->file; f2 != 0; f2 = f2->prev)
+ f2->command_flags |= COMMANDS_NOERROR;
}
f = lookup_file (".SILENT");
if (f != 0 && f->is_target)
{
if (f->deps == 0)
- silent_flag = 1;
+ silent_flag = 1;
else
- for (d = f->deps; d != 0; d = d->next)
- for (f2 = d->file; f2 != 0; f2 = f2->prev)
- f2->command_flags |= COMMANDS_SILENT;
+ for (d = f->deps; d != 0; d = d->next)
+ for (f2 = d->file; f2 != 0; f2 = f2->prev)
+ f2->command_flags |= COMMANDS_SILENT;
}
f = lookup_file (".NOTPARALLEL");
@@ -772,7 +776,7 @@ snap_deps (void)
#endif
}
-/* Set the `command_state' member of FILE and all its `also_make's. */
+/* Set the 'command_state' member of FILE and all its 'also_make's. */
void
set_command_state (struct file *file, enum cmd_state state)
@@ -788,20 +792,21 @@ set_command_state (struct file *file, enum cmd_state state)
/* Convert an external file timestamp to internal form. */
FILE_TIMESTAMP
-file_timestamp_cons (const char *fname, time_t s, int ns)
+file_timestamp_cons (const char *fname, time_t stamp, long int ns)
{
int offset = ORDINARY_MTIME_MIN + (FILE_TIMESTAMP_HI_RES ? ns : 0);
+ FILE_TIMESTAMP s = stamp;
FILE_TIMESTAMP product = (FILE_TIMESTAMP) s << FILE_TIMESTAMP_LO_BITS;
FILE_TIMESTAMP ts = product + offset;
if (! (s <= FILE_TIMESTAMP_S (ORDINARY_MTIME_MAX)
- && product <= ts && ts <= ORDINARY_MTIME_MAX))
+ && product <= ts && ts <= ORDINARY_MTIME_MAX))
{
char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX;
file_timestamp_sprintf (buf, ts);
error (NILF, _("%s: Timestamp out of range; substituting %s"),
- fname ? fname : _("Current time"), buf);
+ fname ? fname : _("Current time"), buf);
}
return ts;
@@ -825,10 +830,10 @@ file_timestamp_now (int *resolution)
struct timespec timespec;
if (clock_gettime (CLOCK_REALTIME, &timespec) == 0)
{
- r = 1;
- s = timespec.tv_sec;
- ns = timespec.tv_nsec;
- goto got_time;
+ r = 1;
+ s = timespec.tv_sec;
+ ns = timespec.tv_nsec;
+ goto got_time;
}
}
# endif
@@ -837,10 +842,10 @@ file_timestamp_now (int *resolution)
struct timeval timeval;
if (gettimeofday (&timeval, 0) == 0)
{
- r = 1000;
- s = timeval.tv_sec;
- ns = timeval.tv_usec * 1000;
- goto got_time;
+ r = 1000;
+ s = timeval.tv_sec;
+ ns = timeval.tv_usec * 1000;
+ goto got_time;
}
}
# endif
@@ -867,8 +872,8 @@ file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
if (tm)
sprintf (p, "%04d-%02d-%02d %02d:%02d:%02d",
- tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
else if (t < 0)
sprintf (p, "%ld", (long) t);
else
@@ -919,7 +924,27 @@ print_file (const void *item)
{
const struct file *f = item;
+ /* If we're not using builtin targets, don't show them.
+
+ Ideally we'd be able to delete them altogether but currently there's no
+ facility to ever delete a file once it's been added. */
+ if (no_builtin_rules_flag && f->builtin)
+ return;
+
putchar ('\n');
+
+ if (f->cmds && f->cmds->recipe_prefix != cmd_prefix)
+ {
+ fputs (".RECIPEPREFIX = ", stdout);
+ cmd_prefix = f->cmds->recipe_prefix;
+ if (cmd_prefix != RECIPEPREFIX_DEFAULT)
+ putchar (cmd_prefix);
+ putchar ('\n');
+ }
+
+ if (f->variables != 0)
+ print_target_variables (f);
+
if (!f->is_target)
puts (_("# Not a target:"));
printf ("%s:%s", f->name, f->double_colon ? ":" : "");
@@ -933,11 +958,13 @@ print_file (const void *item)
puts (_("# Command line target."));
if (f->dontcare)
puts (_("# A default, MAKEFILES, or -include/sinclude makefile."));
+ if (f->builtin)
+ puts (_("# Builtin rule"));
puts (f->tried_implicit
? _("# Implicit rule search has been done.")
: _("# Implicit rule search has not been done."));
if (f->stem != 0)
- printf (_("# Implicit/static pattern stem: `%s'\n"), f->stem);
+ printf (_("# Implicit/static pattern stem: '%s'\n"), f->stem);
if (f->intermediate)
puts (_("# File is an intermediate prerequisite."));
if (f->also_make != 0)
@@ -945,7 +972,7 @@ print_file (const void *item)
const struct dep *d;
fputs (_("# Also makes:"), stdout);
for (d = f->also_make; d != 0; d = d->next)
- printf (" %s", dep_name (d));
+ printf (" %s", dep_name (d));
putchar ('\n');
}
if (f->last_mtime == UNKNOWN_MTIME)
@@ -973,28 +1000,23 @@ print_file (const void *item)
case cs_not_started:
case cs_finished:
switch (f->update_status)
- {
- case -1:
- break;
- case 0:
- puts (_("# Successfully updated."));
- break;
- case 1:
- assert (question_flag);
- puts (_("# Needs to be updated (-q is set)."));
- break;
- case 2:
- puts (_("# Failed to be updated."));
- break;
- default:
- puts (_("# Invalid value in `update_status' member!"));
- fflush (stdout);
- fflush (stderr);
- abort ();
- }
+ {
+ case us_none:
+ break;
+ case us_success:
+ puts (_("# Successfully updated."));
+ break;
+ case us_question:
+ assert (question_flag);
+ puts (_("# Needs to be updated (-q is set)."));
+ break;
+ case us_failed:
+ puts (_("# Failed to be updated."));
+ break;
+ }
break;
default:
- puts (_("# Invalid value in `command_state' member!"));
+ puts (_("# Invalid value in 'command_state' member!"));
fflush (stdout);
fflush (stderr);
abort ();
@@ -1026,7 +1048,7 @@ print_file_data_base (void)
#define VERIFY_CACHED(_p,_n) \
do{\
if (_p->_n && _p->_n[0] && !strcache_iscached (_p->_n)) \
- error (NULL, "%s: Field '%s' not cached: %s\n", _p->name, # _n, _p->_n); \
+ error (NULL, _("%s: Field '%s' not cached: %s"), _p->name, # _n, _p->_n); \
}while(0)
static void