DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T m

⟦f20dfccae⟧ TextFile

    Length: 17105 (0x42d1)
    Types: TextFile
    Names: »maketd.c«

Derivation

└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/laser-setters/dvi-to-ps/maketd/maketd.c« 

TextFile


/*
 * maketd - MAKE Transitive Dependencies. 
 * (This is a lie - the dependencies are not transitive, 
 * but "all" dependencies are correctly made.) 
 *
 * Based loosely on a shell script by Stephan Bechtolsheim
 * Other makefile related features have been added or merged in from other
 * programs. 
 *
 * Written & hacked by Stephen Uitti, PUCC staff, 1985 
 * maketd is Copyright (C) Purdue University, 1985 
 *
 * removed some of Steve's good, but unnecessary, options in favor of more
 * compile time flags & better implicit rules in the makefile 
 * dinked: -q -e * -E -k 
 * Kevin S Braunsdorf, PUCC UNIX Group 1986	(ksb@j.cc.purdue.edu) 
 *
 * Permission is hereby given for its free reproduction and modification for
 * non-commercial purposes, provided that this notice and all embedded
 * copyright notices be retained. Commercial organizations may give away
 * copies as part of their systems provided that they do so without charge,
 * and that they acknowledge the source of the software. 
 */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>		/* for access */
#ifdef pdp11
#include <ndir.h>		/* for MAXPATHLEN, MAXNAMLEN */
#endif
#ifndef pdp11
#include <sys/dir.h>		/* for MAXNAMLEN in 4.2 */
#endif
#include <ctype.h>		/* for isupper */
#include <stdio.h>
extern char *
rindex(), *index(), *strcat(), *strcpy();

#include "srtunq.h"
#include "abrv.h"
#ifndef SYSV
#include "nshpopen.h"
#endif
#include "maketd.h"

#ifndef CPP
#define CPP	"/lib/cpp "
#endif CPP not in Makefile

#ifndef M4
#define M4	"/usr/bin/m4 -M "
#endif M4

/* forward functions */
void    msoio();		/* open output file */
void    rdwr();			/* read old Makefile into new */
void    mkdepend();		/* does the real work */

/* globals */
char   *prgnm;			/* our program name		 */
FILE   *makefd;			/* makefile stream		 */
int     alldep = FALSE;		/* -a all - /usr/include too	 */
char   *targetname = NULL;	/* -t target name for next file */
char   *destsuffix = ".o";	/* -s suffix for targets	 */
int     header = TRUE;		/* print header & trailer	 */
int     usestdout = FALSE;	/* -d use stdout for makefile	 */
int     forcehead = FALSE;	/* -f force header/trailer	 */
int     makenseen = FALSE;	/* output file has been specified */
char   *makename = "makefile";	/* -m default file for edit	 */
int     backedup = FALSE;	/* for interupt recovery	 */
char    backupfn[MAXNAMLEN + 1];/* backup file name		 */
int     ismakeopen = FALSE;	/* if the output file is open	 */
char    objpath[MAXPATHLEN + 1];/* -o prepended to .o's		 */
int     nonlocalo = FALSE;	/* -nonlocalo objects in source dir */
int     replace = FALSE;	/* -r replace depends in Makefile */
char    cppflags[BUFSIZ];	/* -D, -I, -U flags to pass to cpp */
int     shortincl = TRUE;	/* -x do abreviations		 */
int     verbose = FALSE;	/* -v verbage for the debugger	 */

#ifdef M4_M
int     usem4 = FALSE;		/* -4 use m4 in place of cpp */
static char sopts[] = "4abdfhrxv";

#else  M4_M
static char sopts[] = "abdfhrxv";	/* single char opts		 */

#endif M4_M
static SRTUNQ u;		/* unique include files		 */

char    usage[] =
#ifdef M4_M
"Usage: maketd [-a -b -d -f -h -mMAKEFILE -nonlocalo -oDIR -r -sSUFFIX\n\
 -tTARGETNAME -x -v -Iincludedir -Ddefine -Uundefine file...]\n";

#else  M4_M
"Usage: maketd [-4 -a -b -d -f -h -mMAKEFILE -nonlocalo -oDIR -r -sSUFFIX\n\
 -tTARGETNAME -x -v -Iincludedir -Ddefine -Uundefine file...]\n";

