diff options
Diffstat (limited to '')
| -rw-r--r-- | miscutils/crond.c | 12 | ||||
| -rw-r--r-- | miscutils/fbsplash.c | 2 | ||||
| -rw-r--r-- | miscutils/less.c | 2 | ||||
| -rw-r--r-- | miscutils/make.c | 353 | ||||
| -rw-r--r-- | miscutils/man.c | 2 |
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 | ||
| 262 | struct globals { | 267 | struct 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 | ||
| 322 | static int make(struct name *np, int level); | 329 | static int make(struct name *np, int level); |
| 323 | 330 | static 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); | |||
| 336 | static void | 340 | static void |
| 337 | vwarning(FILE *stream, const char *msg, va_list list) | 341 | vwarning(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 | */ |
| 1002 | static struct name * | 1025 | static struct name * |
| 1003 | dyndep(struct name *np, struct rule *imprule) | 1026 | dyndep0(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 | */ | ||
| 1091 | static char * | ||
| 1092 | has_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 | */ | ||
| 1112 | static struct name * | ||
| 1113 | dyndep(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 | */ |
| 1794 | static int | 1885 | static const char * |
| 1795 | is_suffix(const char *s) | 1886 | is_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 | */ | ||
| 1907 | static int | ||
| 1908 | is_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 { | |||
| 1824 | static int | 1947 | static int |
| 1825 | target_type(char *s) | 1948 | target_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 | */ | ||
| 2201 | static char * | ||
| 2202 | inline_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 | */ |
| 2074 | static void | 2214 | static 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 | */ | ||
| 2731 | static char * | ||
| 2732 | remove_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 | |||
| 2588 | static int | 2752 | static int |
| 2589 | make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc, | 2753 | make1(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) |
