Blame config/makedepend/include.c

Packit b099d7
/* $XConsortium: include.c /main/20 1996/12/04 10:11:18 swick $ */
Packit b099d7
/*
Packit b099d7
Packit b099d7
Copyright (c) 1993, 1994  X Consortium
Packit b099d7
Packit b099d7
Permission is hereby granted, free of charge, to any person obtaining a copy
Packit b099d7
of this software and associated documentation files (the "Software"), to deal
Packit b099d7
in the Software without restriction, including without limitation the rights
Packit b099d7
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Packit b099d7
copies of the Software, and to permit persons to whom the Software is
Packit b099d7
furnished to do so, subject to the following conditions:
Packit b099d7
Packit b099d7
The above copyright notice and this permission notice shall be included in
Packit b099d7
all copies or substantial portions of the Software.
Packit b099d7
Packit b099d7
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit b099d7
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit b099d7
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
Packit b099d7
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
Packit b099d7
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit b099d7
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit b099d7
Packit b099d7
Except as contained in this notice, the name of the X Consortium shall not be
Packit b099d7
used in advertising or otherwise to promote the sale, use or other dealings
Packit b099d7
in this Software without prior written authorization from the X Consortium.
Packit b099d7
Packit b099d7
*/
Packit b099d7
Packit b099d7
Packit b099d7
#include "def.h"
Packit b099d7
Packit b099d7
extern struct	inclist	inclist[ MAXFILES ],
Packit b099d7
			*inclistp;
Packit b099d7
extern char	*includedirs[ ];
Packit b099d7
extern char	*notdotdot[ ];
Packit b099d7
extern boolean show_where_not;
Packit b099d7
extern boolean warn_multiple;
Packit b099d7
Packit b099d7
boolean
Packit b099d7
isdot(p)
Packit b099d7
	register char	*p;
Packit b099d7
{
Packit b099d7
	if(p && *p++ == '.' && *p++ == '\0')
Packit b099d7
		return(TRUE);
Packit b099d7
	return(FALSE);
Packit b099d7
}
Packit b099d7
Packit b099d7
boolean
Packit b099d7
isdotdot(p)
Packit b099d7
	register char	*p;
Packit b099d7
{
Packit b099d7
	if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
Packit b099d7
		return(TRUE);
Packit b099d7
	return(FALSE);
Packit b099d7
}
Packit b099d7
Packit b099d7
boolean
Packit b099d7
issymbolic(dir, component)
Packit b099d7
	register char	*dir, *component;
Packit b099d7
{
Packit b099d7
#ifdef S_IFLNK
Packit b099d7
	struct stat	st;
Packit b099d7
	char	buf[ BUFSIZ ], **pp;
Packit b099d7
Packit b099d7
	sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component);
Packit b099d7
	for (pp=notdotdot; *pp; pp++)
Packit b099d7
		if (strcmp(*pp, buf) == 0)
Packit b099d7
			return (TRUE);
Packit b099d7
	if (lstat(buf, &st) == 0
Packit b099d7
	&& (st.st_mode & S_IFMT) == S_IFLNK) {
Packit b099d7
		*pp++ = copy(buf);
Packit b099d7
		if (pp >= &notdotdot[ MAXDIRS ])
Packit b099d7
			fatalerr("out of .. dirs, increase MAXDIRS\n");
Packit b099d7
		return(TRUE);
Packit b099d7
	}
Packit b099d7
#endif
Packit b099d7
	return(FALSE);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Occasionally, pathnames are created that look like .../x/../y
Packit b099d7
 * Any of the 'x/..' sequences within the name can be eliminated.
Packit b099d7
 * (but only if 'x' is not a symbolic link!!)
Packit b099d7
 */
Packit b099d7
void
Packit b099d7
remove_dotdot(path)
Packit b099d7
	char	*path;
Packit b099d7
{
Packit b099d7
	register char	*end, *from, *to, **cp;
Packit b099d7
	char		*components[ MAXFILES ],
Packit b099d7
			newpath[ BUFSIZ ];
Packit b099d7
	boolean		component_copied;
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * slice path up into components.
Packit b099d7
	 */
Packit b099d7
	to = newpath;
Packit b099d7
	if (*path == '/')
Packit b099d7
		*to++ = '/';
Packit b099d7
	*to = '\0';
Packit b099d7
	cp = components;
Packit b099d7
	for (from=end=path; *end; end++)
Packit b099d7
		if (*end == '/') {
Packit b099d7
			while (*end == '/')
Packit b099d7
				*end++ = '\0';
Packit b099d7
			if (*from)
Packit b099d7
				*cp++ = from;
Packit b099d7
			from = end;
Packit b099d7
		}
Packit b099d7
	*cp++ = from;
Packit b099d7
	*cp = NULL;
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * Recursively remove all 'x/..' component pairs.
Packit b099d7
	 */
Packit b099d7
	cp = components;
Packit b099d7
	while(*cp) {
Packit b099d7
		if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))
