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