summaryrefslogtreecommitdiff
path: root/file.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2005-10-24 13:01:39 +0000
committerPaul Smith <psmith@gnu.org>2005-10-24 13:01:39 +0000
commit11095a90f120545c915c92b8ebf48f04723d1837 (patch)
tree73dba88903ea90cdac930057fe8619a8a04fb869 /file.c
parent66459baee27374577d32a78564604ad64228f71d (diff)
downloadgunmake-11095a90f120545c915c92b8ebf48f04723d1837.tar.gz
Make second expansion optional (partial implementation).
I decided this feature was too impacting to make the permanent default behavior. This set of changes makes the default behavior of make the old behavior (no second expansion). If you want second expansion, you must define the .SECONDEXPANSION: special target before the first target that needs it. This set of changes ONLY fixes explicit and static pattern rules to work like this. Implicit rules still have second expansion enabled all the time: I'll work on that next. Note that there is still a backward-incompatibility: now to get the old SysV behavior using $$@ etc. in the prerequisites list you need to set .SECONDEXPANSION: as well.
Diffstat (limited to 'file.c')
-rw-r--r--file.c228
1 files changed, 152 insertions, 76 deletions
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;
}
}
}