#endif
static char *helptext[] = {
#ifdef M4_M
	"-4\tUse m4 in place of cpp\n",
#endif M4_M
	"-a\tdo all dependencies, including /usr/include\n",
	"-b\tgenerate binary, rather than object related dependencies\n",
	"-d\tdependencies to stdout, rather than Makefile\n",
	"-f\tforce header/trailer (use with -d)\n",
	"-h\thelp (this text)\n",
	"-m\tspecify MAKEFILE for edit\n",
	"-nonlocalo Objects live in source directory\n",
	"-o\tprepend DIR to target: DIR/a.o: foo.h\n",
	"-r\treplace dependencies for a target\n",
	"-s\tchange suffix target's SUFFIX: a.SUFFIX: foo.h\n",
	"-t\tchange target's basename: TARGET.o: foo.h\n",
	"-x\tdon't abbreviate includes\n",
	"-v\tprint extra verbose (debug) output to stderr\n",
	"-I\tspecify include directory, as in /lib/cpp\n",
	"-D\tspecify defines, as in /lib/cpp\n",
	"-U\tspecify undefines, as in /lib/cpp\n",
	(char *) 0
};

char    deplin[] = "# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT\n";
char    searchdep[] = "# DO NOT DELETE THIS LINE";
char    trailer[] = "\n# *** Do not add anything here - It will go away. ***\n";

/* some init & argv parsing */
main(argc, argv)
register int argc;
register char **argv;
{
	register a;		/* argv subscript		 */
	register i;		/* tmp				 */
	register len;		/* length of current argument	 */
	register files = FALSE;	/* files ever seen		 */
	register char *q;	/* tmp				 */

	/* prgnm = program name, for error printing */
	if ((prgnm = rindex(argv[0], '/')) == NULL)
		prgnm = argv[0];
	else
		prgnm++;
	catchsig();		/* init signal traps */
	srtinit(&abrv);		/* init abbreviations tree */
	for (a = 1; a < argc; a++) {	/* argv prepass: find all -I's */
		if (argv[a][0] == '-' && argv[a][1] == 'I' && strlen(&argv[a][2]) > 2)
			if ((q = srtin(&abrv, hincl(&argv[a][2]), lngsrt)) != NULL)
				fprintf(stderr, "%s: %s - %s\n", prgnm, q, &argv[a][2]);
	}
	cppflags[0] = '\0';	/* terminate cpp flags string */
	objpath[0] = '\0';	/* init object path */
	srtinit(&u);		/* init sorting database tag */
	for (a = 1; a < argc; a++) {
		len = strlen(argv[a]);
		if (argv[a][0] == '-' && len > 2 && index(sopts, argv[a][1]) != NULL)
			err("options must be listed seperately - '%s'\n", argv[a]);
		if (len > 1 && argv[a][0] == '-') {
			switch (argv[a][1]) {
#ifdef M4_M
			case '4':
				usem4 = TRUE;
				break;
#endif M4_M
			case 'D':	/* /lib/cpp flags to pass */
			case 'I':
			case 'U':
				if (strlen(cppflags) + strlen(argv[a]) + 2 > BUFSIZ)
					err("too many cpp flags - buffer overflow");
				strcat(cppflags, argv[a]);
				strcat(cppflags, " ");	/* add a space separator */
				break;
			case 'a':	/* /usr/include deps too */
				alldep = TRUE;
				break;
			case 'b':	/* target has no suffix */
				destsuffix = "";
				break;
			case 'd':	/* don't edit Makefile */
				if (ismakeopen)
					err("Makefile already open, -d must precede filenames");
				if (makenseen)
					err("Conflict - check -d and -m options");
				makenseen = TRUE;
				usestdout = TRUE;
				if (!forcehead)
					header = FALSE;	/* don't do header &
							 * trailer */
				break;
			case 'f':	/* force header/trailer */
				forcehead = TRUE;
				header = TRUE;
				break;
			case 'h':	/* help */
				fputs(usage, stdout);
				for (i = 0; NULL != helptext[i]; i++)
					fputs(helptext[i], stdout);
				exit(0);
				break;
			case 'm':	/* specify makefile name for edit */
				if (ismakeopen)
					err("Makefile already open, -m must precede filenames");
				if (makenseen)
					err("Conflict, check -m and -d options.");
				if (strlen(makename) == 0)
					err("-m option requires file name.");
				makenseen = TRUE;
				makename = &argv[a][2];
				break;
			case 'n':	/* objects reside with sources */
				if (strcmp("nonlocalo", &argv[a][1]) != 0)
					err("bad -n option");	/* what a crock of an
								 * option */
				if (objpath[0] != '\0')
					err("nonlocalo conflict - check -o's");
				nonlocalo = TRUE;
				break;
			case 'o':
				if (nonlocalo)
					err("object path conflict - check -o's and -nonlocalo's");
				strcpy(objpath, &argv[a][2]);
				i = strlen(objpath);
				if (i == 0)
					err("-o requires path string.");
				if (i >= MAXPATHLEN)
					err("Object path too long: max is %d.", MAXPATHLEN);
				if (objpath[i - 1] != '/')
					strcat(objpath, "/");
				break;
			case 'r':	/* replace mode */
				if (ismakeopen)
					err("Makefile already open, -r must precede filenames");
				replace = TRUE;
				break;
			case 's':	/* destination suffix */
				destsuffix = &argv[a][2];
				break;
			case 't':	/* set target's basename */
				targetname = &argv[a][2];
				if (len <= 2)
					err("target option requires name.");
				break;
			case 'v':	/* user wants to hear noise */
				verbose = TRUE;
				break;
			case 'x':	/* don't abbrev. */
				if (files)
					err("-x option must preceed all files.");
				shortincl = FALSE;
				break;
			default:
				err("Unknown option %s.", argv[a]);
			}	/* end switch */
		} else {	/* must be a filename */
			if (verbose)
				fprintf(stderr, "%s: working on %s.\n", prgnm, argv[a]);
			files = TRUE;	/* at least one file seen */
			if (replace && a != argc - 1)
				err("Only one file allowed with -r (edit aborted)");
			mkdepend(argv[a]);	/* file to process */
			targetname = NULL;	/* affect only one file */
		}		/* if option */
	}			/* for argv */
	if (ismakeopen && header)
		fputs(trailer, makefd);	/* do not delete... */
#if	DEL_BACKUP
	if (backedup)
		if (unlink(backupfn))
			err("Can't delete backup file %s on completion", backupfn);
#endif	DEL_BACKUP
	if (!files)
		err("No files to process, use -h for full help.\n%s", usage);
	exit(0);		/* exit status - good */
}

