#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINESIZE 65536 // NeXT_MOD
#define OUTLINELEN 79
#define IObuffer 50000
#define SALUTATION "# Dependencies for File:"
#define SALUTATIONLEN (sizeof SALUTATION - 1)
#define OLDSALUTATION "# DO NOT DELETE THIS LINE"
#define OLDSALUTATIONLEN (sizeof OLDSALUTATION - 1)
char file_array[IObuffer];
char dep_line[LINESIZE];
char dot_o[LINESIZE];
char *path_component[100];
struct dep {
int len;
char *str;
} dep_files[1000];
int dep_file_index;
qsort_strcmp(a, b)
struct dep *a, *b;
{
extern int strcmp();
return strcmp(a->str, b->str);
}
char *outfile = (char *) 0;
FILE *out;
char *makefile = (char *) 0;
char *real_mak_name;
char shadow_mak_name[LINESIZE];
FILE *mak;
FILE *makout;
char makbuf[LINESIZE];
struct stat makstat;
int mak_eof = 0;
FILE *find_mak(), *temp_mak();
int delete = 0;
int debug = 0;
int D_contents = 0;
int D_depend = 0;
int D_make = 0;
int D_open = 0;
int D_time = 0;
int force = 1;
int update = 0;
int verbose = 0;
int expunge = 0;
char *name;
static void scan_mak(FILE *, FILE *, char *);
static void finish_mak(FILE *, FILE *);
main(argc,argv)
register char **argv;
{
int size;
name = *argv;
{register char *cp =name;
while (*cp) if (*cp++ == '/') name = cp;
}
for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
if (*token++ != '-' || !*token)
break;
else { register int flag;
for ( ; flag = *token++ ; ) {
switch (flag) {
case 'd':
delete++;
break;
case 'f':
force++;
break;
case 'u':
update++;
case 'm':
makefile = *++argv;
if (--argc < 0) goto usage;
break;
case 'o':
outfile = *++argv;
if (--argc < 0) goto usage;
break;
case 'v':
verbose++;
break;
case 'x':
expunge++;
break;
case 'D':
for ( ; flag = *token++ ; )
switch (flag) {
case 'c':
D_contents++;
break;
case 'd':
D_depend++;
break;
case 'm':
D_make++;
break;
case 'o':
D_open++;
break;
case 't':
D_time++;
break;
case 'D':
debug++;
break;
default:
goto letters;
}
goto newtoken;
default:
goto usage;
}
letters: ;
}
}
newtoken: ;
}
if (!expunge && argc < 1) goto usage;
if ((int) outfile && (int) makefile)
goto usage;
if ((int) outfile) {
unlink(outfile);
if ((out = fopen(outfile, "w")) == NULL) {
fprintf(stderr, "%s: outfile = \"%s\" ", name, outfile);
perror("fopen");
fflush(stdout), fflush(stderr);
exit(1);
} else if (D_open)
printf("%s: opened outfile \"%s\"\n", name, outfile);
} else if (mak = find_mak(makefile)) {
makout = temp_mak();
out = makout;
if (expunge)
expunge_mak(mak, makout);
else
skip_mak(mak, makout);
} else if (mak_eof &&
(int)(makout = temp_mak())) {
out = makout;
} else if (makefile) {
fprintf(stderr, "%s: makefile \"%s\" can not be opened or stat'ed\n",
name, makefile);
exit(2);
}
for (; argc--; argv++) {
dep_file_index = 0;
if (size = read_dep(*argv)) {
save_dot_o();
if (D_depend) printf("%s: dot_o = \"%s\"\n", name, dot_o);
parse_dep();
if (mak) scan_mak(mak, makout, dot_o);
if (out) output_dep(out);
if (delete)
unlink(*argv);
}
}
if (mak) finish_mak(mak, makout);
rename(shadow_mak_name, real_mak_name);
exit(0);
usage:
fprintf(stderr, "usage: md -f -Dcdmot -m makefile -o outputfile -v <file1> ... <filen>\n");
exit(1);
}
read_dep(file)
register char *file;
{
register int fd;
register int size;
struct stat statbuf;
if ((fd = open(file, 0)) < 0) {
fprintf(stderr, "%s: file = \"%s\" ", name, file);
perror("open");
fflush(stdout), fflush(stderr);
return 0;
}
if (D_open)
printf("%s: opened dependency file \"%s\"\n", name, file);
if (fstat(fd, &statbuf) < 0) {
fprintf(stderr, "%s: file = \"%s\" ", name, file);
perror("stat");
fflush(stdout), fflush(stderr);
goto out;
}
switch(statbuf.st_mode & S_IFMT) {
case S_IFREG:
if (D_time)
printf("%s: file time = %d\n", name, statbuf.st_mtime);
if (statbuf.st_size > IObuffer) {
fprintf(stderr, "%s: file \"%s\" tooo big for IObuffer\n",
name, file);
goto out;
} else if (force)
break;
else if ((int) mak && statbuf.st_mtime < makstat.st_mtime) {
if (verbose || D_time)
fprintf(stderr, "%s: skipping \"%s\" %d < %d \"%s\"\n",
name, file, statbuf.st_mtime, makstat.st_mtime,
real_mak_name);
goto out;
} else
break;
case S_IFDIR:
case S_IFLNK:
case S_IFCHR:
case S_IFBLK:
case S_IFSOCK:
default:
fprintf(stderr, "%s: bad mode: 0%o on \"%s\"\n",
name, statbuf.st_mode, file);
fflush(stdout), fflush(stderr);
goto out;
}
if ((size = read(fd, file_array, sizeof (file_array))) < 0) {
fprintf(stderr, "%s: file = \"%s\" ", name, file);
perror("read");
fflush(stdout), fflush(stderr);
goto out;
}
file_array[size] = 0;
if (close(fd) < 0) {
fprintf(stderr, "%s: file = \"%s\" ", name, file);
perror("close");
fflush(stdout), fflush(stderr);
return 0;
}
if (D_depend && D_contents)
printf("file_array: \"%s\"\n", file_array);
return size;
out: ;
close(fd);
return 0;
}
save_dot_o()
{
register char *cp = file_array;
register char *svp = dot_o;
register int c;
while ((*svp++ = (c = *cp++)) && c != ':');
*svp = 0;
}
parse_dep()
{
register char *lp = file_array;
register int c;
while (*lp) {register char *tlp = lp;
register char *cp = dep_line;
register int i = 0;
int abspath = 0;
char oldc;
char *oldcp;
while ((c = *lp++) && c != '\n')
{
if (c == '\\')
lp++;
else
*cp++ = c;
}
if (!c)
break;
*cp = 0;
cp = dep_line;
lp[-1] = 0;
while ((c = *cp++) && c != ':'); if (!c) continue;
next_filename:
i = 0;
abspath = 0;
while ((c = *cp) && (c == ' ' || c == '\t')) cp++; if (!c) continue;
if (c == '/')
abspath++;
while (c && c != ' ' && c != '\t') {
if (D_depend) printf("i = %d going \"%s\"\n", i, cp);
while ((c = *cp) && c == '/') cp++; if (!c) break;
path_component[i] = cp;
while ((c = *cp++) && c != '/' && c != ' ' && c != '\t');
if (c) cp[-1]=0;
;
if (!strcmp(path_component[i], "."))
;
else
i++;
}
oldc = c;
oldcp = cp;
cp = tlp;
if (abspath)
*cp++ = '/';
for (c=0; c<i; c++) {register char *ccp = path_component[c];
while (*cp++ = *ccp++);
*--cp = '/';
cp++;
}
*--cp = 0;
c=dep_file_index++;
dep_files[c].str = tlp;
dep_files[c].len = cp - tlp;
if (D_depend)
printf("%s: dep_file[%d] = \"%s\" Len %d\n",
name, dep_file_index - 1, tlp, cp - tlp);
tlp = cp + 1;
if (oldc)
{
cp = oldcp;
goto next_filename;
}
}
}
output_dep(out)
FILE *out;
{
register int j;
register int size = 1000;
register int dot_o_len = strlen(dot_o);
register struct dep *dp = dep_files;
int written = 0;
if (D_depend && debug)
for(j = 0; j < dep_file_index; j++) {
printf("dep_files[%d] = %s\n", j, dep_files[j].str);
}
qsort(dep_files, dep_file_index, sizeof (struct dep), qsort_strcmp);
if (D_depend && debug)
for(j = 0; j < dep_file_index; j++) {
printf("dep_files[%d] = %s\n", j, dep_files[j].str);
}
fprintf(out, "%s %s", SALUTATION, dot_o);
for(j = 0; j < dep_file_index; j++, dp++)
{register int len = dp->len;
register char *str = dp->str;
if (j && len == (dp-1)->len && !strcmp(str, (dp-1)->str))
continue;
written++;
if (size + len + 1 > OUTLINELEN) {
fprintf(out, "\n%s %s", dot_o, str);
size = dot_o_len + len + 1;
} else {
fprintf(out, " %s", str);
size += len + 1;
}
}
fprintf(out, "\n");
if (verbose)
fprintf(stdout, "%s: \"%s\" %d => %d\n", name, dot_o, dep_file_index, written);
}
FILE *
find_mak(file)
char *file;
{
FILE *mak;
if ((int) file) {
if ((mak = fopen(file, "r")) != NULL) {
real_mak_name = file;
} else if (update) {
mak_eof = 1;
real_mak_name = file;
return NULL;
} else {
fprintf(stderr, "%s: file = \"%s\" ", name, file);
perror("fopen");
fflush(stdout), fflush(stderr);
return NULL;
}
} else {
if ((mak = fopen("makefile", "r")) != NULL) {
real_mak_name = "makefile";
} else if ((mak = fopen("Makefile", "r")) != NULL) {
real_mak_name = "Makefile";
} else return NULL;
}
if (fstat(fileno(mak), &makstat) < 0) {
fprintf(stderr, "%s: file = \"%s\" ", name, real_mak_name);
perror("stat");
fflush(stdout), fflush(stderr);
return NULL;
}
if (D_open)
printf("%s: opened makefile \"%s\"\n", name, real_mak_name);
if (D_time)
printf("%s: makefile time = %d\n", name, makstat.st_mtime);
return mak;
}
FILE *
temp_mak()
{
FILE *mak;
strcpy(shadow_mak_name, real_mak_name);
strcat(shadow_mak_name, ".md");
unlink(shadow_mak_name);
if ((mak = fopen(shadow_mak_name, "w")) == NULL) {
fprintf(stderr, "%s: file = \"%s\" ", name, shadow_mak_name);
perror("fopen");
fflush(stdout), fflush(stderr);
return NULL;
}
if (D_open)
printf("%s: opened makefile.md \"%s\"\n", name, shadow_mak_name);
return mak;
}
skip_mak(makin, makout)
register FILE *makin, *makout;
{
register int len = SALUTATIONLEN;
if (D_make)
printf("skipping in \"%s\" ", real_mak_name);
while (fgets(makbuf, LINESIZE, makin) != NULL) {
if (D_make && D_contents)
printf("%s: \"%s\"\n", real_mak_name, makbuf);
if (strncmp(makbuf, SALUTATION, len)) {
fputs(makbuf, makout);
} else
break;
}
mak_eof = feof(makin);
if (mak_eof)
fclose(makin);
if (D_make)
printf("eof = %d str = \"%s\"", mak_eof, makbuf);
}
expunge_mak(makin, makout)
register FILE *makin, *makout;
{
register int len = SALUTATIONLEN;
register int oldlen = OLDSALUTATIONLEN;
if (D_make)
printf("expunging in \"%s\" ", real_mak_name);
while (fgets(makbuf, LINESIZE, makin) != NULL) {
if (D_make && D_contents)
printf("%s: \"%s\"\n", real_mak_name, makbuf);
if (! strncmp(makbuf, SALUTATION, len) ||
! strncmp(makbuf, OLDSALUTATION, oldlen))
break;
else
fputs(makbuf, makout);
}
mak_eof = 1;
if (mak_eof)
fclose(makin);
if (D_make)
printf("eof = %d str = \"%s\"", mak_eof, makbuf);
}
static void
scan_mak(FILE *makin, FILE *makout, char *file)
{
register char *cp = &makbuf[SALUTATIONLEN+1];
register int len = strlen(file);
register int ret;
if (D_make)
printf("scanning in \"%s\" for \"%s\"\n", real_mak_name, file);
do {
if (mak_eof)
return;
ret = strncmp(cp, file, len);
if (D_make)
printf("saw \"%s\" ret = %d\n", cp, ret);
if (ret < 0) {
fputs(makbuf, makout);
while (fgets(makbuf, LINESIZE, makin) != NULL) {
if (strncmp(makbuf, SALUTATION, SALUTATIONLEN)) {
fputs(makbuf, makout);
} else
break;
}
mak_eof = feof(makin);
if (mak_eof)
fclose(makin);
continue;
} else if (ret == 0) {
while (fgets(makbuf, LINESIZE, makin) != NULL) {
if (strncmp(makbuf, SALUTATION, SALUTATIONLEN)) {
;
} else
break;
}
mak_eof = feof(makin);
if (mak_eof)
fclose(makin);
break;
} else {
break;
}
} while (1);
}
static void
finish_mak(FILE *makin, FILE *makout)
{
if (mak_eof)
return;
if (D_make)
printf("finishing in \"%s\"\n", real_mak_name);
fputs(makbuf, makout);
while (fgets(makbuf, LINESIZE, makin) != NULL) {
fputs(makbuf, makout);
}
}