aboutsummaryrefslogtreecommitdiff
path: root/miscutils/make.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--miscutils/make.c316
1 files changed, 237 insertions, 79 deletions
diff --git a/miscutils/make.c b/miscutils/make.c
index 7316408bf..a165274aa 100644
--- a/miscutils/make.c
+++ b/miscutils/make.c
@@ -257,6 +257,11 @@ enum {
257#define MAKE_FAILURE 0x01 257#define MAKE_FAILURE 0x01
258#define MAKE_DIDSOMETHING 0x02 258#define MAKE_DIDSOMETHING 0x02
259 259
260// Return TRUE if c is allowed in a POSIX 2017 macro or target name
261#define ispname(c) (isalpha(c) || isdigit(c) || c == '.' || c == '_')
262// Return TRUE if c is in the POSIX 'portable filename character set'
263#define isfname(c) (ispname(c) || c == '-')
264
260#define HTABSIZE 39 265#define HTABSIZE 39
261 266
262struct globals { 267struct globals {
@@ -320,11 +325,8 @@ struct globals {
320#endif 325#endif
321 326
322static int make(struct name *np, int level); 327static int make(struct name *np, int level);
323 328static struct name *dyndep(struct name *np, struct rule *infrule,
324// Return TRUE if c is allowed in a POSIX 2017 macro or target name 329 const char **ptsuff);
325#define ispname(c) (isalpha(c) || isdigit(c) || c == '.' || c == '_')
326// Return TRUE if c is in the POSIX 'portable filename character set'
327#define isfname(c) (ispname(c) || c == '-')
328 330
329/* 331/*
330 * Utility functions. 332 * Utility functions.
@@ -469,8 +471,7 @@ newcmd(struct cmd **cphead, char *str)
469 /*(*cphead)->c_next = NULL; - xzalloc did it */ 471 /*(*cphead)->c_next = NULL; - xzalloc did it */
470 (*cphead)->c_cmd = xstrdup(str); 472 (*cphead)->c_cmd = xstrdup(str);
471 /*(*cphead)->c_refcnt = 0; */ 473 /*(*cphead)->c_refcnt = 0; */
472 if (makefile) 474 (*cphead)->c_makefile = xstrdup(makefile);
473 (*cphead)->c_makefile = xstrdup(makefile);
474 (*cphead)->c_dispno = dispno; 475 (*cphead)->c_dispno = dispno;
475} 476}
476 477
@@ -993,38 +994,27 @@ suffix(const char *name)
993} 994}
994 995
995/* 996/*
996 * Dynamic dependency. This routine applies the suffix rules 997 * Search for an inference rule to convert some suffix ('psuff')
997 * to try and find a source and a set of rules for a missing 998 * to the target suffix 'tsuff'. The basename of the prerequisite
998 * target. NULL is returned on failure. On success the name of 999 * is 'base'.
999 * the implicit prerequisite is returned and the details are
1000 * placed in the imprule structure provided by the caller.
1001 */ 1000 */
1002static struct name * 1001static struct name *
1003dyndep(struct name *np, struct rule *imprule) 1002dyndep0(char *base, const char *tsuff, struct rule *infrule)
1004{ 1003{
1005 char *suff, *newsuff; 1004 char *psuff;
1006 char *base, *name, *member;
1007 struct name *xp; // Suffixes 1005 struct name *xp; // Suffixes
1008 struct name *sp; // Suffix rule 1006 struct name *sp; // Suffix rule
1009 struct name *pp = NULL; // Implicit prerequisite
1010 struct rule *rp; 1007 struct rule *rp;
1011 struct depend *dp; 1008 struct depend *dp;
1012 bool chain = FALSE; 1009 bool chain = FALSE;
1013 1010
1014 member = NULL;
1015 name = splitlib(np->n_name, &member);
1016
1017 suff = xstrdup(suffix(name));
1018 base = member ? member : name;
1019 *suffix(base) = '\0';
1020
1021 xp = newname(".SUFFIXES"); 1011 xp = newname(".SUFFIXES");
1022 retry: 1012 retry:
1023 for (rp = xp->n_rule; rp; rp = rp->r_next) { 1013 for (rp = xp->n_rule; rp; rp = rp->r_next) {
1024 for (dp = rp->r_dep; dp; dp = dp->d_next) { 1014 for (dp = rp->r_dep; dp; dp = dp->d_next) {
1025 // Generate new suffix rule to try 1015 // Generate new suffix rule to try
1026 newsuff = dp->d_name->n_name; 1016 psuff = dp->d_name->n_name;
1027 sp = findname(auto_concat(newsuff, suff)); 1017 sp = findname(auto_concat(psuff, tsuff));
1028 if (sp && sp->n_rule) { 1018 if (sp && sp->n_rule) {
1029 struct name *ip; 1019 struct name *ip;
1030 int got_ip; 1020 int got_ip;
@@ -1032,9 +1022,8 @@ dyndep(struct name *np, struct rule *imprule)
1032 // Has rule already been used in this chain? 1022 // Has rule already been used in this chain?
1033 if ((sp->n_flag & N_MARK)) 1023 if ((sp->n_flag & N_MARK))
1034 continue; 1024 continue;
1035
1036 // Generate a name for an implicit prerequisite 1025 // Generate a name for an implicit prerequisite
1037 ip = newname(auto_concat(base, newsuff)); 1026 ip = newname(auto_concat(base, psuff));
1038 if ((ip->n_flag & N_DOING)) 1027 if ((ip->n_flag & N_DOING))
1039 continue; 1028 continue;
1040 1029
@@ -1045,20 +1034,19 @@ dyndep(struct name *np, struct rule *imprule)
1045 got_ip = ip->n_tim.tv_sec || (ip->n_flag & N_TARGET); 1034 got_ip = ip->n_tim.tv_sec || (ip->n_flag & N_TARGET);
1046 } else { 1035 } else {
1047 sp->n_flag |= N_MARK; 1036 sp->n_flag |= N_MARK;
1048 got_ip = dyndep(ip, NULL) != NULL; 1037 got_ip = dyndep(ip, NULL, NULL) != NULL;
1049 sp->n_flag &= ~N_MARK; 1038 sp->n_flag &= ~N_MARK;
1050 } 1039 }
1051 1040
1052 if (got_ip) { 1041 if (got_ip) {
1053 // Prerequisite exists or we know how to make it 1042 // Prerequisite exists or we know how to make it
1054 if (imprule) { 1043 if (infrule) {
1055 dp = NULL; 1044 dp = NULL;
1056 newdep(&dp, ip); 1045 newdep(&dp, ip);
1057 imprule->r_dep = dp; 1046 infrule->r_dep = dp;
1058 imprule->r_cmd = sp->n_rule->r_cmd; 1047 infrule->r_cmd = sp->n_rule->r_cmd;
1059 } 1048 }
1060 pp = ip; 1049 return ip;
1061 goto finish;
1062 } 1050 }
1063 } 1051 }
1064 } 1052 }
@@ -1069,9 +1057,87 @@ dyndep(struct name *np, struct rule *imprule)
1069 chain = TRUE; 1057 chain = TRUE;
1070 goto retry; 1058 goto retry;
1071 } 1059 }
1072 finish: 1060 return NULL;
1073 free(suff); 1061}
1062
1063/*
1064 * If 'name' ends with 'suffix' return an allocated string containing
1065 * the name with the suffix removed, else return NULL.
1066 */
1067static char *
1068has_suffix(const char *name, const char *suffix)
1069{
1070 ssize_t delta = strlen(name) - strlen(suffix);
1071 char *base = NULL;
1072
1073 if (delta > 0 && strcmp(name + delta, suffix) == 0) {
1074 base = xstrdup(name);
1075 base[delta] = '\0';
1076 }
1077
1078 return base;
1079}
1080
1081/*
1082 * Dynamic dependency. This routine applies the suffix rules
1083 * to try and find a source and a set of rules for a missing
1084 * target. NULL is returned on failure. On success the name of
1085 * the implicit prerequisite is returned and the rule used is
1086 * placed in the infrule structure provided by the caller.
1087 */
1088static struct name *
1089dyndep(struct name *np, struct rule *infrule, const char **ptsuff)
1090{
1091 const char *tsuff;
1092 char *base, *name, *member;
1093 struct name *pp = NULL; // Implicit prerequisite
1094
1095 member = NULL;
1096 name = splitlib(np->n_name, &member);
1097
1098 // POSIX only allows inference rules with one or two periods.
1099 // As an extension this restriction is lifted, but not for
1100 // targets of the form lib.a(member.o).
1101 if (!posix && member == NULL) {
1102 struct name *xp = newname(".SUFFIXES");
1103 int found_suffix = FALSE;
1104
1105 for (struct rule *rp = xp->n_rule; rp; rp = rp->r_next) {
1106 for (struct depend *dp = rp->r_dep; dp; dp = dp->d_next) {
1107 tsuff = dp->d_name->n_name;
1108 base = has_suffix(name, tsuff);
1109 if (base) {
1110 found_suffix = TRUE;
1111 pp = dyndep0(base, tsuff, infrule);
1112 free(base);
1113 if (pp) {
1114 goto done;
1115 }
1116 }
1117 }
1118 }
1119
1120 if (!found_suffix) {
1121 // The name didn't have a known suffix. Try single-suffix rule.
1122 tsuff = "";
1123 pp = dyndep0(name, tsuff, infrule);
1124 if (pp) {
1125 done:
1126 if (ptsuff) {
1127 *ptsuff = tsuff;
1128 }
1129 }
1130 }
1131 } else {
1132 tsuff = xstrdup(suffix(name));
1133 base = member ? member : name;
1134 *suffix(base) = '\0';
1135
1136 pp = dyndep0(base, tsuff, infrule);
1137 free((void *)tsuff);
1138 }
1074 free(name); 1139 free(name);
1140
1075 return pp; 1141 return pp;
1076} 1142}
1077 1143
@@ -1789,9 +1855,10 @@ readline(FILE *fd, int want_command)
1789} 1855}
1790 1856
1791/* 1857/*
1792 * Return TRUE if the argument is a known suffix. 1858 * Return a pointer to the suffix name if the argument is a known suffix
1859 * or NULL if it isn't.
1793 */ 1860 */
1794static int 1861static const char *
1795is_suffix(const char *s) 1862is_suffix(const char *s)
1796{ 1863{
1797 struct name *np; 1864 struct name *np;
@@ -1802,7 +1869,39 @@ is_suffix(const char *s)
1802 for (rp = np->n_rule; rp; rp = rp->r_next) { 1869 for (rp = np->n_rule; rp; rp = rp->r_next) {
1803 for (dp = rp->r_dep; dp; dp = dp->d_next) { 1870 for (dp = rp->r_dep; dp; dp = dp->d_next) {
1804 if (strcmp(s, dp->d_name->n_name) == 0) { 1871 if (strcmp(s, dp->d_name->n_name) == 0) {
1805 return TRUE; 1872 return dp->d_name->n_name;
1873 }
1874 }
1875 }
1876 return NULL;
1877}
1878
1879/*
1880 * Return TRUE if the argument is formed by concatenating two
1881 * known suffixes.
1882 */
1883static int
1884is_inference_target(const char *s)
1885{
1886 struct name *np;
1887 struct rule *rp1, *rp2;
1888 struct depend *dp1, *dp2;
1889
1890 np = newname(".SUFFIXES");
1891 for (rp1 = np->n_rule; rp1; rp1 = rp1->r_next) {
1892 for (dp1 = rp1->r_dep; dp1; dp1 = dp1->d_next) {
1893 const char *suff1 = dp1->d_name->n_name;
1894 size_t len = strlen(suff1);
1895
1896 if (strncmp(s, suff1, len) == 0) {
1897 for (rp2 = np->n_rule; rp2; rp2 = rp2->r_next) {
1898 for (dp2 = rp2->r_dep; dp2; dp2 = dp2->d_next) {
1899 const char *suff2 = dp2->d_name->n_name;
1900 if (strcmp(s + len, suff2) == 0) {
1901 return TRUE;
1902 }
1903 }
1904 }
1806 } 1905 }
1807 } 1906 }
1808 } 1907 }
@@ -1824,7 +1923,6 @@ enum {
1824static int 1923static int
1825target_type(char *s) 1924target_type(char *s)
1826{ 1925{
1827 char *sfx;
1828 int ret; 1926 int ret;
1829 static const char *s_name = 1927 static const char *s_name =
1830 ".DEFAULT\0" 1928 ".DEFAULT\0"
@@ -1854,9 +1952,6 @@ target_type(char *s)
1854 T_SPECIAL, 1952 T_SPECIAL,
1855 }; 1953 };
1856 1954
1857 if (*s != '.')
1858 return T_NORMAL;
1859
1860 // Check for one of the known special targets 1955 // Check for one of the known special targets
1861 ret = index_in_strings(s_name, s); 1956 ret = index_in_strings(s_name, s);
1862 if (ret >= 0) 1957 if (ret >= 0)
@@ -1864,16 +1959,23 @@ target_type(char *s)
1864 1959
1865 // Check for an inference rule 1960 // Check for an inference rule
1866 ret = T_NORMAL; 1961 ret = T_NORMAL;
1867 sfx = suffix(s); 1962 if (!posix) {
1868 if (is_suffix(sfx)) { 1963 if (is_suffix(s) || is_inference_target(s)) {
1869 if (s == sfx) { // Single suffix rule
1870 ret = T_INFERENCE | T_NOPREREQ | T_COMMAND; 1964 ret = T_INFERENCE | T_NOPREREQ | T_COMMAND;
1871 } else { 1965 }
1872 // Suffix is valid, check that prefix is too 1966 } else {
1873 *sfx = '\0'; 1967 // In POSIX inference rule targets must contain one or two dots
1874 if (is_suffix(s)) 1968 char *sfx = suffix(s);
1969 if (*s == '.' && is_suffix(sfx)) {
1970 if (s == sfx) { // Single suffix rule
1875 ret = T_INFERENCE | T_NOPREREQ | T_COMMAND; 1971 ret = T_INFERENCE | T_NOPREREQ | T_COMMAND;
1876 *sfx = '.'; 1972 } else {
1973 // Suffix is valid, check that prefix is too
1974 *sfx = '\0';
1975 if (is_suffix(s))
1976 ret = T_INFERENCE | T_NOPREREQ | T_COMMAND;
1977 *sfx = '.';
1978 }
1877 } 1979 }
1878 } 1980 }
1879 return ret; 1981 return ret;
@@ -2069,6 +2171,20 @@ pragmas_from_env(void)
2069#endif 2171#endif
2070 2172
2071/* 2173/*
2174 * Determine if a line is a target rule with an inline command.
2175 * Return a pointer to the semicolon separator if it is, else NULL.
2176 */
2177static char *
2178inline_command(char *line)
2179{
2180 char *p = find_char(line, ':');
2181
2182 if (p)
2183 p = strchr(p, ';');
2184 return p;
2185}
2186
2187/*
2072 * Parse input from the makefile and construct a tree structure of it. 2188 * Parse input from the makefile and construct a tree structure of it.
2073 */ 2189 */
2074static void 2190static void
@@ -2287,9 +2403,9 @@ input(FILE *fd, int ilevel)
2287 cp = NULL; 2403 cp = NULL;
2288 s = strchr(q, ';'); 2404 s = strchr(q, ';');
2289 if (s) { 2405 if (s) {
2290 // Retrieve command from expanded copy of line 2406 // Retrieve command from original or expanded copy of line
2291 char *copy3 = expand_macros(copy, FALSE); 2407 char *copy3 = expand_macros(copy, FALSE);
2292 if ((p = find_colon(copy3)) && (p = strchr(p, ';'))) 2408 if ((p = inline_command(copy)) || (p = inline_command(copy3)))
2293 newcmd(&cp, process_command(p + 1)); 2409 newcmd(&cp, process_command(p + 1));
2294 free(copy3); 2410 free(copy3);
2295 *s = '\0'; 2411 *s = '\0';
@@ -2585,9 +2701,34 @@ docmds(struct name *np, struct cmd *cp)
2585 return estat; 2701 return estat;
2586} 2702}
2587 2703
2704/*
2705 * Remove the suffix from a name, either the one provided in 'tsuff'
2706 * or, if 'tsuff' is NULL, one of the known suffixes.
2707 */
2708static char *
2709remove_suffix(const char *name, const char *tsuff)
2710{
2711 char *base = NULL;
2712
2713 if (tsuff != NULL) {
2714 base = has_suffix(name, tsuff);
2715 } else {
2716 struct name *xp = newname(".SUFFIXES");
2717 for (struct rule *rp = xp->n_rule; rp; rp = rp->r_next) {
2718 for (struct depend *dp = rp->r_dep; dp; dp = dp->d_next) {
2719 base = has_suffix(name, dp->d_name->n_name);
2720 if (base) {
2721 return base;
2722 }
2723 }
2724 }
2725 }
2726 return base;
2727}
2728
2588static int 2729static int
2589make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc, 2730make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc,
2590 char *dedup, struct name *implicit) 2731 char *dedup, struct name *implicit, const char *tsuff)
2591{ 2732{
2592 char *name, *member = NULL, *base = NULL, *prereq = NULL; 2733 char *name, *member = NULL, *base = NULL, *prereq = NULL;
2593 2734
@@ -2603,7 +2744,7 @@ make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc,
2603 char *s; 2744 char *s;
2604 2745
2605 // As an extension, if we're not dealing with an implicit 2746 // As an extension, if we're not dealing with an implicit
2606 // rule set $< to the first out-of-date prerequisite. 2747 // prerequisite set $< to the first out-of-date prerequisite.
2607 if (implicit == NULL) { 2748 if (implicit == NULL) {
2608 if (oodate) { 2749 if (oodate) {
2609 s = strchr(oodate, ' '); 2750 s = strchr(oodate, ' ');
@@ -2614,15 +2755,26 @@ make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc,
2614 } else 2755 } else
2615 prereq = implicit->n_name; 2756 prereq = implicit->n_name;
2616 2757
2617 base = member ? member : name; 2758 if (!posix && member == NULL) {
2618 s = suffix(base); 2759 // As an extension remove a suffix that doesn't necessarily
2619 // As an extension, if we're not dealing with an implicit 2760 // start with a period from a target, but not for targets
2620 // rule and the target ends with a known suffix, remove it 2761 // of the form lib.a(member.o).
2621 // and set $* to the stem, else to an empty string. 2762 base = remove_suffix(name, tsuff);
2622 if (implicit == NULL && !is_suffix(s)) 2763 if (base) {
2623 base = NULL; 2764 free(name);
2624 else 2765 name = base;
2625 *s = '\0'; 2766 }
2767 } else {
2768 base = member ? member : name;
2769 s = suffix(base);
2770 // As an extension, if we're not dealing with an implicit
2771 // prerequisite and the target ends with a known suffix,
2772 // remove it and set $* to the stem, else to an empty string.
2773 if (implicit == NULL && !is_suffix(s))
2774 base = NULL;
2775 else
2776 *s = '\0';
2777 }
2626 } 2778 }
2627 setmacro("<", prereq, 0 | M_VALID); 2779 setmacro("<", prereq, 0 | M_VALID);
2628 setmacro("*", base, 0 | M_VALID); 2780 setmacro("*", base, 0 | M_VALID);
@@ -2667,11 +2819,12 @@ make(struct name *np, int level)
2667 struct depend *dp; 2819 struct depend *dp;
2668 struct rule *rp; 2820 struct rule *rp;
2669 struct name *impdep = NULL; // implicit prerequisite 2821 struct name *impdep = NULL; // implicit prerequisite
2670 struct rule imprule; 2822 struct rule infrule;
2671 struct cmd *sc_cmd = NULL; // commands for single-colon rule 2823 struct cmd *sc_cmd = NULL; // commands for single-colon rule
2672 char *oodate = NULL; 2824 char *oodate = NULL;
2673 char *allsrc = NULL; 2825 char *allsrc = NULL;
2674 char *dedup = NULL; 2826 char *dedup = NULL;
2827 const char *tsuff = NULL;
2675 struct timespec dtim = {1, 0}; 2828 struct timespec dtim = {1, 0};
2676 int estat = 0; 2829 int estat = 0;
2677 2830
@@ -2690,10 +2843,10 @@ make(struct name *np, int level)
2690 // as an extension, not for phony targets) 2843 // as an extension, not for phony targets)
2691 sc_cmd = getcmd(np); 2844 sc_cmd = getcmd(np);
2692 if (!sc_cmd && (posix || !(np->n_flag & N_PHONY))) { 2845 if (!sc_cmd && (posix || !(np->n_flag & N_PHONY))) {
2693 impdep = dyndep(np, &imprule); 2846 impdep = dyndep(np, &infrule, &tsuff);
2694 if (impdep) { 2847 if (impdep) {
2695 sc_cmd = imprule.r_cmd; 2848 sc_cmd = infrule.r_cmd;
2696 addrule(np, imprule.r_dep, NULL, FALSE); 2849 addrule(np, infrule.r_dep, NULL, FALSE);
2697 } 2850 }
2698 } 2851 }
2699 2852
@@ -2708,14 +2861,15 @@ make(struct name *np, int level)
2708 } 2861 }
2709 impdep = np; 2862 impdep = np;
2710 } 2863 }
2711 } 2864 } else {
2712 else {
2713 // If any double-colon rule has no commands we need 2865 // If any double-colon rule has no commands we need
2714 // an inference rule (but, as an extension, not for phony targets) 2866 // an inference rule.
2715 for (rp = np->n_rule; rp; rp = rp->r_next) { 2867 for (rp = np->n_rule; rp; rp = rp->r_next) {
2716 if (!rp->r_cmd) { 2868 if (!rp->r_cmd) {
2717 if (posix || !(np->n_flag & N_PHONY)) 2869 // Phony targets don't need an inference rule.
2718 impdep = dyndep(np, &imprule); 2870 if (!posix && (np->n_flag & N_PHONY))
2871 continue;
2872 impdep = dyndep(np, &infrule, &tsuff);
2719 if (!impdep) { 2873 if (!impdep) {
2720 if (doinclude) 2874 if (doinclude)
2721 return 1; 2875 return 1;
@@ -2741,11 +2895,14 @@ make(struct name *np, int level)
2741 // Each double-colon rule is handled separately. 2895 // Each double-colon rule is handled separately.
2742 if ((np->n_flag & N_DOUBLE)) { 2896 if ((np->n_flag & N_DOUBLE)) {
2743 // If the rule has no commands use the inference rule. 2897 // If the rule has no commands use the inference rule.
2898 // Unless there isn't one, as allowed for phony targets.
2744 if (!rp->r_cmd) { 2899 if (!rp->r_cmd) {
2745 locdep = impdep; 2900 if (impdep) {
2746 imprule.r_dep->d_next = rp->r_dep; 2901 locdep = impdep;
2747 rp->r_dep = imprule.r_dep; 2902 infrule.r_dep->d_next = rp->r_dep;
2748 rp->r_cmd = imprule.r_cmd; 2903 rp->r_dep = infrule.r_dep;
2904 rp->r_cmd = infrule.r_cmd;
2905 }
2749 } 2906 }
2750 // A rule with no prerequisities is executed unconditionally. 2907 // A rule with no prerequisities is executed unconditionally.
2751 if (!rp->r_dep) 2908 if (!rp->r_dep)
@@ -2776,7 +2933,7 @@ make(struct name *np, int level)
2776 if (((np->n_flag & N_PHONY) || timespec_le(&np->n_tim, &dtim))) { 2933 if (((np->n_flag & N_PHONY) || timespec_le(&np->n_tim, &dtim))) {
2777 if (!(estat & MAKE_FAILURE)) { 2934 if (!(estat & MAKE_FAILURE)) {
2778 estat |= make1(np, rp->r_cmd, oodate, allsrc, 2935 estat |= make1(np, rp->r_cmd, oodate, allsrc,
2779 dedup, locdep); 2936 dedup, locdep, tsuff);
2780 dtim = (struct timespec){1, 0}; 2937 dtim = (struct timespec){1, 0};
2781 } 2938 }
2782 free(oodate); 2939 free(oodate);
@@ -2792,7 +2949,7 @@ make(struct name *np, int level)
2792 } 2949 }
2793 } 2950 }
2794 if ((np->n_flag & N_DOUBLE) && impdep) 2951 if ((np->n_flag & N_DOUBLE) && impdep)
2795 free(imprule.r_dep); 2952 free(infrule.r_dep);
2796 2953
2797 np->n_flag |= N_DONE; 2954 np->n_flag |= N_DONE;
2798 np->n_flag &= ~N_DOING; 2955 np->n_flag &= ~N_DOING;
@@ -2801,7 +2958,8 @@ make(struct name *np, int level)
2801 ((np->n_flag & N_PHONY) || (timespec_le(&np->n_tim, &dtim)))) { 2958 ((np->n_flag & N_PHONY) || (timespec_le(&np->n_tim, &dtim)))) {
2802 if (!(estat & MAKE_FAILURE)) { 2959 if (!(estat & MAKE_FAILURE)) {
2803 if (sc_cmd) 2960 if (sc_cmd)
2804 estat |= make1(np, sc_cmd, oodate, allsrc, dedup, impdep); 2961 estat |= make1(np, sc_cmd, oodate, allsrc, dedup,
2962 impdep, tsuff);
2805 else if (!doinclude && level == 0 && !(estat & MAKE_DIDSOMETHING)) 2963 else if (!doinclude && level == 0 && !(estat & MAKE_DIDSOMETHING))
2806 warning("nothing to be done for %s", np->n_name); 2964 warning("nothing to be done for %s", np->n_name);
2807 } else if (!doinclude && !quest) { 2965 } else if (!doinclude && !quest) {