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 >= ¬dotdot[ 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