aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--miscutils/crond.c12
-rw-r--r--miscutils/fbsplash.c2
-rw-r--r--miscutils/less.c2
-rw-r--r--miscutils/make.c353
-rw-r--r--miscutils/man.c2
5 files changed, 280 insertions, 91 deletions
diff --git a/miscutils/crond.c b/miscutils/crond.c
index b3762d327..6a384fdfb 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -177,7 +177,7 @@ static void crondlog(unsigned level, const char *msg, va_list va)
177{ 177{
178 if (level >= G.log_level) { 178 if (level >= G.log_level) {
179 /* 179 /*
180 * We are called only for info meesages. 180 * We are called only for info messages.
181 * Warnings/errors use plain bb_[p]error_msg's, which 181 * Warnings/errors use plain bb_[p]error_msg's, which
182 * need not touch syslog_level 182 * need not touch syslog_level
183 * (they are ok with LOG_ERR default). 183 * (they are ok with LOG_ERR default).
@@ -989,7 +989,7 @@ static int check_completions(void)
989 if (line->cl_pid <= 0) 989 if (line->cl_pid <= 0)
990 continue; 990 continue;
991 991
992 r = waitpid(line->cl_pid, NULL, WNOHANG); 992 r = safe_waitpid(line->cl_pid, NULL, WNOHANG);
993 if (r < 0 || r == line->cl_pid) { 993 if (r < 0 || r == line->cl_pid) {
994 process_finished_job(file->cf_username, line); 994 process_finished_job(file->cf_username, line);
995 if (line->cl_pid == 0) { 995 if (line->cl_pid == 0) {
@@ -1001,6 +1001,14 @@ static int check_completions(void)
1001 /* else: r == 0: "process is still running" */ 1001 /* else: r == 0: "process is still running" */
1002 file->cf_has_running = 1; 1002 file->cf_has_running = 1;
1003 } 1003 }
1004
1005 /* Reap any other children we don't actively track.
1006 * Reportedly, some people run crond as init process!
1007 * Thus, we need to reap orphans, like init does.
1008 */
1009 while (wait_any_nohang(NULL) > 0)
1010 continue;
1011
1004//FIXME: if !file->cf_has_running && file->deleted: delete it! 1012//FIXME: if !file->cf_has_running && file->deleted: delete it!
1005//otherwise deleted entries will stay forever, right? 1013//otherwise deleted entries will stay forever, right?
1006 num_still_running += file->cf_has_running; 1014 num_still_running += file->cf_has_running;
diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c
index 2934d8eb7..912a501a3 100644
--- a/miscutils/fbsplash.c
+++ b/miscutils/fbsplash.c
@@ -382,7 +382,7 @@ static void fb_drawimage(void)
382 if (LONE_DASH(G.image_filename)) { 382 if (LONE_DASH(G.image_filename)) {
383 theme_file = stdin; 383 theme_file = stdin;
384 } else { 384 } else {
385 int fd = open_zipped(G.image_filename, /*fail_if_not_compressed:*/ 0); 385 int fd = open_zipped(G.image_filename, /*die_if_not_compressed:*/ 0);
386 if (fd < 0) 386 if (fd < 0)
387 bb_simple_perror_msg_and_die(G.image_filename); 387 bb_simple_perror_msg_and_die(G.image_filename);
388 theme_file = xfdopen_for_read(fd); 388 theme_file = xfdopen_for_read(fd);
diff --git a/miscutils/less.c b/miscutils/less.c
index 467c76e2a..5a8fc5a74 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -1178,7 +1178,7 @@ static int64_t getch_nowait(void)
1178 1178
1179 /* We have kbd_fd in O_NONBLOCK mode, read inside safe_read_key() 1179 /* We have kbd_fd in O_NONBLOCK mode, read inside safe_read_key()
1180 * would not block even if there is no input available */ 1180 * would not block even if there is no input available */
1181 key64 = safe_read_key(kbd_fd, kbd_input, /*timeout off:*/ -2); 1181 key64 = safe_read_key(kbd_fd, kbd_input, /*do not poll:*/ -2);
1182 if ((int)key64 == -1) { 1182 if ((int)key64 == -1) {
1183 if (errno == EAGAIN) { 1183 if (errno == EAGAIN) {
1184 /* No keyboard input available. Since poll() did return, 1184 /* No keyboard input available. Since poll() did return,
diff --git a/miscutils/make.c b/miscutils/make.c
index 7316408bf..8026917b3 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 {
@@ -271,6 +276,7 @@ struct globals {
271 time_t ar_mtime; 276 time_t ar_mtime;
272 int lineno; // Physical line number in file 277 int lineno; // Physical line number in file
273 int dispno; // Line number for display purposes 278 int dispno; // Line number for display purposes
279 struct cmd *curr_cmd;
274 const char *rulepos; 280 const char *rulepos;
275 int rule_idx; 281 int rule_idx;
276#define IF_MAX 10 282#define IF_MAX 10
@@ -302,6 +308,7 @@ struct globals {
302#define ar_mtime (G.ar_mtime) 308#define ar_mtime (G.ar_mtime)
303#define lineno (G.lineno) 309#define lineno (G.lineno)
304#define dispno (G.dispno) 310#define dispno (G.dispno)
311#define curr_cmd (G.curr_cmd)
305#define rulepos (G.rulepos) 312#define rulepos (G.rulepos)
306#define rule_idx (G.rule_idx) 313#define rule_idx (G.rule_idx)
307#define clevel (G.clevel) 314#define clevel (G.clevel)
@@ -320,11 +327,8 @@ struct globals {
320#endif 327#endif
321 328
322static int make(struct name *np, int level); 329static int make(struct name *np, int level);
323 330static struct name *dyndep(struct name *np, struct rule *infrule,
324// Return TRUE if c is allowed in a POSIX 2017 macro or target name 331 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 332
329/* 333/*
330 * Utility functions. 334 * Utility functions.
@@ -336,9 +340,20 @@ static int make(struct name *np, int level);
336static void 340static void
337vwarning(FILE *stream, const char *msg, va_list list) 341vwarning(FILE *stream, const char *msg, va_list list)
338{ 342{
343 const char *m = NULL;
344 int d = 0;
345
346 if (curr_cmd) {
347 m = curr_cmd->c_makefile;
348 d = curr_cmd->c_dispno;
349 } else if (makefile) {
350 m = makefile;
351 d = dispno;
352 }
353
339 fprintf(stream, "%s: ", applet_name); 354 fprintf(stream, "%s: ", applet_name);
340 if (makefile) 355 if (m)
341 fprintf(stream, "(%s:%d): ", makefile, dispno); 356 fprintf(stream, "(%s:%d): ", m, d);
342 vfprintf(stream, msg, list); 357 vfprintf(stream, msg, list);
343 fputc('\n', stream); 358 fputc('\n', stream);
344} 359}
@@ -469,8 +484,7 @@ newcmd(struct cmd **cphead, char *str)
469 /*(*cphead)->c_next = NULL; - xzalloc did it */ 484 /*(*cphead)->c_next = NULL; - xzalloc did it */
470 (*cphead)->c_cmd = xstrdup(str); 485 (*cphead)->c_cmd = xstrdup(str);
471 /*(*cphead)->c_refcnt = 0; */ 486 /*(*cphead)->c_refcnt = 0; */
472 if (makefile) 487 (*cphead)->c_makefile = xstrdup(makefile);
473 (*cphead)->c_makefile = xstrdup(makefile);
474 (*cphead)->c_dispno = dispno; 488 (*cphead)->c_dispno = dispno;
475} 489}
476 490
@@ -725,6 +739,7 @@ addrule(struct name *np, struct depend *dp, struct cmd *cp, int flag)
725{ 739{
726 struct rule *rp; 740 struct rule *rp;
727 struct rule **rpp; 741 struct rule **rpp;
742 struct cmd *old_cp;
728 743
729 // Can't mix single-colon and double-colon rules 744 // Can't mix single-colon and double-colon rules
730 if (!posix && (np->n_flag & N_TARGET)) { 745 if (!posix && (np->n_flag & N_TARGET)) {
@@ -741,7 +756,7 @@ addrule(struct name *np, struct depend *dp, struct cmd *cp, int flag)
741 return; 756 return;
742 } 757 }
743 758
744 if (cp && !(np->n_flag & N_DOUBLE) && getcmd(np)) { 759 if (cp && !(np->n_flag & N_DOUBLE) && (old_cp = getcmd(np))) {
745 // Handle the inference rule redefinition case 760 // Handle the inference rule redefinition case
746 // .DEFAULT rule can also be redefined (as an extension). 761 // .DEFAULT rule can also be redefined (as an extension).
747 if ((np->n_flag & N_INFERENCE) 762 if ((np->n_flag & N_INFERENCE)
@@ -750,7 +765,17 @@ addrule(struct name *np, struct depend *dp, struct cmd *cp, int flag)
750 freerules(np->n_rule); 765 freerules(np->n_rule);
751 np->n_rule = NULL; 766 np->n_rule = NULL;
752 } else { 767 } else {
753 error("commands defined twice for target %s", np->n_name); 768 // We're adding commands to a single colon rule which
769 // already has some. Clear the old ones first.
770 warning("overriding rule for target %s", np->n_name);
771 curr_cmd = old_cp;
772 warning("previous rule for target %s", np->n_name);
773 curr_cmd = NULL;
774
775 for (rp = np->n_rule; rp; rp = rp->r_next) {
776 freecmds(rp->r_cmd);
777 rp->r_cmd = NULL;
778 }
754 } 779 }
755 } 780 }
756 781
@@ -993,38 +1018,27 @@ suffix(const char *name)
993} 1018}
994 1019
995/* 1020/*
996 * Dynamic dependency. This routine applies the suffix rules 1021 * 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 1022 * to the target suffix 'tsuff'. The basename of the prerequisite
998 * target. NULL is returned on failure. On success the name of 1023 * is 'base'.
999 * the implicit prerequisite is returned and the details are
1000 * placed in the imprule structure provided by the caller.
1001 */ 1024 */
1002static struct name * 1025static struct name *
1003dyndep(struct name *np, struct rule *imprule) 1026dyndep0(char *base, const char *tsuff, struct rule *infrule)
1004{ 1027{
1005 char *suff, *newsuff; 1028 char *psuff;
1006 char *base, *name, *member;
1007 struct name *xp; // Suffixes 1029 struct name *xp; // Suffixes
1008 struct name *sp; // Suffix rule 1030 struct name *sp; // Suffix rule
1009 struct name *pp = NULL; // Implicit prerequisite
1010 struct rule *rp; 1031 struct rule *rp;
1011 struct depend *dp; 1032 struct depend *dp;
1012 bool chain = FALSE; 1033 bool chain = FALSE;
1013 1034
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"); 1035 xp = newname(".SUFFIXES");
1022 retry: 1036 retry:
1023 for (rp = xp->n_rule; rp; rp = rp->r_next) { 1037 for (rp = xp->n_rule; rp; rp = rp->r_next) {
1024 for (dp = rp->r_dep; dp; dp = dp->d_next) { 1038 for (dp = rp->r_dep; dp; dp = dp->d_next) {
1025 // Generate new suffix rule to try 1039 // Generate new suffix rule to try
1026 newsuff = dp->d_name->n_name; 1040 psuff = dp->d_name->n_name;
1027 sp = findname(auto_concat(newsuff, suff)); 1041 sp = findname(auto_concat(psuff, tsuff));
1028 if (sp && sp->n_rule) { 1042 if (sp && sp->n_rule) {
1029 struct name *ip; 1043 struct name *ip;
1030 int got_ip; 1044 int got_ip;
@@ -1032,9 +1046,8 @@ dyndep(struct name *np, struct rule *imprule)
1032 // Has rule already been used in this chain? 1046 // Has rule already been used in this chain?
1033 if ((sp->n_flag & N_MARK)) 1047 if ((sp->n_flag & N_MARK))
1034 continue; 1048 continue;
1035
1036 // Generate a name for an implicit prerequisite 1049 // Generate a name for an implicit prerequisite
1037 ip = newname(auto_concat(base, newsuff)); 1050 ip = newname(auto_concat(base, psuff));
1038 if ((ip->n_flag & N_DOING)) 1051 if ((ip->n_flag & N_DOING))
1039 continue; 1052 continue;
1040 1053
@@ -1045,20 +1058,19 @@ dyndep(struct name *np, struct rule *imprule)
1045 got_ip = ip->n_tim.tv_sec || (ip->n_flag & N_TARGET); 1058 got_ip = ip->n_tim.tv_sec || (ip->n_flag & N_TARGET);
1046 } else { 1059 } else {
1047 sp->n_flag |= N_MARK; 1060 sp->n_flag |= N_MARK;
1048 got_ip = dyndep(ip, NULL) != NULL; 1061 got_ip = dyndep(ip, NULL, NULL) != NULL;
1049 sp->n_flag &= ~N_MARK; 1062 sp->n_flag &= ~N_MARK;
1050 } 1063 }
1051 1064
1052 if (got_ip) { 1065 if (got_ip) {
1053 // Prerequisite exists or we know how to make it 1066 // Prerequisite exists or we know how to make it
1054 if (imprule) { 1067 if (infrule) {
1055 dp = NULL; 1068 dp = NULL;
1056 newdep(&dp, ip); 1069 newdep(&dp, ip);
1057 imprule->r_dep = dp; 1070 infrule->r_dep = dp;
1058 imprule->r_cmd = sp->n_rule->r_cmd; 1071 infrule->r_cmd = sp->n_rule->r_cmd;
1059 } 1072 }
1060 pp = ip; 1073 return ip;
1061 goto finish;
1062 } 1074 }
1063 } 1075 }
1064 } 1076 }
@@ -1069,9 +1081,87 @@ dyndep(struct name *np, struct rule *imprule)
1069 chain = TRUE; 1081 chain = TRUE;
1070 goto retry; 1082 goto retry;
1071 } 1083 }
1072 finish: 1084 return NULL;
1073 free(suff); 1085}
1086
1087/*
1088 * If 'name' ends with 'suffix' return an allocated string containing
1089 * the name with the suffix removed, else return NULL.
1090 */
1091static char *
1092has_suffix(const char *name, const char *suffix)
1093{
1094 ssize_t delta = strlen(name) - strlen(suffix);
1095 char *base = NULL;
1096
1097 if (delta > 0 && strcmp(name + delta, suffix) == 0) {
1098 base = xstrdup(name);
1099 base[delta] = '\0';
1100 }
1101
1102 return base;
1103}
1104
1105/*
1106 * Dynamic dependency. This routine applies the suffix rules
1107 * to try and find a source and a set of rules for a missing
1108 * target. NULL is returned on failure. On success the name of
1109 * the implicit prerequisite is returned and the rule used is
1110 * placed in the infrule structure provided by the caller.
1111 */
1112static struct name *
1113dyndep(struct name *np, struct rule *infrule, const char **ptsuff)
1114{
1115 const char *tsuff;
1116 char *base, *name, *member;
1117 struct name *pp = NULL; // Implicit prerequisite
1118
1119 member = NULL;
1120 name = splitlib(np->n_name, &member);
1121
1122 // POSIX only allows inference rules with one or two periods.
1123 // As an extension this restriction is lifted, but not for
1124 // targets of the form lib.a(member.o).
1125 if (!posix && member == NULL) {
1126 struct name *xp = newname(".SUFFIXES");
1127 int found_suffix = FALSE;
1128
1129 for (struct rule *rp = xp->n_rule; rp; rp = rp->r_next) {
1130 for (struct depend *dp = rp->r_dep; dp; dp = dp->d_next) {
1131 tsuff = dp->d_name->n_name;
1132 base = has_suffix(name, tsuff);
1133 if (base) {
1134 found_suffix = TRUE;
1135 pp = dyndep0(base, tsuff, infrule);
1136 free(base);
1137 if (pp) {
1138 goto done;
1139 }
1140 }
1141 }
1142 }
1143
1144 if (!found_suffix) {
1145 // The name didn't have a known suffix. Try single-suffix rule.
1146 tsuff = "";
1147 pp = dyndep0(name, tsuff, infrule);
1148 if (pp) {
1149 done:
1150 if (ptsuff) {
1151 *ptsuff = tsuff;
1152 }
1153 }
1154 }
1155 } else {
1156 tsuff = xstrdup(suffix(name));
1157 base = member ? member : name;
1158 *suffix(base) = '\0';
1159
1160 pp = dyndep0(base, tsuff, infrule);
1161 free((void *)tsuff);
1162 }
1074 free(name); 1163 free(name);
1164
1075 return pp; 1165 return pp;
1076} 1166}
1077 1167
@@ -1789,9 +1879,10 @@ readline(FILE *fd, int want_command)
1789} 1879}
1790 1880
1791/* 1881/*
1792 * Return TRUE if the argument is a known suffix. 1882 * Return a pointer to the suffix name if the argument is a known suffix
1883 * or NULL if it isn't.
1793 */ 1884 */
1794static int 1885static const char *
1795is_suffix(const char *s) 1886is_suffix(const char *s)
1796{ 1887{
1797 struct name *np; 1888 struct name *np;
@@ -1802,7 +1893,39 @@ is_suffix(const char *s)
1802 for (rp = np->n_rule; rp; rp = rp->r_next) { 1893 for (rp = np->n_rule; rp; rp = rp->r_next) {
1803 for (dp = rp->r_dep; dp; dp = dp->d_next) { 1894 for (dp = rp->r_dep; dp; dp = dp->d_next) {
1804 if (strcmp(s, dp->d_name->n_name) == 0) { 1895 if (strcmp(s, dp->d_name->n_name) == 0) {
1805 return TRUE; 1896 return dp->d_name->n_name;
1897 }
1898 }
1899 }
1900 return NULL;
1901}
1902
1903/*
1904 * Return TRUE if the argument is formed by concatenating two
1905 * known suffixes.
1906 */
1907static int
1908is_inference_target(const char *s)
1909{
1910 struct name *np;
1911 struct rule *rp1, *rp2;
1912 struct depend *dp1, *dp2;
1913
1914 np = newname(".SUFFIXES");
1915 for (rp1 = np->n_rule; rp1; rp1 = rp1->r_next) {
1916 for (dp1 = rp1->r_dep; dp1; dp1 = dp1->d_next) {
1917 const char *suff1 = dp1->d_name->n_name;
1918 size_t len = strlen(suff1);
1919
1920 if (strncmp(s, suff1, len) == 0) {
1921 for (rp2 = np->n_rule; rp2; rp2 = rp2->r_next) {
1922 for (dp2 = rp2->r_dep; dp2; dp2 = dp2->d_next) {
1923 const char *suff2 = dp2->d_name->n_name;
1924 if (strcmp(s + len, suff2) == 0) {
1925 return TRUE;
1926 }
1927 }
1928 }
1806 } 1929 }
1807 } 1930 }
1808 } 1931 }
@@ -1824,7 +1947,6 @@ enum {
1824static int 1947static int
1825target_type(char *s) 1948target_type(char *s)
1826{ 1949{
1827 char *sfx;
1828 int ret; 1950 int ret;
1829 static const char *s_name = 1951 static const char *s_name =
1830 ".DEFAULT\0" 1952 ".DEFAULT\0"
@@ -1854,9 +1976,6 @@ target_type(char *s)
1854 T_SPECIAL, 1976 T_SPECIAL,
1855 }; 1977 };
1856 1978
1857 if (*s != '.')
1858 return T_NORMAL;
1859
1860 // Check for one of the known special targets 1979 // Check for one of the known special targets
1861 ret = index_in_strings(s_name, s); 1980 ret = index_in_strings(s_name, s);
1862 if (ret >= 0) 1981 if (ret >= 0)
@@ -1864,16 +1983,23 @@ target_type(char *s)
1864 1983
1865 // Check for an inference rule 1984 // Check for an inference rule
1866 ret = T_NORMAL; 1985 ret = T_NORMAL;
1867 sfx = suffix(s); 1986 if (!posix) {
1868 if (is_suffix(sfx)) { 1987 if (is_suffix(s) || is_inference_target(s)) {
1869 if (s == sfx) { // Single suffix rule
1870 ret = T_INFERENCE | T_NOPREREQ | T_COMMAND; 1988 ret = T_INFERENCE | T_NOPREREQ | T_COMMAND;
1871 } else { 1989 }
1872 // Suffix is valid, check that prefix is too 1990 } else {
1873 *sfx = '\0'; 1991 // In POSIX inference rule targets must contain one or two dots
1874 if (is_suffix(s)) 1992 char *sfx = suffix(s);
1993 if (*s == '.' && is_suffix(sfx)) {
1994 if (s == sfx) { // Single suffix rule
1875 ret = T_INFERENCE | T_NOPREREQ | T_COMMAND; 1995 ret = T_INFERENCE | T_NOPREREQ | T_COMMAND;
1876 *sfx = '.'; 1996 } else {
1997 // Suffix is valid, check that prefix is too
1998 *sfx = '\0';
1999 if (is_suffix(s))
2000 ret = T_INFERENCE | T_NOPREREQ | T_COMMAND;
2001 *sfx = '.';
2002 }
1877 } 2003 }
1878 } 2004 }
1879 return ret; 2005 return ret;
@@ -2069,6 +2195,20 @@ pragmas_from_env(void)
2069#endif 2195#endif
2070 2196
2071/* 2197/*
2198 * Determine if a line is a target rule with an inline command.
2199 * Return a pointer to the semicolon separator if it is, else NULL.
2200 */
2201static char *
2202inline_command(char *line)
2203{
2204 char *p = find_char(line, ':');
2205
2206 if (p)
2207 p = strchr(p, ';');
2208 return p;
2209}
2210
2211/*
2072 * Parse input from the makefile and construct a tree structure of it. 2212 * Parse input from the makefile and construct a tree structure of it.
2073 */ 2213 */
2074static void 2214static void
@@ -2287,9 +2427,9 @@ input(FILE *fd, int ilevel)
2287 cp = NULL; 2427 cp = NULL;
2288 s = strchr(q, ';'); 2428 s = strchr(q, ';');
2289 if (s) { 2429 if (s) {
2290 // Retrieve command from expanded copy of line 2430 // Retrieve command from original or expanded copy of line
2291 char *copy3 = expand_macros(copy, FALSE); 2431 char *copy3 = expand_macros(copy, FALSE);
2292 if ((p = find_colon(copy3)) && (p = strchr(p, ';'))) 2432 if ((p = inline_command(copy)) || (p = inline_command(copy3)))
2293 newcmd(&cp, process_command(p + 1)); 2433 newcmd(&cp, process_command(p + 1));
2294 free(copy3); 2434 free(copy3);
2295 *s = '\0'; 2435 *s = '\0';
@@ -2486,8 +2626,7 @@ docmds(struct name *np, struct cmd *cp)
2486 uint32_t ssilent, signore, sdomake; 2626 uint32_t ssilent, signore, sdomake;
2487 2627
2488 // Location of command in makefile (for use in error messages) 2628 // Location of command in makefile (for use in error messages)
2489 makefile = cp->c_makefile; 2629 curr_cmd = cp;
2490 dispno = cp->c_dispno;
2491 opts &= ~OPT_make; // We want to know if $(MAKE) is expanded 2630 opts &= ~OPT_make; // We want to know if $(MAKE) is expanded
2492 q = command = expand_macros(cp->c_cmd, FALSE); 2631 q = command = expand_macros(cp->c_cmd, FALSE);
2493 ssilent = silent || (np->n_flag & N_SILENT) || dotouch; 2632 ssilent = silent || (np->n_flag & N_SILENT) || dotouch;
@@ -2581,13 +2720,38 @@ docmds(struct name *np, struct cmd *cp)
2581 estat = MAKE_DIDSOMETHING; 2720 estat = MAKE_DIDSOMETHING;
2582 } 2721 }
2583 2722
2584 makefile = NULL; 2723 curr_cmd = NULL;
2585 return estat; 2724 return estat;
2586} 2725}
2587 2726
2727/*
2728 * Remove the suffix from a name, either the one provided in 'tsuff'
2729 * or, if 'tsuff' is NULL, one of the known suffixes.
2730 */
2731static char *
2732remove_suffix(const char *name, const char *tsuff)
2733{
2734 char *base = NULL;
2735
2736 if (tsuff != NULL) {
2737 base = has_suffix(name, tsuff);
2738 } else {
2739 struct name *xp = newname(".SUFFIXES");
2740 for (struct rule *rp = xp->n_rule; rp; rp = rp->r_next) {
2741 for (struct depend *dp = rp->r_dep; dp; dp = dp->d_next) {
2742 base = has_suffix(name, dp->d_name->n_name);
2743 if (base) {
2744 return base;
2745 }
2746 }
2747 }
2748 }
2749 return base;
2750}
2751
2588static int 2752static int
2589make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc, 2753make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc,
2590 char *dedup, struct name *implicit) 2754 char *dedup, struct name *implicit, const char *tsuff)
2591{ 2755{
2592 char *name, *member = NULL, *base = NULL, *prereq = NULL; 2756 char *name, *member = NULL, *base = NULL, *prereq = NULL;
2593 2757
@@ -2603,7 +2767,7 @@ make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc,
2603 char *s; 2767 char *s;
2604 2768
2605 // As an extension, if we're not dealing with an implicit 2769 // As an extension, if we're not dealing with an implicit
2606 // rule set $< to the first out-of-date prerequisite. 2770 // prerequisite set $< to the first out-of-date prerequisite.
2607 if (implicit == NULL) { 2771 if (implicit == NULL) {
2608 if (oodate) { 2772 if (oodate) {
2609 s = strchr(oodate, ' '); 2773 s = strchr(oodate, ' ');
@@ -2614,15 +2778,26 @@ make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc,
2614 } else 2778 } else
2615 prereq = implicit->n_name; 2779 prereq = implicit->n_name;
2616 2780
2617 base = member ? member : name; 2781 if (!posix && member == NULL) {
2618 s = suffix(base); 2782 // As an extension remove a suffix that doesn't necessarily
2619 // As an extension, if we're not dealing with an implicit 2783 // start with a period from a target, but not for targets
2620 // rule and the target ends with a known suffix, remove it 2784 // of the form lib.a(member.o).
2621 // and set $* to the stem, else to an empty string. 2785 base = remove_suffix(name, tsuff);
2622 if (implicit == NULL && !is_suffix(s)) 2786 if (base) {
2623 base = NULL; 2787 free(name);
2624 else 2788 name = base;
2625 *s = '\0'; 2789 }
2790 } else {
2791 base = member ? member : name;
2792 s = suffix(base);
2793 // As an extension, if we're not dealing with an implicit
2794 // prerequisite and the target ends with a known suffix,
2795 // remove it and set $* to the stem, else to an empty string.
2796 if (implicit == NULL && !is_suffix(s))
2797 base = NULL;
2798 else
2799 *s = '\0';
2800 }
2626 } 2801 }
2627 setmacro("<", prereq, 0 | M_VALID); 2802 setmacro("<", prereq, 0 | M_VALID);
2628 setmacro("*", base, 0 | M_VALID); 2803 setmacro("*", base, 0 | M_VALID);
@@ -2667,11 +2842,12 @@ make(struct name *np, int level)
2667 struct depend *dp; 2842 struct depend *dp;
2668 struct rule *rp; 2843 struct rule *rp;
2669 struct name *impdep = NULL; // implicit prerequisite 2844 struct name *impdep = NULL; // implicit prerequisite
2670 struct rule imprule; 2845 struct rule infrule;
2671 struct cmd *sc_cmd = NULL; // commands for single-colon rule 2846 struct cmd *sc_cmd = NULL; // commands for single-colon rule
2672 char *oodate = NULL; 2847 char *oodate = NULL;
2673 char *allsrc = NULL; 2848 char *allsrc = NULL;
2674 char *dedup = NULL; 2849 char *dedup = NULL;
2850 const char *tsuff = NULL;
2675 struct timespec dtim = {1, 0}; 2851 struct timespec dtim = {1, 0};
2676 int estat = 0; 2852 int estat = 0;
2677 2853
@@ -2690,10 +2866,10 @@ make(struct name *np, int level)
2690 // as an extension, not for phony targets) 2866 // as an extension, not for phony targets)
2691 sc_cmd = getcmd(np); 2867 sc_cmd = getcmd(np);
2692 if (!sc_cmd && (posix || !(np->n_flag & N_PHONY))) { 2868 if (!sc_cmd && (posix || !(np->n_flag & N_PHONY))) {
2693 impdep = dyndep(np, &imprule); 2869 impdep = dyndep(np, &infrule, &tsuff);
2694 if (impdep) { 2870 if (impdep) {
2695 sc_cmd = imprule.r_cmd; 2871 sc_cmd = infrule.r_cmd;
2696 addrule(np, imprule.r_dep, NULL, FALSE); 2872 addrule(np, infrule.r_dep, NULL, FALSE);
2697 } 2873 }
2698 } 2874 }
2699 2875
@@ -2708,14 +2884,15 @@ make(struct name *np, int level)
2708 } 2884 }
2709 impdep = np; 2885 impdep = np;
2710 } 2886 }
2711 } 2887 } else {
2712 else {
2713 // If any double-colon rule has no commands we need 2888 // If any double-colon rule has no commands we need
2714 // an inference rule (but, as an extension, not for phony targets) 2889 // an inference rule.
2715 for (rp = np->n_rule; rp; rp = rp->r_next) { 2890 for (rp = np->n_rule; rp; rp = rp->r_next) {
2716 if (!rp->r_cmd) { 2891 if (!rp->r_cmd) {
2717 if (posix || !(np->n_flag & N_PHONY)) 2892 // Phony targets don't need an inference rule.
2718 impdep = dyndep(np, &imprule); 2893 if (!posix && (np->n_flag & N_PHONY))
2894 continue;
2895 impdep = dyndep(np, &infrule, &tsuff);
2719 if (!impdep) { 2896 if (!impdep) {
2720 if (doinclude) 2897 if (doinclude)
2721 return 1; 2898 return 1;
@@ -2741,11 +2918,14 @@ make(struct name *np, int level)
2741 // Each double-colon rule is handled separately. 2918 // Each double-colon rule is handled separately.
2742 if ((np->n_flag & N_DOUBLE)) { 2919 if ((np->n_flag & N_DOUBLE)) {
2743 // If the rule has no commands use the inference rule. 2920 // If the rule has no commands use the inference rule.
2921 // Unless there isn't one, as allowed for phony targets.
2744 if (!rp->r_cmd) { 2922 if (!rp->r_cmd) {
2745 locdep = impdep; 2923 if (impdep) {
2746 imprule.r_dep->d_next = rp->r_dep; 2924 locdep = impdep;
2747 rp->r_dep = imprule.r_dep; 2925 infrule.r_dep->d_next = rp->r_dep;
2748 rp->r_cmd = imprule.r_cmd; 2926 rp->r_dep = infrule.r_dep;
2927 rp->r_cmd = infrule.r_cmd;
2928 }
2749 } 2929 }
2750 // A rule with no prerequisities is executed unconditionally. 2930 // A rule with no prerequisities is executed unconditionally.
2751 if (!rp->r_dep) 2931 if (!rp->r_dep)
@@ -2776,7 +2956,7 @@ make(struct name *np, int level)
2776 if (((np->n_flag & N_PHONY) || timespec_le(&np->n_tim, &dtim))) { 2956 if (((np->n_flag & N_PHONY) || timespec_le(&np->n_tim, &dtim))) {
2777 if (!(estat & MAKE_FAILURE)) { 2957 if (!(estat & MAKE_FAILURE)) {
2778 estat |= make1(np, rp->r_cmd, oodate, allsrc, 2958 estat |= make1(np, rp->r_cmd, oodate, allsrc,
2779 dedup, locdep); 2959 dedup, locdep, tsuff);
2780 dtim = (struct timespec){1, 0}; 2960 dtim = (struct timespec){1, 0};
2781 } 2961 }
2782 free(oodate); 2962 free(oodate);
@@ -2792,7 +2972,7 @@ make(struct name *np, int level)
2792 } 2972 }
2793 } 2973 }
2794 if ((np->n_flag & N_DOUBLE) && impdep) 2974 if ((np->n_flag & N_DOUBLE) && impdep)
2795 free(imprule.r_dep); 2975 free(infrule.r_dep);
2796 2976
2797 np->n_flag |= N_DONE; 2977 np->n_flag |= N_DONE;
2798 np->n_flag &= ~N_DOING; 2978 np->n_flag &= ~N_DOING;
@@ -2801,7 +2981,8 @@ make(struct name *np, int level)
2801 ((np->n_flag & N_PHONY) || (timespec_le(&np->n_tim, &dtim)))) { 2981 ((np->n_flag & N_PHONY) || (timespec_le(&np->n_tim, &dtim)))) {
2802 if (!(estat & MAKE_FAILURE)) { 2982 if (!(estat & MAKE_FAILURE)) {
2803 if (sc_cmd) 2983 if (sc_cmd)
2804 estat |= make1(np, sc_cmd, oodate, allsrc, dedup, impdep); 2984 estat |= make1(np, sc_cmd, oodate, allsrc, dedup,
2985 impdep, tsuff);
2805 else if (!doinclude && level == 0 && !(estat & MAKE_DIDSOMETHING)) 2986 else if (!doinclude && level == 0 && !(estat & MAKE_DIDSOMETHING))
2806 warning("nothing to be done for %s", np->n_name); 2987 warning("nothing to be done for %s", np->n_name);
2807 } else if (!doinclude && !quest) { 2988 } else if (!doinclude && !quest) {
diff --git a/miscutils/man.c b/miscutils/man.c
index 3954455b4..38c1b9aa3 100644
--- a/miscutils/man.c
+++ b/miscutils/man.c
@@ -143,7 +143,7 @@ static int run_pipe(char *man_filename, int man, int level)
143 143
144 ordinary_manpage: 144 ordinary_manpage:
145 close(STDIN_FILENO); 145 close(STDIN_FILENO);
146 open_zipped(man_filename, /*fail_if_not_compressed:*/ 0); /* guaranteed to use fd 0 (STDIN_FILENO) */ 146 open_zipped(man_filename, /*die_if_not_compressed:*/ 0); /* guaranteed to use fd 0 (STDIN_FILENO) */
147 if (man) { 147 if (man) {
148 int w = get_terminal_width(-1); 148 int w = get_terminal_width(-1);
149 if (w > 10) 149 if (w > 10)