/*
 * msoio - Make Sure Output Is Open. 
 * Interacts strongly via globals: makefd, backedup, backupfn, 
 * makename, header, ismakeopen 
 */
void
msoio(targ)
char   *targ;			/* if -r, is target name */
{
	FILE   *tmpfd;		/* temp file desc for -d */
	char    buf[BUFSIZ];	/* for reading the makefile */

	if (ismakeopen)
		return;
	ismakeopen = TRUE;	/* will be: all errs are fatal */
	if (usestdout) {
		makefd = stdout;
		if (header) {
			fputc('\n', makefd);	/* one blank line */
			fputs(deplin, makefd);	/* the first line */
		}
		/* scan "makefile" or "Makefile" for include defines */
		if (access(makename, R_OK) != 0) {
			makename[0] = 'M';	/* try Makefile */
			if (access(makename, R_OK) != 0)
				return;	/* just punt */
		}
		if ((tmpfd = fopen(makename, "r")) == NULL)
			return;	/* just punt */
		while (fgets(buf, BUFSIZ, tmpfd) != NULL)
			srchincl(buf);	/* scan whole file */
		fclose(tmpfd);
		return;
	}			/* ... if standard out */
	/*  !makenseen means (default) try "makefile" then "Makefile" */
	if (!makenseen && access(makename, F_OK) != 0)
		makename[0] = 'M';	/* try Makefile */
	/* side effect: "Makefile" will be created if neither exist */
	if (access(makename, F_OK) == 0) {	/* if makefile exits */
		strcpy(backupfn, makename);	/* get rid of .bak */
		strcat(backupfn, ".bak");
		if (access(backupfn, F_OK) == 0) {
			if (unlink(backupfn))
				err("Can't remove %s for pre-edit\n", backupfn);
		}
		if (link(makename, backupfn))	/* mv makefile to .bak */
			err("Can't link %s to %s.", backupfn, makename);
		backedup = TRUE;/* for interupt status */
		if (unlink(makename))
			err("Can't unlink %s during rename.", makename);
	} else {
		backupfn[0] = '\0';	/* no copy (no makefile) */
	}
	if ((makefd = fopen(makename, "w")) == NULL)
		err("Can't open output file '%s' for write.", makename);
	if (backupfn[0] != '\0')/* if no .bak file - done */
		rdwr(targ);	/* read/write Makefile */
	else
		fputs(deplin, makefd);	/* must start with this */
}

