]>
Commit | Line | Data |
---|---|---|
d1b2a10e | 1 | /* |
2 | * $XConsortium: include.c,v 1.6 88/09/22 13:52:38 jim Exp $ | |
3 | */ | |
4 | #include "def.h" | |
5 | ||
6 | extern struct inclist inclist[ MAXFILES ], | |
7 | *inclistp; | |
8 | extern char *includedirs[ ]; | |
9 | extern char *notdotdot[ ]; | |
10 | extern boolean show_where_not; | |
11 | ||
12 | struct inclist *inc_path(file, include, dot) | |
13 | register char *file, | |
14 | *include; | |
15 | boolean dot; | |
16 | { | |
17 | static char path[ BUFSIZ ]; | |
18 | register char **pp, *p; | |
19 | register struct inclist *ip; | |
20 | struct stat st; | |
21 | boolean found = FALSE; | |
22 | ||
23 | /* | |
24 | * Check all previously found include files for a path that | |
25 | * has already been expanded. | |
26 | */ | |
27 | for (ip = inclist; ip->i_file; ip++) | |
28 | if ((strcmp(ip->i_incstring, include) == 0) && !ip->i_included_sym) | |
29 | { | |
30 | found = TRUE; | |
31 | break; | |
32 | } | |
33 | ||
34 | /* | |
35 | * If the path was surrounded by "", then check the absolute | |
36 | * path provided. | |
37 | */ | |
38 | if (!found && dot) { | |
39 | if (stat(include, &st) == 0) { | |
40 | ip = newinclude(include, include); | |
41 | found = TRUE; | |
42 | } | |
43 | else if (show_where_not) | |
44 | log("\tnot in %s\n", include); | |
45 | } | |
46 | ||
47 | /* | |
48 | * See if this include file is in the directory of the | |
49 | * file being compiled. | |
50 | */ | |
51 | if (!found) { | |
52 | for (p=file+strlen(file); p>file; p--) | |
53 | if (*p == '/') | |
54 | break; | |
55 | if (p == file) | |
56 | strcpy(path, include); | |
57 | else { | |
58 | strncpy(path, file, (p-file) + 1); | |
59 | path[ (p-file) + 1 ] = '\0'; | |
60 | strcpy(path + (p-file) + 1, include); | |
61 | } | |
62 | remove_dotdot(path); | |
63 | if (stat(path, &st) == 0) { | |
64 | ip = newinclude(path, include); | |
65 | found = TRUE; | |
66 | } | |
67 | else if (show_where_not) | |
68 | log("\tnot in %s\n", path); | |
69 | } | |
70 | ||
71 | /* | |
72 | * Check the include directories specified. (standard include dir | |
73 | * should be at the end.) | |
74 | */ | |
75 | if (!found) | |
76 | for (pp = includedirs; *pp; pp++) { | |
77 | sprintf(path, "%s/%s", *pp, include); | |
78 | remove_dotdot(path); | |
79 | if (stat(path, &st) == 0) { | |
80 | ip = newinclude(path, include); | |
81 | found = TRUE; | |
82 | break; | |
83 | } | |
84 | else if (show_where_not) | |
85 | log("\tnot in %s\n", path); | |
86 | } | |
87 | ||
88 | if (!found) { | |
89 | /* | |
90 | * If we've announced where it's not include it anyway so | |
91 | * it gets on the dependency list. | |
92 | */ | |
93 | if (show_where_not) | |
94 | ip = newinclude(include, include); | |
95 | else | |
96 | ip = NULL; | |
97 | } | |
98 | return(ip); | |
99 | } | |
100 | ||
101 | /* | |
102 | * Ocaisionally, pathnames are created that look like ../x/../y | |
103 | * Any of the 'x/..' sequences within the name can be eliminated. | |
104 | * (but only if 'x' is not a symbolic link!!) | |
105 | */ | |
106 | remove_dotdot(path) | |
107 | char *path; | |
108 | { | |
109 | register char *end, *from, *to, **cp; | |
110 | char *components[ MAXFILES ], | |
111 | newpath[ BUFSIZ ]; | |
112 | boolean component_copied; | |
113 | ||
114 | /* | |
115 | * slice path up into components. | |
116 | */ | |
117 | to = newpath; | |
118 | if (*path == '/') | |
119 | *to++ = '/'; | |
120 | *to = '\0'; | |
121 | cp = components; | |
122 | for (from=end=path; *end; end++) | |
123 | if (*end == '/') { | |
124 | while (*end == '/') | |
125 | *end++ = '\0'; | |
126 | if (*from) | |
127 | *cp++ = from; | |
128 | from = end; | |
129 | } | |
130 | *cp++ = from; | |
131 | *cp = NULL; | |
132 | ||
133 | /* | |
134 | * Now copy the path, removing all 'x/..' components. | |
135 | */ | |
136 | cp = components; | |
137 | component_copied = FALSE; | |
138 | while(*cp) { | |
139 | if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))) { | |
140 | if (issymbolic(newpath, *cp)) | |
141 | goto dont_remove; | |
142 | cp++; | |
143 | } else { | |
144 | dont_remove: | |
145 | if (component_copied) | |
146 | *to++ = '/'; | |
147 | component_copied = TRUE; | |
148 | for (from = *cp; *from; ) | |
149 | *to++ = *from++; | |
150 | *to = '\0'; | |
151 | } | |
152 | cp++; | |
153 | } | |
154 | *to++ = '\0'; | |
155 | ||
156 | /* | |
157 | * copy the reconstituted path back to our pointer. | |
158 | */ | |
159 | strcpy(path, newpath); | |
160 | } | |
161 | ||
162 | isdot(p) | |
163 | register char *p; | |
164 | { | |
165 | if(p && *p++ == '.' && *p++ == '\0') | |
166 | return(TRUE); | |
167 | return(FALSE); | |
168 | } | |
169 | ||
170 | isdotdot(p) | |
171 | register char *p; | |
172 | { | |
173 | if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0') | |
174 | return(TRUE); | |
175 | return(FALSE); | |
176 | } | |
177 | ||
178 | issymbolic(dir, component) | |
179 | register char *dir, *component; | |
180 | { | |
181 | struct stat st; | |
182 | char buf[ BUFSIZ ], **pp; | |
183 | ||
184 | sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component); | |
185 | for (pp=notdotdot; *pp; pp++) | |
186 | if (strcmp(*pp, buf) == 0) | |
187 | return (TRUE); | |
188 | if (lstat(buf, &st) == 0 | |
189 | && (st.st_mode & S_IFMT) == S_IFLNK) { | |
190 | *pp++ = copy(buf); | |
191 | if (pp >= ¬dotdot[ MAXDIRS ]) | |
192 | log_fatal("out of .. dirs, increase MAXDIRS\n"); | |
193 | return(TRUE); | |
194 | } | |
195 | return(FALSE); | |
196 | } | |
197 | ||
198 | /* | |
199 | * Add an include file to the list of those included by 'file'. | |
200 | */ | |
201 | struct inclist *newinclude(newfile, incstring) | |
202 | register char *newfile, *incstring; | |
203 | { | |
204 | register struct inclist *ip; | |
205 | ||
206 | /* | |
207 | * First, put this file on the global list of include files. | |
208 | */ | |
209 | ip = inclistp++; | |
210 | if (inclistp == inclist + MAXFILES - 1) | |
211 | log_fatal("out of space: increase MAXFILES\n"); | |
212 | ip->i_file = copy(newfile); | |
213 | ip->i_included_sym = FALSE; | |
214 | if (incstring == NULL) | |
215 | ip->i_incstring = ip->i_file; | |
216 | else | |
217 | ip->i_incstring = copy(incstring); | |
218 | ||
219 | return(ip); | |
220 | } | |
221 | ||
222 | included_by(ip, newfile) | |
223 | register struct inclist *ip, *newfile; | |
224 | { | |
225 | register i; | |
226 | ||
227 | if (ip == NULL) | |
228 | return; | |
229 | /* | |
230 | * Put this include file (newfile) on the list of files included | |
231 | * by 'file'. If 'file' is NULL, then it is not an include | |
232 | * file itself (i.e. was probably mentioned on the command line). | |
233 | * If it is already on the list, don't stick it on again. | |
234 | */ | |
235 | if (ip->i_list == NULL) | |
236 | ip->i_list = (struct inclist **) | |
237 | malloc(sizeof(struct inclist *) * ++ip->i_listlen); | |
238 | else { | |
239 | for (i=0; i<ip->i_listlen; i++) | |
240 | if (ip->i_list[ i ] == newfile) { | |
241 | if (!ip->i_included_sym) | |
242 | { | |
243 | /* only bitch if ip has */ | |
244 | /* no #include SYMBOL lines */ | |
245 | log("%s includes %s more than once!\n", | |
246 | ip->i_file, newfile->i_file); | |
247 | log("Already have\n"); | |
248 | for (i=0; i<ip->i_listlen; i++) | |
249 | log("\t%s\n", ip->i_list[i]->i_file); | |
250 | } | |
251 | return; | |
252 | } | |
253 | ip->i_list = (struct inclist **) realloc(ip->i_list, | |
254 | sizeof(struct inclist *) * ++ip->i_listlen); | |
255 | } | |
256 | ip->i_list[ ip->i_listlen-1 ] = newfile; | |
257 | } | |
258 | ||
259 | inc_clean () | |
260 | { | |
261 | register struct inclist *ip; | |
262 | ||
263 | for (ip = inclist; ip < inclistp; ip++) { | |
264 | ip->i_marked = FALSE; | |
265 | } | |
266 | } |