/* $Header: dlist.c,v 1.1 85/04/23 13:56:29 nicklin Exp $ */ /* * Author: Peter J. Nicklin */ #include #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 */ /* * 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) { warn("out of memory"); 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) { warn("out of memory"); 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 */ void putinchain(); /* output nested subinclude filenames */ void putobjd(); /* output object file name */ void rmprinttag(); /* remove "already printed" tags */ 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 */ void putinclude(); /* output include file pathname */ void putinchain(); /* output nested subinclude file names*/ 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 strlen(); /* string length */ void putobj(); /* output object file name */ COLUMN = strlen(srcblk->key) + strlen(OBJSFX) + 1; putobj(srcblk->key, ofp); 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; }