Packit b099d7
		    && !issymbolic(newpath, *cp))
Packit b099d7
		{
Packit b099d7
		    char **fp = cp + 2;
Packit b099d7
		    char **tp = cp;
Packit b099d7
Packit b099d7
		    do 
Packit b099d7
			*tp++ = *fp; /* move all the pointers down */
Packit b099d7
		    while (*fp++);
Packit b099d7
		    if (cp != components)
Packit b099d7
			cp--;	/* go back and check for nested ".." */
Packit b099d7
		} else {
Packit b099d7
		    cp++;
Packit b099d7
		}
Packit b099d7
	}
Packit b099d7
	/*
Packit b099d7
	 * Concatenate the remaining path elements.
Packit b099d7
	 */
Packit b099d7
	cp = components;
Packit b099d7
	component_copied = FALSE;
Packit b099d7
	while(*cp) {
Packit b099d7
		if (component_copied)
Packit b099d7
			*to++ = '/';
Packit b099d7
		component_copied = TRUE;
Packit b099d7
		for (from = *cp; *from; )
Packit b099d7
			*to++ = *from++;
Packit b099d7
		*to = '\0';
Packit b099d7
		cp++;
Packit b099d7
	}
Packit b099d7
	*to++ = '\0';
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * copy the reconstituted path back to our pointer.
Packit b099d7
	 */
Packit b099d7
	strcpy(path, newpath);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Add an include file to the list of those included by 'file'.
Packit b099d7
 */
Packit b099d7
struct inclist *newinclude(newfile, incstring)
Packit b099d7
	register char	*newfile, *incstring;
Packit b099d7
{
Packit b099d7
	register struct inclist	*ip;
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * First, put this file on the global list of include files.
Packit b099d7
	 */
Packit b099d7
	ip = inclistp++;
Packit b099d7
	if (inclistp == inclist + MAXFILES - 1)
Packit b099d7
		fatalerr("out of space: increase MAXFILES\n");
Packit b099d7
	ip->i_file = copy(newfile);
Packit b099d7
Packit b099d7
	if (incstring == NULL)
Packit b099d7
		ip->i_incstring = ip->i_file;
Packit b099d7
	else
Packit b099d7
		ip->i_incstring = copy(incstring);
Packit b099d7
Packit b099d7
	return(ip);
Packit b099d7
}
Packit b099d7
Packit b099d7
void
Packit b099d7
included_by(ip, newfile)
Packit b099d7
	register struct inclist	*ip, *newfile;
Packit b099d7
{
Packit b099d7
	register int i;
Packit b099d7
Packit b099d7
	if (ip == NULL)
Packit b099d7
		return;
Packit b099d7
	/*
Packit b099d7
	 * Put this include file (newfile) on the list of files included
Packit b099d7
	 * by 'file'.  If 'file' is NULL, then it is not an include
Packit b099d7
	 * file itself (i.e. was probably mentioned on the command line).
Packit b099d7
	 * If it is already on the list, don't stick it on again.
Packit b099d7
	 */
Packit b099d7
	if (ip->i_list == NULL) {
Packit b099d7
		ip->i_list = (struct inclist **)
Packit b099d7
			malloc(sizeof(struct inclist *) * ++ip->i_listlen);
Packit b099d7
		ip->i_merged = (boolean *)
Packit b099d7
		    malloc(sizeof(boolean) * ip->i_listlen);
Packit b099d7
	} else {
Packit b099d7
		for (i=0; i<ip->i_listlen; i++)
Packit b099d7
			if (ip->i_list[ i ] == newfile) {
Packit b099d7
			    i = strlen(newfile->i_file);
Packit b099d7
			    if (!(ip->i_flags & INCLUDED_SYM) &&
Packit b099d7
				!(i > 2 &&
Packit b099d7
				  newfile->i_file[i-1] == 'c' &&
Packit b099d7
				  newfile->i_file[i-2] == '.'))
Packit b099d7
			    {
Packit b099d7
				/* only bitch if ip has */
Packit b099d7
				/* no #include SYMBOL lines  */
Packit b099d7
				/* and is not a .c file */
Packit b099d7
				if (warn_multiple)
Packit b099d7
				{
Packit b099d7
					warning("%s includes %s more than once!\n",
Packit b099d7
						ip->i_file, newfile->i_file);
Packit b099d7
					warning1("Already have\n");
Packit b099d7
					for (i=0; i<ip->i_listlen; i++)
Packit b099d7
						warning1("\t%s\n", ip->i_list[i]->i_file);
Packit b099d7
				}
Packit b099d7
			    }
Packit b099d7
			    return;
Packit b099d7
			}
Packit b099d7
		ip->i_list = (struct inclist **) realloc(ip->i_list,
Packit b099d7
			sizeof(struct inclist *) * ++ip->i_listlen);
Packit b099d7
		ip->i_merged = (boolean *)
Packit b099d7
		    realloc(ip->i_merged, sizeof(boolean) * ip->i_listlen);
Packit b099d7
	}
Packit b099d7
	ip->i_list[ ip->i_listlen-1 ] = newfile;
Packit b099d7
	ip->i_merged[ ip->i_listlen-1 ] = FALSE;
Packit b099d7
}
Packit b099d7
Packit b099d7
void
Packit b099d7
inc_clean ()
Packit b099d7
{
Packit b099d7
	register struct inclist *ip;
Packit b099d7
Packit b099d7
	for (ip = inclist; ip < inclistp; ip++) {
Packit b099d7
		ip->i_flags &= ~MARKED;
Packit b099d7
	}
Packit b099d7
}
Packit b099d7
Packit b099d7
struct inclist *inc_path(file, include, dot)
Packit b099d7
	register char	*file,
