summaryrefslogtreecommitdiff
path: root/file.c
diff options
context:
space:
mode:
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;
}
}
}