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