4.4BSD/usr/src/contrib/mkmf/src/misc.c

Compare this file to the similar file:
Show the results in this format:

/*
 * Copyright (c) 1983, 1985, 1991, 1993 Peter J. Nicklin.
 * Copyright (c) 1991, 1993 Version Technology.
 * All Rights Reserved.
 *
 * $License: VT.1.1 $
 * 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.  (3) All advertising materials  mentioning
 * features or  use  of  this  software  must  display  the  following
 * acknowledgement:  ``This  product  includes  software  developed by
 * Version Technology.''  Neither the name of Version  Technology  nor
 * the  name  of  Peter J. Nicklin  may  be used to endorse or promote
 * products derived from this software without specific prior  written
 * permission.
 *
 * THIS SOFTWARE IS PROVIDED BY VERSION TECHNOLOGY ``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  VERSION  TECHNOLOGY  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.
 *
 * Report problems and direct questions to nicklin@netcom.com
 *
 * $Header: misc.c,v 4.10 93/05/25 21:49:09 nicklin Exp $
 *
 * Author: Peter J. Nicklin
 */
#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>
#include "Mkmf.h"
#include "config.h"
#include "dir.h"
#include "hash.h"
#include "macro.h"
#include "null.h"
#include "path.h"
#include "target.h"
#include "stringx.h"
#include "suffix.h"
#include "yesno.h"

/*
 * answer() installs a line from stdin in the macro definition table.
 * exit(1) is called if EOF, error, or out of memory.
 */
void
answer(mdefkey, mdefval)
	char *mdefkey;			/* macro definition key */
	int mdefval;			/* macro definition value */
{
	extern HASH *MDEFTABLE;		/* macro definition table */
	char answerbuf[ANSWERBUFSIZE];	/* answer from stdin */
	char *gets();			/* get a line from stdin */
	HASHBLK *htinstall();		/* install hash table entry */

	if (gets(answerbuf) == NULL)
		exit(1);
	if (*answerbuf != '\0')
		if (htinstall(mdefkey, answerbuf, mdefval, MDEFTABLE) == NULL)
			exit(1);
}



/*
 * fastcopy() copies file to stream fp. Returns integer YES if successful,
 * otherwise NO.
 */
fastcopy(filename, ofp)
	char *filename;			/* file to be copied */
	register FILE *ofp;		/* output stream */
{
	register int ifd;		/* input file descriptor */
	register int n;			/* byte count */
	char buf[BUFSIZ];		/* I/O buffer */

	if ((ifd = OPEN(filename, 0, 0644)) == -1)
		{
		pperror("");
		return(NO);
		}
	while ((n = read(ifd, buf, BUFSIZ)) > 0)
		write(fileno(ofp), buf, n);
	close(ifd);
	return(YES);
}



/*
 * findmf() locates the makefile to be edited. The type of makefile
 * is returned in target. The pathname to the makefile is returned
 * in mfpath. Returns YES if makefile or makefile template can be
 * opened, otherwise NO.
 */
findmf(mfname, mfpath, target)
	char *mfname;			/* name of target makefile */
	char *mfpath;			/* path to target makefile */
	TARGET *target;			/* type of makefile target */
{
	extern int CFLAG;		/* makefile creation message */
	int readmf();			/* read makefile */
	int targettype;			/* type of makefile requested */
	void findmftemplate();		/* find makefile template */

	targettype = target->type;
	if (FILEXIST(mfname))
		{
		if (!FILEWRITE(mfname))
			{
			pperror(mfname);
			target->type = VERROR;
			return(NO);
			}
		if (readmf(mfname, target) == VERROR)
			return(NO);
		if (targettype != VUNKNOWN && targettype != target->type)
			{
			if (targettype == VPROGRAM)
				{
				warns("%s not a program makefile", mfname);
				}
			else if (targettype == VLIBRARY)
				{
				warns("%s not a library makefile", mfname);
				}
			else	{
				warns("%s: unknown makefile type", mfname);
				}
			return(NO);
			}
		strcpy(mfpath, mfname);
		}
	else	{
		target->type = (targettype == VLIBRARY) ? VLIBRARY : VPROGRAM;
		findmftemplate(mfpath, target);
		if (readmf(mfpath, target) == VERROR)
			return(NO);
		if (CFLAG == YES)
			warn2("creating %s from %s", mfname, mfpath);
		}
	return(YES);
}



/*
 * findmftemplate() returns the pathname of a makefile template in mfpath.
 */
