2003-03-15 Glen Nakamura <glen@imodulo.com>
[official-gcc.git] / gcc / c-incpath.c
blob06c9346edede9d62a7227d24ac422cd1c5622f94
1 /* Set up combined include path chain for the preprocessor.
2 Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
5 Broken out of cppinit.c and cppfiles.c and rewritten Mar 2003.
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "cpplib.h"
26 #include "prefix.h"
27 #include "intl.h"
28 #include "c-incpath.h"
29 #include "cppdefault.h"
31 /* Windows does not natively support inodes, and neither does MSDOS.
32 Cygwin's emulation can generate non-unique inodes, so don't use it.
33 VMS has non-numeric inodes. */
34 #ifdef VMS
35 # define INO_T_EQ(A, B) (!memcmp (&(A), &(B), sizeof (A)))
36 # define INO_T_COPY(DEST, SRC) memcpy(&(DEST), &(SRC), sizeof (SRC))
37 #else
38 # if (defined _WIN32 && ! defined (_UWIN)) || defined __MSDOS__
39 # define INO_T_EQ(A, B) 0
40 # else
41 # define INO_T_EQ(A, B) ((A) == (B))
42 # endif
43 # define INO_T_COPY(DEST, SRC) (DEST) = (SRC)
44 #endif
46 static void add_env_var_paths PARAMS ((const char *, int));
47 static void add_standard_paths PARAMS ((const char *, const char *, int));
48 static void free_path PARAMS ((struct cpp_path *, int));
49 static void merge_include_chains PARAMS ((cpp_reader *, int));
50 static struct cpp_path *
51 remove_duplicates PARAMS ((cpp_reader *, struct cpp_path *,
52 struct cpp_path *, struct cpp_path *, int));
54 /* Include chains heads and tails. */
55 static struct cpp_path *heads[4];
56 static struct cpp_path *tails[4];
57 static bool quote_ignores_source_dir;
58 enum { REASON_QUIET = 0, REASON_NOENT, REASON_DUP, REASON_DUP_SYS };
60 /* Free an element of the include chain, possibly giving a reason. */
61 static void
62 free_path (path, reason)
63 struct cpp_path *path;
64 int reason;
66 switch (reason)
68 case REASON_DUP:
69 case REASON_DUP_SYS:
70 fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"), path->name);
71 if (reason == REASON_DUP_SYS)
72 fprintf (stderr,
73 _(" as it is a non-system directory that duplicates a system directory\n"));
74 break;
76 case REASON_NOENT:
77 fprintf (stderr, _("ignoring nonexistent directory \"%s\"\n"),
78 path->name);
79 break;
81 case REASON_QUIET:
82 default:
83 break;
86 free ((PTR) path->name);
87 free (path);
90 /* Read ENV_VAR for a PATH_SEPARATOR-separated list of file names; and
91 append all the names to the search path CHAIN. */
92 static void
93 add_env_var_paths (env_var, chain)
94 const char *env_var;
95 int chain;
97 char *p, *q, *path;
99 GET_ENVIRONMENT (q, env_var);
101 if (!q)
102 return;
104 for (p = q; *q; p = q + 1)
106 q = p;
107 while (*q != 0 && *q != PATH_SEPARATOR)
108 q++;
110 if (p == q)
111 path = xstrdup (".");
112 else
114 path = xmalloc (q - p + 1);
115 memcpy (path, p, q - p);
116 path[q - p] = '\0';
119 add_path (path, chain, chain == SYSTEM);
123 /* Append the standard include chain defined in cppdefault.c. */
124 static void
125 add_standard_paths (sysroot, iprefix, cxx_stdinc)
126 const char *sysroot, *iprefix;
127 int cxx_stdinc;
129 const struct default_include *p;
130 size_t len = 0;
132 if (iprefix)
133 len = cpp_GCC_INCLUDE_DIR_len;
135 for (p = cpp_include_defaults; p->fname; p++)
137 if (!p->cplusplus || cxx_stdinc)
139 char *str;
141 /* Should this directory start with the sysroot? */
142 if (sysroot && p->add_sysroot)
143 str = concat (sysroot, p->fname, NULL);
144 /* Does this directory start with the prefix? If so, search
145 "translated" versions of GNU directories. These have
146 /usr/local/lib/gcc... replaced by iprefix. */
147 else if (len && !strncmp (p->fname, cpp_GCC_INCLUDE_DIR, len))
148 str = concat (iprefix, p->fname + len, NULL);
149 else
150 str = update_path (p->fname, p->component);
152 add_path (str, SYSTEM, p->cxx_aware);
157 /* For each duplicate path in chain HEAD, keep just the first one.
158 Remove each path in chain HEAD that also exists in chain SYSTEM.
159 Set the NEXT pointer of the last path in the resulting chain to
160 JOIN, unless it duplicates JOIN in which case the last path is
161 removed. Return the head of the resulting chain. Any of HEAD,
162 JOIN and SYSTEM can be NULL. */
163 static struct cpp_path *
164 remove_duplicates (pfile, head, system, join, verbose)
165 cpp_reader *pfile;
166 struct cpp_path *head;
167 struct cpp_path *system;
168 struct cpp_path *join;
169 int verbose;
171 struct cpp_path **pcur, *tmp, *cur;
172 struct stat st;
174 for (pcur = &head; *pcur; )
176 int reason = REASON_QUIET;
178 cur = *pcur;
179 cpp_simplify_path (cur->name);
181 if (stat (cur->name, &st))
183 /* Dirs that don't exist are silently ignored, unless verbose. */
184 if (errno != ENOENT)
185 cpp_errno (pfile, DL_ERROR, cur->name);
186 else
187 reason = REASON_NOENT;
189 else if (!S_ISDIR (st.st_mode))
190 cpp_error_with_line (pfile, DL_ERROR, 0, 0,
191 "%s: not a directory", cur->name);
192 else
194 INO_T_COPY (cur->ino, st.st_ino);
195 cur->dev = st.st_dev;
197 /* Remove this one if it is in the system chain. */
198 reason = REASON_DUP_SYS;
199 for (tmp = system; tmp; tmp = tmp->next)
200 if (INO_T_EQ (tmp->ino, cur->ino) && tmp->dev == cur->dev)
201 break;
203 if (!tmp)
205 /* Dupicate of something earlier in the same chain? */
206 reason = REASON_DUP;
207 for (tmp = head; tmp != cur; tmp = tmp->next)
208 if (INO_T_EQ (cur->ino, tmp->ino) && cur->dev == tmp->dev)
209 break;
211 if (tmp == cur
212 /* Last in the chain and duplicate of JOIN? */
213 && !(cur->next == NULL && join
214 && INO_T_EQ (cur->ino, join->ino)
215 && cur->dev == join->dev))
217 /* Unique, so keep this directory. */
218 pcur = &cur->next;
219 continue;
224 /* Remove this entry from the chain. */
225 *pcur = cur->next;
226 free_path (cur, verbose ? reason: REASON_QUIET);
229 *pcur = join;
230 return head;
233 /* Merge the four include chains together in the order quote, bracket,
234 system, after. Remove duplicate dirs (as determined by
235 INO_T_EQ()).
237 We can't just merge the lists and then uniquify them because then
238 we may lose directories from the <> search path that should be
239 there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however safe
240 to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written -Ibar -I- -Ifoo
241 -Iquux. */
242 static void
243 merge_include_chains (pfile, verbose)
244 cpp_reader *pfile;
245 int verbose;
247 /* Join the SYSTEM and AFTER chains. Remove duplicates in the
248 resulting SYSTEM chain. */
249 if (heads[SYSTEM])
250 tails[SYSTEM]->next = heads[AFTER];
251 else
252 heads[SYSTEM] = heads[AFTER];
253 heads[SYSTEM] = remove_duplicates (pfile, heads[SYSTEM], 0, 0, verbose);
255 /* Remove duplicates from BRACKET that are in itself or SYSTEM, and
256 join it to SYSTEM. */
257 heads[BRACKET] = remove_duplicates (pfile, heads[BRACKET], heads[SYSTEM],
258 heads[SYSTEM], verbose);
260 /* Remove duplicates from QUOTE that are in itself or SYSTEM, and
261 join it to BRACKET. */
262 heads[QUOTE] = remove_duplicates (pfile, heads[QUOTE], heads[SYSTEM],
263 heads[BRACKET], verbose);
265 /* If verbose, print the list of dirs to search. */
266 if (verbose)
268 struct cpp_path *p;
270 fprintf (stderr, _("#include \"...\" search starts here:\n"));
271 for (p = heads[QUOTE];; p = p->next)
273 if (p == heads[BRACKET])
274 fprintf (stderr, _("#include <...> search starts here:\n"));
275 if (!p)
276 break;
277 fprintf (stderr, " %s\n", p->name);
279 fprintf (stderr, _("End of search list.\n"));
283 /* Use given -I paths for #include "..." but not #include <...>, and
284 don't search the directory of the present file for #include "...".
285 (Note that -I. -I- is not the same as the default setup; -I. uses
286 the compiler's working dir.) */
287 void
288 split_quote_chain ()
290 heads[QUOTE] = heads[BRACKET];
291 tails[QUOTE] = tails[BRACKET];
292 heads[BRACKET] = NULL;
293 tails[BRACKET] = NULL;
294 /* This is NOT redundant. */
295 quote_ignores_source_dir = true;
298 /* Add PATH to the include chain CHAIN. PATH must be malloc-ed and
299 NUL-terminated. */
300 void
301 add_path (path, chain, cxx_aware)
302 char *path;
303 int chain;
304 int cxx_aware;
306 struct cpp_path *p;
308 p = (struct cpp_path *) xmalloc (sizeof (struct cpp_path));
309 p->next = NULL;
310 p->name = path;
311 if (chain == SYSTEM || chain == AFTER)
312 p->sysp = 1 + !cxx_aware;
313 else
314 p->sysp = 0;
316 if (tails[chain])
317 tails[chain]->next = p;
318 else
319 heads[chain] = p;
320 tails[chain] = p;
323 /* Exported function to handle include chain merging, duplicate
324 removal, and registration with cpplib. */
325 void
326 register_include_chains (pfile, sysroot, iprefix,
327 stdinc, cxx_stdinc, verbose)
328 cpp_reader *pfile;
329 const char *sysroot, *iprefix;
330 int stdinc, cxx_stdinc, verbose;
332 static const char *const lang_env_vars[] =
333 { "C_INCLUDE_PATH", "CPLUS_INCLUDE_PATH",
334 "OBJC_INCLUDE_PATH", "OBJCPLUS_INCLUDE_PATH" };
335 cpp_options *cpp_opts = cpp_get_options (pfile);
336 size_t idx = (cpp_opts->objc ? 2: 0);
338 if (cpp_opts->cplusplus)
339 idx++;
340 else
341 cxx_stdinc = false;
343 /* CPATH and language-dependent environment variables may add to the
344 include chain. */
345 add_env_var_paths ("CPATH", BRACKET);
346 add_env_var_paths (lang_env_vars[idx], SYSTEM);
348 /* Finally chain on the standard directories. */
349 if (stdinc)
350 add_standard_paths (sysroot, iprefix, cxx_stdinc);
352 merge_include_chains (pfile, verbose);
354 cpp_set_include_chains (pfile, heads[QUOTE], heads[BRACKET],
355 quote_ignores_source_dir);