summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>1999-09-03 22:46:28 +0000
committerPaul Smith <psmith@gnu.org>1999-09-03 22:46:28 +0000
commit7b8462d5d4e0dc27276548189dd1039d5396a8c9 (patch)
treed38ac0ac88ba4b64006ecbfad092d1446eef47d9
parent415d779d6e522b0607bf26a58220356b43b7b3ea (diff)
downloadmake-7b8462d5d4e0dc27276548189dd1039d5396a8c9.tar.gz
* Removed a memory stomp (reading freed memory).
* Fixed some infinite recursion on rebuilt makefiles bugs.
-rw-r--r--ChangeLog21
-rw-r--r--main.c5
-rw-r--r--read.c67
-rw-r--r--remake.c18
4 files changed, 78 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog
index 3b808635..4e69369d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+1999-09-03 Paul D. Smith <psmith@gnu.org>
+
+ * remake.c (notice_finished_file): Always set mtime_before_update
+ if it's not been set, not just if we ran some rules. Otherwise we
+ may have a situation where a target's prerequisite was rebuilt but
+ not changed, so this target's rules weren't run, then
+ update_goal_chain() sees mtime_before_update != last_mtime and
+ thinks that the top-level target changed when it really didn't.
+ This can cause an infinite loop when remaking makefiles.
+ (update_goal_chain): If we get back to the top and we don't know
+ what the goal's last_mtime was, find it now. We need to know so
+ we can compare it to mtime_before_update later (this is only
+ crucial when remaking makefiles--should we only do it then?)
+
+1999-09-02 Paul D. Smith <psmith@gnu.org>
+
+ * read.c (read_makefile): If "override" appears as the first
+ prerequisite, look further to ensure this is really a
+ target-specific variable definition, and not just some
+ prerequisite named "override".
+
1999-09-01 Paul D. Smith <psmith@gnu.org>
* function.c (IS_PATHSEP) [WINDOWS32]: Allow backslash separators
diff --git a/main.c b/main.c
index 86921bc1..802e889b 100644
--- a/main.c
+++ b/main.c
@@ -1331,7 +1331,8 @@ int main (int argc, char ** argv)
(ignore the jobserver pipe for this make) but print a message. */
if (job_slots > 0)
- error (NILF, _("warning: -jN set for submakes: ignoring jobserver."));
+ error (NILF,
+ _("warning: -jN forced in submake: disabling jobserver mode."));
/* Create a duplicate pipe, that will be closed in the SIGCHLD
handler. If this fails with EBADF, the parent has closed the pipe
@@ -1344,7 +1345,7 @@ int main (int argc, char ** argv)
pfatal_with_name (_("dup jobserver"));
error (NILF,
- _("warning: jobserver unavailable (using -j1). Add `+' to parent make rule."));
+ _("warning: jobserver unavailable: using -j1. Add `+' to parent make rule."));
job_slots = 1;
}
diff --git a/read.c b/read.c
index bf2be059..ed9a2b09 100644
--- a/read.c
+++ b/read.c
@@ -177,10 +177,12 @@ read_all_makefiles (makefiles)
while ((name = find_next_token (&p, &length)) != 0)
{
+ name = xstrdup (name);
if (*p != '\0')
*p++ = '\0';
- (void) read_makefile (name,
- RM_NO_DEFAULT_GOAL | RM_INCLUDED | RM_DONTCARE);
+ if (read_makefile (name,
+ RM_NO_DEFAULT_GOAL|RM_INCLUDED|RM_DONTCARE) < 2)
+ free (name);
}
free (value);
@@ -269,7 +271,9 @@ read_all_makefiles (makefiles)
FILENAME is added to the `read_makefiles' chain.
- Returns 1 if a file was found and read, 0 if not. */
+ Returns 0 if a file was not found or not read.
+ Returns 1 if FILENAME was found and read.
+ Returns 2 if FILENAME was read, and we kept a reference (don't free it). */
static int
read_makefile (filename, flags)
@@ -289,6 +293,7 @@ read_makefile (filename, flags)
int len, reading_target;
int ignoring = 0, in_ignored_define = 0;
int no_targets = 0; /* Set when reading a rule without targets. */
+ int using_filename = 0;
struct floc fileinfo;
char *passed_filename = filename;
@@ -307,10 +312,12 @@ read_makefile (filename, flags)
do \
{ \
if (filenames != 0) \
- record_files (filenames, pattern, pattern_percent, deps, \
- cmds_started, commands, commands_idx, \
- two_colon, &fileinfo, \
- !(flags & RM_NO_DEFAULT_GOAL)); \
+ { \
+ record_files (filenames, pattern, pattern_percent, deps, \
+ cmds_started, commands, commands_idx, two_colon, \
+ &fileinfo, !(flags & RM_NO_DEFAULT_GOAL)); \
+ using_filename |= commands_idx > 0; \
+ } \
filenames = 0; \
commands_idx = 0; \
if (pattern) { free(pattern); pattern = 0; } \
@@ -685,16 +692,18 @@ read_makefile (filename, flags)
{
struct nameseq *next = files->next;
char *name = files->name;
+ int r;
+
free ((char *)files);
files = next;
- if (! read_makefile (name, (RM_INCLUDED | RM_NO_TILDE
- | (noerror ? RM_DONTCARE : 0)))
- && ! noerror)
+ r = read_makefile (name, (RM_INCLUDED | RM_NO_TILDE
+ | (noerror ? RM_DONTCARE : 0)));
+ if (!r && !noerror)
error (&fileinfo, "%s: %s", name, strerror (errno));
- /* We can't free NAME here, in case some of the commands,
- etc. still contain references to the filename. */
+ if (r < 2)
+ free (name);
}
/* Free any space allocated by conditional_line. */
@@ -880,7 +889,7 @@ read_makefile (filename, flags)
continue;
}
/* This should never be possible; we handled it above. */
- assert(*p2 != '\0');
+ assert (*p2 != '\0');
++p2;
/* Is this a one-colon or two-colon entry? */
@@ -895,25 +904,31 @@ read_makefile (filename, flags)
if (*lb_next != '\0')
{
unsigned int l = p2 - variable_buffer;
- plen = strlen(p2);
- (void)variable_buffer_output(p2+plen,
- lb_next, strlen(lb_next)+1);
+ plen = strlen (p2);
+ (void) variable_buffer_output (p2+plen,
+ lb_next, strlen (lb_next)+1);
p2 = variable_buffer + l;
}
- wtype = get_next_mword(p2, NULL, &p, &len);
+
+ /* See if it's an "override" keyword; if so see if what comes after
+ it looks like a variable definition. */
+
+ wtype = get_next_mword (p2, NULL, &p, &len);
+
v_origin = o_file;
- if (wtype == w_static && (len == (sizeof("override")-1)
- && strneq(p, "override", len)))
+ if (wtype == w_static && (len == (sizeof ("override")-1)
+ && strneq (p, "override", len)))
{
v_origin = o_override;
- (void)get_next_mword(p+len, NULL, &p, &len);
+ wtype = get_next_mword (p+len, NULL, &p, &len);
}
- else if (wtype != w_eol)
- wtype = get_next_mword(p+len, NULL, NULL, NULL);
- if (wtype == w_varassign || v_origin == o_override)
+ if (wtype != w_eol)
+ wtype = get_next_mword (p+len, NULL, NULL, NULL);
+
+ if (wtype == w_varassign)
{
- record_target_var(filenames, p, two_colon, v_origin, &fileinfo);
+ record_target_var (filenames, p, two_colon, v_origin, &fileinfo);
filenames = 0;
continue;
}
@@ -929,7 +944,7 @@ read_makefile (filename, flags)
if (*lb_next != '\0')
{
unsigned int l = p2 - variable_buffer;
- (void)variable_expand_string(p2 + plen, lb_next, (long)-1);
+ (void) variable_expand_string (p2 + plen, lb_next, (long)-1);
p2 = variable_buffer + l;
/* Look for a semicolon in the expanded line. */
@@ -1046,7 +1061,7 @@ read_makefile (filename, flags)
reading_file = 0;
- return 1;
+ return 1+using_filename;
}
/* Execute a `define' directive.
diff --git a/remake.c b/remake.c
index 38d643b1..1e21e618 100644
--- a/remake.c
+++ b/remake.c
@@ -1,5 +1,5 @@
/* Basic dependency engine for GNU Make.
-Copyright (C) 1988,89,90,91,92,93,94,95,96,97 Free Software Foundation, Inc.
+Copyright (C) 1988,89,90,91,92,93,94,95,96,97,99 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -154,6 +154,13 @@ update_goal_chain (goals, makefiles)
x = update_file (file, makefiles ? 1 : 0);
check_renamed (file);
+ /* If we don't know what the file's last mtime was, find it. */
+ if (! file->last_mtime)
+ {
+ (void) f_mtime (file, 0);
+ check_renamed (file);
+ }
+
/* Set the goal's `changed' flag if any commands were started
by calling update_file above. We check this flag below to
decide when to give an "up to date" diagnostic. */
@@ -553,7 +560,8 @@ update_file_1 (file, depth)
if (depth == 0 && keep_going_flag
&& !just_print_flag && !question_flag)
- error (NILF, _("Target `%s' not remade because of errors."), file->name);
+ error (NILF,
+ _("Target `%s' not remade because of errors."), file->name);
return dep_status;
}
@@ -736,13 +744,13 @@ notice_finished_file (file)
}
}
+ if (file->mtime_before_update == 0)
+ file->mtime_before_update = file->last_mtime;
+
if (ran && !file->phony)
{
struct file *f;
- assert(file->mtime_before_update == 0);
- file->mtime_before_update = file->last_mtime;
-
if (just_print_flag || question_flag
|| (file->is_target && file->cmds == 0))
file->last_mtime = NEW_MTIME;