/* create beginging of new Makefile by reading old one */
void
rdwr(targ)
char   *targ;
{
	register FILE *oldfd;	/* file pointer for .old */
	char    rwbuf[BUFSIZ];	/* temp for read/write */
	register tlen;		/* targ length */
	register puntln = FALSE;/* punt current line? */
	register contln = FALSE;/* previous line ended with '\'? */
	register blankln = 0;	/* number of blank lines seen */
	register srchsn = FALSE;/* search line seen? */

	if ((oldfd = fopen(backupfn, "r")) == NULL)
		err("Can't open backup copy of %s\n", makename);
	tlen = strlen(targ);
	while (fgets(rwbuf, BUFSIZ, oldfd) != NULL) {	/* until EOF */
		if (!srchsn) {
			if (strncmp(searchdep, rwbuf, (sizeof searchdep) - 1) == 0) {
				srchsn = TRUE;
				fputs(deplin, makefd);	/* re-write this line */
				if (!replace)
					break;
				continue;	/* don't print this line */
			}
		} else {
			if (strcmp("\n", rwbuf) == 0) {
				if (!puntln)
					blankln++;
				contln = FALSE;
				puntln = FALSE;
				continue;	/* don't output this blank
						 * line */
			}
			if (!contln) {
				if (strncmp(targ, rwbuf, tlen) == 0)
					puntln = TRUE;
				else if (strcmp(&trailer[1], rwbuf) == 0)
					puntln = TRUE;
			}
			if (lastlnch(rwbuf) == '\\')
				contln = TRUE;
			else
				contln = FALSE;
		}		/* if srchsn */
		if (!puntln) {
			srchincl(&rwbuf[0]);	/* search this line for
						 * defines */
			if (blankln != 0) {	/* compress mult blank lines
						 * to one */
				putc('\n', makefd);
				blankln = 0;
			}
			fputs(rwbuf, makefd);	/* non targ lines */
		}
	}			/* while fgets */
	if (!srchsn)		/* deplin never found */
		fputs(deplin, makefd);	/* so write one */
	(void) fclose(oldfd);	/* close the .old file for gigles */
}

#define MAXCOL 78		/* output width max for makefile */

