include.c revision 63165362
10eb10989Smrg/*
20eb10989Smrg
30eb10989SmrgCopyright (c) 1993, 1994, 1998 The Open Group
40eb10989Smrg
50eb10989SmrgPermission to use, copy, modify, distribute, and sell this software and its
60eb10989Smrgdocumentation for any purpose is hereby granted without fee, provided that
70eb10989Smrgthe above copyright notice appear in all copies and that both that
80eb10989Smrgcopyright notice and this permission notice appear in supporting
90eb10989Smrgdocumentation.
100eb10989Smrg
110eb10989SmrgThe above copyright notice and this permission notice shall be included in
120eb10989Smrgall copies or substantial portions of the Software.
130eb10989Smrg
140eb10989SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
150eb10989SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
160eb10989SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
170eb10989SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
180eb10989SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
190eb10989SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
200eb10989Smrg
210eb10989SmrgExcept as contained in this notice, the name of The Open Group shall not be
220eb10989Smrgused in advertising or otherwise to promote the sale, use or other dealings
230eb10989Smrgin this Software without prior written authorization from The Open Group.
240eb10989Smrg
250eb10989Smrg*/
260eb10989Smrg
270eb10989Smrg
280eb10989Smrg#include "def.h"
290eb10989Smrg
300eb10989Smrgextern struct	inclist	inclist[ MAXFILES ],
310eb10989Smrg			*inclistp, *inclistnext;
3263165362Smrgextern const char	*includedirs[ ],
3363165362Smrg			**includedirsnext;
340eb10989Smrgextern char	*notdotdot[ ];
350eb10989Smrgextern boolean show_where_not;
360eb10989Smrgextern boolean warn_multiple;
370eb10989Smrg
380eb10989Smrgstatic boolean
3963165362Smrgisdot(const char *p)
400eb10989Smrg{
410eb10989Smrg	if(p && *p++ == '.' && *p++ == '\0')
420eb10989Smrg		return(TRUE);
430eb10989Smrg	return(FALSE);
440eb10989Smrg}
450eb10989Smrg
460eb10989Smrgstatic boolean
4763165362Smrgisdotdot(const char *p)
480eb10989Smrg{
490eb10989Smrg	if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
500eb10989Smrg		return(TRUE);
510eb10989Smrg	return(FALSE);
520eb10989Smrg}
530eb10989Smrg
540eb10989Smrgstatic boolean
5563165362Smrgissymbolic(const char *dir, const char *component)
560eb10989Smrg{
570eb10989Smrg#ifdef S_IFLNK
580eb10989Smrg	struct stat	st;
590eb10989Smrg	char	buf[ BUFSIZ ], **pp;
600eb10989Smrg
610eb10989Smrg	sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component);
620eb10989Smrg	for (pp=notdotdot; *pp; pp++)
630eb10989Smrg		if (strcmp(*pp, buf) == 0)
640eb10989Smrg			return (TRUE);
650eb10989Smrg	if (lstat(buf, &st) == 0
660eb10989Smrg	&& (st.st_mode & S_IFMT) == S_IFLNK) {
670eb10989Smrg		*pp++ = copy(buf);
680eb10989Smrg		if (pp >= &notdotdot[ MAXDIRS ])
690eb10989Smrg			fatalerr("out of .. dirs, increase MAXDIRS\n");
700eb10989Smrg		return(TRUE);
710eb10989Smrg	}
720eb10989Smrg#endif
730eb10989Smrg	return(FALSE);
740eb10989Smrg}
750eb10989Smrg
760eb10989Smrg/*
770eb10989Smrg * Occasionally, pathnames are created that look like .../x/../y
780eb10989Smrg * Any of the 'x/..' sequences within the name can be eliminated.
790eb10989Smrg * (but only if 'x' is not a symbolic link!!)
800eb10989Smrg */
810eb10989Smrgstatic void
820eb10989Smrgremove_dotdot(char *path)
830eb10989Smrg{
840eb10989Smrg	register char	*end, *from, *to, **cp;
850eb10989Smrg	char		*components[ MAXFILES ],
860eb10989Smrg			newpath[ BUFSIZ ];
870eb10989Smrg	boolean		component_copied;
880eb10989Smrg
890eb10989Smrg	/*
900eb10989Smrg	 * slice path up into components.
910eb10989Smrg	 */
920eb10989Smrg	to = newpath;
930eb10989Smrg	if (*path == '/')
940eb10989Smrg		*to++ = '/';
950eb10989Smrg	*to = '\0';
960eb10989Smrg	cp = components;
970eb10989Smrg	for (from=end=path; *end; end++)
980eb10989Smrg		if (*end == '/') {
990eb10989Smrg			while (*end == '/')
1000eb10989Smrg				*end++ = '\0';
1010eb10989Smrg			if (*from)
1020eb10989Smrg				*cp++ = from;
1030eb10989Smrg			from = end;
1040eb10989Smrg		}
1050eb10989Smrg	*cp++ = from;
1060eb10989Smrg	*cp = NULL;
1070eb10989Smrg
1080eb10989Smrg	/*
1090eb10989Smrg	 * Recursively remove all 'x/..' component pairs.
1100eb10989Smrg	 */
1110eb10989Smrg	cp = components;
1120eb10989Smrg	while(*cp) {
1130eb10989Smrg		if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))
1140eb10989Smrg		    && !issymbolic(newpath, *cp))
1150eb10989Smrg		{
1160eb10989Smrg		    char **fp = cp + 2;
1170eb10989Smrg		    char **tp = cp;
1180eb10989Smrg
1190eb10989Smrg		    do
1200eb10989Smrg			*tp++ = *fp; /* move all the pointers down */
1210eb10989Smrg		    while (*fp++);
1220eb10989Smrg		    if (cp != components)
1230eb10989Smrg			cp--;	/* go back and check for nested ".." */
1240eb10989Smrg		} else {
1250eb10989Smrg		    cp++;
1260eb10989Smrg		}
1270eb10989Smrg	}
1280eb10989Smrg	/*
1290eb10989Smrg	 * Concatenate the remaining path elements.
1300eb10989Smrg	 */
1310eb10989Smrg	cp = components;
1320eb10989Smrg	component_copied = FALSE;
1330eb10989Smrg	while(*cp) {
1340eb10989Smrg		if (component_copied)
1350eb10989Smrg			*to++ = '/';
1360eb10989Smrg		component_copied = TRUE;
1370eb10989Smrg		for (from = *cp; *from; )
1380eb10989Smrg			*to++ = *from++;
1390eb10989Smrg		*to = '\0';
1400eb10989Smrg		cp++;
1410eb10989Smrg	}
1420eb10989Smrg	*to++ = '\0';
1430eb10989Smrg
1440eb10989Smrg	/*
1450eb10989Smrg	 * copy the reconstituted path back to our pointer.
1460eb10989Smrg	 */
1470eb10989Smrg	strcpy(path, newpath);
1480eb10989Smrg}
1490eb10989Smrg
1500eb10989Smrg/*
1510eb10989Smrg * Add an include file to the list of those included by 'file'.
1520eb10989Smrg */
1530eb10989Smrgstruct inclist *
15463165362Smrgnewinclude(const char *newfile, const char *incstring)
1550eb10989Smrg{
1560eb10989Smrg	register struct inclist	*ip;
1570eb10989Smrg
1580eb10989Smrg	/*
1590eb10989Smrg	 * First, put this file on the global list of include files.
1600eb10989Smrg	 */
1610eb10989Smrg	ip = inclistp++;
1620eb10989Smrg	if (inclistp == inclist + MAXFILES - 1)
1630eb10989Smrg		fatalerr("out of space: increase MAXFILES\n");
1640eb10989Smrg	ip->i_file = copy(newfile);
1650eb10989Smrg
1660eb10989Smrg	if (incstring == NULL)
1670eb10989Smrg		ip->i_incstring = ip->i_file;
1680eb10989Smrg	else
1690eb10989Smrg		ip->i_incstring = copy(incstring);
1700eb10989Smrg
1710eb10989Smrg	inclistnext = inclistp;
1720eb10989Smrg	return(ip);
1730eb10989Smrg}
1740eb10989Smrg
1750eb10989Smrgvoid
1760eb10989Smrgincluded_by(struct inclist *ip, struct inclist *newfile)
1770eb10989Smrg{
1780eb10989Smrg	register int i;
1790eb10989Smrg
1800eb10989Smrg	if (ip == NULL)
1810eb10989Smrg		return;
1820eb10989Smrg	/*
1830eb10989Smrg	 * Put this include file (newfile) on the list of files included
1840eb10989Smrg	 * by 'file'.  If 'file' is NULL, then it is not an include
1850eb10989Smrg	 * file itself (i.e. was probably mentioned on the command line).
1860eb10989Smrg	 * If it is already on the list, don't stick it on again.
1870eb10989Smrg	 */
1880eb10989Smrg	if (ip->i_list == NULL) {
1890eb10989Smrg		ip->i_list = (struct inclist **)
1900eb10989Smrg			malloc(sizeof(struct inclist *) * ++ip->i_listlen);
1910eb10989Smrg		ip->i_merged = (boolean *)
1920eb10989Smrg		    malloc(sizeof(boolean) * ip->i_listlen);
1930eb10989Smrg	} else {
1940eb10989Smrg		for (i=0; i<ip->i_listlen; i++)
1950eb10989Smrg			if (ip->i_list[ i ] == newfile) {
1960eb10989Smrg			    i = strlen(newfile->i_file);
1970eb10989Smrg			    if (!(ip->i_flags & INCLUDED_SYM) &&
1980eb10989Smrg				!(i > 2 &&
1990eb10989Smrg				  newfile->i_file[i-1] == 'c' &&
2000eb10989Smrg				  newfile->i_file[i-2] == '.'))
2010eb10989Smrg			    {
2020eb10989Smrg				/* only bitch if ip has */
2030eb10989Smrg				/* no #include SYMBOL lines  */
2040eb10989Smrg				/* and is not a .c file */
2050eb10989Smrg				if (warn_multiple)
2060eb10989Smrg				{
2070eb10989Smrg					warning("%s includes %s more than once!\n",
2080eb10989Smrg						ip->i_file, newfile->i_file);
2090eb10989Smrg					warning1("Already have\n");
2100eb10989Smrg					for (i=0; i<ip->i_listlen; i++)
2110eb10989Smrg						warning1("\t%s\n", ip->i_list[i]->i_file);
2120eb10989Smrg				}
2130eb10989Smrg			    }
2140eb10989Smrg			    return;
2150eb10989Smrg			}
2160eb10989Smrg		ip->i_list = (struct inclist **) realloc(ip->i_list,
2170eb10989Smrg			sizeof(struct inclist *) * ++ip->i_listlen);
2180eb10989Smrg		ip->i_merged = (boolean *)
2190eb10989Smrg		    realloc(ip->i_merged, sizeof(boolean) * ip->i_listlen);
2200eb10989Smrg	}
2210eb10989Smrg	ip->i_list[ ip->i_listlen-1 ] = newfile;
2220eb10989Smrg	ip->i_merged[ ip->i_listlen-1 ] = FALSE;
2230eb10989Smrg}
2240eb10989Smrg
2250eb10989Smrgvoid
2260eb10989Smrginc_clean (void)
2270eb10989Smrg{
2280eb10989Smrg	register struct inclist *ip;
2290eb10989Smrg
2300eb10989Smrg	for (ip = inclist; ip < inclistp; ip++) {
2310eb10989Smrg		ip->i_flags &= ~MARKED;
2320eb10989Smrg	}
2330eb10989Smrg}
2340eb10989Smrg
2350eb10989Smrgstruct inclist *
23663165362Smrginc_path(const char *file, const char *include, int type)
2370eb10989Smrg{
2380eb10989Smrg	static char		path[ BUFSIZ ];
23963165362Smrg	register const char	**pp, *p;
2400eb10989Smrg	register struct inclist	*ip;
2410eb10989Smrg	struct stat		st;
2420eb10989Smrg
2430eb10989Smrg	/*
2440eb10989Smrg	 * Check all previously found include files for a path that
2450eb10989Smrg	 * has already been expanded.
2460eb10989Smrg	 */
2470eb10989Smrg	if ((type == INCLUDE) || (type == INCLUDEDOT))
2480eb10989Smrg		inclistnext = inclist;
2490eb10989Smrg	ip = inclistnext;
2500eb10989Smrg
2510eb10989Smrg	for (; ip->i_file; ip++) {
2520eb10989Smrg		if ((strcmp(ip->i_incstring, include) == 0) &&
2530eb10989Smrg		    !(ip->i_flags & INCLUDED_SYM)) {
2540eb10989Smrg			inclistnext = ip + 1;
2550eb10989Smrg			return ip;
2560eb10989Smrg		}
2570eb10989Smrg	}
2580eb10989Smrg
2590eb10989Smrg	if (inclistnext == inclist) {
2600eb10989Smrg		/*
2610eb10989Smrg		 * If the path was surrounded by "" or is an absolute path,
2620eb10989Smrg		 * then check the exact path provided.
2630eb10989Smrg		 */
2640eb10989Smrg		if ((type == INCLUDEDOT) ||
2650eb10989Smrg		    (type == INCLUDENEXTDOT) ||
2660eb10989Smrg		    (*include == '/')) {
2670eb10989Smrg			if (stat(include, &st) == 0)
2680eb10989Smrg				return newinclude(include, include);
2690eb10989Smrg			if (show_where_not)
2700eb10989Smrg				warning1("\tnot in %s\n", include);
2710eb10989Smrg		}
2720eb10989Smrg
2730eb10989Smrg		/*
2740eb10989Smrg		 * If the path was surrounded by "" see if this include file is
2750eb10989Smrg		 * in the directory of the file being parsed.
2760eb10989Smrg		 */
2770eb10989Smrg		if ((type == INCLUDEDOT) || (type == INCLUDENEXTDOT)) {
2780eb10989Smrg			for (p=file+strlen(file); p>file; p--)
2790eb10989Smrg				if (*p == '/')
2800eb10989Smrg					break;
2810eb10989Smrg			if (p == file) {
2820eb10989Smrg				strcpy(path, include);
2830eb10989Smrg			} else {
2840eb10989Smrg				strncpy(path, file, (p-file) + 1);
2850eb10989Smrg				path[ (p-file) + 1 ] = '\0';
2860eb10989Smrg				strcpy(path + (p-file) + 1, include);
2870eb10989Smrg			}
2880eb10989Smrg			remove_dotdot(path);
2890eb10989Smrg			if (stat(path, &st) == 0)
2900eb10989Smrg				return newinclude(path, include);
2910eb10989Smrg			if (show_where_not)
2920eb10989Smrg				warning1("\tnot in %s\n", path);
2930eb10989Smrg		}
2940eb10989Smrg	}
2950eb10989Smrg
2960eb10989Smrg	/*
2970eb10989Smrg	 * Check the include directories specified.  Standard include dirs
2980eb10989Smrg	 * should be at the end.
2990eb10989Smrg	 */
3000eb10989Smrg	if ((type == INCLUDE) || (type == INCLUDEDOT))
3010eb10989Smrg		includedirsnext = includedirs;
3020eb10989Smrg	pp = includedirsnext;
3030eb10989Smrg
3040eb10989Smrg	for (; *pp; pp++) {
3050eb10989Smrg		sprintf(path, "%s/%s", *pp, include);
3060eb10989Smrg		remove_dotdot(path);
3070eb10989Smrg		if (stat(path, &st) == 0) {
3080eb10989Smrg			includedirsnext = pp + 1;
3090eb10989Smrg			return newinclude(path, include);
3100eb10989Smrg		}
3110eb10989Smrg		if (show_where_not)
3120eb10989Smrg			warning1("\tnot in %s\n", path);
3130eb10989Smrg	}
3140eb10989Smrg
3150eb10989Smrg	return NULL;
3160eb10989Smrg}
317