4.4BSD/usr/src/contrib/mkmf/src/depend.c
/*
* 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: depend.c,v 4.10 93/05/25 21:17:49 nicklin Exp $
*
* Author: Peter J. Nicklin
*/
#include <ctype.h>
#include <stdio.h>
#include "Mkmf.h"
#include "config.h"
#include "dlist.h"
#include "hash.h"
#include "macro.h"
#include "null.h"
#include "path.h"
#include "slist.h"
#include "stringx.h"
#include "yesno.h"
#define CURINCLUDE "./"
#define TOLOWER(c) (isupper(c) ? tolower(c) : (c))
#define ISWHITESPACE(c) (c == ' ' || c == '\t')
#define SKIPWHITESPACE(c, f) while ((c = getc(f))==' ' || c=='\t'); ungetc(c,f);
#define USRINCLUDE "/usr/include/"
#define USRINCLUDECC "/usr/include/CC/"
/*
* Include file state
*/
#define NOTFOUND 0 /* not found anywhere */
#define EXTERNAL 1 /* not found in current directory */
#define INTERNAL 2 /* found in current directory */
#define FROMRULE 3 /* derived from tranformation rule */
#define SYSTEM 4 /* a system header file */
static char SYSINCLUDE[PATHSIZE]; /* /usr/include pathname buffer */
static char SYSINCLUDECC[PATHSIZE]; /* /usr/include/CC pathname buffer */
static int SYSINCLUDELEN; /* length of SYSINCLUDE */
/*
* Include files are stored in hash tables by direct chaining (See
* p. 134 in `The C Programming Language' by Kernighan and Ritchie).
* Included include files are also added to a singly-linked list
* attached to the hash table entry for the include file.
*/
static HASH *C_INCLUDETABLE = NULL; /* C include file hash table */
static HASH *CXX_INCLUDETABLE = NULL; /* C++ include file hash table */
static HASH *F_INCLUDETABLE = NULL; /* Fortran include file hash table */
static HASH *P_INCLUDETABLE = NULL; /* Pascal include file hash table */
/*
* Additional include directories are specified via the -I compiler
* command line option. These directories are stored in singly-linked lists.
* We also assume that the last look-up directory is "/usr/include".
*/
static SLIST *C_INCDIR; /* C include directories */
static SLIST *CXX_INCDIR; /* C++ include directories */
static SLIST *F_INCDIR; /* Fortran include directories */
static SLIST *P_INCDIR; /* Pascal include directories */
SLIST *EXTLIST; /* external header file name list */
SLIST *SYSLIST; /* system header file name list */
extern char *PGN; /* program name */
extern int SYSHDRS; /* search system header files? */
extern HASH *MDEFTABLE; /* macro definition table */
/*
* addincdir() adds directories containing include files to the
* appropriate singly-linked list. The pathnames to the directories
* are derived from makefile macro definitions.
*/
void
addincdir()
{
char *slappend(); /* append to singly-linked list */
HASHBLK *htb; /* hash table entry block */
HASHBLK *htlookup(); /* find hash table entry */
int cleanup(); /* remove temporary makefile and exit */
void getI(); /* get include directory pathnames */
/* initialize system include pathnames */
initsysinclude();
/* C CFLAGS macro */
if ((htb = htlookup(MCFLAGS, MDEFTABLE)) != NULL)
getI(htb->h_key, htb->h_def, C_INCDIR);
if (slappend(SYSINCLUDE, C_INCDIR) == NULL)
cleanup();
/* C++ CXXFLAGS macro */
if ((htb = htlookup(MCXXFLAGS, MDEFTABLE)) != NULL)
getI(htb->h_key, htb->h_def, CXX_INCDIR);
/* C++ C++FLAGS macro */
if ((htb = htlookup(MCPXFLAGS, MDEFTABLE)) != NULL)
getI(htb->h_key, htb->h_def, CXX_INCDIR);
/* C++ CCFLAGS macro */
if ((htb = htlookup(MCCFLAGS, MDEFTABLE)) != NULL)
getI(htb->h_key, htb->h_def, CXX_INCDIR);
if (slappend(SYSINCLUDECC, CXX_INCDIR) == NULL ||
slappend(SYSINCLUDE, CXX_INCDIR) == NULL)
cleanup();
/* Fortran FFLAGS macro */
if ((htb = htlookup(MFFLAGS, MDEFTABLE)) != NULL)
getI(htb->h_key, htb->h_def, F_INCDIR);
if (slappend(SYSINCLUDE, F_INCDIR) == NULL)
cleanup();
/* Pascal PFLAGS macro */
if ((htb = htlookup(MPFLAGS, MDEFTABLE)) != NULL)
getI(htb->h_key, htb->h_def, P_INCDIR);
if (slappend(SYSINCLUDE, P_INCDIR) == NULL)
cleanup();
}
/*
* findinclude() tries to find the pathname of an include file. Returns
* integer INTERNAL if found in the current directory, EXTERNAL if found
* somewhere else, FROMRULE if derived from a transformation rule,
* SYSTEM if a system header file, otherwise NOTFOUND. The pathname
* is copied into incpath.
*/
#define LOCALDIR(f) (strchr(f, _PSC) == NULL)
#define ISYSINCLUDE(f) (strncmp(f, SYSINCLUDE, SYSINCLUDELEN) == 0)
#define INCLUDETYPE(f) (LOCALDIR(f) ? INTERNAL : (ISYSINCLUDE(f) ? SYSTEM : EXTERNAL))
findinclude(incpath, incname, lastname, type)
char *incpath; /* pathname receiving buffer */
register char *incname; /* include file name */
char *lastname; /* file that includes incname */
int type; /* file type */
{
register char *pp; /* include file path pointer */
char *optpath(); /* optimize pathname */
char *pathcat(); /* pathname concatenation */
char *pathhead(); /* remove pathname tail */
char *strpcpy(); /* string copy and update pointer */
int applyrule(); /* apply transformation rules */
SLBLK *slb; /* singly-linked list block */
SLIST *slist; /* include directory list pointer */
/*
* look for an absolute include file name
*/
if (*incname == '/')
{
strcpy(incpath, incname);
return(FILEXIST(incpath) ? INCLUDETYPE(incpath) : NOTFOUND);
}
/*
* search the current include directory for an #include file
* whose name is enclosed in " ", or see if it can be generated
* by a transformation rule in the current working directory.
*/
if (*incname != '<')
{
if (LOCALDIR(lastname))
{
if (LOCALDIR(incname))
{
if (applyrule(incname, incpath) == YES)
return(FROMRULE);
}
strcpy(incpath, incname);
if (FILEXIST(incpath))
return(INCLUDETYPE(incpath));
}
else {
strcpy(incpath, lastname);
pathcat(incpath, pathhead(incpath), incname);
optpath(incpath);
if (FILEXIST(incpath))
return(INCLUDETYPE(incpath));
}
}
/*
* search directory list
*/
switch (type)
{
case INCLUDE_C:
slist = C_INCDIR;
break;
case INCLUDE_CXX:
slist = CXX_INCDIR;
break;
case INCLUDE_FORTRAN:
slist = F_INCDIR;
break;
case INCLUDE_PASCAL:
slist = P_INCDIR;
break;
}
for (slb = slist->head; slb != NULL; slb = slb->next)
{
pp = strpcpy(incpath, slb->key);
if (*incname == '<')
{
pp = strpcpy(pp, incname+1);
pp[-1] = '\0';
}
else {
strcpy(pp, incname);
}
optpath(incpath);
if (FILEXIST(incpath))
return(INCLUDETYPE(incpath));
}
return(NOTFOUND);
}
/*
* getI() appends include directories found via the -I compiler option to
* a singly linked list.
*/
void
getI(mnam, mdef, slist)
char *mnam; /* compiler options macro name */
char *mdef; /* compiler options macro definition */
SLIST *slist; /* singly-linked list */
{
char *getoption(); /* get next token */
char incpath[PATHSIZE]; /* include directory pathname buffer */
char *slappend(); /* append to singly-linked list */
int cleanup(); /* remove temporary makefile and exit */
while ((mdef = getoption(incpath, mdef, "-I")) != NULL)
{
if (*incpath == '\0')
{
warns("missing include directory in %s macro definition", mnam);
break;
}
else {
strcat(incpath, PATHSEP);
if (slappend(incpath, slist) == NULL)
cleanup();
}
}
}
/*
* getinclude() fetchs an include file name from a line of source code.
* /usr/include '<' and '>' delimiters remain with the filename to
* distinguish it from an include file in a local directory. Returns
* NO if syntax error, otherwise YES.
*/
getinclude(incname, curname, lineno, ifp)
char *curname; /* current file name */
char *incname; /* include file name receiving buffer */
int lineno; /* current line number */
register FILE *ifp; /* input stream */
{
register char *ip; /* include file name buffer pointer */
register int c; /* current character */
SKIPWHITESPACE(c, ifp);
for (ip = incname; (c = getc(ifp)) != EOF; ip++)
{
*ip = c;
if (c == '\n' || c == '\t' || c == ' ' ||
c == ';' || c == ',' || c == '$' )
{
ungetc(c, ifp);
break;
}
}
*ip = '\0';
if ((*incname == '<' && ip[-1] != '>') ||
(*incname == '\"' && ip[-1] != '\"') ||
(*incname == '\'' && ip[-1] != '\'') ||
(*incname == '(' && ip[-1] != ')'))
{
fprintf(stderr,
"%s: \"%s\", line %d: bad include syntax for %s\n",
PGN, curname, lineno, incname);
return(NO);
}
if (*incname == '\"' || *incname == '\'' || *incname == '(')
{
ip[-1] = '\0';
ip = incname + 1;
while (*incname++ = *ip++)
continue;
}
return(YES);
}
/*
* inclink() stores a pointer to a hash table block (which contains
* include file information) somewhere. Returns a pointer to the somewhere,
* or calls cleanup() if out of memory.
*/
INCBLK *
inclink(htb)
HASHBLK *htb; /* hash table block pointer to save */
{
char *malloc(); /* memory allocator */
INCBLK *iblk; /* pointer to new include chain block */
int cleanup(); /* remove temporary makefile and exit */
if ((iblk = (INCBLK *) malloc(sizeof(INCBLK))) == NULL)
{
nocore();
cleanup();
}
iblk->i_loop = NO;
iblk->i_hblk = htb;
iblk->i_next = NULL;
return(iblk);
}
/*
* instalinclude() adds an include file name to the appropriate include
* file hash table. Returns a pointer to the hash table block, or calls
* cleanup() if out of memory.
*/
HASHBLK *
instalinclude(incname, incpath, type)
char *incname; /* name of include file */
char *incpath; /* path to include file */
int type; /* type of source file */
{
HASH *htinit(); /* initialize hash table */
HASHBLK *htb; /* hash table block */
HASHBLK *htinstall(); /* install hash table entry */
int cleanup(); /* remove temporary makefile and exit */
int ilen; /* include path length */
ilen = strlen(incpath);
switch (type)
{
case INCLUDE_C:
if (C_INCLUDETABLE == NULL)
{
C_INCLUDETABLE = htinit(INCLUDETABLESIZE);
}
htb = htinstall(incname, incpath, ilen, C_INCLUDETABLE);
break;
case INCLUDE_CXX:
if (CXX_INCLUDETABLE == NULL)
{
CXX_INCLUDETABLE = htinit(INCLUDETABLESIZE);
}
htb = htinstall(incname, incpath, ilen, CXX_INCLUDETABLE);
break;
case INCLUDE_FORTRAN:
if (F_INCLUDETABLE == NULL)
{
F_INCLUDETABLE = htinit(INCLUDETABLESIZE);
}
htb = htinstall(incname, incpath, ilen, F_INCLUDETABLE);
break;
case INCLUDE_PASCAL:
if (P_INCLUDETABLE == NULL)
{
P_INCLUDETABLE = htinit(INCLUDETABLESIZE);
}
htb = htinstall(incname, incpath, ilen, P_INCLUDETABLE);
break;
default:
htb = NULL;
break;
}
if (htb == NULL)
cleanup();
return(htb);
}
/*
* lookupinclude() returns a pointer to an include hash table block
* corresponding to incname and type. Returns null if not found.
*/
HASHBLK *
lookupinclude(incname, type)
char *incname; /* name of include file */
int type; /* type of source file */
{
HASH *includetable; /* include file hash table */
HASHBLK *htlookup(); /* find hash table entry */
switch (type)
{
case INCLUDE_C:
includetable = C_INCLUDETABLE;
break;
case INCLUDE_CXX:
includetable = CXX_INCLUDETABLE;
break;
case INCLUDE_FORTRAN:
includetable = F_INCLUDETABLE;
break;
case INCLUDE_PASCAL:
includetable = P_INCLUDETABLE;
break;
default:
includetable = NULL;
break;
}
return((includetable == NULL) ? NULL : htlookup(incname, includetable));
}
/*
* mkdepend() creates include file dependencies for object files and installs
* them to dependency list dlp. Returns a pointer to the dependency list.
*/
DLIST *
mkdepend()
{
extern SLIST *SRCLIST; /* source file name list */
char *suffix; /* suffix pointer */
DLBLK *dlappend(); /* append dependency list */
DLIST *dlinit(); /* initialize dependency list */
DLIST *dlist; /* dependency list */
INCBLK *ibp; /* pointer to chain of include files */
INCBLK *readC(); /* read C include-style files */
INCBLK *readF(); /* read Fortran include-style files */
INCBLK *readP(); /* read Pascal include-style files */
int cleanup(); /* remove temporary makefile and exit */
int lookuptypeofinclude(); /* look up the brand of include */
int slsort(); /* sort singly-linked list */
int type; /* source file type */
SLBLK *lbp; /* list block pointer */
SLIST *slinit(); /* initialize singly-linked list */
void addincdir(); /* add to list of include directories */
void rmprinttag(); /* remove "already printed" tags */
/* initialize include file look-up lists */
C_INCDIR = slinit();
CXX_INCDIR = slinit();
F_INCDIR = slinit();
P_INCDIR = slinit();
/* add additional include directories */
addincdir();
/* initialize external and system header file name lists */
EXTLIST = slinit();
SYSLIST = slinit();
/* initialize dependency list */
dlist = dlinit();
for (lbp = SRCLIST->head; lbp != NULL; lbp = lbp->next)
{
suffix = strrchr(lbp->key, '.');
type = lookuptypeofinclude(++suffix);
switch (type)
{
case INCLUDE_C:
case INCLUDE_CXX:
ibp = readC(lbp->key, 0, lbp->key, type);
break;
case INCLUDE_FORTRAN:
ibp = readF(lbp->key, 0, lbp->key, type);
break;
case INCLUDE_PASCAL:
ibp = readP(lbp->key, 0, lbp->key, type);
break;
case INCLUDE_NONE:
ibp = NULL;
break;
}
if (ibp != NULL)
{
if (dlappend(type, lbp, ibp, dlist) == NULL)
cleanup();
}
}
if (slsort(strcmp, EXTLIST) == NO || slsort(strcmp, SYSLIST) == NO)
cleanup();
return(dlist);
}
/*
* notfound() prints a "can't find" filename error message.
*/
void
notfound(curname, lineno, incname)
char *curname; /* current file name */
char *incname; /* name of include file */
int lineno; /* current line number */
{
if (PGN != NULL && *PGN != '\0')
{
fprintf(stderr, "%s: ", PGN);
}
if (*incname == '<')
{
fprintf(stderr, "\"%s\", line %d: can't find %s\n",
curname, lineno, incname);
}
else {
fprintf(stderr, "\"%s\", line %d: can't find \"%s\"\n",
curname, lineno, incname);
}
}
/*
* readC() searches C files for included files. Returns a pointer to
* the chain of include files installed or found in the include file
* hash table, or null if no include files found.
*/
INCBLK *
readC(lastfile, lastline, curname, type)
char *lastfile; /* parent file name */
int lastline; /* current line in parent file */
char *curname; /* current file name */
int type; /* file type */
{
register char *p; /* include string pointer */
register FILE *ifp; /* input file stream */
register int c; /* current character */
char incname[PATHSIZE]; /* name of include file */
char incpath[PATHSIZE]; /* path to include file */
char *slappend(); /* append pathname to list */
FILE *fopen(); /* open file */
HASHBLK *ftb; /* fromrule hash table entry block */
HASHBLK *htb; /* hash table entry block */
HASHBLK *instalinclude(); /* install include name in hash table */
HASHBLK *lookupinclude(); /* look up include in hash table */
INCBLK *i_head = NULL; /* head of include chain */
INCBLK *i_tail = NULL; /* tail of include chain */
INCBLK *inclink(); /* link include file hash blocks */
int cleanup(); /* remove temporary makefile and exit */
int findinclude(); /* locate include file */
int getinclude(); /* get include name from input line */
int inctype; /* origin of include file */
int lineno = 1; /* current line number */
void notfound(); /* print "can't find" filename msg */
if ((ifp = fopen(curname, "r")) == NULL)
{
if (lastline > 0)
fprintf(stderr, "%s: \"%s\", line %d: ", PGN,
lastfile, lastline);
else
fprintf(stderr, "%s: ", PGN);
perror(curname);
return(NULL);
}
while ((c = getc(ifp)) != EOF)
{
if (ISWHITESPACE(c))
continue;
if (c != '#')
goto nextline;
SKIPWHITESPACE(c, ifp);
for (p = "include"; (c = getc(ifp)) == *p && *p != '\0' ; p++)
continue;
if (*p != '\0')
goto nextline;
ungetc(c, ifp);
if (getinclude(incname, curname, lineno, ifp) == NO)
goto nextline;
if ((htb = lookupinclude(incname, type)) == NULL)
{
inctype = findinclude(incpath, incname, curname, type);
if (inctype == INTERNAL)
{
htb = instalinclude(incname, incpath, type);
}
else if (inctype == SYSTEM && SYSHDRS == YES)
{
htb = instalinclude(incname, incpath, type);
if (slappend(incpath, SYSLIST) == NULL)
cleanup();
}
else if (inctype == SYSTEM && SYSHDRS == NO)
{
goto nextline;
}
else if (inctype == EXTERNAL)
{
htb = instalinclude(incname, incpath, type);
if (slappend(incpath, EXTLIST) == NULL)
cleanup();
}
else if (inctype == FROMRULE)
{
htb = instalinclude(incname, incname, type);
ftb = instalinclude(incpath, incpath, type);
}
else {
notfound(curname, lineno, incname);
goto nextline;
}
/* look for nested include files */
htb->h_sub = readC(curname, lineno, incpath, type);
if (inctype == FROMRULE)
ftb->h_sub = htb->h_sub;
}
if (i_tail == NULL)
{
i_head = i_tail = inclink(htb);
}
else {
i_tail = i_tail->i_next = inclink(htb);
}
nextline: while (c != '\n' && c != EOF)
c = getc(ifp);
lineno++;
}
fclose(ifp);
return(i_head);
}
/*
* readF() searches Fortran files for included files. Returns a pointer
* to the chain of include files installed or found in the include file
* hash table, or null if no include files found.
*/
INCBLK *
readF(lastfile, lastline, curname, type)
char *lastfile; /* parent file name */
int lastline; /* current line in parent file */
char *curname; /* current file name */
int type; /* file type */
{
register char *p; /* include string pointer */
register FILE *ifp; /* input file stream */
register int c; /* current character */
char incname[PATHSIZE]; /* name of include file */
char incpath[PATHSIZE]; /* path to include file */
char *slappend(); /* append pathname to list */
FILE *fopen(); /* open file */
HASHBLK *ftb; /* fromrule hash table entry block */
HASHBLK *htb; /* hash table entry block */
HASHBLK *instalinclude(); /* install include name in hash table */
HASHBLK *lookupinclude(); /* look up include in hash table */
INCBLK *i_head = NULL; /* head of include chain */
INCBLK *i_tail = NULL; /* tail of include chain */
INCBLK *inclink(); /* link include file hash blocks */
int cleanup(); /* remove temporary makefile and exit */
int findinclude(); /* locate include file */
int getinclude(); /* get include name from input line */
int inctype; /* origin of include file */
int lineno = 1; /* current line number */
void notfound(); /* print "can't find" filename msg */
if ((ifp = fopen(curname, "r")) == NULL)
{
if (lastline > 0)
fprintf(stderr, "%s: \"%s\", line %d: ", PGN,
lastfile, lastline);
else
fprintf(stderr, "%s: ", PGN);
perror(curname);
return(NULL);
}
while ((c = getc(ifp)) != EOF)
{
if (c == 'c' || c == 'C' || c == '*' || c == '\n')
goto nextline;
while ((c = getc(ifp)) == ' ' || c == '\t' || c == '#' || c == '$')
continue;
for (p = "include"; *p == TOLOWER(c) && *p != '\0'; p++)
c = getc(ifp);
if (*p != '\0')
goto nextline;
ungetc(c, ifp);
if (getinclude(incname, curname, lineno, ifp) == NO)
goto nextline;
if ((htb = lookupinclude(incname, type)) == NULL)
{
inctype = findinclude(incpath, incname, curname, type);
if (inctype == INTERNAL)
{
htb = instalinclude(incname, incpath, type);
}
else if (inctype == SYSTEM && SYSHDRS == YES)
{
htb = instalinclude(incname, incpath, type);
if (slappend(incpath, SYSLIST) == NULL)
cleanup();
}
else if (inctype == SYSTEM && SYSHDRS == NO)
{
goto nextline;
}
else if (inctype == EXTERNAL)
{
htb = instalinclude(incname, incpath, type);
if (slappend(incpath, EXTLIST) == NULL)
cleanup();
}
else if (inctype == FROMRULE)
{
htb = instalinclude(incname, incname, type);
ftb = instalinclude(incpath, incpath, type);
}
else {
notfound(curname, lineno, incname);
goto nextline;
}
/* look for nested include files */
htb->h_sub = readF(curname, lineno, incpath, type);
if (inctype == FROMRULE)
ftb->h_sub = htb->h_sub;
}
if (i_tail == NULL)
{
i_head = i_tail = inclink(htb);
}
else {
i_tail = i_tail->i_next = inclink(htb);
}
nextline: while (c != '\n' && c != EOF)
c = getc(ifp);
lineno++;
}
fclose(ifp);
return(i_head);
}
/*
* readP() searches Pascal files for included files. Returns a pointer
* to the chain of include files installed or found in the include file
* hash table, or null if no include files found.
*/
INCBLK *
readP(lastfile, lastline, curname, type)
char *lastfile; /* parent file name */
int lastline; /* current line in parent file */
char *curname; /* current file name */
int type; /* file type */
{
register char *p; /* include string pointer */
register FILE *ifp; /* input file stream */
register int c; /* current character */
char incname[PATHSIZE]; /* name of include file */
char incpath[PATHSIZE]; /* path to include file */
char *slappend(); /* append pathname to list */
FILE *fopen(); /* open file */
HASHBLK *ftb; /* fromrule hash table entry block */
HASHBLK *htb; /* hash table entry block */
HASHBLK *instalinclude(); /* install include name in hash table */
HASHBLK *lookupinclude(); /* look up include in hash table */
INCBLK *i_head = NULL; /* head of include chain */
INCBLK *i_tail = NULL; /* tail of include chain */
INCBLK *inclink(); /* link include file hash blocks */
int cleanup(); /* remove temporary makefile and exit */
int findinclude(); /* locate include file */
int getinclude(); /* get include name from input line */
int inctype; /* origin of include file */
int lineno = 1; /* current line number */
void notfound(); /* print "can't find" filename msg */
if ((ifp = fopen(curname, "r")) == NULL)
{
if (lastline > 0)
fprintf(stderr, "%s: \"%s\", line %d: ", PGN,
lastfile, lastline);
else
fprintf(stderr, "%s: ", PGN);
perror(curname);
return(NULL);
}
while ((c = getc(ifp)) != EOF)
{
if (ISWHITESPACE(c))
continue;
if (c != '#' && c != '$')
goto nextline;
while ((c = getc(ifp)) == ' ' || c == '\t')
continue;
for (p = "include"; *p == TOLOWER(c) && *p != '\0'; p++)
c = getc(ifp);
if (*p != '\0')
goto nextline;
ungetc(c, ifp);
if (getinclude(incname, curname, lineno, ifp) == NO)
goto nextline;
if ((htb = lookupinclude(incname, type)) == NULL)
{
inctype = findinclude(incpath, incname, curname, type);
if (inctype == INTERNAL)
{
htb = instalinclude(incname, incpath, type);
}
else if (inctype == SYSTEM && SYSHDRS == YES)
{
htb = instalinclude(incname, incpath, type);
if (slappend(incpath, SYSLIST) == NULL)
cleanup();
}
else if (inctype == SYSTEM && SYSHDRS == NO)
{
goto nextline;
}
else if (inctype == EXTERNAL)
{
htb = instalinclude(incname, incpath, type);
if (slappend(incpath, EXTLIST) == NULL)
cleanup();
}
else if (inctype == FROMRULE)
{
htb = instalinclude(incname, incname, type);
ftb = instalinclude(incpath, incpath, type);
}
else {
notfound(curname, lineno, incname);
goto nextline;
}
/* look for nested include files */
htb->h_sub = readP(curname, lineno, incpath, type);
if (inctype == FROMRULE)
ftb->h_sub = htb->h_sub;
}
if (i_tail == NULL)
{
i_head = i_tail = inclink(htb);
}
else {
i_tail = i_tail->i_next = inclink(htb);
}
nextline: while (c != '\n' && c != EOF)
c = getc(ifp);
lineno++;
}
fclose(ifp);
return(i_head);
}
initsysinclude()
{
HASHBLK *htb; /* hash table entry block */
HASHBLK *htlookup(); /* find hash table entry */
#ifdef _HasCompileSysType
if ((htb = htlookup(MCOMPILESYSTYPE, MDEFTABLE)) != NULL)
{
sprintf(SYSINCLUDE, "/%s", htb->h_def);
sprintf(SYSINCLUDECC, "/%s", htb->h_def);
}
#endif
strcat(SYSINCLUDE, USRINCLUDE);
strcat(SYSINCLUDECC, USRINCLUDECC);
SYSINCLUDELEN = strlen(SYSINCLUDE)-1; /* length - last '/' */
}