source: trunk/src/makedep/include.c@ 164

Last change on this file since 164 was 164, checked in by bird, 21 years ago

Initial revision

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