Packit b099d7
			*include;
Packit b099d7
	boolean	dot;
Packit b099d7
{
Packit b099d7
	static char	path[ BUFSIZ ];
Packit b099d7
	register char		**pp, *p;
Packit b099d7
	register struct inclist	*ip;
Packit b099d7
	struct stat	st;
Packit b099d7
	boolean	found = FALSE;
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * Check all previously found include files for a path that
Packit b099d7
	 * has already been expanded.
Packit b099d7
	 */
Packit b099d7
	for (ip = inclist; ip->i_file; ip++)
Packit b099d7
	    if ((strcmp(ip->i_incstring, include) == 0) &&
Packit b099d7
		!(ip->i_flags & INCLUDED_SYM))
Packit b099d7
	    {
Packit b099d7
		found = TRUE;
Packit b099d7
		break;
Packit b099d7
	    }
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * If the path was surrounded by "" or is an absolute path,
Packit b099d7
	 * then check the exact path provided.
Packit b099d7
	 */
Packit b099d7
	if (!found && (dot || *include == '/')) {
Packit b099d7
		if (stat(include, &st) == 0) {
Packit b099d7
			ip = newinclude(include, include);
Packit b099d7
			found = TRUE;
Packit b099d7
		}
Packit b099d7
		else if (show_where_not)
Packit b099d7
			warning1("\tnot in %s\n", include);
Packit b099d7
	}
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * If the path was surrounded by "" see if this include file is in the
Packit b099d7
	 * directory of the file being parsed.
Packit b099d7
	 */
Packit b099d7
	if (!found && dot) {
Packit b099d7
		for (p=file+strlen(file); p>file; p--)
Packit b099d7
			if (*p == '/')
Packit b099d7
				break;
Packit b099d7
		if (p == file)
Packit b099d7
			strcpy(path, include);
Packit b099d7
		else {
Packit b099d7
			strncpy(path, file, (p-file) + 1);
Packit b099d7
			path[ (p-file) + 1 ] = '\0';
Packit b099d7
			strcpy(path + (p-file) + 1, include);
Packit b099d7
		}
Packit b099d7
		remove_dotdot(path);
Packit b099d7
		if (stat(path, &st) == 0) {
Packit b099d7
			ip = newinclude(path, include);
Packit b099d7
			found = TRUE;
Packit b099d7
		}
Packit b099d7
		else if (show_where_not)
Packit b099d7
			warning1("\tnot in %s\n", path);
Packit b099d7
	}
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * Check the include directories specified. (standard include dir
Packit b099d7
	 * should be at the end.)
Packit b099d7
	 */
Packit b099d7
	if (!found)
Packit b099d7
		for (pp = includedirs; *pp; pp++) {
Packit b099d7
			sprintf(path, "%s/%s", *pp, include);
Packit b099d7
			remove_dotdot(path);
Packit b099d7
			if (stat(path, &st) == 0) {
Packit b099d7
				ip = newinclude(path, include);
Packit b099d7
				found = TRUE;
Packit b099d7
				break;
Packit b099d7
			}
Packit b099d7
			else if (show_where_not)
Packit b099d7
				warning1("\tnot in %s\n", path);
Packit b099d7
		}
Packit b099d7
Packit b099d7
	if (!found)
Packit b099d7
		ip = NULL;
Packit b099d7
	return(ip);
Packit b099d7
}