Fixed Savannah bug #16053.

This commit is contained in:
Boris Kolpackov 2006-03-17 14:24:20 +00:00
parent 50eb3cf5e5
commit 22886f8a74
11 changed files with 138 additions and 63 deletions

View file

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

6
dep.h
View file

@ -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));

24
file.c
View file

@ -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

View file

@ -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);

18
main.c
View file

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

36
misc.c
View file

@ -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)

25
read.c
View file

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

View file

@ -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;

9
rule.c
View file

@ -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;
}

View file

@ -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

View file

@ -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;