📄 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. */voidaddincdir(){ 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. */voidgetI(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));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -