From e49b2f15c9c875f7db16064834ffac123f48b612 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Fri, 3 Sep 1999 22:46:28 +0000 Subject: [PATCH] * Removed a memory stomp (reading freed memory). * Fixed some infinite recursion on rebuilt makefiles bugs. --- ChangeLog | 21 +++++++++++++++++ main.c | 5 +++-- read.c | 67 ++++++++++++++++++++++++++++++++++--------------------- remake.c | 18 ++++++++++----- 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 + + * 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 + + * 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 * 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;