4.4BSD/usr/src/contrib/mkmf/src/dlist.c
/*
* Copyright (c) 1985, 1991 Peter J. Nicklin.
* Copyright (c) 1991 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: dlist.c,v 4.3 91/11/25 19:44:59 nicklin Exp $
*
* Author: Peter J. Nicklin
*/
#include <stdio.h>
#include "Mkmf.h"
#include "dlist.h"
#include "hash.h"
#include "null.h"
#include "slist.h"
#include "yesno.h"
static HASHBLK *printtag = NULL; /* include files already printed */
static int COLUMN; /* last column printed */
static void putinchain(); /* output nested subinclude filenames */
static void putinclude(); /* output include file pathname */
static void putobjd(); /* output object file name */
static void rmprinttag(); /* remove "already printed" tags */
/*
* dlappend() adds a dependency chain block to the end of a list of
* dependency chain blocks. Each dependency chain block consists of a pointer
* to a source file name block contained in a singly-linked list, and a pointer
* to the head of the dependent list of included files. Returns a pointer to
* the dependency chain block, or a null pointer if out of memory.
*/
DLBLK *
dlappend(srctyp, srcblk, incblk, dlist)
int srctyp; /* source file type */
SLBLK *srcblk; /* pointer to the source file block */
INCBLK *incblk; /* included file dependency chain */
DLIST *dlist; /* pointer to list head block */
{
char *malloc(); /* memory allocator */
DLBLK *dblk; /* pointer to dependency list block */
if (dlist == NULL)
return(NULL);
if ((dblk = (DLBLK *) malloc(sizeof(DLBLK))) == NULL)
{
nocore();
return(NULL);
}
dblk->d_src = srcblk;
dblk->d_type = srctyp;
dblk->d_incl = incblk;
dblk->d_next = NULL;
if (dlist->d_tail == NULL)
{
dlist->d_head = dlist->d_tail = dblk;
}
else {
dlist->d_tail = dlist->d_tail->d_next = dblk;
}
return(dblk);
}
/*
* dlinit() returns a pointer to the head block of a dependency list, or
* null pointer if out of memory.
*/
DLIST *
dlinit()
{
char *malloc(); /* memory allocator */
DLIST *dlist; /* pointer to list head block */
if ((dlist = (DLIST *) malloc(sizeof(DLIST))) == NULL)
{
nocore();
return(NULL);
}
dlist->d_head = dlist->d_tail = NULL;
return(dlist);
}
/*
* dlprint() appends the object-include file dependencies to the end of
* a makefile. Transitive closure is checked by making suring that an
* object-include file dependency is not generated if the source file is
* included in another file.
*/
void
dlprint(dlist, ofp)
DLIST *dlist; /* dependency list */
FILE *ofp; /* output stream */
{
DLBLK *dblk; /* pointer to dependency list block */
HASHBLK *lookupinclude(); /* look up include name in hash table */
INCBLK *iblk; /* cur. include file hash table blk */
if (dlist->d_head != NULL)
fprintf(ofp, "%s\n", DEPENDMARK);
for (dblk=dlist->d_head; dblk != NULL; dblk=dblk->d_next)
{
if (lookupinclude(dblk->d_src->key, dblk->d_type) == NULL)
{
putobjd(dblk->d_src, ofp);
for (iblk=dblk->d_incl; iblk != NULL; iblk=iblk->i_next)
{
putinchain(iblk->i_hblk, ofp);
}
fprintf(ofp, "\n");
rmprinttag();
}
}
}
/*
* putinchain() outputs a chain of nested include file names. It changes
* the sign of each chain block h_val field as it traverses the chain to
* detect looping.
*/
static void
putinchain(htb, ofp)
HASHBLK *htb; /* hash table blk including chain */
FILE *ofp; /* output stream */
{
INCBLK *iblk; /* cur. include file hash table blk */
putinclude(htb, ofp);
htb->h_val = -htb->h_val;
for (iblk=htb->h_sub; iblk != NULL; iblk=iblk->i_next)
{
if (iblk->i_hblk->h_val < 0)
{
if (iblk->i_loop == NO)
{
warn2("recursive include nesting of \"%s\" in \"%s\"",
iblk->i_hblk->h_def, htb->h_def);
iblk->i_loop = YES;
}
continue;
}
putinchain(iblk->i_hblk, ofp);
}
htb->h_val = -htb->h_val;
}
#define MAXLINE 80
#define TABSIZE 8
/*
* putinclude() writes an include file pathname to stream ofp if
* if it has not already been written on the current dependency line.
* and adds the hash block containing the file pathname to the
* "already printed" printtag list. The last block on the list
* points back onto itself rather than at NULL so that the non-NULL
* tag will indicate that the filename has already been seen.
*/
static void
putinclude(htb, ofp)
HASHBLK *htb; /* include file hash block */
FILE *ofp; /* output stream */
{
if (htb->h_tag == NULL)
{
COLUMN += htb->h_val + 1;
if (COLUMN >= (MAXLINE - 2))
{
fprintf(ofp, " \\\n\t%s", htb->h_def);
COLUMN = htb->h_val + TABSIZE;
}
else {
fprintf(ofp, " %s", htb->h_def);
}
/* add to "already printed" filenames */
htb->h_tag = (printtag == NULL) ? htb :printtag;
printtag = htb;
}
}
/*
* putobjd() writes an object file dependency name.
*/
static void
putobjd(srcblk, ofp)
SLBLK *srcblk; /* source file name list block */
FILE *ofp; /* output stream */
{
extern char OBJSFX[]; /* object file name suffix */
int putobj(); /* output object file name */
COLUMN = putobj(srcblk->key, ofp) + 1;
fprintf(ofp, ":");
}
/*
* rmprinttag() removes the chain of tags indicating that an include
* file dependency has already been printed for the current source file.
*/
static void
rmprinttag()
{
register HASHBLK *curhtb; /* current hash table block */
register HASHBLK *nxthtb; /* next hash table block */
for (curhtb = printtag; curhtb != NULL; curhtb = nxthtb)
{
nxthtb = curhtb->h_tag;
curhtb->h_tag = NULL;
}
printtag = NULL;
}