xref: /aoo41x/main/soltools/mkdepend/include.c (revision cdf0e10c)
1*cdf0e10cSrcweir /* $XConsortium: include.c,v 1.17 94/12/05 19:33:08 gildea Exp $ */
2*cdf0e10cSrcweir /*
3*cdf0e10cSrcweir 
4*cdf0e10cSrcweir Copyright (c) 1993, 1994  X Consortium
5*cdf0e10cSrcweir 
6*cdf0e10cSrcweir Permission is hereby granted, free of charge, to any person obtaining a copy
7*cdf0e10cSrcweir of this software and associated documentation files (the "Software"), to deal
8*cdf0e10cSrcweir in the Software without restriction, including without limitation the rights
9*cdf0e10cSrcweir to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10*cdf0e10cSrcweir copies of the Software, and to permit persons to whom the Software is
11*cdf0e10cSrcweir furnished to do so, subject to the following conditions:
12*cdf0e10cSrcweir 
13*cdf0e10cSrcweir The above copyright notice and this permission notice shall be included in
14*cdf0e10cSrcweir all copies or substantial portions of the Software.
15*cdf0e10cSrcweir 
16*cdf0e10cSrcweir THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*cdf0e10cSrcweir IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*cdf0e10cSrcweir FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19*cdf0e10cSrcweir X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20*cdf0e10cSrcweir AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*cdf0e10cSrcweir CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*cdf0e10cSrcweir 
23*cdf0e10cSrcweir Except as contained in this notice, the name of the X Consortium shall not be
24*cdf0e10cSrcweir used in advertising or otherwise to promote the sale, use or other dealings
25*cdf0e10cSrcweir in this Software without prior written authorization from the X Consortium.
26*cdf0e10cSrcweir 
27*cdf0e10cSrcweir */
28*cdf0e10cSrcweir 
29*cdf0e10cSrcweir 
30*cdf0e10cSrcweir #include "def.h"
31*cdf0e10cSrcweir #include <string.h>
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir void remove_dotdot( char * );
34*cdf0e10cSrcweir int isdot( char * );
35*cdf0e10cSrcweir int isdotdot( char * );
36*cdf0e10cSrcweir int issymbolic(char * dir, char * component);
37*cdf0e10cSrcweir int exists_path(struct IncludesCollection*, char*);
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir 
40*cdf0e10cSrcweir extern struct	inclist	inclist[ MAXFILES ],
41*cdf0e10cSrcweir 			*inclistp;
42*cdf0e10cSrcweir extern char	*includedirs[ ];
43*cdf0e10cSrcweir extern char	*notdotdot[ ];
44*cdf0e10cSrcweir extern boolean show_where_not;
45*cdf0e10cSrcweir extern boolean warn_multiple;
46*cdf0e10cSrcweir 
inc_path(file,include,dot,incCollection)47*cdf0e10cSrcweir struct inclist *inc_path(file, include, dot, incCollection)
48*cdf0e10cSrcweir 	register char	*file,
49*cdf0e10cSrcweir 			*include;
50*cdf0e10cSrcweir 	boolean	dot;
51*cdf0e10cSrcweir     struct IncludesCollection* incCollection;
52*cdf0e10cSrcweir {
53*cdf0e10cSrcweir 	static char	path[ BUFSIZ ];
54*cdf0e10cSrcweir 	register char		**pp, *p;
55*cdf0e10cSrcweir 	register struct inclist	*ip;
56*cdf0e10cSrcweir 	struct stat	st;
57*cdf0e10cSrcweir 	boolean	found = FALSE;
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir 	/*
60*cdf0e10cSrcweir 	 * Check all previously found include files for a path that
61*cdf0e10cSrcweir 	 * has already been expanded.
62*cdf0e10cSrcweir 	 */
63*cdf0e10cSrcweir 	for (ip = inclist; ip->i_file; ip++)
64*cdf0e10cSrcweir 	    if ((strcmp(ip->i_incstring, include) == 0) && !ip->i_included_sym)
65*cdf0e10cSrcweir 	    {
66*cdf0e10cSrcweir 		found = TRUE;
67*cdf0e10cSrcweir 		break;
68*cdf0e10cSrcweir 	    }
69*cdf0e10cSrcweir 
70*cdf0e10cSrcweir 	/*
71*cdf0e10cSrcweir 	 * If the path was surrounded by "" or is an absolute path,
72*cdf0e10cSrcweir 	 * then check the exact path provided.
73*cdf0e10cSrcweir 	 */
74*cdf0e10cSrcweir // FIXME: creates duplicates in the dependency files if absolute paths are
75*cdf0e10cSrcweir // given, which certainly is not the intended behavior. Also it slows down
76*cdf0e10cSrcweir // makedepend performance considerably.
77*cdf0e10cSrcweir //	if (!found && (dot || *include == '/')) {
78*cdf0e10cSrcweir //
79*cdf0e10cSrcweir //		if ((exists_path(incCollection, include)) && stat(include, &st) == 0 && !( st.st_mode & S_IFDIR)) {
80*cdf0e10cSrcweir //			ip = newinclude(include, include);
81*cdf0e10cSrcweir //			found = TRUE;
82*cdf0e10cSrcweir //		}
83*cdf0e10cSrcweir //		else if (show_where_not)
84*cdf0e10cSrcweir //			warning1("\tnot in %s\n", include);
85*cdf0e10cSrcweir //	}
86*cdf0e10cSrcweir 
87*cdf0e10cSrcweir 	/*
88*cdf0e10cSrcweir 	 * See if this include file is in the directory of the
89*cdf0e10cSrcweir 	 * file being compiled.
90*cdf0e10cSrcweir 	 */
91*cdf0e10cSrcweir 	if (!found) {
92*cdf0e10cSrcweir 		for (p=file+strlen(file); p>file; p--)
93*cdf0e10cSrcweir 			if (*p == '/')
94*cdf0e10cSrcweir 				break;
95*cdf0e10cSrcweir 		if (p == file)
96*cdf0e10cSrcweir 			strcpy(path, include);
97*cdf0e10cSrcweir 		else {
98*cdf0e10cSrcweir 			strncpy(path, file, (p-file) + 1);
99*cdf0e10cSrcweir 			path[ (p-file) + 1 ] = '\0';
100*cdf0e10cSrcweir 			strcpy(path + (p-file) + 1, include);
101*cdf0e10cSrcweir 		}
102*cdf0e10cSrcweir 		remove_dotdot(path);
103*cdf0e10cSrcweir 		if ((exists_path(incCollection, path)) && stat(path, &st) == 0 && !( st.st_mode & S_IFDIR)) {
104*cdf0e10cSrcweir 			ip = newinclude(path, include);
105*cdf0e10cSrcweir 			found = TRUE;
106*cdf0e10cSrcweir 		}
107*cdf0e10cSrcweir 		else if (show_where_not)
108*cdf0e10cSrcweir 			warning1("\tnot in %s\n", path);
109*cdf0e10cSrcweir 	}
110*cdf0e10cSrcweir 
111*cdf0e10cSrcweir 	/*
112*cdf0e10cSrcweir 	 * Check the include directories specified. (standard include dir
113*cdf0e10cSrcweir 	 * should be at the end.)
114*cdf0e10cSrcweir 	 */
115*cdf0e10cSrcweir 	if (!found)
116*cdf0e10cSrcweir 		for (pp = includedirs; *pp; pp++) {
117*cdf0e10cSrcweir 			sprintf(path, "%s/%s", *pp, include);
118*cdf0e10cSrcweir 			remove_dotdot(path);
119*cdf0e10cSrcweir 			if ((exists_path(incCollection, path)) && stat(path, &st) == 0 && !(st.st_mode & S_IFDIR)) {
120*cdf0e10cSrcweir 				ip = newinclude(path, include);
121*cdf0e10cSrcweir 				found = TRUE;
122*cdf0e10cSrcweir 				break;
123*cdf0e10cSrcweir 			}
124*cdf0e10cSrcweir 			else if (show_where_not)
125*cdf0e10cSrcweir 				warning1("\tnot in %s\n", path);
126*cdf0e10cSrcweir 		}
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir 	if (!found)
129*cdf0e10cSrcweir 		ip = NULL;
130*cdf0e10cSrcweir 	return(ip);
131*cdf0e10cSrcweir }
132*cdf0e10cSrcweir 
exists_path(incCollection,path)133*cdf0e10cSrcweir int exists_path(incCollection, path)
134*cdf0e10cSrcweir     struct IncludesCollection* incCollection;
135*cdf0e10cSrcweir     char* path;
136*cdf0e10cSrcweir {
137*cdf0e10cSrcweir     convert_slashes(path);
138*cdf0e10cSrcweir     return call_IncludesCollection_exists(incCollection, path);
139*cdf0e10cSrcweir }
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir /*
142*cdf0e10cSrcweir  * Occasionally, pathnames are created that look like .../x/../y
143*cdf0e10cSrcweir  * Any of the 'x/..' sequences within the name can be eliminated.
144*cdf0e10cSrcweir  * (but only if 'x' is not a symbolic link!!)
145*cdf0e10cSrcweir  */
remove_dotdot(path)146*cdf0e10cSrcweir void remove_dotdot(path)
147*cdf0e10cSrcweir 	char	*path;
148*cdf0e10cSrcweir {
149*cdf0e10cSrcweir 	register char	*end, *from, *to, **cp;
150*cdf0e10cSrcweir 	char		*components[ MAXFILES ],
151*cdf0e10cSrcweir 			newpath[ BUFSIZ ];
152*cdf0e10cSrcweir 	boolean		component_copied;
153*cdf0e10cSrcweir 
154*cdf0e10cSrcweir 	/*
155*cdf0e10cSrcweir 	 * slice path up into components.
156*cdf0e10cSrcweir 	 */
157*cdf0e10cSrcweir 	to = newpath;
158*cdf0e10cSrcweir 	if (*path == '/')
159*cdf0e10cSrcweir 		*to++ = '/';
160*cdf0e10cSrcweir 	*to = '\0';
161*cdf0e10cSrcweir 	cp = components;
162*cdf0e10cSrcweir 	for (from=end=path; *end; end++)
163*cdf0e10cSrcweir 		if (*end == '/') {
164*cdf0e10cSrcweir 			while (*end == '/')
165*cdf0e10cSrcweir 				*end++ = '\0';
166*cdf0e10cSrcweir 			if (*from)
167*cdf0e10cSrcweir 				*cp++ = from;
168*cdf0e10cSrcweir 			from = end;
169*cdf0e10cSrcweir 		}
170*cdf0e10cSrcweir 	*cp++ = from;
171*cdf0e10cSrcweir 	*cp = NULL;
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir 	/*
174*cdf0e10cSrcweir 	 * Recursively remove all 'x/..' component pairs.
175*cdf0e10cSrcweir 	 */
176*cdf0e10cSrcweir 	cp = components;
177*cdf0e10cSrcweir 	while(*cp) {
178*cdf0e10cSrcweir 		if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))
179*cdf0e10cSrcweir 		    && !issymbolic(newpath, *cp))
180*cdf0e10cSrcweir 		{
181*cdf0e10cSrcweir 		    char **fp = cp + 2;
182*cdf0e10cSrcweir 		    char **tp = cp;
183*cdf0e10cSrcweir 
184*cdf0e10cSrcweir 		    do
185*cdf0e10cSrcweir 			*tp++ = *fp; /* move all the pointers down */
186*cdf0e10cSrcweir 		    while (*fp++);
187*cdf0e10cSrcweir 		    if (cp != components)
188*cdf0e10cSrcweir 			cp--;	/* go back and check for nested ".." */
189*cdf0e10cSrcweir 		} else {
190*cdf0e10cSrcweir 		    cp++;
191*cdf0e10cSrcweir 		}
192*cdf0e10cSrcweir 	}
193*cdf0e10cSrcweir 	/*
194*cdf0e10cSrcweir 	 * Concatenate the remaining path elements.
195*cdf0e10cSrcweir 	 */
196*cdf0e10cSrcweir 	cp = components;
197*cdf0e10cSrcweir 	component_copied = FALSE;
198*cdf0e10cSrcweir 	while(*cp) {
199*cdf0e10cSrcweir 		if (component_copied)
200*cdf0e10cSrcweir 			*to++ = '/';
201*cdf0e10cSrcweir 		component_copied = TRUE;
202*cdf0e10cSrcweir 		for (from = *cp; *from; )
203*cdf0e10cSrcweir 			*to++ = *from++;
204*cdf0e10cSrcweir 		*to = '\0';
205*cdf0e10cSrcweir 		cp++;
206*cdf0e10cSrcweir 	}
207*cdf0e10cSrcweir 	*to++ = '\0';
208*cdf0e10cSrcweir 
209*cdf0e10cSrcweir 	/*
210*cdf0e10cSrcweir 	 * copy the reconstituted path back to our pointer.
211*cdf0e10cSrcweir 	 */
212*cdf0e10cSrcweir 	strcpy(path, newpath);
213*cdf0e10cSrcweir }
214*cdf0e10cSrcweir 
isdot(p)215*cdf0e10cSrcweir int isdot(p)
216*cdf0e10cSrcweir 	register char	*p;
217*cdf0e10cSrcweir {
218*cdf0e10cSrcweir 	if(p && *p++ == '.' && *p++ == '\0')
219*cdf0e10cSrcweir 		return(TRUE);
220*cdf0e10cSrcweir 	return(FALSE);
221*cdf0e10cSrcweir }
222*cdf0e10cSrcweir 
isdotdot(p)223*cdf0e10cSrcweir int isdotdot(p)
224*cdf0e10cSrcweir 	register char	*p;
225*cdf0e10cSrcweir {
226*cdf0e10cSrcweir 	if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
227*cdf0e10cSrcweir 		return(TRUE);
228*cdf0e10cSrcweir 	return(FALSE);
229*cdf0e10cSrcweir }
230*cdf0e10cSrcweir 
issymbolic(dir,component)231*cdf0e10cSrcweir int issymbolic(dir, component)
232*cdf0e10cSrcweir 	register char	*dir, *component;
233*cdf0e10cSrcweir {
234*cdf0e10cSrcweir #ifdef S_IFLNK
235*cdf0e10cSrcweir 	struct stat	st;
236*cdf0e10cSrcweir 	char	buf[ BUFSIZ ], **pp;
237*cdf0e10cSrcweir 
238*cdf0e10cSrcweir 	sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component);
239*cdf0e10cSrcweir 	for (pp=notdotdot; *pp; pp++)
240*cdf0e10cSrcweir 		if (strcmp(*pp, buf) == 0)
241*cdf0e10cSrcweir 			return (TRUE);
242*cdf0e10cSrcweir 	if (lstat(buf, &st) == 0
243*cdf0e10cSrcweir 	&& (st.st_mode & S_IFMT) == S_IFLNK) {
244*cdf0e10cSrcweir 		*pp++ = copy(buf);
245*cdf0e10cSrcweir 		if (pp >= &notdotdot[ MAXDIRS ])
246*cdf0e10cSrcweir 			fatalerr("out of .. dirs, increase MAXDIRS\n");
247*cdf0e10cSrcweir 		return(TRUE);
248*cdf0e10cSrcweir 	}
249*cdf0e10cSrcweir #endif
250*cdf0e10cSrcweir 	return(FALSE);
251*cdf0e10cSrcweir }
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir /*
254*cdf0e10cSrcweir  * Add an include file to the list of those included by 'file'.
255*cdf0e10cSrcweir  */
newinclude(newfile,incstring)256*cdf0e10cSrcweir struct inclist *newinclude(newfile, incstring)
257*cdf0e10cSrcweir 	register char	*newfile, *incstring;
258*cdf0e10cSrcweir {
259*cdf0e10cSrcweir 	register struct inclist	*ip;
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir 	/*
262*cdf0e10cSrcweir 	 * First, put this file on the global list of include files.
263*cdf0e10cSrcweir 	 */
264*cdf0e10cSrcweir 	ip = inclistp++;
265*cdf0e10cSrcweir 	if (inclistp == inclist + MAXFILES - 1)
266*cdf0e10cSrcweir 		fatalerr("out of space: increase MAXFILES\n");
267*cdf0e10cSrcweir 	ip->i_file = copy(newfile);
268*cdf0e10cSrcweir 	ip->i_included_sym = FALSE;
269*cdf0e10cSrcweir 	if (incstring == NULL)
270*cdf0e10cSrcweir 		ip->i_incstring = ip->i_file;
271*cdf0e10cSrcweir 	else
272*cdf0e10cSrcweir 		ip->i_incstring = copy(incstring);
273*cdf0e10cSrcweir 
274*cdf0e10cSrcweir 	return(ip);
275*cdf0e10cSrcweir }
276*cdf0e10cSrcweir 
included_by(ip,newfile)277*cdf0e10cSrcweir void included_by(ip, newfile)
278*cdf0e10cSrcweir 	register struct inclist	*ip, *newfile;
279*cdf0e10cSrcweir {
280*cdf0e10cSrcweir 	register int i;
281*cdf0e10cSrcweir 
282*cdf0e10cSrcweir 	if (ip == NULL)
283*cdf0e10cSrcweir 		return;
284*cdf0e10cSrcweir 	/*
285*cdf0e10cSrcweir 	 * Put this include file (newfile) on the list of files included
286*cdf0e10cSrcweir 	 * by 'file'.  If 'file' is NULL, then it is not an include
287*cdf0e10cSrcweir 	 * file itself (i.e. was probably mentioned on the command line).
288*cdf0e10cSrcweir 	 * If it is already on the list, don't stick it on again.
289*cdf0e10cSrcweir 	 */
290*cdf0e10cSrcweir 	if (ip->i_list == NULL)
291*cdf0e10cSrcweir 		ip->i_list = (struct inclist **)
292*cdf0e10cSrcweir 			malloc(sizeof(struct inclist *) * ++ip->i_listlen);
293*cdf0e10cSrcweir 	else {
294*cdf0e10cSrcweir 		for (i=0; i<ip->i_listlen; i++)
295*cdf0e10cSrcweir 			if (ip->i_list[ i ] == newfile) {
296*cdf0e10cSrcweir 			    i = strlen(newfile->i_file);
297*cdf0e10cSrcweir 			    if (!ip->i_included_sym &&
298*cdf0e10cSrcweir 				!(i > 2 &&
299*cdf0e10cSrcweir 				  newfile->i_file[i-1] == 'c' &&
300*cdf0e10cSrcweir 				  newfile->i_file[i-2] == '.'))
301*cdf0e10cSrcweir 			    {
302*cdf0e10cSrcweir 				/* only complain if ip has */
303*cdf0e10cSrcweir 				/* no #include SYMBOL lines  */
304*cdf0e10cSrcweir 				/* and is not a .c file */
305*cdf0e10cSrcweir 				if (warn_multiple)
306*cdf0e10cSrcweir 				{
307*cdf0e10cSrcweir 					warning("%s includes %s more than once!\n",
308*cdf0e10cSrcweir 						ip->i_file, newfile->i_file);
309*cdf0e10cSrcweir 					warning1("Already have\n");
310*cdf0e10cSrcweir 					for (i=0; i<ip->i_listlen; i++)
311*cdf0e10cSrcweir 						warning1("\t%s\n", ip->i_list[i]->i_file);
312*cdf0e10cSrcweir 				}
313*cdf0e10cSrcweir 			    }
314*cdf0e10cSrcweir 			    return;
315*cdf0e10cSrcweir 			}
316*cdf0e10cSrcweir 		ip->i_list = (struct inclist **) realloc(ip->i_list,
317*cdf0e10cSrcweir 			sizeof(struct inclist *) * ++ip->i_listlen);
318*cdf0e10cSrcweir 	}
319*cdf0e10cSrcweir 	ip->i_list[ ip->i_listlen-1 ] = newfile;
320*cdf0e10cSrcweir }
321*cdf0e10cSrcweir 
inc_clean()322*cdf0e10cSrcweir void inc_clean ()
323*cdf0e10cSrcweir {
324*cdf0e10cSrcweir 	register struct inclist *ip;
325*cdf0e10cSrcweir 
326*cdf0e10cSrcweir 	for (ip = inclist; ip < inclistp; ip++) {
327*cdf0e10cSrcweir 		ip->i_marked = FALSE;
328*cdf0e10cSrcweir 	}
329*cdf0e10cSrcweir }
330