summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@kolpackov.net>2006-03-17 14:24:20 +0000
committerBoris Kolpackov <boris@kolpackov.net>2006-03-17 14:24:20 +0000
commit22886f8a74b5925030889fed52af5a8add5617d7 (patch)
treec28340c4ca8f7956e259f671b3202b6bf0874a35
parent50eb3cf5e5a8a68b68e966a6607f668f2c36191e (diff)
downloadgunmake-22886f8a74b5925030889fed52af5a8add5617d7.tar.gz
Fixed Savannah bug #16053.
-rw-r--r--ChangeLog17
-rw-r--r--dep.h6
-rw-r--r--file.c24
-rw-r--r--implicit.c17
-rw-r--r--main.c18
-rw-r--r--misc.c36
-rw-r--r--read.c25
-rw-r--r--remake.c4
-rw-r--r--rule.c9
-rw-r--r--tests/ChangeLog4
-rw-r--r--tests/scripts/features/statipattrules41
11 files changed, 138 insertions, 63 deletions
diff --git a/ChangeLog b/ChangeLog
index abe3b9b..6fc7aef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2006-03-17 Boris Kolpackov <boris@kolpackov.net>
+
+ * dep.h (struct dep): Add the stem field.
+ * misc.c (alloc_dep, free_dep): New functions.
+ (copy_dep_chain): Copy stem.
+ (free_dep_chain): Use free_dep.
+ * read.c (record_files): Store stem in the dependency line.
+ * file.c (expand_deps): Use stem stored in the dependency line. Use
+ free_dep_chain instead of free_ns_chain.
+ * implicit.c (pattern_search): Use alloc_dep and free_dep.
+ * read.c (read_all_makefiles, eval_makefile, eval): Ditto.
+ * main.c (main, handle_non_switch_argument): Ditto.
+ * remake.c (check_dep): Ditto.
+ * rule.c (convert_suffix_rule, freerule): Ditto.
+
2006-03-14 Paul D. Smith <psmith@gnu.org>
* expand.c (variable_append): Instead of appending everything then
@@ -155,7 +170,7 @@
2006-02-08 Boris Kolpackov <boris@kolpackov.net>
- * job.h (struct child): Add dontcare bitfield.
+ * job.h (struct child): Add the dontcare bitfield.
* job.c (new_job): Cache dontcare flag.
* job.c (reap_children): Use cached dontcare flag instead of the
one in struct file. Fixes Savannah bug #15641.
diff --git a/dep.h b/dep.h
index aafadb2..f0923cc 100644
--- a/dep.h
+++ b/dep.h
@@ -28,7 +28,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
/* Structure representing one dependency of a file.
Each struct file's `deps' points to a chain of these,
- chained through the `next'.
+ chained through the `next'. `stem' is the stem for this
+ dep line of static pattern rule or NULL.
Note that the first two words of this match a struct nameseq. */
@@ -36,6 +37,7 @@ struct dep
{
struct dep *next;
char *name;
+ char *stem;
struct file *file;
unsigned int changed : 8;
unsigned int ignore_mtime : 1;
@@ -72,6 +74,8 @@ extern struct nameseq *ar_glob PARAMS ((char *arname, char *member_pattern, unsi
extern char *dep_name ();
#endif
+extern struct dep *alloc_dep PARAMS ((void));
+extern void free_dep PARAMS ((struct dep *d));
extern struct dep *copy_dep_chain PARAMS ((const struct dep *d));
extern void free_dep_chain PARAMS ((struct dep *d));
extern void free_ns_chain PARAMS ((struct nameseq *n));
diff --git a/file.c b/file.c
index a0e8222..90dd123 100644
--- a/file.c
+++ b/file.c
@@ -460,6 +460,7 @@ expand_deps (struct file *f)
{
struct dep *d;
struct dep *old = f->deps;
+ char *file_stem = f->stem;
unsigned int last_dep_has_cmds = f->updating;
int initialized = 0;
@@ -491,20 +492,29 @@ expand_deps (struct file *f)
free (d->name);
d->name = savestring (buffer, o - buffer);
- d->staticpattern = 0;
+ d->staticpattern = 0; /* Clear staticpattern so that we don't
+ re-expand %s below. */
}
/* We are going to do second expansion so initialize file variables
- for the file. */
+ for the file. Since the stem for static pattern rules comes from
+ individual dep lines, we will temporarily set f->stem to d->stem.
+ */
if (!initialized)
{
initialize_file_variables (f, 0);
initialized = 1;
}
+ if (d->stem != 0)
+ f->stem = d->stem;
+
set_file_variables (f);
p = variable_expand_for_file (d->name, f);
+
+ if (d->stem != 0)
+ f->stem = file_stem;
}
/* Parse the prerequisites. */
@@ -527,12 +537,12 @@ expand_deps (struct file *f)
/* We have to handle empty stems specially, because that
would be equivalent to $(patsubst %,dp->name,) which
will always be empty. */
- if (f->stem[0] == '\0')
+ if (d->stem[0] == '\0')
/* This needs memmove() in ISO C. */
bcopy (percent+1, percent, strlen (percent));
else
{
- char *o = patsubst_expand (buffer, f->stem, pattern,
+ char *o = patsubst_expand (buffer, d->stem, pattern,
dp->name, pattern+1,
percent+1);
if (o == buffer)
@@ -552,7 +562,9 @@ expand_deps (struct file *f)
dp = new = new->next;
else
dp = dl->next = dp->next;
- free ((char *)df);
+ /* @@ Are we leaking df->name here? */
+ df->name = 0;
+ free_dep (df);
continue;
}
}
@@ -604,7 +616,7 @@ expand_deps (struct file *f)
}
}
- free_ns_chain ((struct nameseq *) old);
+ free_dep_chain (old);
}
/* For each dependency of each file, make the `struct dep' point
diff --git a/implicit.c b/implicit.c
index 8085ea1..a5d3700 100644
--- a/implicit.c
+++ b/implicit.c
@@ -802,8 +802,7 @@ pattern_search (struct file *file, int archive,
while (dep != 0)
{
struct dep *next = dep->next;
- free (dep->name);
- free ((char *)dep);
+ free_dep (dep);
dep = next;
}
file->deps = 0;
@@ -862,15 +861,12 @@ pattern_search (struct file *file, int archive,
}
}
- dep = (struct dep *) xmalloc (sizeof (struct dep));
+ dep = alloc_dep ();
dep->ignore_mtime = d->ignore_mtime;
- dep->staticpattern = 0;
- dep->need_2nd_expansion = 0;
s = d->name; /* Hijacking the name. */
d->name = 0;
if (recursions == 0)
{
- dep->name = 0;
dep->file = lookup_file (s);
if (dep->file == 0)
/* enter_file consumes S's storage. */
@@ -883,9 +879,8 @@ pattern_search (struct file *file, int archive,
else
{
dep->name = s;
- dep->file = 0;
- dep->changed = 0;
}
+
if (d->intermediate_file == 0 && tryrules[foundrule]->terminal)
{
/* If the file actually existed (was not an intermediate file),
@@ -943,11 +938,9 @@ pattern_search (struct file *file, int archive,
if (i != matches[foundrule])
{
struct file *f;
- struct dep *new = (struct dep *) xmalloc (sizeof (struct dep));
+ struct dep *new = alloc_dep ();
+
/* GKM FIMXE: handle '|' here too */
- new->ignore_mtime = 0;
- new->staticpattern = 0;
- new->need_2nd_expansion = 0;
new->name = p = (char *) xmalloc (rule->lens[i] + fullstemlen + 1);
bcopy (rule->targets[i], p,
rule->suffixes[i] - rule->targets[i] - 1);
diff --git a/main.c b/main.c
index a645e44..53a2e2e 100644
--- a/main.c
+++ b/main.c
@@ -1850,7 +1850,7 @@ main (int argc, char **argv, char **envp)
last->next = d->next;
/* Free the storage. */
- free ((char *) d);
+ free_dep (d);
d = last == 0 ? read_makefiles : last->next;
@@ -2172,12 +2172,7 @@ main (int argc, char **argv, char **envp)
}
}
- goals = (struct dep *) xmalloc (sizeof (struct dep));
- goals->next = 0;
- goals->name = 0;
- goals->ignore_mtime = 0;
- goals->staticpattern = 0;
- goals->need_2nd_expansion = 0;
+ goals = alloc_dep ();
goals->file = default_goal_file;
}
}
@@ -2333,19 +2328,16 @@ handle_non_switch_argument (char *arg, int env)
if (goals == 0)
{
- goals = (struct dep *) xmalloc (sizeof (struct dep));
+ goals = alloc_dep ();
lastgoal = goals;
}
else
{
- lastgoal->next = (struct dep *) xmalloc (sizeof (struct dep));
+ lastgoal->next = alloc_dep ();
lastgoal = lastgoal->next;
}
- lastgoal->name = 0;
+
lastgoal->file = f;
- lastgoal->ignore_mtime = 0;
- lastgoal->staticpattern = 0;
- lastgoal->need_2nd_expansion = 0;
{
/* Add this target name to the MAKECMDGOALS variable. */
diff --git a/misc.c b/misc.c
index 43df799..082bcc6 100644
--- a/misc.c
+++ b/misc.c
@@ -479,6 +479,32 @@ find_next_token (char **ptr, unsigned int *lengthptr)
return p;
}
+
+/* Allocate a new `struct dep' with all fields initialized to 0. */
+
+struct dep *
+alloc_dep ()
+{
+ struct dep *d = (struct dep *) xmalloc (sizeof (struct dep));
+ bzero ((char *) d, sizeof (struct dep));
+ return d;
+}
+
+
+/* Free `struct dep' along with `name' and `stem'. */
+
+void
+free_dep (struct dep *d)
+{
+ if (d->name != 0)
+ free (d->name);
+
+ if (d->stem != 0)
+ free (d->stem);
+
+ free ((char *)d);
+}
+
/* Copy a chain of `struct dep', making a new chain
with the same contents as the old one. */
@@ -493,8 +519,12 @@ copy_dep_chain (const struct dep *d)
{
c = (struct dep *) xmalloc (sizeof (struct dep));
bcopy ((char *) d, (char *) c, sizeof (struct dep));
+
if (c->name != 0)
c->name = xstrdup (c->name);
+ if (c->stem != 0)
+ c->stem = xstrdup (c->stem);
+
c->next = 0;
if (firstnew == 0)
firstnew = lastnew = c;
@@ -516,14 +546,12 @@ free_dep_chain (struct dep *d)
{
struct dep *df = d;
d = d->next;
-
- free (df->name);
- free ((char *)df);
+ free_dep (df);
}
}
/* Free a chain of `struct nameseq'. Each nameseq->name is freed
- as well. Can be used on `struct dep' chains.*/
+ as well. For `struct dep' chains use free_dep_chain. */
void
free_ns_chain (struct nameseq *n)
diff --git a/read.c b/read.c
index 0c78c7f..f6e8986 100644
--- a/read.c
+++ b/read.c
@@ -248,13 +248,9 @@ read_all_makefiles (char **makefiles)
tail = tail->next;
for (p = default_makefiles; *p != 0; ++p)
{
- struct dep *d = (struct dep *) xmalloc (sizeof (struct dep));
- d->name = 0;
+ struct dep *d = alloc_dep ();
d->file = enter_file (*p);
d->file->dontcare = 1;
- d->ignore_mtime = 0;
- d->staticpattern = 0;
- d->need_2nd_expansion = 0;
/* Tell update_goal_chain to bail out as soon as this file is
made, and main not to die if we can't make this file. */
d->changed = RM_DONTCARE;
@@ -366,18 +362,14 @@ eval_makefile (char *filename, int flags)
}
/* Add FILENAME to the chain of read makefiles. */
- deps = (struct dep *) xmalloc (sizeof (struct dep));
+ deps = alloc_dep ();
deps->next = read_makefiles;
read_makefiles = deps;
- deps->name = 0;
deps->file = lookup_file (filename);
if (deps->file == 0)
deps->file = enter_file (xstrdup (filename));
filename = deps->file->name;
deps->changed = flags;
- deps->ignore_mtime = 0;
- deps->staticpattern = 0;
- deps->need_2nd_expansion = 0;
if (flags & RM_DONTCARE)
deps->file->dontcare = 1;
@@ -1177,14 +1169,8 @@ eval (struct ebuffer *ebuf, int set_default)
if (beg <= end && *beg != '\0')
{
/* Put all the prerequisites here; they'll be parsed later. */
- deps = (struct dep *) xmalloc (sizeof (struct dep));
- deps->next = 0;
+ deps = alloc_dep ();
deps->name = savestring (beg, end - beg + 1);
- deps->file = 0;
- deps->changed = 0;
- deps->ignore_mtime = 0;
- deps->staticpattern = 0;
- deps->need_2nd_expansion = 0;
}
else
deps = 0;
@@ -2111,7 +2097,10 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
pattern_percent+1, percent+1);
f->stem = savestring (buffer, o - buffer);
if (this)
- this->staticpattern = 1;
+ {
+ this->staticpattern = 1;
+ this->stem = xstrdup (f->stem);
+ }
}
/* Free name if not needed further. */
diff --git a/remake.c b/remake.c
index da231b4..2dfade3 100644
--- a/remake.c
+++ b/remake.c
@@ -994,13 +994,13 @@ check_dep (struct file *file, unsigned int depth,
if (lastd == 0)
{
file->deps = d->next;
- free ((char *) d);
+ free_dep (d);
d = file->deps;
}
else
{
lastd->next = d->next;
- free ((char *) d);
+ free_dep (d);
d = lastd->next;
}
continue;
diff --git a/rule.c b/rule.c
index 527b5b0..e988db5 100644
--- a/rule.c
+++ b/rule.c
@@ -201,12 +201,8 @@ convert_suffix_rule (char *target, char *source, struct commands *cmds)
depname = xmalloc (1 + len + 1);
depname[0] = '%';
bcopy (source, depname + 1, len + 1);
- deps = (struct dep *) xmalloc (sizeof (struct dep));
- deps->next = 0;
+ deps = alloc_dep ();
deps->name = depname;
- deps->ignore_mtime = 0;
- deps->staticpattern = 0;
- deps->need_2nd_expansion = 0;
}
create_pattern_rule (names, percents, 0, deps, cmds, 0);
@@ -428,7 +424,8 @@ freerule (struct rule *rule, struct rule *lastrule)
t = dep->next;
/* We might leak dep->name here, but I'm not sure how to fix this: I
think that pointer might be shared (e.g., in the file hash?) */
- free ((char *) dep);
+ dep->name = 0; /* Make sure free_dep does not free name. */
+ free_dep (dep);
dep = t;
}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 05dfaec..67cf900 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2006-03-17 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/statipattrules: Add tests for bug #16053.
+
2006-03-09 Paul Smith <psmith@gnu.org>
* scripts/features/escape: Use "pre:" not "p:" to avoid conflicts
diff --git a/tests/scripts/features/statipattrules b/tests/scripts/features/statipattrules
index 429b56a..3f363de 100644
--- a/tests/scripts/features/statipattrules
+++ b/tests/scripts/features/statipattrules
@@ -67,4 +67,45 @@ foo.baz: ;@:
',
'', '');
+
+# TEST #6: make sure the second stem does not overwrite the first
+# perprerequisite's stem (Savannah bug #16053).
+#
+run_make_test('
+all.foo.bar: %.foo.bar: %.one
+
+all.foo.bar: %.bar: %.two
+
+all.foo.bar:
+ @echo $*
+ @echo $^
+
+.DEFAULT:;@:
+',
+'',
+'all.foo
+all.one all.foo.two');
+
+
+# TEST #7: make sure the second stem does not overwrite the first
+# perprerequisite's stem when second expansion is enabled
+# (Savannah bug #16053).
+#
+run_make_test('
+.SECONDEXPANSION:
+
+all.foo.bar: %.foo.bar: %.one $$*-one
+
+all.foo.bar: %.bar: %.two $$*-two
+
+all.foo.bar:
+ @echo $*
+ @echo $^
+
+.DEFAULT:;@:
+',
+'',
+'all.foo
+all.one all-one all.foo.two all.foo-two');
+
1;