void
findmftemplate(mfpath, target)
	char *mfpath;			/* path to target makefile */
	TARGET *target;			/* type of makefile target */
{
	extern char *MAKEFILE;		/* makefile template name */
	extern int FFLAG;	        /* makefile template pathname flag */
	extern int LIBOBJ;		/* load object file into library? */
	char *cwp;			/* current project pathname pointer */
	char *getcwp();			/* get current project pathname */
	char *mktname();		/* make template name */
	char *pathcat();		/* pathname concatenation */
	char tname[MAXNAMLEN+1];	/* template name */

	if (FFLAG == YES)
		{
		strcpy(mfpath, MAKEFILE);
		return;
		}
	strcpy(tname, MAKEFILE);
	if (strrchr(tname, '.') == NULL)
		switch (target->type)
			{
			case VPROGRAM:
				mktname(tname, SPROGRAM);
				break;
			case VLIBRARY:
				if (LIBOBJ == 1)
					{
					mktname(tname, SLIBRARY2);
					}
				else	{
					mktname(tname, SLIBRARY);
					}
				break;
			}

	cwp = getcwp();
	if (cwp == NULL ||
	    !FILEXIST(pathcat(mfpath, pathcat(mfpath, cwp, MKMFLIB), tname)))
		pathcat(mfpath, pathcat(mfpath, INSTALLDIR, MKMFLIB), tname);
}



/*
 * gettoken() copies the next token from token buffer to token. Returns a
 * pointer to the first character after the token, or null upon reaching
 * the end of the token buffer.
 */
char *
gettoken(token, tp)
	register char *token;		/* receiving token */
	register char *tp;		/* token buffer pointer */
{
	while (isspace(*tp) && *tp != '\0')
		tp++;
	if (*tp == '\0')
		{
		*token = '\0';
		return(NULL);
		}
	while (!isspace(*tp) && *tp != '\0')
		*token++ = *tp++;
	*token = '\0';
	return(tp);
}



/*
 * getoption() copies the next matching option from token buffer to token.
 * Returns a pointer to the first character after the token, or null upon
 * reaching the end of the token buffer.
 */
char *
getoption(token, tp, option)
	register char *token;		/* receiving token */
	register char *tp;		/* token buffer pointer */
	register char *option;		/* option leader string */
{
	int optlen = strlen(option);	/* option length */

	if ((tp = gettoken(token, tp)) == NULL)
		return(NULL);

	/* skip non-matching options */
	while (strncmp(token, option, optlen) != 0)
		{
		if ((tp = gettoken(token, tp)) == NULL)
			{
			return(NULL);
			}
		}

	if (EQUAL(token, option))
		tp = gettoken(token, tp);		/* -X option */
	else
		(void) gettoken(token, token+optlen);	/* -Xoption */

	return(tp);
}



/*
 * getpath() copies the next pathname from path buffer to path. Returns a
 * pointer to the first character after the path, or null upon reaching
 * the end of the path buffer.
 */
char *
getpath(path, pp)
	register char *path;		/* receiving path */
	register char *pp;		/* path buffer pointer */
{
	while ((isspace(*pp) || *pp == ':') && *pp != '\0')
		pp++;
	if (*pp == '\0')
		{
		*path = '\0';
		return(NULL);
		}
	while (!(isspace(*pp) || *pp == ':') && *pp != '\0')
		*path++ = *pp++;
	*path = '\0';
	return(pp);
}



/*
 * libobj() returns NO if the definition of the OBJS macro contains regular
 * object file names, and YES if it contains $(LIBRARY)(objfile) file names
 * (indicating that each object file should be inserted into a library
 * immediately after compilation). Only the first line of the macro is
 * scanned for $(LIBRARY).
 */
int
libobj(bp)
	register char *bp;		/* buffer pointer */
{
	register char *sbp;		/* save buffer pointer */
	register char *mp;		/* macro name pointer */

	while (*bp++ != '=')
		continue;
	if (WHITESPACE(*bp))
		bp++;
	for (mp = DLIBRARY, sbp = bp; *mp == *bp && *mp != '\0'; mp++, bp++)
		continue;
	if (*mp == '\0')
		return(YES);
	for (mp = dLIBRARY, bp = sbp; *mp == *bp && *mp != '\0'; mp++, bp++)
		continue;
	if (*mp == '\0')
		return(YES);
	return(NO);
}



/*
 * mktname() concatenates a suffix to a makefile template name. Returns
 * name if successful, otherwise NULL.
 */
char *
mktname(base, suffix)
	char *base;			/* template basename */
	char *suffix;			/* template suffix */
{
	if (strlen(base) + strlen(suffix) > MAXNAMLEN)
		{
		warn("makefile template name too long");
		return(NULL);
		}
	else	{
		return(strcat(base, suffix));
		}
}



