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

  1. /* $Header: depend.c,v 1.14 86/05/15 09:01:04 lepreau Exp $ */
  2.  
  3. /*
  4.  * Author: Peter J. Nicklin
  5.  */
  6. #include <ctype.h>
  7. #include <stdio.h>
  8. #include "Mkmf.h"
  9. #include "dlist.h"
  10. #include "hash.h"
  11. #include "macro.h"
  12. #include "null.h"
  13. #include "path.h"
  14. #include "slist.h"
  15. #include "system.h"
  16. #include "yesno.h"
  17.  
  18. #define USRINCLUDE        "/usr/include/"
  19. #define CURINCLUDE        "./"
  20. #define TOLOWER(c)        (isupper(c) ? tolower(c) : (c))
  21. #define SKIPWHITESPACE(c, f) while ((c = getc(f))==' ' || c=='\t'); ungetc(c,f);
  22.  
  23. /*
  24.  * Include file state
  25.  */
  26. #define NOTFOUND        0    /* not found anywhere */
  27. #define EXTERNAL        1    /* not found in current directory */
  28. #define INTERNAL        2    /* found in current directory */
  29. #define FROMRULE        3    /* derived from tranformation rule */
  30.  
  31. /*
  32.  * Include files are stored in hash tables by direct chaining (See
  33.  * p. 134 in `The C Programming Language' by Kernighan and Ritchie).
  34.  * Included include files are also added to a singly-linked list
  35.  * attached to the hash table entry for the include file.
  36.  */
  37. static HASH *C_INCLUDETABLE = NULL;    /* C include file hash table */
  38. static HASH *F_INCLUDETABLE = NULL;    /* Fortran include file hash table */
  39. static HASH *P_INCLUDETABLE = NULL;    /* Pascal include file hash table */
  40. /*
  41.  * Additional include directories are specified via the -I compiler
  42.  * command line option. These directories are stored in singly-linked lists.
  43.  * We also assume that the last look-up directory is "/usr/include".
  44.  */
  45. static SLIST *C_INCDIR;            /* C include directories */
  46. static SLIST *F_INCDIR;            /* Fortran include directories */
  47. static SLIST *P_INCDIR;            /* Pascal include directories */
  48.  
  49. SLIST *EXTLIST;                /* external header file name list */
  50.  
  51. extern char *PGN;            /* program name */
  52.  
  53. /*
  54.  * addincdir() adds directories containing include files to the
  55.  * appropriate singly-linked list. The pathnames to the directories
  56.  * are derived from makefile macro definitions.
  57.  */
  58. void
  59. addincdir()
  60. {
  61.     extern HASH *MDEFTABLE;        /* macro definition table */
  62.     char *slappend();        /* append to singly-linked list */
  63.     HASHBLK *htb;            /* hash table entry block */
  64.     HASHBLK *htlookup();        /* find hash table entry */
  65.     int cleanup();            /* remove temporary makefile and exit */
  66.     void getI();            /* get include directory pathnames */
  67.     extern int dashI;        /* include directories to scan */
  68.  
  69.     /* C files */
  70.     if ((htb = htlookup(MCFLAGS, MDEFTABLE)) != NULL)
  71.         getI(htb->h_key, htb->h_def, C_INCDIR);
  72.     if (slappend(USRINCLUDE, C_INCDIR) == NULL)
  73.         cleanup();
  74.  
  75.     /* add any directories specified via the mkmf -I flag. */
  76.     if (dashI) {
  77.         if ((htb = htlookup(MMOREINCDIRS, MDEFTABLE)) != NULL)
  78.             getI(htb->h_key, htb->h_def, C_INCDIR);
  79.         if (slappend(USRINCLUDE, C_INCDIR) == NULL)
  80.             cleanup();
  81.     }
  82.     
  83.     /* Fortran files */
  84.     if ((htb = htlookup(MFFLAGS, MDEFTABLE)) != NULL)
  85.         getI(htb->h_key, htb->h_def, F_INCDIR);
  86.     if (slappend(USRINCLUDE, F_INCDIR) == NULL)
  87.         cleanup();
  88.  
  89.     /* Pascal files */
  90.     if ((htb = htlookup(MPFLAGS, MDEFTABLE)) != NULL)
  91.         getI(htb->h_key, htb->h_def, P_INCDIR);
  92.     if (slappend(USRINCLUDE, P_INCDIR) == NULL)
  93.         cleanup();
  94. }
  95.  
  96.  
  97.  
  98. /*
  99.  * findinclude() tries to find the pathname of an include file. Returns
  100.  * integer INTERNAL if found in the current directory, EXTERNAL if found
  101.  * somewhere else, FROMRULE if derived from a transformation rule,
  102.  * otherwise NOTFOUND. The pathname is copied into incpath.
  103.  */
  104. #define LOCALDIR(f)    (index(f, _PSC) == NULL)
  105. #define INCLUDETYPE(f) ((index(f, _PSC) == NULL) ? INTERNAL : EXTERNAL)
  106.  
  107. findinclude(incpath, incname, lastname, type)
  108.     char *incpath;            /* pathname receiving buffer */
  109.     register char *incname;        /* include file name */
  110.     char *lastname;            /* file that includes incname */
  111.     int type;            /* file type */
  112. {
  113.     register char *pp;        /* include file path pointer */
  114.     char *index();            /* find occurrence of character */
  115.     char *optpath();        /* optimize pathname */
  116.     char *pathcat();        /* pathname concatenation */
  117.     char *pathhead();        /* remove pathname tail */
  118.     char *strcpy();            /* string copy */
  119.     char *strpcpy();        /* string copy and update pointer */
  120.     int lookuprule();        /* look up transformation rules */
  121.     SLBLK *slb;            /* singly-linked list block */
  122.     SLIST *slist;            /* include directory list pointer */
  123.  
  124.     /*
  125.      * look in /usr/include only
  126.      */
  127.     if (*incname == '<')
  128.         {
  129.         pp = strpcpy(incpath, USRINCLUDE);
  130.         for (incname++; *incname != '>'; incname++, pp++)
  131.             *pp = *incname;
  132.         *pp = '\0';
  133.         return(FILEXIST(incpath) ? EXTERNAL : NOTFOUND);
  134.         }
  135.  
  136.     /*
  137.      * look for an absolute include file name
  138.      */
  139.     if (*incname == '/')
  140.         {
  141.         strcpy(incpath, incname);
  142.         return(FILEXIST(incpath) ? EXTERNAL : NOTFOUND);
  143.         }
  144.  
  145.     /*
  146.      * look in current include directory to see if the file exists,
  147.      * or can be generated by a transformation rule in the current
  148.      * working directory.
  149.      */
  150.     if (LOCALDIR(lastname))
  151.         {
  152.         if (LOCALDIR(incname))
  153.             {
  154.             if (lookuprule(incname, incpath) == YES)
  155.                 return(FROMRULE);
  156.             }
  157.         strcpy(incpath, incname);
  158.         if (FILEXIST(incpath))
  159.             return(INCLUDETYPE(incpath));
  160.         }
  161.     else    {
  162.         strcpy(incpath, lastname);
  163.         pathcat(incpath, pathhead(incpath), incname);
  164.         optpath(incpath);
  165.         if (FILEXIST(incpath))
  166.             return(INCLUDETYPE(incpath));
  167.         }
  168.  
  169.     /*
  170.      * search directory list
  171.      */
  172.     switch (type)
  173.         {
  174.         case INCLUDE_C:
  175.             slist = C_INCDIR;
  176.             break;
  177.         case INCLUDE_FORTRAN:
  178.             slist = F_INCDIR;
  179.             break;
  180.         case INCLUDE_PASCAL:
  181.             slist = P_INCDIR;
  182.             break;
  183.         }
  184.     for (slb = slist->head; slb != NULL; slb = slb->next)
  185.         {
  186.         pp = strpcpy(incpath, slb->key);
  187.         strcpy(pp, incname);
  188.         optpath(incpath);
  189.         if (FILEXIST(incpath))
  190.             return(INCLUDETYPE(incpath));
  191.         }
  192.     return(NOTFOUND);
  193. }
  194.  
  195.  
  196.  
  197. /*
  198.  * getI() appends include directories found via the -I compiler option to
  199.  * a singly linked list.
  200.  */
  201. void
  202. getI(mnam, mdef, slist)
  203.     char *mnam;            /* compiler options macro name */
  204.     char *mdef;            /* compiler options macro definition */
  205.     SLIST *slist;            /* singly-linked list */
  206. {
  207.     char *gettoken();        /* get next token */
  208.     char incpath[PATHSIZE];        /* include directory pathname buffer */
  209.     char *slappend();        /* append to singly-linked list */
  210.     char *strcat();            /* string concatenation */
  211.     int cleanup();            /* remove temporary makefile and exit */
  212.  
  213.     while ((mdef = gettoken(incpath, mdef)) != NULL)
  214.         if (incpath[0] == '-' && incpath[1] == 'I')
  215.             if (incpath[2] == '\0')    /* -I dir option */
  216.                 {
  217.                 if ((mdef = gettoken(incpath, mdef)) != NULL)
  218.                     {
  219.                     strcat(incpath, PATHSEP);
  220.                     if (slappend(incpath, slist) == NULL)
  221.                         cleanup();
  222.                     }
  223.                 else    {
  224.                     warn2("missing include directory in %s %s",
  225.                            mnam, "macro definition");
  226.                     break;
  227.                     }
  228.                 }
  229.             else    {        /* -Idir option */
  230.                 strcat(incpath+2, PATHSEP);
  231.                 if (slappend(incpath+2, slist) == NULL)
  232.                     cleanup();
  233.                 }
  234. }
  235.  
  236.  
  237.  
  238. /*
  239.  * getinclude() fetchs an include file name from a line of source code.
  240.  * /usr/include '<' and '>' delimiters remain with the filename to
  241.  * distinguish it from an include file in a local directory. Returns
  242.  * NO if syntax error, otherwise YES.
  243.  */
  244. getinclude(incname, curname, lineno, ifp)
  245.     char *curname;            /* current file name */
  246.     char *incname;            /* include file name receiving buffer */
  247.     int lineno;            /* current line number */
  248.     register FILE *ifp;        /* input stream */
  249. {
  250.     register char *ip;        /* include file name buffer pointer */
  251.     register int c;            /* current character */
  252.  
  253.     SKIPWHITESPACE(c, ifp);
  254.     for (ip = incname; (c = getc(ifp)) != EOF; ip++)
  255.         {
  256.         *ip = c;
  257.         if (c == '\n' || c == '\t' || c == ' ' || c == ';'  || c == ',')
  258.             {
  259.             ungetc(c, ifp);
  260.             break;
  261.             }
  262.         }
  263.     *ip = '\0';
  264.  
  265. #ifndef ORIGINAL
  266.     if (*incname == '<' && ip[-1] == '>')
  267.         return (NO);
  268. #endif !ORIGINAL
  269.     if ((*incname == '<'  && ip[-1] != '>')  ||
  270.         (*incname == '\"' && ip[-1] != '\"') ||
  271.         (*incname == '\'' && ip[-1] != '\'') ||
  272.         (*incname == '('  && ip[-1] != ')'))
  273.         {
  274.         fprintf(stderr,
  275.             "%s: \"%s\", line %d: bad include syntax for %s\n",
  276.             PGN, curname, lineno, incname);
  277.         return(NO);
  278.         }
  279.     if (*incname == '\"' || *incname == '\'' || *incname == '(')
  280.         {
  281.         ip[-1] = '\0';
  282.         ip = incname + 1;
  283.         while (*incname++ = *ip++)
  284.             continue;
  285.         }
  286.     return(YES);
  287. }
  288.  
  289.  
  290.  
  291. /*
  292.  * inclink() stores a pointer to a hash table block (which contains
  293.  * include file information) somewhere. Returns a pointer to the somewhere,
  294.  * or calls cleanup() if out of memory.
  295.  */
  296. INCBLK *
  297. inclink(htb)
  298.     HASHBLK *htb;            /* hash table block pointer to save */
  299. {
  300.     char *malloc();            /* memory allocator */
  301.     INCBLK *iblk;            /* pointer to new include chain block */
  302.     int cleanup();            /* remove temporary makefile and exit */
  303.  
  304.     if ((iblk = (INCBLK *) malloc(sizeof(INCBLK))) == NULL)
  305.         {
  306.         warn("out of memory");
  307.         cleanup();
  308.         }
  309.     iblk->i_loop = NO;
  310.     iblk->i_hblk = htb;
  311.     iblk->i_next = NULL;
  312.     return(iblk);
  313. }
  314.  
  315.  
  316.  
  317. /*
  318.  * instalinclude() adds an include file name to the appropriate include
  319.  * file hash table. Returns a pointer to the hash table block, or calls
  320.  * cleanup() if out of memory.
  321.  */
  322. HASHBLK *
  323. instalinclude(incname, incpath, type)
  324.     char *incname;            /* name of include file */
  325.     char *incpath;            /* path to include file */
  326.     int type;            /* type of source file */
  327. {
  328.     HASH *htinit();            /* initialize hash table */
  329.     HASHBLK *htb = NULL;        /* hash table block */
  330.     HASHBLK *htinstall();        /* install hash table entry */
  331.     int cleanup();            /* remove temporary makefile and exit */
  332.     int ilen;            /* include path length */
  333.     int strlen();            /* string length */
  334.  
  335.     ilen = strlen(incpath);
  336.     switch (type)
  337.         {
  338.         case INCLUDE_C:
  339.             if (C_INCLUDETABLE == NULL)
  340.                 {
  341.                 C_INCLUDETABLE = htinit(INCLUDETABLESIZE);
  342.                 }
  343.             htb = htinstall(incname, incpath, ilen, C_INCLUDETABLE);
  344.             break;
  345.         case INCLUDE_FORTRAN:
  346.             if (F_INCLUDETABLE == NULL)
  347.                 {
  348.                 F_INCLUDETABLE = htinit(INCLUDETABLESIZE);
  349.                 }
  350.             htb = htinstall(incname, incpath, ilen, F_INCLUDETABLE);
  351.             break;
  352.         case INCLUDE_PASCAL:
  353.             if (P_INCLUDETABLE == NULL)
  354.                 {
  355.                 P_INCLUDETABLE = htinit(INCLUDETABLESIZE);
  356.                 }
  357.             htb = htinstall(incname, incpath, ilen, P_INCLUDETABLE);
  358.             break;
  359.         }
  360.     if (htb == NULL)
  361.         cleanup();
  362.     return(htb);
  363. }
  364.  
  365.  
  366.  
  367. /*
  368.  * lookupinclude() returns a pointer to an include hash table block
  369.  * corresponding to incname and type. Returns null if not found.
  370.  */
  371. HASHBLK *
  372. lookupinclude(incname, type)
  373.     char *incname;            /* name of include file */
  374.     int type;            /* type of source file */
  375. {
  376.     HASH *includetable = NULL;    /* include file hash table */
  377.     HASHBLK *htlookup();        /* find hash table entry */
  378.  
  379.     switch (type)
  380.         {
  381.         case INCLUDE_C:
  382.             includetable = C_INCLUDETABLE;
  383.             break;
  384.         case INCLUDE_FORTRAN:
  385.             includetable = F_INCLUDETABLE;
  386.             break;
  387.         case INCLUDE_PASCAL:
  388.             includetable = P_INCLUDETABLE;
  389.             break;
  390.         }
  391.     return((includetable == NULL) ? NULL : htlookup(incname, includetable));
  392. }
  393.  
  394.  
  395.  
  396. /*
  397.  * mkdepend() creates include file dependencies for object files and installs
  398.  * them to dependency list dlp. Returns a pointer to the dependency list.
  399.  */
  400. DLIST *
  401. mkdepend()
  402. {
  403.     extern SLIST *SRCLIST;        /* source file name list */
  404.     char *rindex();            /* find last occurrence of character */
  405.     char *suffix;            /* suffix pointer */
  406.     DLBLK *dlappend();        /* append dependency list */
  407.     DLIST *dlinit();        /* initialize dependency list */
  408.     DLIST *dlist;            /* dependency list */
  409.     INCBLK *ibp;            /* pointer to chain of include files */
  410.     INCBLK *readC();        /* read C include-style files */
  411.     INCBLK *readF();        /* read Fortran include-style files */
  412.     INCBLK *readP();        /* read Pascal include-style files */
  413.     int cleanup();            /* remove temporary makefile and exit */
  414.     int lookuptypeofinclude();    /* look up the brand of include */
  415.     int slsort();            /* sort singly-linked list */
  416.     int strcmp();            /* string comparison */
  417.     int type;            /* source file type */
  418.     SLBLK *lbp;            /* list block pointer */
  419.     SLIST *slinit();        /* initialize singly-linked list */
  420.     void addincdir();        /* add to list of include directories */
  421.     void rmprinttag();        /* remove "already printed" tags */
  422.  
  423.     /* initialize include file look-up lists */
  424.     C_INCDIR = slinit();
  425.     F_INCDIR = slinit();
  426.     P_INCDIR = slinit();
  427.  
  428.     /* add additional include directories */
  429.     addincdir();
  430.  
  431.     /* initialize external header file name list */
  432.     EXTLIST = slinit();
  433.  
  434.     /* initialize dependency list */
  435.     dlist = dlinit();
  436.      
  437.     for (lbp = SRCLIST->head; lbp != NULL; lbp = lbp->next)
  438.         {
  439.         suffix = rindex(lbp->key, '.');
  440.         type = lookuptypeofinclude(++suffix);
  441.         switch (type)
  442.             {
  443.             case INCLUDE_C:
  444.                 ibp = readC(lbp->key, 0, lbp->key);
  445.                 break;
  446.             case INCLUDE_FORTRAN:
  447.                 ibp = readF(lbp->key, 0, lbp->key);
  448.                 break;
  449.             case INCLUDE_PASCAL:
  450.                 ibp = readP(lbp->key, 0, lbp->key);
  451.                 break;
  452.             case INCLUDE_NONE:
  453.                 ibp = NULL;
  454.                 break;
  455.             }
  456.         if (ibp != NULL)
  457.             {
  458.             if (dlappend(type, lbp, ibp, dlist) == NULL)
  459.                 cleanup();
  460.             }
  461.         }
  462.     if (slsort(strcmp, EXTLIST) == NO)
  463.         cleanup();
  464.     return(dlist);
  465. }
  466.  
  467.  
  468.  
  469. /*
  470.  * notfound() prints a "can't find" filename error message.
  471.  */
  472. void
  473. notfound(curname, lineno, incname)
  474.     char *curname;            /* current file name */
  475.     char *incname;            /* name of include file */
  476.     int lineno;            /* current line number */
  477. {
  478.     if (PGN != NULL && *PGN != '\0')
  479.         {
  480.         fprintf(stderr, "%s: ", PGN);
  481.         }
  482.     if (*incname == '<')
  483.         {
  484.         fprintf(stderr, "\"%s\", line %d: can't find %s\n",
  485.             curname, lineno, incname);
  486.         }
  487.     else    {
  488.         fprintf(stderr, "\"%s\", line %d: can't find \"%s\"\n",
  489.             curname, lineno, incname);
  490.         }
  491. }
  492.  
  493.  
  494.  
  495. /*
  496.  * readC() searches C files for included files. Returns a pointer to
  497.  * the chain of include files installed or found in the include file
  498.  * hash table, or null if no include files found.
  499.  */
  500. INCBLK *
  501. readC(lastfile, lastline, curname)
  502.     char *lastfile;            /* parent file name */
  503.     int lastline;            /* current line in parent file */
  504.     char *curname;            /* current file name */
  505. {
  506.     register char *p;        /* include string pointer */
  507.     register FILE *ifp;        /* input file stream */
  508.     register int c;            /* current character */
  509.     char incname[PATHSIZE];        /* name of include file */
  510.     char incpath[PATHSIZE];        /* path to include file */
  511.     char *slappend();        /* append pathname to list */
  512.     FILE *fopen();            /* open file */
  513.     HASHBLK *ftb;            /* fromrule hash table entry block */
  514.     HASHBLK *htb = NULL;        /* hash table entry block */
  515.     HASHBLK *instalinclude();    /* install include name in hash table */
  516.     HASHBLK *lookupinclude();    /* look up include in hash table */
  517.     INCBLK *i_head = NULL;        /* head of include chain */
  518.     INCBLK *i_tail = NULL;        /* tail of include chain */
  519.     INCBLK *inclink();        /* link include file hash blocks */
  520.     int cleanup();            /* remove temporary makefile and exit */
  521.     int findinclude();        /* locate include file */
  522.     int getinclude();        /* get include name from input line */
  523.     int inctype;            /* origin of include file */
  524.     int lineno = 1;            /* current line number */
  525.     int strlen();            /* string length */
  526.     int type;            /* file type */
  527.     void notfound();        /* print "can't find" filename msg */
  528.  
  529.     type = INCLUDE_C;
  530.  
  531.     if ((ifp = fopen(curname, "r")) == NULL)
  532.         {
  533.         if (lastline > 0)
  534.             fprintf(stderr, "%s: \"%s\", line %d: ", PGN,
  535.                 lastfile, lastline);
  536.         else
  537.             fprintf(stderr, "%s: ", PGN);
  538.         perror(curname);
  539.         return(NULL);
  540.         }
  541.     while ((c = getc(ifp)) != EOF)
  542.         {
  543.         if (c != '#')
  544.             goto nextline;
  545.         SKIPWHITESPACE(c, ifp);
  546.         for (p = "include"; (c = getc(ifp)) == *p && *p != '\0' ; p++)
  547.             continue;
  548.         if (*p != '\0')
  549.             goto nextline;
  550.         if (getinclude(incname, curname, lineno, ifp) == NO)
  551.             goto nextline;
  552.         if ((htb = lookupinclude(incname, type)) == NULL)
  553.             {
  554.             inctype = findinclude(incpath, incname, curname, type);
  555.             if (inctype == INTERNAL)
  556.                 {
  557.                 htb = instalinclude(incname, incpath, type);
  558.                 }
  559.             else if (inctype == EXTERNAL)
  560.                 {
  561.                 htb = instalinclude(incname, incpath, type);
  562.                 if (slappend(incpath, EXTLIST) == NULL)
  563.                     cleanup();
  564.                 }
  565.             else if (inctype == FROMRULE)
  566.                 {
  567.                 htb = instalinclude(incname, incname, type);
  568.                 ftb = instalinclude(incpath, incpath, type);
  569.                 }
  570.             else    {
  571.                 notfound(curname, lineno, incname);
  572.                 goto nextline;
  573.                 }
  574.  
  575.             /* look for nested include files */
  576.             htb->h_sub = readC(curname, lineno, incpath);
  577.  
  578.             if (inctype == FROMRULE) 
  579.                 ftb->h_sub = htb->h_sub;
  580.             }
  581.         if (i_tail == NULL)
  582.             {
  583.             i_head = i_tail = inclink(htb);
  584.             }
  585.         else    {
  586.             i_tail = i_tail->i_next = inclink(htb);
  587.             }
  588. nextline:    while (c != '\n' && c != EOF)
  589.             c = getc(ifp);
  590.         lineno++;
  591.         }
  592.     fclose(ifp);
  593.     return(i_head);
  594. }
  595.  
  596.  
  597.  
  598. /*
  599.  * readF() searches Fortran files for included files. Returns a pointer
  600.  * to the chain of include files installed or found in the include file
  601.  * hash table, or null if no include files found.
  602.  */
  603. INCBLK *
  604. readF(lastfile, lastline, curname)
  605.     char *lastfile;            /* parent file name */
  606.     int lastline;            /* current line in parent file */
  607.     char *curname;            /* current file name */
  608. {
  609.     register char *p;        /* include string pointer */
  610.     register FILE *ifp;        /* input file stream */
  611.     register int c;            /* current character */
  612.     char incname[PATHSIZE];        /* name of include file */
  613.     char incpath[PATHSIZE];        /* path to include file */
  614.     char *slappend();        /* append pathname to list */
  615.     FILE *fopen();            /* open file */
  616.     HASHBLK *ftb;            /* fromrule hash table entry block */
  617.     HASHBLK *htb = NULL;        /* hash table entry block */
  618.     HASHBLK *instalinclude();    /* install include name in hash table */
  619.     HASHBLK *lookupinclude();    /* look up include in hash table */
  620.     INCBLK *i_head = NULL;        /* head of include chain */
  621.     INCBLK *i_tail = NULL;        /* tail of include chain */
  622.     INCBLK *inclink();        /* link include file hash blocks */
  623.     int cleanup();            /* remove temporary makefile and exit */
  624.     int findinclude();        /* locate include file */
  625.     int getinclude();        /* get include name from input line */
  626.     int inctype;            /* origin of include file */
  627.     int lineno = 1;            /* current line number */
  628.     int strlen();            /* string length */
  629.     int type;            /* file type */
  630.     void notfound();        /* print "can't find" filename msg */
  631.  
  632.     type = INCLUDE_FORTRAN;
  633.  
  634.     if ((ifp = fopen(curname, "r")) == NULL)
  635.         {
  636.         if (lastline > 0)
  637.             fprintf(stderr, "%s: \"%s\", line %d: ", PGN,
  638.                 lastfile, lastline);
  639.         else
  640.             fprintf(stderr, "%s: ", PGN);
  641.         perror(curname);
  642.         return(NULL);
  643.         }
  644.     while ((c = getc(ifp)) != EOF)
  645.         {
  646.         if (c == 'c' || c == 'C' || c == '*' || c == '\n')
  647.             goto nextline;
  648.         while ((c = getc(ifp)) == ' ' || c == '\t')
  649.             continue;
  650.         for (p = "include"; *p == TOLOWER(c) && *p != '\0'; p++)
  651.             c = getc(ifp);
  652.         if (*p != '\0')
  653.             goto nextline;
  654.         if (getinclude(incname, curname, lineno, ifp) == NO)
  655.             goto nextline;
  656.         if ((htb = lookupinclude(incname, type)) == NULL)
  657.             {
  658.             inctype = findinclude(incpath, incname, curname, type);
  659.             if (inctype == INTERNAL)
  660.                 {
  661.                 htb = instalinclude(incname, incpath, type);
  662.                 }
  663.             else if (inctype == EXTERNAL)
  664.                 {
  665.                 htb = instalinclude(incname, incpath, type);
  666.                 if (slappend(incpath, EXTLIST) == NULL)
  667.                     cleanup();
  668.                 }
  669.             else if (inctype == FROMRULE)
  670.                 {
  671.                 htb = instalinclude(incname, incname, type);
  672.                 ftb = instalinclude(incpath, incpath, type);
  673.                 }
  674.             else    {
  675.                 notfound(curname, lineno, incname);
  676.                 goto nextline;
  677.                 }
  678.  
  679.             /* look for nested include files */
  680.             htb->h_sub = readF(curname, lineno, incpath);
  681.  
  682.             if (inctype == FROMRULE) 
  683.                 ftb->h_sub = htb->h_sub;
  684.             }
  685.         if (i_tail == NULL)
  686.             {
  687.             i_head = i_tail = inclink(htb);
  688.             }
  689.         else    {
  690.             i_tail = i_tail->i_next = inclink(htb);
  691.             }
  692. nextline:    while (c != '\n' && c != EOF)
  693.             c = getc(ifp);
  694.         lineno++;
  695.         }
  696.     fclose(ifp);
  697.     return(i_head);
  698. }
  699.  
  700.  
  701.  
  702. /*
  703.  * readP() searches Pascal files for included files. Returns a pointer
  704.  * to the chain of include files installed or found in the include file
  705.  * hash table, or null if no include files found.
  706.  */
  707. INCBLK *
  708. readP(lastfile, lastline, curname)
  709.     char *lastfile;            /* parent file name */
  710.     int lastline;            /* current line in parent file */
  711.     char *curname;            /* current file name */
  712. {
  713.     register char *p;        /* include string pointer */
  714.     register FILE *ifp;        /* input file stream */
  715.     register int c;            /* current character */
  716.     char incname[PATHSIZE];        /* name of include file */
  717.     char incpath[PATHSIZE];        /* path to include file */
  718.     char *slappend();        /* append pathname to list */
  719.     FILE *fopen();            /* open file */
  720.     HASHBLK *ftb;            /* fromrule hash table entry block */
  721.     HASHBLK *htb = NULL;        /* hash table entry block */
  722.     HASHBLK *instalinclude();    /* install include name in hash table */
  723.     HASHBLK *lookupinclude();    /* look up include in hash table */
  724.     INCBLK *i_head = NULL;        /* head of include chain */
  725.     INCBLK *i_tail = NULL;        /* tail of include chain */
  726.     INCBLK *inclink();        /* link include file hash blocks */
  727.     int cleanup();            /* remove temporary makefile and exit */
  728.     int findinclude();        /* locate include file */
  729.     int getinclude();        /* get include name from input line */
  730.     int inctype;            /* origin of include file */
  731.     int lineno = 1;            /* current line number */
  732.     int strlen();            /* string length */
  733.     int type;            /* file type */
  734.     void notfound();        /* print "can't find" filename msg */
  735.  
  736.     type = INCLUDE_PASCAL;
  737.  
  738.     if ((ifp = fopen(curname, "r")) == NULL)
  739.         {
  740.         if (lastline > 0)
  741.             fprintf(stderr, "%s: \"%s\", line %d: ", PGN,
  742.                 lastfile, lastline);
  743.         else
  744.             fprintf(stderr, "%s: ", PGN);
  745.         perror(curname);
  746.         return(NULL);
  747.         }
  748.     while ((c = getc(ifp)) != EOF)
  749.         {
  750.         if (c != '#')
  751.             goto nextline;
  752.         while ((c = getc(ifp)) == ' ' || c == '\t')
  753.             continue;
  754.         for (p = "include"; *p == TOLOWER(c) && *p != '\0'; p++)
  755.             c = getc(ifp);
  756.         if (*p != '\0')
  757.             goto nextline;
  758.         if (getinclude(incname, curname, lineno, ifp) == NO)
  759.             goto nextline;
  760.         if ((htb = lookupinclude(incname, type)) == NULL)
  761.             {
  762.             inctype = findinclude(incpath, incname, curname, type);
  763.             if (inctype == INTERNAL)
  764.                 {
  765.                 htb = instalinclude(incname, incpath, type);
  766.                 }
  767.             else if (inctype == EXTERNAL)
  768.                 {
  769.                 htb = instalinclude(incname, incpath, type);
  770.                 if (slappend(incpath, EXTLIST) == NULL)
  771.                     cleanup();
  772.                 }
  773.             else if (inctype == FROMRULE)
  774.                 {
  775.                 htb = instalinclude(incname, incname, type);
  776.                 ftb = instalinclude(incpath, incpath, type);
  777.                 }
  778.             else    {
  779.                 notfound(curname, lineno, incname);
  780.                 goto nextline;
  781.                 }
  782.  
  783.             /* look for nested include files */
  784.             htb->h_sub = readP(curname, lineno, incpath);
  785.  
  786.             if (inctype == FROMRULE) 
  787.                 ftb->h_sub = htb->h_sub;
  788.             }
  789.         if (i_tail == NULL)
  790.             {
  791.             i_head = i_tail = inclink(htb);
  792.             }
  793.         else    {
  794.             i_tail = i_tail->i_next = inclink(htb);
  795.             }
  796. nextline:    while (c != '\n' && c != EOF)
  797.             c = getc(ifp);
  798.         lineno++;
  799.         }
  800.     fclose(ifp);
  801.     return(i_head);
  802. }
  803.