summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog36
-rw-r--r--NEWS24
-rw-r--r--dep.h4
-rw-r--r--doc/make.texi62
-rw-r--r--file.c228
-rw-r--r--filedef.h10
-rw-r--r--implicit.c14
-rw-r--r--main.c9
-rw-r--r--make.h2
-rw-r--r--misc.c17
-rw-r--r--read.c130
-rw-r--r--rule.c5
-rw-r--r--tests/ChangeLog12
-rwxr-xr-xtests/run_make_tests.pl7
-rw-r--r--tests/scripts/features/order_only104
-rw-r--r--tests/scripts/features/se_explicit24
-rw-r--r--tests/scripts/features/se_statpat4
-rw-r--r--tests/scripts/features/statipattrules65
-rw-r--r--tests/scripts/misc/general425
-rw-r--r--tests/scripts/variables/automatic7
20 files changed, 460 insertions, 329 deletions
diff --git a/ChangeLog b/ChangeLog
index 83e1fa8..1aadcd6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2005-10-24 Paul D. Smith <psmith@gnu.org>
+
+ Make secondary expansion optional: its enabled by declaring the
+ special target .SECONDEXPANSION.
+
+ * NEWS: Update information on second expansion capabilities.
+ * doc/make.texi (Secondary Expansion): Document the
+ .SECONDEXPANSION special target and its behavior.
+ * dep.h (struct dep): Add a flag STATICPATTERN, set to true if the
+ prerequisite list was found in a static pattern rule.
+ (free_dep_chain): Declare a prototype.
+ * file.c (parse_prereqs): New function: break out some complexity
+ from expand_deps().
+ (expand_deps): If we aren't doing second expansion, replace % with
+ the stem for static pattern rules. Call the new function.
+ * filedef.h (parse_prereqs): Declare a prototype.
+ * implicit.c (pattern_search): Initialize the new staticpattern
+ field.
+ * main.c (second_expansion): Declare a global variable to remember
+ if the special target has been seen. Initialize the new
+ staticpattern field for prerequisites.
+ * make.h: Extern for second_expansion.
+ * misc.c (free_dep_chain): New function: frees a struct dep list.
+ * read.c (read_all_makefiles): Initialize the staticpattern field.
+ (eval_makefile): Ditto.
+ (record_files): Check for the .SECONDEXPANSION target and set
+ second_expansion global if it's found.
+ Use the new free_dep_chain() instead of doing it by hand.
+ Set the staticpattern field for prereqs of static pattern targets.
+
+2005-10-16 Paul D. Smith <psmith@gnu.org>
+
+ * main.c (main): Set CURDIR to be a file variable instead of a
+ default, so that values of CURDIR inherited from the environment
+ won't override the make value.
+
2005-09-26 Paul D. Smith <psmith@gnu.org>
* job.c (construct_command_argv_internal): If the line is empty
diff --git a/NEWS b/NEWS
index 5adb7a9..e6b3322 100644
--- a/NEWS
+++ b/NEWS
@@ -18,15 +18,21 @@ Version 3.81beta3
* WARNING: Backward-incompatibility!
GNU make now implements a generic "second expansion" feature on the
- prerequisites of both explicit and implicit (pattern) rules. After
- all rules have been parsed the prerequisites are expanded again, this
- time with all the automatic variables in scope. This means that in
- addition to using standard SysV $$@ in prerequisites lists, you can
- also use complex functions such as $$(notdir $$@) etc. This behavior
- applies to implicit rules, as well, where the second expansion occurs
- after the rule is matched. However, this means that you need to
- double-quote any "$" in your filenames; instead of "foo: boo$$bar" you
- now must write "foo: foo$$$$bar".
+ prerequisites of both explicit and implicit (pattern) rules. In order
+ to enable this feature, the special target '.SECONDEXPANSION' must be
+ defined before the first target which takes advantage of it. If this
+ feature is enabled then after all rules have been parsed the
+ prerequisites are expanded again, this time with all the automatic
+ variables in scope. This means that in addition to using standard
+ SysV $$@ in prerequisites lists, you can also use complex functions
+ such as $$(notdir $$@) etc. This behavior applies to implicit rules,
+ as well, where the second expansion occurs when the rule is matched.
+ However, this means that you need to double-quote any "$" in your
+ filenames; instead of "foo: boo$$bar" you now must write "foo:
+ foo$$$$bar". Note that the SysV $$@ etc. feature, which used to be
+ available by default, is now ONLY available when the .SECONDEXPANSION
+ target is defined. If your makefiles take advantage of this SysV
+ feature you will need to update them.
* WARNING: Backward-incompatibility!
In order to comply with POSIX, the way in which GNU make processes
diff --git a/dep.h b/dep.h
index 7e6a853..1be8db6 100644
--- a/dep.h
+++ b/dep.h
@@ -40,6 +40,7 @@ struct dep
struct file *file;
unsigned int changed : 8;
unsigned int ignore_mtime : 1;
+ unsigned int staticpattern : 1;
unsigned int need_2nd_expansion : 1;
};
@@ -72,7 +73,8 @@ extern struct nameseq *ar_glob PARAMS ((char *arname, char *member_pattern, unsi
extern char *dep_name ();
#endif
-extern struct dep *copy_dep_chain 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));
extern struct dep *read_all_makefiles PARAMS ((char **makefiles));
extern int eval_buffer PARAMS ((char *buffer));
diff --git a/doc/make.texi b/doc/make.texi
index 526aec6..cc5f061 100644
--- a/doc/make.texi
+++ b/doc/make.texi
@@ -1612,22 +1612,31 @@ static pattern rules, and simple prerequisite definitions.
@cindex secondary expansion
@cindex expansion, secondary
+@findex .SECONDEXPANSION
In the previous section we learned that GNU @code{make} works in two
distinct phases: a read-in phase and a target-update phase
-(@pxref{Reading Makefiles, , How @code{make} Reads a Makefile}).
-There is an extra wrinkle that comes in between those two phases,
-right at the end of the read-in phase: at that time, all the
-prerequisites of all of the targets are expanded a @emph{second time}.
-In most circumstances this secondary expansion will have no effect,
-since all variable and function references will have been expanded
-during the initial parsing of the makefiles. In order to take
-advantage of the secondary expansion phase of the parser, then, it's
-necessary to @emph{escape} the variable or function reference in the
-makefile. In this case the first expansion merely un-escapes the
-reference but doesn't expand it, and expansion is left to the
-secondary expansion phase. For example, consider this makefile:
-
-@example
+(@pxref{Reading Makefiles, , How @code{make} Reads a Makefile}). GNU
+make also has the ability to enable a @emph{second expansion} of the
+prerequisites (only) for some or all targets defined in the makefile.
+In order for this second expansion to occur, the special target
+@code{.SECONDEXPANSION} must be defined before the first prerequisite
+list that makes use of this feature.
+
+If that special target is defined then in between the two phases
+mentioned above, right at the end of the read-in phase, all the
+prerequisites of the targets defined after the special target are
+expanded a @emph{second time}. In most circumstances this secondary
+expansion will have no effect, since all variable and function
+references will have been expanded during the initial parsing of the
+makefiles. In order to take advantage of the secondary expansion
+phase of the parser, then, it's necessary to @emph{escape} the
+variable or function reference in the makefile. In this case the
+first expansion merely un-escapes the reference but doesn't expand it,
+and expansion is left to the secondary expansion phase. For example,
+consider this makefile:
+
+@example
+.SECONDEXPANSION:
ONEVAR = onefile
TWOVAR = twofile
myfile: $(ONEVAR) $$(TWOVAR)
@@ -1651,6 +1660,7 @@ appear, unescaped, in the prerequisites list. One difference becomes
apparent if the variables are reset; consider this example:
@example
+.SECONDEXPANSION:
AVAR = top
onefile: $(AVAR)
twofile: $$(AVAR)
@@ -1670,10 +1680,11 @@ target. This means that you can use variables such as @code{$@@},
expected values, just as in the command script. All you have to do is
defer the expansion by escaping the @code{$}. Also, secondary
expansion occurs for both explicit and implicit (pattern) rules.
-Knowing this, the possible uses for this feature are almost endless.
-For example:
+Knowing this, the possible uses for this feature increase
+dramatically. For example:
@example
+.SECONDEXPANSION:
main_OBJS := main.o try.o test.o
lib_OBJS := lib.o api.o
@@ -1694,6 +1705,7 @@ You can also mix functions here, as long as they are properly escaped:
main_SRCS := main.c try.c test.c
lib_SRCS := lib.c api.c
+.SECONDEXPANSION:
main lib: $$(patsubst %.c,%.o,$$($$@@_SRCS))
@end example
@@ -1723,6 +1735,8 @@ the same target (@code{$$+} with repetitions and @code{$$^}
without). The following example will help illustrate these behaviors:
@example
+.SECONDEXPANSION:
+
foo: foo.1 bar.1 $$< $$^ $$+ # line #1
foo: foo.2 bar.2 $$< $$^ $$+ # line #2
@@ -1763,6 +1777,8 @@ target pattern. The value of the automatic variables is derived in
the same fashion as for static pattern rules. As an example:
@example
+.SECONDEXPANSION:
+
foo: bar
foo foz: fo%: bo%
@@ -1781,6 +1797,8 @@ expansion) to all the patterns in the prerequisites list. As an
example:
@example
+.SECONDEXPANSION:
+
/tmp/foo.o:
%.o: $$(addsuffix /%.c,foo bar) foo.h
@@ -2880,6 +2898,18 @@ intermediate files, except that they are never automatically deleted.
as secondary (i.e., no target is removed because it is considered
intermediate).
+@findex .SECONDEXPANSION
+@item .SECONDEXPANSION
+
+If @code{.SECONDEXPANSION} is mentioned as a target anwyeren in the
+makefile, then all prerequisite lists defined @emph{after} it appears
+will be expanded a second time after all makefiles have been read in.
+@xref{Secondary Expansion, ,Secondary Expansion}.
+
+The prerequisites of the special target @code{.SUFFIXES} are the list
+of suffixes to be used in checking for suffix rules.
+@xref{Suffix Rules, , Old-Fashioned Suffix Rules}.
+
@findex .DELETE_ON_ERROR
@item .DELETE_ON_ERROR
@cindex removing targets on failure
diff --git a/file.c b/file.c
index 9f9ddb5..ddec34d 100644
--- a/file.c
+++ b/file.c
@@ -405,6 +405,42 @@ remove_intermediates (int sig)
}
}
+struct dep *
+parse_prereqs (char *p)
+{
+ struct dep *new = (struct dep *)
+ multi_glob (parse_file_seq (&p, '|', sizeof (struct dep), 1),
+ sizeof (struct dep));
+
+ if (*p)
+ {
+ /* Files that follow '|' are "order-only" prerequisites that satisfy the
+ dependency by existing: their modification times are irrelevant. */
+ struct dep *ood;
+
+ ++p;
+ ood = (struct dep *)
+ multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
+ sizeof (struct dep));
+
+ if (! new)
+ new = ood;
+ else
+ {
+ struct dep *dp;
+ for (dp = new; dp->next != NULL; dp = dp->next)
+ ;
+ dp->next = ood;
+ }
+
+ for (; ood != NULL; ood = ood->next)
+ ood->ignore_mtime = 1;
+ }
+
+ return new;
+}
+
+
/* Set the intermediate flag. */
static void
@@ -418,8 +454,7 @@ set_intermediate (const void *item)
static void
expand_deps (struct file *f)
{
- struct dep *d, *d1;
- struct dep *new = 0;
+ struct dep *d;
struct dep *old = f->deps;
unsigned int last_dep_has_cmds = f->updating;
int initialized = 0;
@@ -429,97 +464,138 @@ expand_deps (struct file *f)
for (d = old; d != 0; d = d->next)
{
- if (d->name != 0)
- {
- char *p;
+ struct dep *new, *d1;
+ char *p;
- /* If we need a second expansion on these, set up the file
- variables, etc. It takes a lot of extra memory and processing
- to do this, so only do it if it's needed. */
- if (! d->need_2nd_expansion)
- p = d->name;
- else
+ if (! d->name)
+ continue;
+
+ /* Create the dependency list.
+ If we're not doing 2nd expansion, then it's just the name. */
+ if (! d->need_2nd_expansion)
+ p = d->name;
+ else
+ {
+ /* If it's from a static pattern rule, convert the patterns into
+ "$*" so they'll expand properly. */
+ if (d->staticpattern)
{
- /* We are going to do second expansion so initialize file
- variables for the file. */
- if (!initialized)
- {
- initialize_file_variables (f, 0);
- initialized = 1;
- }
+ char *o;
+ char *buffer = variable_expand ("");
- set_file_variables (f);
+ o = subst_expand (buffer, d->name, "%", "$*", 1, 2, 0);
- p = variable_expand_for_file (d->name, f);
+ free (d->name);
+ d->name = savestring (buffer, o - buffer);
+ d->staticpattern = 0;
}
- /* Parse the dependencies. */
- new = (struct dep *)
- multi_glob (
- parse_file_seq (&p, '|', sizeof (struct dep), 1),
- sizeof (struct dep));
-
- if (*p)
+ /* We are going to do second expansion so initialize file variables
+ for the file. */
+ if (!initialized)
{
- /* Files that follow '|' are special prerequisites that
- need only exist in order to satisfy the dependency.
- Their modification times are irrelevant. */
- struct dep **d_ptr;
+ initialize_file_variables (f, 0);
+ initialized = 1;
+ }
- for (d_ptr = &new; *d_ptr; d_ptr = &(*d_ptr)->next)
- ;
- ++p;
+ set_file_variables (f);
- *d_ptr = (struct dep *)
- multi_glob (
- parse_file_seq (&p, '\0', sizeof (struct dep), 1),
- sizeof (struct dep));
+ p = variable_expand_for_file (d->name, f);
+ }
- for (d1 = *d_ptr; d1 != 0; d1 = d1->next)
- d1->ignore_mtime = 1;
- }
+ /* Parse the prerequisites. */
+ new = parse_prereqs (p);
- /* Enter them as files. */
- for (d1 = new; d1 != 0; d1 = d1->next)
+ /* If this dep list was from a static pattern rule, expand the %s. We
+ use patsubst_expand to translate the prerequisites' patterns into
+ plain prerequisite names. */
+ if (new && d->staticpattern)
+ {
+ char *pattern = "%";
+ char *buffer = variable_expand ("");
+ struct dep *dp = new, *dl = 0;
+
+ while (dp != 0)
{
- d1->file = lookup_file (d1->name);
- if (d1->file == 0)
- d1->file = enter_file (d1->name);
- else
- free (d1->name);
- d1->name = 0;
- d1->need_2nd_expansion = 0;
+ char *percent = find_percent (dp->name);
+ if (percent)
+ {
+ /* 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')
+ /* This needs memmove() in ISO C. */
+ bcopy (percent+1, percent, strlen (percent));
+ else
+ {
+ char *o = patsubst_expand (buffer, f->stem, pattern,
+ dp->name, pattern+1,
+ percent+1);
+ if (o == buffer)
+ dp->name[0] = '\0';
+ else
+ {
+ free (dp->name);
+ dp->name = savestring (buffer, o - buffer);
+ }
+ }
+
+ /* If the name expanded to the empty string, ignore it. */
+ if (dp->name[0] == '\0')
+ {
+ struct dep *df = dp;
+ if (dp == new)
+ dp = new = new->next;
+ else
+ dp = dl->next = dp->next;
+ free ((char *)df);
+ continue;
+ }
+ }
+ dl = dp;
+ dp = dp->next;
}
+ }
+
+ /* Enter them as files. */
+ for (d1 = new; d1 != 0; d1 = d1->next)
+ {
+ d1->file = lookup_file (d1->name);
+ if (d1->file == 0)
+ d1->file = enter_file (d1->name);
+ else
+ free (d1->name);
+ d1->name = 0;
+ d1->staticpattern = 0;
+ d1->need_2nd_expansion = 0;
+ }
+
+ /* Add newly parsed deps to f->deps. If this is the last dependency
+ line and this target has commands then put it in front so the
+ last dependency line (the one with commands) ends up being the
+ first. This is important because people expect $< to hold first
+ prerequisite from the rule with commands. If it is not the last
+ dependency line or the rule does not have commands then link it
+ at the end so it appears in makefile order. */
- /* Add newly parsed deps to f->deps. If this is the last
- dependency line and this target has commands then put
- it in front so the last dependency line (the one with
- commands) ends up being the first. This is important
- because people expect $< to hold first prerequisite
- from the rule with commands. If it is not the last
- dependency line or the rule does not have commands
- then link it at the end so it appears in makefile
- order. */
-
- if (new != 0)
+ if (new != 0)
+ {
+ if (d->next == 0 && last_dep_has_cmds)
{
- if (d->next == 0 && last_dep_has_cmds)
- {
- struct dep **d_ptr;
- for (d_ptr = &new; *d_ptr; d_ptr = &(*d_ptr)->next)
- ;
+ struct dep **d_ptr;
+ for (d_ptr = &new; *d_ptr; d_ptr = &(*d_ptr)->next)
+ ;
- *d_ptr = f->deps;
- f->deps = new;
- }
- else
- {
- struct dep **d_ptr;
- for (d_ptr = &f->deps; *d_ptr; d_ptr = &(*d_ptr)->next)
- ;
+ *d_ptr = f->deps;
+ f->deps = new;
+ }
+ else
+ {
+ struct dep **d_ptr;
+ for (d_ptr = &f->deps; *d_ptr; d_ptr = &(*d_ptr)->next)
+ ;
- *d_ptr = new;
- }
+ *d_ptr = new;
}
}
}
diff --git a/filedef.h b/filedef.h
index ea5c5bd..ae71110 100644
--- a/filedef.h
+++ b/filedef.h
@@ -84,17 +84,16 @@ struct file
unsigned int is_target:1; /* Nonzero if file is described as target. */
unsigned int cmd_target:1; /* Nonzero if file was given on cmd line. */
unsigned int phony:1; /* Nonzero if this is a phony file
- i.e., a dependency of .PHONY. */
+ i.e., a prerequisite of .PHONY. */
unsigned int intermediate:1;/* Nonzero if this is an intermediate file. */
- /* Nonzero, for an intermediate file,
- means remove_intermediates should not delete it. */
- unsigned int secondary:1;
+ unsigned int secondary:1; /* Nonzero means remove_intermediates should
+ not delete it. */
unsigned int dontcare:1; /* Nonzero if no complaint is to be made if
this target cannot be remade. */
unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name. */
unsigned int pat_searched:1;/* Nonzero if we already searched for
pattern-specific variables. */
- unsigned int considered:1; /* equal to `considered' if file has been
+ unsigned int considered:1; /* equal to 'considered' if file has been
considered on current scan of goal chain */
};
@@ -105,6 +104,7 @@ extern char **default_goal_name;
extern struct file *lookup_file PARAMS ((char *name));
extern struct file *enter_file PARAMS ((char *name));
+extern struct dep *parse_prereqs PARAMS ((char *prereqs));
extern void remove_intermediates PARAMS ((int sig));
extern void snap_deps PARAMS ((void));
extern void rename_file PARAMS ((struct file *file, char *name));
diff --git a/implicit.c b/implicit.c
index cae4c40..57510d7 100644
--- a/implicit.c
+++ b/implicit.c
@@ -477,12 +477,6 @@ pattern_search (struct file *file, int archive,
/* Try each dependency; see if it "exists". */
- /* @@ There is always only one dep line for any given implicit
- rule. So the loop is not necessary. Can rule->deps be 0?
-
- Watch out for conversion of suffix rules to implicit rules.
- */
-
for (dep = rule->deps; dep != 0; dep = dep->next)
{
unsigned int len;
@@ -513,7 +507,7 @@ pattern_search (struct file *file, int archive,
we just replace % with the stem value, later, when we do
the second expansion, we will re-expand this stem value
once again. This is not good especially if you have
- certain characters in your setm (like $).
+ certain characters in your stem (like $).
Instead, we will replace % with $* and allow the second
expansion to take care of it for us. This way (since $*
@@ -836,6 +830,7 @@ pattern_search (struct file *file, int archive,
dep = (struct dep *) xmalloc (sizeof (struct dep));
dep->ignore_mtime = d->ignore_mtime;
+ dep->staticpattern = 0;
dep->need_2nd_expansion = 0;
s = d->name; /* Hijacking the name. */
d->name = 0;
@@ -917,6 +912,7 @@ pattern_search (struct file *file, int archive,
struct dep *new = (struct dep *) xmalloc (sizeof (struct 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,
@@ -928,12 +924,12 @@ pattern_search (struct file *file, int archive,
rule->lens[i] - (rule->suffixes[i] - rule->targets[i]) + 1);
new->file = enter_file (new->name);
new->next = file->also_make;
-
+
/* Set precious flag. */
f = lookup_file (rule->targets[i]);
if (f && f->precious)
new->file->precious = 1;
-
+
file->also_make = new;
}
diff --git a/main.c b/main.c
index 37c6ef6..8c52724 100644
--- a/main.c
+++ b/main.c
@@ -486,6 +486,11 @@ struct file *default_file;
int posix_pedantic;
+/* Nonzero if we have seen the '.SECONDEXPANSION' target.
+ This turns on secondary expansion of prerequisites. */
+
+int second_expansion;
+
/* Nonzero if we have seen the `.NOTPARALLEL' target.
This turns off parallel builds for this invocation of make. */
@@ -1437,7 +1442,7 @@ main (int argc, char **argv, char **envp)
starting_directory = current_directory;
}
- (void) define_variable ("CURDIR", 6, current_directory, o_default, 0);
+ (void) define_variable ("CURDIR", 6, current_directory, o_file, 0);
/* Read any stdin makefiles into temporary files. */
@@ -2174,6 +2179,7 @@ main (int argc, char **argv, char **envp)
goals->next = 0;
goals->name = 0;
goals->ignore_mtime = 0;
+ goals->staticpattern = 0;
goals->need_2nd_expansion = 0;
goals->file = default_goal_file;
}
@@ -2341,6 +2347,7 @@ handle_non_switch_argument (char *arg, int env)
lastgoal->name = 0;
lastgoal->file = f;
lastgoal->ignore_mtime = 0;
+ lastgoal->staticpattern = 0;
lastgoal->need_2nd_expansion = 0;
{
diff --git a/make.h b/make.h
index 8636928..9724780 100644
--- a/make.h
+++ b/make.h
@@ -500,7 +500,7 @@ extern int print_data_base_flag, question_flag, touch_flag, always_make_flag;
extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
extern int print_version_flag, print_directory_flag, check_symlink_flag;
extern int warn_undefined_variables_flag, posix_pedantic, not_parallel;
-extern int clock_skew_detected, rebuilding_makefiles;
+extern int second_expansion, clock_skew_detected, rebuilding_makefiles;
/* can we run commands via 'sh -c xxx' or must we use batch files? */
extern int batch_mode_shell;
diff --git a/misc.c b/misc.c
index ac50270..6f12683 100644
--- a/misc.c
+++ b/misc.c
@@ -485,7 +485,7 @@ find_next_token (char **ptr, unsigned int *lengthptr)
with the same contents as the old one. */
struct dep *
-copy_dep_chain (struct dep *d)
+copy_dep_chain (const struct dep *d)
{
register struct dep *c;
struct dep *firstnew = 0;
@@ -508,6 +508,21 @@ copy_dep_chain (struct dep *d)
return firstnew;
}
+
+/* Free a chain of 'struct dep'. */
+
+void
+free_dep_chain (struct dep *d)
+{
+ while (d != 0)
+ {
+ struct dep *df = d;
+ d = d->next;
+
+ free (df->name);
+ free ((char *)df);
+ }
+}
/* Free a chain of `struct nameseq'. Each nameseq->name is freed
as well. Can be used on `struct dep' chains.*/
diff --git a/read.c b/read.c
index 0f07ee9..bad07eb 100644
--- a/read.c
+++ b/read.c
@@ -258,6 +258,7 @@ read_all_makefiles (char **makefiles)
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. */
@@ -378,6 +379,7 @@ eval_makefile (char *filename, int flags)
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;
@@ -1160,7 +1162,7 @@ eval (struct ebuffer *ebuf, int set_default)
pattern_percent = find_percent (pattern);
if (pattern_percent == 0)
fatal (fstart, _("target pattern contains no `%%'"));
- free((char *)target);
+ free ((char *)target);
}
else
pattern = 0;
@@ -1172,21 +1174,12 @@ eval (struct ebuffer *ebuf, int set_default)
if (beg <= end && *beg != '\0')
{
- char *top;
- const char *fromp = beg;
-
- /* Make a copy of the dependency string. Note if we find '$'. */
- deps = (struct dep*) xmalloc (sizeof (struct dep));
+ /* Put all the prerequisites here; they'll be parsed later. */
+ deps = (struct dep *) xmalloc (sizeof (struct dep));
deps->next = 0;
- deps->name = top = (char *) xmalloc (end - beg + 2);
+ deps->name = xstrdup (beg);
+ deps->staticpattern = 0;
deps->need_2nd_expansion = 0;
- while (fromp <= end)
- {
- if (*fromp == '$')
- deps->need_2nd_expansion = 1;
- *(top++) = *(fromp++);
- }
- *top = '\0';
deps->file = 0;
}
else
@@ -1918,19 +1911,19 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
{
char *name = filenames->name;
struct file *f;
- struct dep *d;
- struct dep *this;
+ struct dep *this = 0;
char *implicit_percent;
nextf = filenames->next;
free (filenames);
- /* Check for .POSIX. We used to do this in snap_deps() but that's not
- good enough: it doesn't happen until after the makefile is read,
- which means we cannot use its value during parsing. */
+ /* Check for special targets. Do it here instead of, say, snap_deps()
+ so that we can immediately use the value. */
if (streq (name, ".POSIX"))
posix_pedantic = 1;
+ else if (streq (name, ".SECONDEXPANSION"))
+ second_expansion = 1;
implicit_percent = find_percent (name);
implicit |= implicit_percent != 0;
@@ -1965,40 +1958,19 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
continue;
}
- /* If there are multiple filenames, copy the chain DEPS
- for all but the last one. It is not safe for the same deps
- to go in more than one place in the database. */
- this = nextf != 0 ? copy_dep_chain (deps) : deps;
-
- if (pattern != 0)
- {
- /* If this is an extended static rule:
- `targets: target%pattern: dep%pattern; cmds',
- translate each dependency pattern into a plain filename
- using the target pattern and this target's name. */
- if (!pattern_matches (pattern, pattern_percent, name))
- {
- /* Give a warning if the rule is meaningless. */
- error (flocp,
- _("target `%s' doesn't match the target pattern"), name);
- this = 0;
- }
- else
- /* We use subst_expand to do the work of translating % to $* in
- the dependency line. */
-
- if (this != 0 && find_percent (this->name) != 0)
- {
- char *o;
- char *buffer = variable_expand ("");
-
- o = subst_expand (buffer, this->name, "%", "$*", 1, 2, 0);
-
- free (this->name);
- this->name = savestring (buffer, o - buffer);
- this->need_2nd_expansion = 1;
- }
- }
+ /* If this is a static pattern rule:
+ `targets: target%pattern: dep%pattern; cmds',
+ make sure the pattern matches this target name. */
+ if (pattern && !pattern_matches (pattern, pattern_percent, name))
+ error (flocp, _("target `%s' doesn't match the target pattern"), name);
+ else if (deps)
+ {
+ /* If there are multiple filenames, copy the chain DEPS for all but
+ the last one. It is not safe for the same deps to go in more
+ than one place in the database. */
+ this = nextf != 0 ? copy_dep_chain (deps) : deps;
+ this->need_2nd_expansion = second_expansion;
+ }
if (!two_colon)
{
@@ -2038,18 +2010,11 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
if (cmds != 0)
f->cmds = cmds;
- /* Defining .SUFFIXES with no dependencies
- clears out the list of suffixes. */
+ /* Defining .SUFFIXES with no dependencies clears out the list of
+ suffixes. */
if (f == suffix_file && this == 0)
{
- d = f->deps;
- while (d != 0)
- {
- struct dep *nextd = d->next;
- free (d->name);
- free ((char *)d);
- d = nextd;
- }
+ free_dep_chain (f->deps);
f->deps = 0;
}
else if (this != 0)
@@ -2109,38 +2074,40 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
}
else
{
- /* Double-colon. Make a new record
- even if the file already has one. */
+ /* Double-colon. Make a new record even if there already is one. */
f = lookup_file (name);
+
/* Check for both : and :: rules. Check is_target so
we don't lose on default suffix rules or makefiles. */
if (f != 0 && f->is_target && !f->double_colon)
fatal (flocp,
_("target file `%s' has both : and :: entries"), f->name);
f = enter_file (name);
- /* If there was an existing entry and it was a double-colon
- entry, enter_file will have returned a new one, making it the
- prev pointer of the old one, and setting its double_colon
- pointer to the first one. */
+ /* If there was an existing entry and it was a double-colon entry,
+ enter_file will have returned a new one, making it the prev
+ pointer of the old one, and setting its double_colon pointer to
+ the first one. */
if (f->double_colon == 0)
- /* This is the first entry for this name, so we must
- set its double_colon pointer to itself. */
+ /* This is the first entry for this name, so we must set its
+ double_colon pointer to itself. */
f->double_colon = f;
f->is_target = 1;
f->deps = this;
f->cmds = cmds;
}
- /* If this is a static pattern rule, set the file's stem to
- the part of its name that matched the `%' in the pattern,
- so you can use $* in the commands. */
- if (pattern != 0)
+ /* If this is a static pattern rule, set the stem to the part of its
+ name that matched the `%' in the pattern, so you can use $* in the
+ commands. */
+ if (pattern)
{
static char *percent = "%";
char *buffer = variable_expand ("");
char *o = patsubst_expand (buffer, name, pattern, percent,
pattern_percent+1, percent+1);
f->stem = savestring (buffer, o - buffer);
+ if (this)
+ this->staticpattern = 1;
}
/* Free name if not needed further. */
@@ -2152,9 +2119,9 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
}
/* If this target is a default target, update DEFAULT_GOAL_FILE. */
- if (strcmp (*default_goal_name, name) == 0
+ if (streq (*default_goal_name, name)
&& (default_goal_file == 0
- || strcmp (default_goal_file->name, name) != 0))
+ || ! streq (default_goal_file->name, name)))
default_goal_file = f;
}
@@ -2162,6 +2129,9 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
{
targets[target_idx] = 0;
target_percents[target_idx] = 0;
+ deps->need_2nd_expansion = second_expansion;
+ /* We set this to indicate we've not yet parsed the prereq string. */
+ deps->staticpattern = 1;
create_pattern_rule (targets, target_percents, two_colon, deps, cmds, 1);
free ((char *) target_percents);
}
@@ -2291,9 +2261,9 @@ find_percent (char *pattern)
struct nameseq *
parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
{
- register struct nameseq *new = 0;
- register struct nameseq *new1, *lastnew1;
- register char *p = *stringp;
+ struct nameseq *new = 0;
+ struct nameseq *new1, *lastnew1;
+ char *p = *stringp;
char *q;
char *name;
diff --git a/rule.c b/rule.c
index 152e7e6..235e470 100644
--- a/rule.c
+++ b/rule.c
@@ -206,6 +206,7 @@ convert_suffix_rule (char *target, char *source, struct commands *cmds)
deps->next = 0;
deps->name = depname;
deps->ignore_mtime = 0;
+ deps->staticpattern = 0;
deps->need_2nd_expansion = 0;
}
@@ -476,8 +477,8 @@ create_pattern_rule (char **targets, char **target_percents,
int terminal, struct dep *deps,
struct commands *commands, int override)
{
- register struct rule *r = (struct rule *) xmalloc (sizeof (struct rule));
- register unsigned int max_targets, i;
+ unsigned int max_targets, i;
+ struct rule *r = (struct rule *) xmalloc (sizeof (struct rule));
r->cmds = commands;
r->deps = deps;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 594361f..c936301 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,15 @@
+2005-10-24 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/misc/general4: Test '$$' in prerequisites list.
+ * scripts/features/statipattrules: Rewrite to use run_make_test().
+ Add various static pattern info.
+ * scripts/features/se_statpat: Enable .SECONDEXPANSION target.
+ * scripts/features/se_explicit: Add tests for handling '$$' in
+ prerequisite lists with and without setting .SECONDEXPANSION.
+ * scripts/features/order_only: Convert to run_make_test().
+ * run_make_tests.pl (set_more_defaults): If we can't get the value
+ of $(MAKE) from make, then fatal immediately.
+
2005-08-31 Paul D. Smith <psmith@gnu.org>
* run_make_tests.pl (get_this_pwd): Require the POSIX module (in
diff --git a/tests/run_make_tests.pl b/tests/run_make_tests.pl
index 66be520..d51b72a 100755
--- a/tests/run_make_tests.pl
+++ b/tests/run_make_tests.pl
@@ -253,8 +253,11 @@ sub set_more_defaults
# Find the full pathname of Make. For DOS systems this is more
# complicated, so we ask make itself.
- $make_path = `sh -c 'echo "all:;\@echo \\\$(MAKE)" | $make_path -f-'`;
- chop $make_path;
+ my $mk = `sh -c 'echo "all:;\@echo \\\$(MAKE)" | $make_path -f-'`;
+ chop $mk;
+ $mk or die "FATAL ERROR: Cannot determine the value of \$(MAKE):\n
+'echo \"all:;\@echo \\\$(MAKE)\" | $make_path -f-' failed!\n";
+ $make_path = $mk;
print "Make\t= `$make_path'\n" if $debug;
$string = `$make_path -v -f /dev/null 2> /dev/null`;
diff --git a/tests/scripts/features/order_only b/tests/scripts/features/order_only
index 82a7253..4ebdc2b 100644
--- a/tests/scripts/features/order_only
+++ b/tests/scripts/features/order_only
@@ -5,9 +5,18 @@ $details = "\
Create makefiles with various combinations of normal and order-only
prerequisites and ensure they behave properly. Test the \$| variable.";
-open(MAKEFILE,"> $makefile");
+# TEST #0 -- Basics
-print MAKEFILE <<'EOF';
+run_make_test('
+%r: | baz ; @echo $< $^ $|
+bar: foo
+foo:;@:
+baz:;@:',
+ '', "foo foo baz\n");
+
+# TEST #1 -- First try: the order-only prereqs need to be built.
+
+run_make_test(q!
foo: bar | baz
@echo '$$^ = $^'
@echo '$$| = $|'
@@ -16,34 +25,19 @@ foo: bar | baz
.PHONY: baz
bar baz:
- touch $@
-EOF
-
-close(MAKEFILE);
-
-
-# TEST #1 -- just the syntax
-
-&run_make_with_options($makefile, "", &get_logfile);
-$answer = "touch bar\ntouch baz\n\$^ = bar\n\$| = baz\ntouch foo\n";
-&compare_output($answer,&get_logfile(1));
+ touch $@!,
+ '', "touch bar\ntouch baz\n\$^ = bar\n\$| = baz\ntouch foo\n");
# TEST #2 -- now we do it again: baz is PHONY but foo should _NOT_ be updated
-&run_make_with_options($makefile, "", &get_logfile);
-$answer = "touch baz\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, '', "touch baz\n");
unlink(qw(foo bar baz));
-# Test prereqs that are both order and non-order
-
-$makefile2 = &get_tmpfile;
-
-open(MAKEFILE,"> $makefile2");
+# TEST #3 -- Make sure the order-only prereq was promoted to normal.
-print MAKEFILE <<'EOF';
+run_make_test(q!
foo: bar | baz
@echo '$$^ = $^'
@echo '$$| = $|'
@@ -54,33 +48,21 @@ foo: baz
.PHONY: baz
bar baz:
- touch $@
-EOF
-
-close(MAKEFILE);
-
-# TEST #3 -- Make sure the order-only prereq was promoted to normal.
-
-&run_make_with_options($makefile2, "", &get_logfile);
-$answer = "touch bar\ntouch baz\n\$^ = bar baz\n\$| = \ntouch foo\n";
-&compare_output($answer,&get_logfile(1));
+ touch $@!,
+ '', "touch bar\ntouch baz\n\$^ = bar baz\n\$| = \ntouch foo\n");
# TEST #4 -- now we do it again
-&run_make_with_options($makefile2, "", &get_logfile);
-$answer = "touch baz\n\$^ = bar baz\n\$| = \ntouch foo\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, '', "touch baz\n\$^ = bar baz\n\$| = \ntouch foo\n");
unlink(qw(foo bar baz));
# Test empty normal prereqs
-$makefile3 = &get_tmpfile;
-
-open(MAKEFILE,"> $makefile3");
+# TEST #5 -- make sure the parser was correct.
-print MAKEFILE <<'EOF';
+run_make_test(q!
foo:| baz
@echo '$$^ = $^'
@echo '$$| = $|'
@@ -89,33 +71,20 @@ foo:| baz
.PHONY: baz
baz:
- touch $@
-EOF
-
-close(MAKEFILE);
-
-# TEST #5 -- make sure the parser was correct.
-
-&run_make_with_options($makefile3, "", &get_logfile);
-$answer = "touch baz\n\$^ = \n\$| = baz\ntouch foo\n";
-&compare_output($answer,&get_logfile(1));
-
+ touch $@!,
+ '', "touch baz\n\$^ = \n\$| = baz\ntouch foo\n");
# TEST #6 -- now we do it again: this time foo won't be built
-&run_make_with_options($makefile3, "", &get_logfile);
-$answer = "touch baz\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, '', "touch baz\n");
unlink(qw(foo baz));
# Test order-only in pattern rules
-$makefile4 = &get_tmpfile;
-
-open(MAKEFILE,"> $makefile4");
+# TEST #7 -- make sure the parser was correct.
-print MAKEFILE <<'EOF';
+run_make_test(q!
%.w : %.x | baz
@echo '$$^ = $^'
@echo '$$| = $|'
@@ -125,22 +94,13 @@ all: foo.w
.PHONY: baz
foo.x baz:
- touch $@
-EOF
-
-close(MAKEFILE);
-
-# TEST #7 -- make sure the parser was correct.
-
-&run_make_with_options($makefile4, "", &get_logfile);
-$answer = "touch foo.x\ntouch baz\n\$^ = foo.x\n\$| = baz\ntouch foo.w\n";
-&compare_output($answer,&get_logfile(1));
+ touch $@!,
+ '',
+ "touch foo.x\ntouch baz\n\$^ = foo.x\n\$| = baz\ntouch foo.w\n");
# TEST #8 -- now we do it again: this time foo.w won't be built
-&run_make_with_options($makefile4, "", &get_logfile);
-$answer = "touch baz\n";
-&compare_output($answer,&get_logfile(1));
+run_make_test(undef, '', "touch baz\n");
unlink(qw(foo.w foo.x baz));
@@ -151,8 +111,8 @@ run_make_test('
%r: | baz ; @echo $< $^ $|
bar: foo
foo:;@:
-baz:;@:
-', '', "foo foo baz\n");
+baz:;@:',
+ '', "foo foo baz\n");
1;
diff --git a/tests/scripts/features/se_explicit b/tests/scripts/features/se_explicit
index 0e696be..01860a9 100644
--- a/tests/scripts/features/se_explicit
+++ b/tests/scripts/features/se_explicit
@@ -3,9 +3,29 @@ $description = "Test second expansion in ordinary rules.";
$details = "";
-# Test #1: automatic variables.
+# TEST #0: Test handing of '$' in prerequisites with and without second
+# expansion.
+
+run_make_test(q!
+ifdef SE
+ .SECONDEXPANSION:
+endif
+foo$$bar: bar$$baz bar$$biz ; @echo '$@ : $^'
+PRE = one two
+bar$$baz: $$(PRE)
+baraz: $$(PRE)
+PRE = three four
+.DEFAULT: ; @echo '$@'
+!,
+ '',
+ "\$\nbar\$biz\nfoo\$bar : bar\$baz bar\$biz");
+
+run_make_test(undef, 'SE=1', "three\nfour\nbariz\nfoo\$bar : baraz bariz");
+
+# TEST #1: automatic variables.
#
run_make_test('
+.SECONDEXPANSION:
.DEFAULT: ; @echo $@
foo: bar baz
@@ -41,6 +61,7 @@ buz.5
# Test #2: target/pattern -specific variables.
#
run_make_test('
+.SECONDEXPANSION:
.DEFAULT: ; @echo $@
foo.x: $$a $$b
@@ -59,6 +80,7 @@ baz
# Test #3: order of prerequisites.
#
run_make_test('
+.SECONDEXPANSION:
.DEFAULT: ; @echo $@
all: foo bar baz
diff --git a/tests/scripts/features/se_statpat b/tests/scripts/features/se_statpat
index 3c54622..096b240 100644
--- a/tests/scripts/features/se_statpat
+++ b/tests/scripts/features/se_statpat
@@ -6,6 +6,7 @@ $details = "";
# Test #1: automatic variables.
#
run_make_test('
+.SECONDEXPANSION:
.DEFAULT: ; @echo $@
foo.a foo.b: foo.%: bar.% baz.%
@@ -41,6 +42,7 @@ a.6
# Test #2: target/pattern -specific variables.
#
run_make_test('
+.SECONDEXPANSION:
.DEFAULT: ; @echo $@
foo.x foo.y: foo.%: $$(%_a) $$($$*_b)
@@ -60,6 +62,7 @@ baz
# Test #3: order of prerequisites.
#
run_make_test('
+.SECONDEXPANSION:
.DEFAULT: ; @echo $@
all: foo.a bar.a baz.a
@@ -106,6 +109,7 @@ baz.a.2
# Test #4: Make sure stem triple-expansion does not happen.
#
run_make_test('
+.SECONDEXPANSION:
foo$$bar: f%r: % $$*.1
@echo \'$*\'
diff --git a/tests/scripts/features/statipattrules b/tests/scripts/features/statipattrules
index 0ca2bb7..429b56a 100644
--- a/tests/scripts/features/statipattrules
+++ b/tests/scripts/features/statipattrules
@@ -9,79 +9,62 @@ name and the target name with .c. It also does the same thing
for another target filtered with .elc and creates a command
to emacs a .el file";
-open(MAKEFILE,"> $makefile");
-print MAKEFILE <<'EOF';
-files = foo.elc bar.o lose.o
-
-$(filter %.o,$(files)): %.o: %.c ; @echo CC -c $(CFLAGS) $< -o $@
-
-$(filter %.elc,$(files)): %.elc: %.el ; @echo emacs $<
-EOF
-close(MAKEFILE);
-
-
&touch('bar.c', 'lose.c');
-# TEST #1
+# TEST #0
# -------
-&run_make_with_options($makefile, '', &get_logfile);
-$answer = "CC -c bar.c -o bar.o\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test('
+files = foo.elc bar.o lose.o
+
+$(filter %.o,$(files)): %.o: %.c ; @echo CC -c $(CFLAGS) $< -o $@
+$(filter %.elc,$(files)): %.elc: %.el ; @echo emacs $<
+',
+ '',
+ 'CC -c bar.c -o bar.o');
-# TEST #2
+# TEST #1
# -------
-&run_make_with_options($makefile, 'lose.o', &get_logfile);
-$answer = "CC -c lose.c -o lose.o\n";
-&compare_output($answer, &get_logfile(1));
+run_make_test(undef, 'lose.o', 'CC -c lose.c -o lose.o');
-# TEST #3
+# TEST #2
# -------
&touch("foo.el");
-&run_make_with_options($makefile, 'foo.elc', &get_logfile);
-$answer = "emacs foo.el\n";
-&compare_output($answer, &get_logfile(1));
-
+run_make_test(undef, 'foo.elc', 'emacs foo.el');
+# Clean up after the first tests.
unlink('foo.el', 'bar.c', 'lose.c');
-# TEST #4 -- PR/1670: don't core dump on invalid static pattern rules
+# TEST #3 -- PR/1670: don't core dump on invalid static pattern rules
# -------
-$makefile2 = &get_tmpfile;
-open(MAKEFILE, "> $makefile2");
-print MAKEFILE "foo: foo%: % ; \@echo \$@\n";
-close(MAKEFILE);
+run_make_test('
+.DEFAULT: ; @echo $@
+foo: foo%: % %.x % % % y.% % ; @echo $@
+',
+ '', ".x\ny.\nfoo");
-&run_make_with_options($makefile2, '', &get_logfile);
-$answer = "foo\n";
-&compare_output($answer, &get_logfile(1));
-# TEST #5 -- bug #12180: core dump on a stat pattern rule with an empty
+# TEST #4 -- bug #12180: core dump on a stat pattern rule with an empty
# prerequisite list.
-#
run_make_test('
foo.x bar.x: %.x : ; @echo $@
',
-'',
-'foo.x
-');
+ '', 'foo.x');
-# TEST #6 -- bug #13881: double colon static pattern rule does not
+# TEST #5 -- bug #13881: double colon static pattern rule does not
# substitute %.
-#
run_make_test('
foo.bar:: %.bar: %.baz
foo.baz: ;@:
',
-'',
-'');
+ '', '');
1;
diff --git a/tests/scripts/misc/general4 b/tests/scripts/misc/general4
index 63320e2..0b5c94a 100644
--- a/tests/scripts/misc/general4
+++ b/tests/scripts/misc/general4
@@ -5,8 +5,7 @@ This tests random features of make's algorithms, often somewhat obscure,
which have either broken at some point in the past or seem likely to
break.";
-open(MAKEFILE,"> $makefile");
-print MAKEFILE <<'EOF';
+run_make_test('
# Make sure that subdirectories built as prerequisites are actually handled
# properly.
@@ -16,13 +15,8 @@ dir/subdir: ; @echo mkdir -p dir/subdir
dir/subdir/file.b: dir/subdir ; @echo touch dir/subdir/file.b
-dir/subdir/%.a: dir/subdir/%.b ; @echo cp $< $@
-EOF
-close(MAKEFILE);
-
-&run_make_with_options($makefile,"",&get_logfile);
-$answer = "mkdir -p dir/subdir\ntouch dir/subdir/file.b\ncp dir/subdir/file.b dir/subdir/file.a\n";
-&compare_output($answer,&get_logfile(1));
+dir/subdir/%.a: dir/subdir/%.b ; @echo cp $< $@',
+ '', "mkdir -p dir/subdir\ntouch dir/subdir/file.b\ncp dir/subdir/file.b dir/subdir/file.a\n");
# Test implicit rules
@@ -47,4 +41,17 @@ fox: baz
'done bar');
unlink('bar');
+
+# Test implicit rules with '$' in the name (see se_implicit)
+
+run_make_test(q!
+%.foo : baz$$bar ; @echo 'done $<'
+%.foo : bar$$baz ; @echo 'done $<'
+test.foo:
+fox: baz
+.DEFAULT baz$$bar bar$$baz: ; @echo '$@'
+!,
+ '',
+ 'done bar');
+
1;
diff --git a/tests/scripts/variables/automatic b/tests/scripts/variables/automatic
index 484cd16..dc08bd7 100644
--- a/tests/scripts/variables/automatic
+++ b/tests/scripts/variables/automatic
@@ -27,7 +27,7 @@ $(dir)/bar.y baz.z : ; touch $@
EOF
close(MAKEFILE);
-# TEST #1 -- simple test
+# TEST #0 -- simple test
# -------
# Touch these into the past
@@ -46,7 +46,7 @@ touch $dir/foo.x\n";
unlink(qw(foo.x bar.y baz.z));
-# TEST #2 -- test the SysV emulation of $$@ etc.
+# TEST #1 -- test the SysV emulation of $$@ etc.
# -------
$makefile2 = &get_tmpfile;
@@ -54,6 +54,7 @@ $makefile2 = &get_tmpfile;
open(MAKEFILE, "> $makefile2");
print MAKEFILE "dir = $dir\n";
print MAKEFILE <<'EOF';
+.SECONDEXPANSION:
.SUFFIXES:
.DEFAULT: ; @echo '$@'
@@ -78,7 +79,7 @@ $answer = ".x\n$dir/x.z.x\nx\n\$@.x\n$dir.x\nx.z.x\n.y\n$dir/y.z.y\n\y\n\$@.y\n$
$answer = "$dir/biz.x\n$dir.x\nbiz.x\n";
&compare_output($answer, &get_logfile(1));
-# TEST #3 -- test for Savannah bug #12320.
+# TEST #2 -- test for Savannah bug #12320.
#
run_make_test('
.SUFFIXES: .b .src