/*
 * nocore() places an "out of memory" error message on the standard error
 * output stream stderr.
 */
nocore()
{
	warn("out of memory");
}



/*
 * putobj() converts a source file name to an object file name and then
 * writes the file name to stream. Returns the length of the file name.
 */
putobj(s, stream)
	register char *s;		/* source file name */
	register FILE *stream;		/* output stream */
{
	register int baselen = 0;	/* length of object file basename */
	register char *dot;		/* pointer to suffix */
	char *pathsep;			/* pathname separator */
	static int psfxlen = 0;		/* length of object prefix & suffix */
	extern int LIBOBJ;		/* load object file into library? */
	extern char OBJSFX[];		/* object file name suffix */

	if (psfxlen == 0)
		{
		psfxlen = strlen(OBJSFX);
		if (LIBOBJ) psfxlen += strlen(DLIBRARY) + 2;
		}
	if ((pathsep = strrchr(s, _PSC)) != NULL)
		s = pathsep + 1;
	dot = strrchr(s, '.');
	if (LIBOBJ)
		{
		fprintf(stream, "%s(", DLIBRARY);
		while (s != dot)
			{
			putc(*s++, stream);
			baselen++;
			}
		fprintf(stream, "%s)", OBJSFX);
		}
	else	{
		while (s != dot)
			{
			putc(*s++, stream);
			baselen++;
			}
		fprintf(stream, "%s", OBJSFX);
		}
	return(psfxlen+baselen);
}



/*
 * readmf() reads a makefile and loads CFLAGS, FFLAGS, and SUFFIX definitions
 * into the macro definition table if they do not already exist. Returns
 * integer VLIBRARY, VPROGRAM, or VUNKNOWN according to the type of makefile,
 * or VERROR if cannot open makefile.
 */
readmf(mfname, target)
	char *mfname;			/* name of makefile */
	TARGET *target;			/* type of makefile target */
{
	register char *bp;		/* buffer pointer */
	extern char IOBUF[];		/* I/O buffer line */
	extern HASH *MDEFTABLE;		/* macro definition table */
	extern int LIBOBJ;		/* load object file into library? */
	char *findmacro();		/* is the line a macro definition? */
	char *findrule();		/* is the line a rule definition? */
	char *getlin();			/* get a line from input stream */
	char *getmacro();		/* get macro def from input stream */
	char macrodef[MACRODEFSIZE];	/* macro definition buffer */
	char macroname[MACRONAMSIZE];	/* macro name buffer */
	char rulename[2*SUFFIXSIZE+3];	/* transformation rule name */
	FILE *fopen();			/* open file */
	FILE *fp;			/* file pointer */
	HASHBLK *htinstall();		/* install hash table entry */
	HASHBLK *htlookup();		/* find hash table entry */
	int libobj();			/* is object file loaded into library?*/
	int storerule();		/* store transformation rule */
	void purgcontinue();		/* get rid of continuation lines */

	target->type = target->dest = VUNKNOWN;
	if ((fp = fopen(mfname, "r")) == NULL)
		{
		pperror(mfname);
		target->type = VERROR;
		return(target->type);
		}
	while (getlin(fp) != NULL)
		{
		if (EQUAL(IOBUF, DEPENDMARK))
			break;
		for (bp = IOBUF; *bp == ' '; bp++)
			continue;
		if (findmacro(macroname, bp) != NULL)
			{
			if (EQUAL(macroname, MPROGRAM))
				{
				target->type = VPROGRAM;
				}
			else if (EQUAL(macroname, MLIBRARY))
				{
				target->type = VLIBRARY;
				}
			else if (EQUAL(macroname, MDESTDIR))
				{
				target->dest = VDESTDIR;
				}

			if (EQUAL(macroname, MOBJECTS))
				{
				if (libobj(bp) == YES)
					LIBOBJ = 1;
				purgcontinue;
				}

			/* does macro definition already exist? */
			if (htlookup(macroname, MDEFTABLE) != NULL)
				continue;

			if (htinstall(macroname, getmacro(macrodef, fp),
				      VREADONLY, MDEFTABLE) == NULL)
				{
				fclose(fp);
				return(NO);
				}
			}
		else if (*bp == '.' && findrule(rulename, bp) != NULL)
			{
			if (storerule(rulename) == NO)
				{
				fclose(fp);
				return(NO);
				}
			}
		}
	fclose(fp);
	return(target->type);
}