1 /* $XConsortium: include.c,v 1.17 94/12/05 19:33:08 gildea Exp $ */
4 Copyright (c) 1993, 1994 X Consortium
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:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
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.
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.
30 #pragma warning(disable : 4996)
40 #define strcasecmp strcmpi
41 #define strncasecmp strnicmp
44 extern inclist inc_list[MAXFILES], *inclistp;
45 extern char *includedirs[ ];
46 extern char *excludedirs[ ];
47 extern char *notdotdot[ ];
48 extern bool show_where_not;
49 extern bool warn_multiple;
52 void remove_dotdot(char *path);
53 int isdot(register char *p);
54 int isdotdot(register char *p);
55 int issymbolic(register char *dir, register char *component);
56 void included_by(register inclist *ip, register inclist *newfile);
58 inclist *inc_path(register char *file, register char *include, bool dot,
61 static char path[ BUFSIZ ];
62 register char **pp, *p;
67 //fprintf(stderr, "file=%s include=%s\n", file, include);
68 const size_t inclen = strlen(include);
70 register char *cpp_point = include + inclen - 4;
71 if (!strcasecmp(".cpp", cpp_point)) {
72 // this is a CPP file include, which we skip.
73 //fprintf(stderr, "!found match at point: %s\n", cpp_point);
74 //hold failure_okay = true;
79 ////////fprintf(stderr, "incpath entry\n");
82 * Check all previously found include files for a path that
83 * has already been expanded.
85 for (ip = inc_list; ip->i_file; ip++)
86 if ((strcmp(ip->i_incstring, include) == 0) && !ip->i_included_sym) {
92 * If the path was surrounded by "" or is an absolute path,
93 * then check the exact path provided.
95 if (!found && (dot || *include == '/' || *include == '\\')) {
96 if (stat(include, &st) == 0) {
97 ip = newinclude(include, include);
100 else if (show_where_not)
101 warning1("\tnot in %s\n", include);
105 * See if this include file is in the directory of the
106 * file being compiled.
109 for (p=file+strlen(file); p>file; p--)
110 if (*p == '/' || *p == '\\')
113 strcpy(path, include);
115 strncpy(path, file, (p-file) + 1);
116 path[ (p-file) + 1 ] = '\0';
117 strcpy(path + (p-file) + 1, include);
120 if (stat(path, &st) == 0) {
121 ip = newinclude(path, include);
124 else if (show_where_not)
125 warning1("\tnot in %s\n", path);
129 * Check the include directories specified. (standard include dir
130 * should be at the end.)
133 for (pp = includedirs; *pp; pp++) {
134 sprintf(path, "%s/%s", *pp, include);
136 if (stat(path, &st) == 0) {
138 bool exclude_it = false;
139 for (pp2 = excludedirs; *pp2; pp2++) {
140 ////////fprintf(stderr, "comparing %s with %s\n", *pp, *pp2);
141 if (!strncmp(*pp, *pp2, strlen(*pp2))) {
142 // this file is supposed to be excluded.
147 ////////if (exclude_it) fprintf(stderr, "excluding path %s\n", path);
152 ip = newinclude(path, include);
157 else if (show_where_not)
158 warning1("\tnot in %s\n", path);
167 * Occasionally, pathnames are created that look like .../x/../y
168 * Any of the 'x/..' sequences within the name can be eliminated.
169 * (but only if 'x' is not a symbolic link!!)
171 void remove_dotdot(char *path)
173 register char *end, *from, *to, **cp;
174 char *components[ MAXFILES ], newpath[ BUFSIZ ];
175 bool component_copied;
178 * slice path up into components.
181 if (*path == '/' || *path == '\\')
185 for (from=end=path; *end; end++)
186 if (*end == '/' || *end == '\\') {
187 while (*end == '/' || *end == '\\')
197 * Recursively remove all 'x/..' component pairs.
201 if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))
202 && !issymbolic(newpath, *cp))
208 *tp++ = *fp; /* move all the pointers down */
210 if (cp != components)
211 cp--; /* go back and check for nested ".." */
217 * Concatenate the remaining path elements.
220 component_copied = false;
222 if (component_copied)
224 component_copied = true;
225 for (from = *cp; *from; )
233 * copy the reconstituted path back to our pointer.
235 strcpy(path, newpath);
238 int isdot(register char *p)
240 if(p && *p++ == '.' && *p++ == '\0')
245 int isdotdot(register char *p)
247 if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
252 int issymbolic(register char *dir, register char *component)
256 char buf[ BUFSIZ ], **pp;
258 sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component);
259 for (pp=notdotdot; *pp; pp++)
260 if (strcmp(*pp, buf) == 0)
262 if (lstat(buf, &st) == 0
263 && (st.st_mode & S_IFMT) == S_IFLNK) {
265 if (pp >= ¬dotdot[ MAXDIRS ])
266 fatalerr("out of .. dirs, increase MAXDIRS\n");
274 * Add an include file to the list of those included by 'file'.
276 inclist *newinclude(register char *newfile, register char *incstring)
278 register inclist *ip;
281 * First, put this file on the global list of include files.
284 if (inclistp == inc_list + MAXFILES - 1)
285 fatalerr("out of space: increase MAXFILES\n");
286 ip->i_file = copy(newfile);
287 ip->i_included_sym = false;
288 if (incstring == NULL)
289 ip->i_incstring = ip->i_file;
291 ip->i_incstring = copy(incstring);
296 void included_by(register inclist *ip, register inclist *newfile)
303 * Put this include file (newfile) on the list of files included
304 * by 'file'. If 'file' is NULL, then it is not an include
305 * file itself (i.e. was probably mentioned on the command line).
306 * If it is already on the list, don't stick it on again.
308 if (ip->i_list == NULL)
309 ip->i_list = (inclist **)
310 malloc(sizeof(inclist *) * ++ip->i_listlen);
312 for (i=0; i<ip->i_listlen; i++)
313 if (ip->i_list[ i ] == newfile) {
314 i = int(strlen(newfile->i_file));
315 if (!ip->i_included_sym &&
317 newfile->i_file[i-1] == 'c' &&
318 newfile->i_file[i-2] == '.'))
320 /* only complain if ip has */
321 /* no #include SYMBOL lines */
322 /* and is not a .c file */
325 warning("%s includes %s more than once!\n",
326 ip->i_file, newfile->i_file);
327 warning1("Already have\n");
328 for (i=0; i<ip->i_listlen; i++)
329 warning1("\t%s\n", ip->i_list[i]->i_file);
334 ip->i_list = (inclist **) realloc(ip->i_list,
335 sizeof(inclist *) * ++ip->i_listlen);
337 ip->i_list[ ip->i_listlen-1 ] = newfile;
342 register inclist *ip;
344 for (ip = inc_list; ip < inclistp; ip++) {
345 ip->i_marked = false;