/* mkdepend - name is historical, but does the "real work" */
void
mkdepend(infile)
char   *infile;
{
	register char *p;	/* temp pointer */
	register char *q;	/* temp pointer */
	register char *r;	/* temp pointer */
	register FILE *cppfd;	/* file desc for /lib/cpp */
	char    buf[BUFSIZ];	/* temp buff */
	char    basename[MAXNAMLEN + 1];	/* just the file name */
	register oplen;		/* length target & path */
	register le;		/* length of current output line */
	register char *targ;	/* target's name */
	register i;		/* tmp for index */
	register firstln;	/* first line of a list */

	if ((p = rindex(infile, '/')) == NULL)	/* past path */
		p = infile;
	else
		p++;
	if (nonlocalo && p != infile) {	/* objpath = source path */
		for (q = objpath, r = infile; r < p;)
			*q++ = *r++;
		*q = '\0';	/* null terminate */
	}
	strcpy(basename, p);
	if ((p = rindex(basename, '.')) != NULL)
		*p = '\0';	/* remove trailing ".*" */
	if (targetname != NULL)	/* set up target's name */
		targ = targetname;
	else
		targ = basename;
	if (makename == NULL) {
		makename = "Makefile";
		if (access(makename, F_OK) != 0)
			makename[0] = 'm';	/* not a real check */
	}
	msoio(targ);		/* Make Sure Output Is Open */
	abrvsetup();		/* create abrev table, write defs. */
	if (access(infile, R_OK) != 0) {
		fprintf(stderr, "%s: Can't open input file '%s', skipped.\n",
			prgnm, infile);
		return;
	}
	(void) strcpy(buf, CPP);/* build cpp cmd line */
#if CPP_M
	strcat(buf, "-M ");	/* -M flag - does dependencies */
#endif
#ifdef M4_M
	if (TRUE == usem4)
		(void) strcpy(buf, M4);
#endif M4_M
	if (strlen(buf) + strlen(cppflags) + strlen(infile) + 1 > BUFSIZ)
		err("cpp command line buffer overflow");
	(void) strcat(buf, cppflags);	/* add command flags */
	(void) strcat(buf, infile);	/* add file name */
	srtfree(&u);		/* init insertion sorter */
	if (verbose)
		fprintf(stderr, "%s: cpp line is '%s'\n", prgnm, buf);
#ifdef SYSV
	if ((cppfd = popen(buf, "r")) == NULL)
#else
	if ((cppfd = nshpopen(buf, "r")) == NULL)
#endif SYSV
		err("Can't open pipe for %s", buf);
#if CPP_M
	while (fgets(buf, BUFSIZ, cppfd) != NULL) {
		if ((p = index(buf, ':')) == NULL)
			err("cpp -M format error - colon");
		p++;		/* pass colon */
		if (*p++ != SPC)
			err("cpp -M format error - space");
		p = hincl(p);	/* skip any uglies in include path */
		if (!alldep && strncmp("/usr/include", p, 12) == 0)
			continue;	/* ignore /usr/include... stuff */
		if (index(p, '\n') != NULL)	/* replace newline with EOS */
			*index(p, '\n') = '\0';
		if ((q = srtin(&u, p, (int (*) ()) 0)) != NULL)	/* insert into list */
			fprintf(stderr, "%s: %s - %s\n", prgnm, q, p);	/* warning */
	}
#else
	while (fgets(buf, BUFSIZ, cppfd) != NULL) {
		if (buf[0] != '#')	/* must start with '#' */
			continue;
		if ((p = index(buf, '"')) == NULL)	/* find first double
							 * quote */
			continue;
		p++;
		p = hincl(p);	/* skip any uglies in include path */
		if (index(p, '"') != NULL)	/* terminate the file name */
			*index(p, '"') = '\0';
		if (!alldep && strncmp("/usr/include", p, 12) == 0)
			continue;	/* ignore /usr/include... stuff */
		if ((q = srtin(&u, p, (int (*) ()) 0)) != NULL)	/* insert into list */
			fprintf(stderr, "%s: %s - %s\n", prgnm, q, p);	/* warning */
	}
#endif
	srtgti(&u);		/* init for srtgets */
	/* 2 for colon space */
	oplen = strlen(objpath) + strlen(targ) + strlen(destsuffix) + 2;
	le = MAXCOL;		/* force new line output */
	firstln = TRUE;		/* first line of a file entry */
	while ((p = srtgets(&u)) != NULL) {	/* write out the entries */
		if (shortincl)
			if ((i = findabr(p)) != MXABR)	/* i = found index or
							 * MXABR */
				p += abrvlen[i] - 2;
		if (le + strlen(p) >= MAXCOL) {
			if (firstln) {
				le = oplen;
				fprintf(makefd, "\n%s%s%s: ", objpath, targ, destsuffix);
				firstln = FALSE;
			} else {
				le = 8;
				fprintf(makefd, " \\\n\t");
			}
		} else {
			fputc(SPC, makefd);
		}
		if (shortincl && i != MXABR) {
			if ('/' != p[2] && '\000' != p[2]) {
				fprintf(makefd, "${%c}", 'A' + i);
				le += 4;
			} else {
				fprintf(makefd, "$%c", 'A' + i);
				le += 2;
			}
			p += 2;	/* right place */
		}
		fputs(p, makefd);
		le += 1 + strlen(p);
	}
	fputc('\n', makefd);	/* end with newline */
#ifdef SYSV
	pclose(cppfd);		/* end of that file */
#else
	nshpclose(cppfd);	/* end of that file */
#endif SYSV
}