/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matthias Scheler.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
if (buf == MAP_FAILED)
err(EXIT_FAILURE, "unable to mmap file %s", fname);
lim = buf + sz - 1;
/* Remove leading "./" from filenames */
for (ptr = buf; ptr < lim; ptr++) {
if (ptr[1] != '.' || ptr[2] != '/'
|| !isspace((unsigned char)ptr[0]))
continue;
ptr[1] = ' ';
ptr[2] = ' ';
}
for (line = eol = buf; eol <= lim;) {
while (eol <= lim && *eol++ != '\n')
/* Find end of this line */
continue;
if (line == eol - 1) {
/* empty line - ignore */
line = eol;
continue;
}
if (eol[-2] == '\\')
/* Assemble continuation lines */
continue;
for (colon = line; *colon != ':'; colon++) {
if (colon >= eol) {
colon = NULL;
break;
}
}
if (isspace((unsigned char)*line) || colon == NULL) {
/* No dependency - just transcribe line */
if (write(dependfile, line, eol - line) < 0)
goto wrerror;
line = eol;
continue;
}
if (suff_list != NULL) {
/* Find the .o: */
/* First allow for any whitespace */
for (suf = colon; suf > buf; suf--) {
if (!isspace((unsigned char)suf[-1]))
break;
}
if (suf == buf)
errx(EXIT_FAILURE,
"Corrupted file `%s'", fname);
/* Then look for any valid suffix */
for (sl = suff_list; sl != NULL;
sl = sl->next) {
if (sl->len && buf <= suf - sl->len &&
!memcmp(suf - sl->len, sl->suff,
sl->len))
break;
}
/*
* Not found, check for .o, since the
* original file will have it.
*/
if (sl == NULL) {
if (memcmp(suf - 2, ".o", 2) == 0)
slen = 2;
else
slen = 0;
} else
slen = sl->len;
}
if (suff_list != NULL && slen != 0) {
suf -= slen;
for (sl = suff_list; sl != NULL; sl = sl->next)
{
if (sl != suff_list)
if (write(dependfile, " ", 1)
< 0)
goto wrerror;
if (prefix != NULL)
if (write(dependfile, prefix,
strlen(prefix)) < 0)
goto wrerror;
if (write(dependfile, line,
suf - line) < 0)
goto wrerror;
if (write(dependfile, sl->suff,
sl->len) < 0)
goto wrerror;
}
if (write(dependfile, colon, eol - colon) < 0)
goto wrerror;
} else {
if (prefix != NULL)
if (write(dependfile, prefix,
strlen(prefix)) < 0)
goto wrerror;
if (write(dependfile, line, eol - line) < 0)
goto wrerror;
}
if (oflag)
save_for_optional(colon + 1, eol);
line = eol;
}
munmap(buf, sz);
}
if (oflag && opt != NULL) {
if (write(dependfile, ".OPTIONAL:", 10) < 0)
goto wrerror;
width = 9;
sz = write_optional(dependfile, opt, 0);
if (sz == (size_t)-1)
goto wrerror;
/* 'depth' is about 39 for an i386 kernel */
/* fprintf(stderr, "Recursion depth %d\n", sz); */
}
close(dependfile);
exit(EXIT_SUCCESS);
wrerror:
err(EXIT_FAILURE, "unable to %s to file %s",
aflag & O_TRUNC ? "write" : "append", filename);
}
/*
* Only save each file once - the kernel .depend is 3MB and there is
* no point doubling its size.
* The data seems to be 'random enough' so the simple binary tree
* only has a reasonable depth.
*/
static void
save_for_optional(const char *start, const char *limit)
{
opt_t **l, *n;
const char *name, *end;
int c;
while (start < limit && strchr(" \t\n\\", *start))
start++;
for (name = start; ; name = end) {
while (name < limit && strchr(" \t\n\\", *name))
name++;
for (end = name; end < limit && !strchr(" \t\n\\", *end);)
end++;
if (name >= limit)
break;
if (end[-1] == 'c' && end[-2] == '.' && name == start)
/* ignore dependency on the files own .c */
continue;
for (l = &opt;;) {
n = *l;
if (n == NULL) {
n = malloc(sizeof *n + (end - name));
n->left = n->right = 0;
n->len = end - name;
n->count = 1;
n->name[0] = ' ';
memcpy(n->name + 1, name, end - name);
*l = n;
break;
}
c = (end - name) - n->len;
if (c == 0)
c = memcmp(n->name + 1, name, (end - name));
if (c == 0) {
/* Duplicate */
n->count++;
break;
}
if (c < 0)
l = &n->left;
else
l = &n->right;
}
}
}