home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8712 / mkmf / 1 / src / dlist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-13  |  5.4 KB  |  220 lines

  1. /* $Header: dlist.c,v 1.1 85/04/23 13:56:29 nicklin Exp $ */
  2.  
  3. /*
  4.  * Author: Peter J. Nicklin
  5.  */
  6. #include <stdio.h>
  7. #include "Mkmf.h"
  8. #include "dlist.h"
  9. #include "hash.h"
  10. #include "null.h"
  11. #include "slist.h"
  12. #include "yesno.h"
  13.  
  14. static HASHBLK *printtag = NULL;    /* include files already printed */
  15. static int COLUMN;            /* last column printed */
  16.  
  17. /*
  18.  * dlappend() adds a dependency chain block to the end of a list of
  19.  * dependency chain blocks. Each dependency chain block consists of a pointer
  20.  * to a source file name block contained in a singly-linked list, and a pointer
  21.  * to the head of the dependent list of included files. Returns a pointer to
  22.  * the dependency chain block, or a null pointer if out of memory.
  23.  */
  24. DLBLK *
  25. dlappend(srctyp, srcblk, incblk, dlist)
  26.     int srctyp;            /* source file type */
  27.     SLBLK *srcblk;            /* pointer to the source file block */
  28.     INCBLK *incblk;            /* included file dependency chain */
  29.     DLIST *dlist;            /* pointer to list head block */
  30. {
  31.     char *malloc();            /* memory allocator */
  32.     DLBLK *dblk;            /* pointer to dependency list block */
  33.  
  34.     if (dlist == NULL)
  35.         return(NULL);
  36.     if ((dblk = (DLBLK *) malloc(sizeof(DLBLK))) == NULL)
  37.         {
  38.         warn("out of memory");
  39.         return(NULL);
  40.         }
  41.     dblk->d_src = srcblk;
  42.     dblk->d_type = srctyp;
  43.     dblk->d_incl = incblk;
  44.     dblk->d_next = NULL;
  45.     if (dlist->d_tail == NULL)
  46.         {
  47.         dlist->d_head = dlist->d_tail = dblk;
  48.         }
  49.     else    {
  50.         dlist->d_tail = dlist->d_tail->d_next = dblk;
  51.         }
  52.     return(dblk);
  53. }
  54.  
  55.  
  56.  
  57. /*
  58.  * dlinit() returns a pointer to the head block of a dependency list, or
  59.  * null pointer if out of memory.
  60.  */
  61. DLIST *
  62. dlinit()
  63. {
  64.     char *malloc();            /* memory allocator */
  65.     DLIST *dlist;            /* pointer to list head block */
  66.  
  67.     if ((dlist = (DLIST *) malloc(sizeof(DLIST))) == NULL)
  68.         {
  69.         warn("out of memory");
  70.         return(NULL);
  71.         }
  72.     dlist->d_head = dlist->d_tail = NULL;
  73.     return(dlist);
  74. }
  75.  
  76.  
  77.  
  78. /*
  79.  * dlprint() appends the object-include file dependencies to the end of
  80.  * a makefile. Transitive closure is checked by making suring that an
  81.  * object-include file dependency is not generated if the source file is
  82.  * included in another file.
  83.  */
  84. void
  85. dlprint(dlist, ofp)
  86.     DLIST *dlist;            /* dependency list */
  87.     FILE *ofp;            /* output stream */
  88. {
  89.     DLBLK *dblk;            /* pointer to dependency list block */
  90.     HASHBLK *lookupinclude();    /* look up include name in hash table */
  91.     INCBLK *iblk;            /* cur. include file hash table blk */
  92.     void putinchain();        /* output nested subinclude filenames */
  93.     void putobjd();            /* output object file name */
  94.     void rmprinttag();        /* remove "already printed" tags */
  95.  
  96.     fprintf(ofp, "%s\n", DEPENDMARK);
  97.     for (dblk=dlist->d_head; dblk != NULL; dblk=dblk->d_next)
  98.         {
  99.         if (lookupinclude(dblk->d_src->key, dblk->d_type) == NULL)
  100.             {
  101.             putobjd(dblk->d_src, ofp);
  102.             for (iblk=dblk->d_incl; iblk != NULL; iblk=iblk->i_next)
  103.                 {
  104.                 putinchain(iblk->i_hblk, ofp);
  105.                 }
  106.             fprintf(ofp, "\n");
  107.             rmprinttag();
  108.             }
  109.         }
  110. }
  111.  
  112.  
  113.  
  114. /*
  115.  * putinchain() outputs a chain of nested include file names. It changes
  116.  * the sign of each chain block h_val field as it traverses the chain to
  117.  * detect looping.
  118.  */
  119. static void
  120. putinchain(htb, ofp)
  121.     HASHBLK *htb;            /* hash table blk including chain */
  122.     FILE *ofp;            /* output stream */
  123. {
  124.     INCBLK *iblk;            /* cur. include file hash table blk */
  125.     void putinclude();        /* output include file pathname */
  126.     void putinchain();        /* output nested subinclude file names*/
  127.  
  128.     putinclude(htb, ofp);
  129.     htb->h_val = -htb->h_val;
  130.     for (iblk=htb->h_sub; iblk != NULL; iblk=iblk->i_next)
  131.         {
  132.         if (iblk->i_hblk->h_val < 0)
  133.             {
  134.             if (iblk->i_loop == NO)
  135.                 {
  136.                 warn2("recursive include nesting of \"%s\" in \"%s\"",
  137.                       iblk->i_hblk->h_def, htb->h_def);
  138.                 iblk->i_loop = YES;
  139.                 }
  140.             continue;
  141.             }
  142.         putinchain(iblk->i_hblk, ofp);
  143.         }
  144.     htb->h_val = -htb->h_val;
  145. }
  146.  
  147.  
  148.  
  149. #define MAXLINE        80
  150. #define    TABSIZE        8
  151.  
  152. /*
  153.  * putinclude() writes an include file pathname to stream ofp if
  154.  * if it has not already been written on the current dependency line.
  155.  * and adds the hash block containing the file pathname to the
  156.  * "already printed" printtag list. The last block on the list
  157.  * points back onto itself rather than at NULL so that the non-NULL
  158.  * tag will indicate that the filename has already been seen.
  159.  */
  160. static void
  161. putinclude(htb, ofp)
  162.     HASHBLK *htb;            /* include file hash block */
  163.     FILE *ofp;            /* output stream */
  164. {
  165.     if (htb->h_tag == NULL)
  166.         {
  167.         COLUMN += htb->h_val + 1;
  168.         if (COLUMN >= (MAXLINE - 2))
  169.             {
  170.             fprintf(ofp, " \\\n\t%s", htb->h_def);
  171.             COLUMN = htb->h_val + TABSIZE;
  172.             }
  173.         else    {
  174.             fprintf(ofp, " %s", htb->h_def);
  175.             }
  176.         /* add to "already printed" filenames */
  177.         htb->h_tag = (printtag == NULL) ? htb :printtag;
  178.         printtag = htb;
  179.         }
  180. }
  181.  
  182.  
  183.  
  184. /*
  185.  * putobjd() writes an object file dependency name.
  186.  */
  187. static void
  188. putobjd(srcblk, ofp)
  189.     SLBLK *srcblk;            /* source file name list block */
  190.     FILE *ofp;            /* output stream */
  191. {
  192.     extern char OBJSFX[];        /* object file name suffix */
  193.     int strlen();            /* string length */
  194.     void putobj();            /* output object file name */
  195.  
  196.     COLUMN = strlen(srcblk->key) + strlen(OBJSFX) + 1;
  197.     putobj(srcblk->key, ofp);
  198.     fprintf(ofp, ":");
  199. }
  200.  
  201.  
  202.  
  203. /*
  204.  * rmprinttag() removes the chain of tags indicating that an include
  205.  * file dependency has already been printed for the current source file.
  206.  */
  207. static void
  208. rmprinttag()
  209. {
  210.     register HASHBLK *curhtb;    /* current hash table block */
  211.     register HASHBLK *nxthtb;    /* next hash table block */
  212.  
  213.     for (curhtb = printtag; curhtb != NULL; curhtb = nxthtb)
  214.         {
  215.         nxthtb = curhtb->h_tag;
  216.         curhtb->h_tag = NULL;
  217.         }
  218.     printtag = NULL;
  219. }
  220.