diff --git a/bootstrap.conf b/bootstrap.conf index 7c4c9ab7..bd37f1b9 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -49,5 +49,6 @@ fdl findprog-in getloadavg host-cpu-c-abi +mempcpy strerror make-glob" diff --git a/src/config.h-vms.template b/src/config.h-vms.template index 7cd393db..62daac2d 100644 --- a/src/config.h-vms.template +++ b/src/config.h-vms.template @@ -324,6 +324,9 @@ this program. If not, see . */ /* Define to 1 if you have the header file. */ /* #undef HAVE_MEMORY_H */ +/* Define to 1 if you have the `mempcpy' function. */ +/* #undef HAVE_MEMPCPY */ + /* Define to 1 if you have the header file. */ /* #undef HAVE_NDIR_H */ diff --git a/src/config.h.W32.template b/src/config.h.W32.template index f847be87..bd3b4763 100644 --- a/src/config.h.W32.template +++ b/src/config.h.W32.template @@ -177,6 +177,9 @@ this program. If not, see . */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 +/* Define to 1 if you have the `mempcpy' function. */ +/* #undef HAVE_MEMPCPY */ + /* Define to 1 if you have the 'mkstemp' function. */ /* #undef HAVE_MKSTEMP */ diff --git a/src/implicit.c b/src/implicit.c index 3c7fba76..7505ff69 100644 --- a/src/implicit.c +++ b/src/implicit.c @@ -54,6 +54,9 @@ try_implicit_rule (struct file *file, unsigned int depth) _("Looking for archive-member implicit rule for '%s'.\n")); if (pattern_search (file, 1, depth, 0)) return 1; + DBS (DB_IMPLICIT, + (_("No archive-member implicit rule found for '%s'.\n"), + file->name)); } #endif @@ -309,7 +312,9 @@ pattern_search (struct file *file, int archive, don't use it here. */ if (rule->in_use) { - DBS (DB_IMPLICIT, (_("Avoiding implicit rule recursion.\n"))); + DBS (DB_IMPLICIT, + (_("Avoiding implicit rule recursion for rule '%s'.\n"), + get_rule_defn (rule))); continue; } @@ -432,6 +437,8 @@ pattern_search (struct file *file, int archive, for (intermed_ok = 0; intermed_ok < 2; ++intermed_ok) { pat = deplist; + if (intermed_ok) + DBS (DB_IMPLICIT, (_("Trying harder.\n"))); /* Try each pattern rule till we find one that applies. If it does, expand its dependencies (as substituted) and chain them in DEPS. */ @@ -480,6 +487,10 @@ pattern_search (struct file *file, int archive, } } + DBS (DB_IMPLICIT, + (_("Trying pattern rule '%s' with stem '%.*s'.\n"), + get_rule_defn (rule), (int) stemlen, stem)); + if (stemlen + (check_lastslash ? pathlen : 0) > GET_PATH_MAX) { DBS (DB_IMPLICIT, (_("Stem too long: '%s%.*s'.\n"), @@ -488,9 +499,6 @@ pattern_search (struct file *file, int archive, continue; } - DBS (DB_IMPLICIT, (_("Trying pattern rule with stem '%.*s'.\n"), - (int) stemlen, stem)); - if (!check_lastslash) { memcpy (stem_str, stem, stemlen); @@ -712,9 +720,10 @@ pattern_search (struct file *file, int archive, /* Go through the nameseq and handle each as a prereq name. */ for (d = dl; d != 0; d = d->next) { - struct dep *expl_d; - struct file *f; + struct file *df; int is_rule = d->name == dep_name (dep); + int explicit; + int exists = -1; if (file_impossible_p (d->name)) { @@ -723,9 +732,11 @@ pattern_search (struct file *file, int archive, second pass either since we know that will fail. */ DBS (DB_IMPLICIT, (is_rule - ? _("Rejecting impossible rule prerequisite '%s'.\n") - : _("Rejecting impossible implicit prerequisite '%s'.\n"), - d->name)); + ? _("Rejecting rule '%s' due to impossible rule" + " prerequisite '%s'.\n") + : _("Rejecting rule '%s' due to impossible implicit" + " prerequisite '%s'.\n"), + get_rule_defn (rule), d->name)); tryrules[ri].rule = 0; failed = 1; @@ -742,38 +753,41 @@ pattern_search (struct file *file, int archive, ? _("Trying rule prerequisite '%s'.\n") : _("Trying implicit prerequisite '%s'.\n"), d->name)); - /* If this prereq is also explicitly mentioned for FILE, - skip all tests below since it must be built no matter - which implicit rule we choose. */ + df = lookup_file (d->name); - for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next) - if (streq (dep_name (expl_d), d->name)) - break; - if (expl_d != 0) - { - (pat++)->name = d->name; - continue; - } - - /* f->is_explicit is set when this file is mentioned - explicitly on some other rule. d->is_explicit is set when - this file is mentioned explicitly on this rule. */ - f = lookup_file (d->name); - if (f && !f->is_explicit && !d->is_explicit) - f->intermediate = 1; - - /* The DEP->changed flag says that this dependency resides - in a nonexistent directory. So we normally can skip - looking for the file. However, if CHECK_LASTSLASH is - set, then the dependency file we are actually looking for - is in a different directory (the one gotten by prepending - FILENAME's directory), so it might actually exist. */ - - /* @@ dep->changed check is disabled. */ - if (f /* || ((!dep->changed || check_lastslash) */ - || file_exists_p (d->name)) + /* If we found a file for the dep, set its intermediate flag. + df->is_explicit is set when the dep file is mentioned + explicitly on some other rule. d->is_explicit is set when + the dep file is mentioned explicitly on this rule. E.g.: + %.x : %.y ; ... + then: + one.x: + one.y: # df->is_explicit + vs. + one.x: one.y # d->is_explicit + */ + if (df && !df->is_explicit && !d->is_explicit) + df->intermediate = 1; + + /* If the pattern prereq is also explicitly mentioned for + FILE, skip all tests below since it must be built no + matter which implicit rule we choose. */ + explicit = df || (exists = file_exists_p (d->name)) != 0; + if (!explicit) + for (struct dep *dp = file->deps; dp != 0; dp = dp->next) + if (streq (d->name, dep_name (dp))) + { + explicit = 1; + break; + } + + if (explicit) { (pat++)->name = d->name; + if (exists > 0) + DBS (DB_IMPLICIT, (_("Found '%s'.\n"), d->name)); + else + DBS (DB_IMPLICIT, (_("'%s' ought to exist.\n"), d->name)); continue; } @@ -785,7 +799,7 @@ pattern_search (struct file *file, int archive, if (vname) { DBS (DB_IMPLICIT, - (_("Found prerequisite '%s' as VPATH '%s'\n"), + (_("Found prerequisite '%s' as VPATH '%s'.\n"), d->name, vname)); (pat++)->name = d->name; continue; @@ -833,6 +847,14 @@ pattern_search (struct file *file, int archive, /* A dependency of this rule does not exist. Therefore, this rule fails. */ + if (intermed_ok) + DBS (DB_IMPLICIT, + (_("Rejecting rule '%s' " + "due to impossible prerequisite '%s'.\n"), + get_rule_defn (rule), d->name)); + else + DBS (DB_IMPLICIT, (_("Not found '%s'.\n"), d->name)); + failed = 1; break; } @@ -1042,5 +1064,11 @@ pattern_search (struct file *file, int archive, free (tryrules); free (deplist); + if (rule) + DBS (DB_IMPLICIT, (_("Found implicit rule '%s' for '%s'.\n"), + get_rule_defn (rule), filename)); + else + DBS (DB_IMPLICIT, (_("No implicit rule found for '%s'.\n"), filename)); + return rule != 0; } diff --git a/src/job.c b/src/job.c index ee59b95b..54fadf00 100644 --- a/src/job.c +++ b/src/job.c @@ -922,7 +922,7 @@ reap_children (int block, int err) to fork/exec but I don't want to bother with that. Just do the best we can. */ - EINTRLOOP(r, stat(c->cmd_name, &st)); + EINTRLOOP(r, stat (c->cmd_name, &st)); if (r < 0) e = strerror (errno); else if (S_ISDIR(st.st_mode) || !(st.st_mode & S_IXUSR)) diff --git a/src/makeint.h b/src/makeint.h index eb78b402..15dc07d5 100644 --- a/src/makeint.h +++ b/src/makeint.h @@ -671,6 +671,11 @@ int strncasecmp (const char *s1, const char *s2, int n); # endif #endif +#if !HAVE_MEMPCPY +/* Create our own, in misc.c */ +void *mempcpy (void *dest, const void *src, size_t n); +#endif + #define OUTPUT_SYNC_NONE 0 #define OUTPUT_SYNC_LINE 1 #define OUTPUT_SYNC_TARGET 2 diff --git a/src/misc.c b/src/misc.c index 3072952c..f400135b 100644 --- a/src/misc.c +++ b/src/misc.c @@ -846,3 +846,11 @@ get_path_max (void) return value; } #endif + +#if !HAVE_MEMPCPY +void * +mempcpy (void *dest, const void *src, size_t n) +{ + return (char *) memcpy (dest, src, n) + n; +} +#endif diff --git a/src/remake.c b/src/remake.c index 9b71ce61..bd6d8e51 100644 --- a/src/remake.c +++ b/src/remake.c @@ -509,10 +509,7 @@ update_file_1 (struct file *file, unsigned int depth) if (!file->phony && file->cmds == 0 && !file->tried_implicit) { - if (try_implicit_rule (file, depth)) - DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n")); - else - DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n")); + try_implicit_rule (file, depth); file->tried_implicit = 1; } if (file->cmds == 0 && !file->is_target @@ -1045,10 +1042,7 @@ check_dep (struct file *file, unsigned int depth, if (!file->phony && file->cmds == 0 && !file->tried_implicit) { - if (try_implicit_rule (file, depth)) - DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n")); - else - DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n")); + try_implicit_rule (file, depth); file->tried_implicit = 1; } if (file->cmds == 0 && !file->is_target diff --git a/src/rule.c b/src/rule.c index 7efca58b..16aec7fe 100644 --- a/src/rule.c +++ b/src/rule.c @@ -59,6 +59,55 @@ struct file *suffix_file; /* Maximum length of a suffix. */ static size_t maxsuffix; + +/* Return the rule definition: space separated rule targets, followed by + either a colon or two colons in the case of a terminal rule, followed by + space separated rule prerequisites, followed by a pipe, followed by + order-only prerequisites, if present. */ + +const char *get_rule_defn (struct rule *r) +{ + if (r->_defn == NULL) + { + unsigned int k; + ptrdiff_t len = 8; // Reserve for ":: ", " | " and the null terminator. + char *p; + const char *sep = ""; + const struct dep *dep, *ood = 0; + + for (k = 0; k < r->num; ++k) + len += r->lens[k] + 1; // Add one for a space. + + for (dep = r->deps; dep; dep = dep->next) + len += strlen (dep_name (dep)) + 1; // Add one for a space. + + p = r->_defn = xmalloc (len); + for (k = 0; k < r->num; ++k, sep = " ") + p = mempcpy (mempcpy (p, sep, strlen (sep)), r->targets[k], r->lens[k]); + *p++ = ':'; + if (r->terminal) + *p++ = ':'; + + /* Copy all normal dependencies; note any order-only deps. */ + for (dep = r->deps; dep; dep = dep->next) + if (dep->ignore_mtime == 0) + p = mempcpy (mempcpy (p, " ", 1), dep_name (dep), + strlen (dep_name (dep))); + else if (ood == 0) + ood = dep; + + /* Copy order-only deps, if we have any. */ + for (sep = " | "; ood; ood = ood->next, sep = " ") + if (ood->ignore_mtime) + p = mempcpy (mempcpy (p, sep, strlen (sep)), dep_name (ood), + strlen (dep_name (ood))); + *p = '\0'; + assert (p - r->_defn < len); + } + + return r->_defn; +} + /* Compute the maximum dependency length and maximum number of dependencies of all implicit rules. Also sets the subdir flag for a rule when appropriate, @@ -398,6 +447,7 @@ install_pattern_rule (struct pspec *p, int terminal) r->targets = xmalloc (sizeof (const char *)); r->suffixes = xmalloc (sizeof (const char *)); r->lens = xmalloc (sizeof (unsigned int)); + r->_defn = NULL; r->lens[0] = (unsigned int) strlen (p->target); r->targets[0] = p->target; @@ -439,6 +489,7 @@ freerule (struct rule *rule, struct rule *lastrule) free ((void *)rule->targets); free ((void *)rule->suffixes); free (rule->lens); + free ((void *) rule->_defn); /* We can't free the storage for the commands because there are ways that they could be in more than one place: @@ -488,6 +539,7 @@ create_pattern_rule (const char **targets, const char **target_percents, r->targets = targets; r->suffixes = target_percents; r->lens = xmalloc (n * sizeof (unsigned int)); + r->_defn = NULL; for (i = 0; i < n; ++i) { @@ -505,17 +557,8 @@ create_pattern_rule (const char **targets, const char **target_percents, static void /* Useful to call from gdb. */ print_rule (struct rule *r) { - unsigned int i; - - for (i = 0; i < r->num; ++i) - { - fputs (r->targets[i], stdout); - putchar ((i + 1 == r->num) ? ':' : ' '); - } - if (r->terminal) - putchar (':'); - - print_prereqs (r->deps); + fputs (get_rule_defn (r), stdout); + putchar ('\n'); if (r->cmds != 0) print_commands (r->cmds); diff --git a/src/rule.h b/src/rule.h index 120a6827..c18ae518 100644 --- a/src/rule.h +++ b/src/rule.h @@ -25,6 +25,7 @@ struct rule const char **suffixes; /* Suffixes (after '%') of each target. */ struct dep *deps; /* Dependencies of the rule. */ struct commands *cmds; /* Commands to execute. */ + char *_defn; /* Definition of the rule. */ unsigned short num; /* Number of targets. */ char terminal; /* If terminal (double-colon). */ char in_use; /* If in use by a parent pattern_search. */ @@ -54,4 +55,5 @@ void install_pattern_rule (struct pspec *p, int terminal); void create_pattern_rule (const char **targets, const char **target_percents, unsigned short num, int terminal, struct dep *deps, struct commands *commands, int override); +const char *get_rule_defn (struct rule *rule); void print_rule_data_base (void);