aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog53
-rw-r--r--gcc/Makefile.in10
-rw-r--r--gcc/c-incpath.c27
-rw-r--r--gcc/c-incpath.h10
-rw-r--r--gcc/c-opts.c5
-rw-r--r--gcc/c.opt4
-rw-r--r--gcc/config/darwin-c.c317
-rw-r--r--gcc/config/darwin.h14
-rw-r--r--gcc/config/t-darwin3
-rw-r--r--gcc/cppfiles.c97
-rw-r--r--gcc/cpplib.h20
-rw-r--r--gcc/doc/invoke.texi30
-rw-r--r--gcc/doc/tm.texi13
-rw-r--r--gcc/fix-header.c6
-rw-r--r--gcc/gcc.c2
-rw-r--r--gcc/hooks.c10
-rw-r--r--gcc/hooks.h2
-rw-r--r--gcc/target-def.h4
-rw-r--r--gcc/testsuite/gcc.dg/framework-1.c4
19 files changed, 609 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d538709..fd13ce7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,56 @@
+2004-03-03 Mike Stump <mrs@apple.com>
+
+ Add framework support for darwin.
+
+ * c-incpath.c: Include target.h and machmode.h.
+ (add_path): Use a consistent style for cpp_dir. Initialize
+ p->construct to 0.
+ (add_cpp_dir_path): New.
+ (register_include_chains): Add use of extra_includes callback.
+ (hook_void_int): Add.
+ (target_c_incpath): Add.
+ * c-incpath.h (add_cpp_dir_path): New.
+ (target_c_incpath_s): Add.
+ (target_c_incpath): Add.
+ (C_INCPATH_INIT): Add.
+ * c-opts.c (c_common_missing_argument,
+ c_common_handle_option): Add -F argument processing.
+ * c.opt: Add -F argument processing.
+ * gcc.c (trad_capable_cpp): Add -F argument processing.
+ * cppfiles.c (find_file_in_dir): Update to use construct
+ callback.
+ (search_path_exhausted, cpp_get_path, cpp_get_buffer,
+ cpp_get_prev): New.
+ (_cpp_find_file): Use search_path_exhausted.
+ (make_cpp_dir): Initialize construct to 0.
+ * cpplib.h (missing_header_cb
+ cpp_get_path, cpp_get_buffer, cpp_get_file, cpp_get_prev): New.
+ (cpp_callbacks): Add missing_header
+ (cpp_dir): Add construct.
+ * target-def.h: (TARGET_OPTF): New.
+ * hooks.c (hook_void_int, hook_void_charptr): Add.
+ * hooks.h (hook_void_int, hook_void_charptr): Add.
+ * Makefile.in (c-incpath.o) : Add $(TARGET_H) and
+ $(MACHMODE_H) dependencies.
+ * doc/invoke.texi (Darwin Options): Document -F.
+ * doc/tm.texi (TARGET_EXTRA_INCLUDES): Add.
+ (TARGET_OPTF): Add.
+ * fix-header.c (target_c_incpath): Add.
+
+ * config/darwin-c.c: Add c-incpath.h include.
+ (using_frameworks, find_subframework_file,
+ find_subframework_header, add_system_framework_path,
+ frameworks_in_use, num_frameworks, max_frameworks,
+ add_framework, find_framework, struct framework_header,
+ framework_header_dirs, framework_construct_pathname,
+ find_subframework_file, add_system_framework_path,
+ add_framework_path, framework_defaults,
+ darwin_register_frameworks, find_subframework_header): Add.
+ * config/darwin.h (TARGET_EXTRA_INCLUDES, TARGET_OPTF): New.
+ (TARGET_OPTION_TRANSLATE_TABLE): Add -framework support.
+ (CPP_SPEC): Add __APPLE_CC__ support.
+ * t-darwin (darwin-c.o): Add c-incpath.h dependency.
+
2004-03-04 Jan Hubicka <jh@suse.cz>
* cselib.c (cselib_finish): Fix miss-application of my previous
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 416e230..994f0e8 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1297,7 +1297,8 @@ c-parse.y: c-parse.in
$(SHELL) $(srcdir)/../move-if-change tmp-c-parse.y $@
c-incpath.o: c-incpath.c c-incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \
- intl.h prefix.h coretypes.h $(TM_H) cppdefault.h
+ intl.h prefix.h coretypes.h $(TM_H) cppdefault.h $(TARGET_H) \
+ $(MACHMODE_H)
c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) $(C_TREE_H) $(GGC_H) $(TARGET_H) flags.h function.h output.h \
@@ -1360,9 +1361,10 @@ c-common.o : c-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
c-pretty-print.o : c-pretty-print.c $(C_PRETTY_PRINT_H) \
$(C_COMMON_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) real.h
-c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- c-pragma.h flags.h toplev.h langhooks.h tree-inline.h $(DIAGNOSTIC_H) \
- intl.h debug.h $(C_COMMON_H) opts.h options.h $(PARAMS_H)
+c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) c-pragma.h flags.h toplev.h langhooks.h \
+ tree-inline.h $(DIAGNOSTIC_H) intl.h debug.h $(C_COMMON_H) \
+ opts.h options.h $(PARAMS_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$< $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@
diff --git a/gcc/c-incpath.c b/gcc/c-incpath.c
index 7b08c1a..7f6cbdf 100644
--- a/gcc/c-incpath.c
+++ b/gcc/c-incpath.c
@@ -21,6 +21,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "machmode.h"
+#include "target.h"
#include "tm.h"
#include "cpplib.h"
#include "prefix.h"
@@ -298,20 +300,33 @@ split_quote_chain (void)
quote_ignores_source_dir = true;
}
+/* Add P to the chain specified by CHAIN. */
+
+void
+add_cpp_dir_path (cpp_dir *p, int chain)
+{
+ if (tails[chain])
+ tails[chain]->next = p;
+ else
+ heads[chain] = p;
+ tails[chain] = p;
+}
+
/* Add PATH to the include chain CHAIN. PATH must be malloc-ed and
NUL-terminated. */
void
add_path (char *path, int chain, int cxx_aware)
{
- struct cpp_dir *p;
+ cpp_dir *p;
- p = xmalloc (sizeof (struct cpp_dir));
+ p = xmalloc (sizeof (cpp_dir));
p->next = NULL;
p->name = path;
if (chain == SYSTEM || chain == AFTER)
p->sysp = 1 + !cxx_aware;
else
p->sysp = 0;
+ p->construct = 0;
if (tails[chain])
tails[chain]->next = p;
@@ -347,8 +362,16 @@ register_include_chains (cpp_reader *pfile, const char *sysroot,
if (stdinc)
add_standard_paths (sysroot, iprefix, cxx_stdinc);
+ target_c_incpath.extra_includes (stdinc);
+
merge_include_chains (pfile, verbose);
cpp_set_include_chains (pfile, heads[QUOTE], heads[BRACKET],
quote_ignores_source_dir);
}
+
+#ifndef TARGET_EXTRA_INCLUDES
+static void hook_void_int(int u ATTRIBUTE_UNUSED) { }
+
+struct target_c_incpath_s target_c_incpath = { hook_void_int };
+#endif
diff --git a/gcc/c-incpath.h b/gcc/c-incpath.h
index 31ed657..80b4130 100644
--- a/gcc/c-incpath.h
+++ b/gcc/c-incpath.h
@@ -19,5 +19,15 @@ extern void split_quote_chain (void);
extern void add_path (char *, int, int);
extern void register_include_chains (cpp_reader *, const char *,
const char *, int, int, int);
+extern void add_cpp_dir_path (struct cpp_dir *, int);
+
+struct target_c_incpath_s {
+ /* Do extra includes processing. STDINC is false iff -nostdinc was given. */
+ void (*extra_includes) (int);
+};
+
+extern struct target_c_incpath_s target_c_incpath;
+
+#define C_INCPATH_INIT { TARGET_EXTRA_INCLUDES }
enum { QUOTE = 0, BRACKET, SYSTEM, AFTER };
diff --git a/gcc/c-opts.c b/gcc/c-opts.c
index b4f3851..6d9696a 100644
--- a/gcc/c-opts.c
+++ b/gcc/c-opts.c
@@ -153,6 +153,7 @@ c_common_missing_argument (const char *opt, size_t code)
error ("macro name missing after \"%s\"", opt);
break;
+ case OPT_F:
case OPT_I:
case OPT_idirafter:
case OPT_isysroot:
@@ -285,6 +286,10 @@ c_common_handle_option (size_t scode, const char *arg, int value)
cpp_opts->print_include_names = 1;
break;
+ case OPT_F:
+ TARGET_OPTF (xstrdup (arg));
+ break;
+
case OPT_I:
if (strcmp (arg, "-"))
add_path (xstrdup (arg), BRACKET, 0);
diff --git a/gcc/c.opt b/gcc/c.opt
index 0674627..151c2de 100644
--- a/gcc/c.opt
+++ b/gcc/c.opt
@@ -93,6 +93,10 @@ C ObjC C++ ObjC++ Joined Separate
E
C ObjC C++ ObjC++ Undocumented
+F
+C ObjC C++ ObjC++ Joined Separate
+-F <dir> Add <dir> to the end of the main framework include path
+
H
C ObjC C++ ObjC++
Print the name of header files as they are used
diff --git a/gcc/config/darwin-c.c b/gcc/config/darwin-c.c
index fb51455..a4c6d8bd 100644
--- a/gcc/config/darwin-c.c
+++ b/gcc/config/darwin-c.c
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "c-pragma.h"
#include "c-tree.h"
+#include "c-incpath.h"
#include "toplev.h"
#include "tm_p.h"
@@ -34,11 +35,16 @@ Boston, MA 02111-1307, USA. */
#define BAD(msgid) do { warning (msgid); return; } while (0)
+static bool using_frameworks = false;
+
/* Maintain a small stack of alignments. This is similar to pragma
pack's stack, but simpler. */
static void push_field_alignment (int);
static void pop_field_alignment (void);
+static const char *find_subframework_file (const char *, const char *);
+static void add_system_framework_path (char *);
+static const char *find_subframework_header (cpp_reader *pfile, const char *header);
typedef struct align_stack
{
@@ -147,3 +153,314 @@ darwin_pragma_unused (cpp_reader *pfile ATTRIBUTE_UNUSED)
if (c_lex (&x) != CPP_EOF)
warning ("junk at end of '#pragma unused'");
}
+
+static struct {
+ size_t len;
+ const char *name;
+ cpp_dir* dir;
+} *frameworks_in_use;
+static int num_frameworks = 0;
+static int max_frameworks = 0;
+
+
+/* Remember which frameworks have been seen, so that we can ensure
+ that all uses of that framework come from the same framework. DIR
+ is the place where the named framework NAME, which is of length
+ LEN, was found. */
+
+static void
+add_framework (const char *name, size_t len, cpp_dir *dir)
+{
+ int i;
+ for (i = 0; i < num_frameworks; ++i)
+ {
+ if (len == frameworks_in_use[i].len
+ && strncmp (name, frameworks_in_use[i].name, len) == 0)
+ {
+ return;
+ }
+ }
+ if (i >= max_frameworks)
+ {
+ max_frameworks = i*2;
+ frameworks_in_use = xrealloc (frameworks_in_use,
+ max_frameworks*sizeof(*frameworks_in_use));
+ }
+ frameworks_in_use[num_frameworks].name = name;
+ frameworks_in_use[num_frameworks].len = len;
+ frameworks_in_use[num_frameworks].dir = dir;
+ ++num_frameworks;
+}
+
+/* Recall if we have seen the named framework NAME, before, and where
+ we saw it. NAME is LEN bytes long. The return value is the place
+ where it was seen before. */
+
+static struct cpp_dir*
+find_framework (const char *name, size_t len)
+{
+ int i;
+ for (i = 0; i < num_frameworks; ++i)
+ {
+ if (len == frameworks_in_use[i].len
+ && strncmp (name, frameworks_in_use[i].name, len) == 0)
+ {
+ return frameworks_in_use[i].dir;
+ }
+ }
+ return 0;
+}
+
+/* There are two directories in a framework that contain header files,
+ Headers and PrivateHeaders. We search Headers first as it is more
+ common to upgrade a header from PrivateHeaders to Headers and when
+ that is done, the old one might hang around and be out of data,
+ causing grief. */
+
+struct framework_header {const char * dirName; int dirNameLen; };
+static struct framework_header framework_header_dirs[] = {
+ { "Headers", 7 },
+ { "PrivateHeaders", 14 },
+ { NULL, 0 }
+};
+
+/* Returns a pointer to a malloced string that contains the real pathname
+ to the file, given the base name and the name. */
+
+static char *
+framework_construct_pathname (const char *fname, cpp_dir *dir)
+{
+ char *buf;
+ size_t fname_len, frname_len;
+ cpp_dir *fast_dir;
+ char *frname;
+ struct stat st;
+ int i;
+
+ /* Framework names must have a / in them. */
+ buf = strchr (fname, '/');
+ if (buf)
+ fname_len = buf - fname;
+ else
+ return 0;
+
+ fast_dir = find_framework (fname, fname_len);
+
+ /* Framework includes must all come from one framework. */
+ if (fast_dir && dir != fast_dir)
+ return 0;
+
+ frname = xmalloc (strlen (fname) + dir->len + 2
+ + strlen(".framework/") + strlen("PrivateHeaders"));
+ strncpy (&frname[0], dir->name, dir->len);
+ frname_len = dir->len;
+ if (frname_len && frname[frname_len-1] != '/')
+ frname[frname_len++] = '/';
+ strncpy (&frname[frname_len], fname, fname_len);
+ frname_len += fname_len;
+ strncpy (&frname[frname_len], ".framework/", strlen (".framework/"));
+ frname_len += strlen (".framework/");
+
+ /* Append framework_header_dirs and header file name */
+ for (i = 0; framework_header_dirs[i].dirName; i++)
+ {
+ strncpy (&frname[frname_len],
+ framework_header_dirs[i].dirName,
+ framework_header_dirs[i].dirNameLen);
+ strcpy (&frname[frname_len + framework_header_dirs[i].dirNameLen],
+ &fname[fname_len]);
+
+ if (stat (frname, &st) == 0)
+ {
+ add_framework (fname, fname_len, dir);
+ return frname;
+ }
+ }
+
+ free (frname);
+ return 0;
+}
+
+/* Search for FNAME in sub-frameworks. pname is the context that we
+ wish to search in. Return the path the file was found at,
+ otherwise return 0. */
+
+static const char*
+find_subframework_file (const char *fname, const char *pname)
+{
+ char *sfrname;
+ const char *dot_framework = ".framework/";
+ char *bufptr;
+ int sfrname_len, i, fname_len;
+ struct cpp_dir *fast_dir;
+ static struct cpp_dir subframe_dir;
+ struct stat st;
+
+ bufptr = strchr (fname, '/');
+
+ /* Subframework files must have / in the name. */
+ if (bufptr == 0)
+ return 0;
+
+ fname_len = bufptr - fname;
+ fast_dir = find_framework (fname, fname_len);
+
+ /* Sub framework header filename includes parent framework name and
+ header name in the "CarbonCore/OSUtils.h" form. If it does not
+ include slash it is not a sub framework include. */
+ bufptr = strstr (pname, dot_framework);
+
+ /* If the parent header is not of any framework, then this header
+ can not be part of any subframework. */
+ if (!bufptr)
+ return 0;
+
+ /* Now translate. For example, +- bufptr
+ fname = CarbonCore/OSUtils.h |
+ pname = /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
+ into
+ sfrname = /System/Library/Frameworks/Foundation.framework/Frameworks/CarbonCore.framework/Headers/OSUtils.h */
+
+ sfrname = (char *) xmalloc (strlen (pname) + strlen (fname) + 2 +
+ strlen ("Frameworks/") + strlen (".framework/")
+ + strlen ("PrivateHeaders"));
+
+ bufptr += strlen (dot_framework);
+
+ sfrname_len = bufptr - pname;
+
+ strncpy (&sfrname[0], pname, sfrname_len);
+
+ strncpy (&sfrname[sfrname_len], "Frameworks/", strlen ("Frameworks/"));
+ sfrname_len += strlen("Frameworks/");
+
+ strncpy (&sfrname[sfrname_len], fname, fname_len);
+ sfrname_len += fname_len;
+
+ strncpy (&sfrname[sfrname_len], ".framework/", strlen (".framework/"));
+ sfrname_len += strlen (".framework/");
+
+ /* Append framework_header_dirs and header file name */
+ for (i = 0; framework_header_dirs[i].dirName; i++)
+ {
+ strncpy (&sfrname[sfrname_len],
+ framework_header_dirs[i].dirName,
+ framework_header_dirs[i].dirNameLen);
+ strcpy (&sfrname[sfrname_len + framework_header_dirs[i].dirNameLen],
+ &fname[fname_len]);
+
+ if (stat (sfrname, &st) == 0)
+ {
+ if (fast_dir != &subframe_dir)
+ {
+ if (fast_dir)
+ warning ("subframework include %s conflicts with framework include",
+ fname);
+ else
+ add_framework (fname, fname_len, &subframe_dir);
+ }
+
+ return sfrname;
+ }
+ }
+ free (sfrname);
+
+ return 0;
+}
+
+/* Add PATH to the system includes. PATH must be malloc-ed and
+ NUL-terminated. System framework paths are C++ aware. */
+
+static void
+add_system_framework_path (char *path)
+{
+ int cxx_aware = 1;
+ cpp_dir *p;
+
+ p = xmalloc (sizeof (cpp_dir));
+ p->next = NULL;
+ p->name = path;
+ p->sysp = 1 + !cxx_aware;
+ p->construct = framework_construct_pathname;
+ using_frameworks = 1;
+
+ add_cpp_dir_path (p, SYSTEM);
+}
+
+/* Add PATH to the bracket includes. PATH must be malloc-ed and
+ NUL-terminated. */
+
+void
+add_framework_path (char *path)
+{
+ cpp_dir *p;
+
+ p = xmalloc (sizeof (cpp_dir));
+ p->next = NULL;
+ p->name = path;
+ p->sysp = 0;
+ p->construct = framework_construct_pathname;
+ using_frameworks = 1;
+
+ add_cpp_dir_path (p, BRACKET);
+}
+
+static const char *framework_defaults [] =
+ {
+ "/System/Library/Frameworks",
+ "/Library/Frameworks",
+ "/Local/Library/Frameworks",
+ };
+
+
+/* Register all the system framework paths if STDINC is true and setup
+ the missing_header callback for subframework searching if any
+ frameworks had been registered. */
+
+void
+darwin_register_frameworks (int stdinc)
+{
+ if (stdinc)
+ {
+ size_t i;
+
+ /* Setup default search path for frameworks. */
+ for (i=0; i<sizeof (framework_defaults)/sizeof(const char *); ++i)
+ {
+ /* System Framework headers are cxx aware. */
+ add_system_framework_path (xstrdup (framework_defaults[i]));
+ }
+ }
+
+ if (using_frameworks)
+ cpp_get_callbacks (parse_in)->missing_header = find_subframework_header;
+}
+
+/* Search for HEADER in context dependent way. The return value is
+ the malloced name of a header to try and open, if any, or NULL
+ otherwise. This is called after normal header lookup processing
+ fails to find a header. We search each file in the include stack,
+ using FUNC, starting from the most deeply nested include and
+ finishing with the main input file. We stop searching when FUNC
+ returns non-zero. */
+
+static const char*
+find_subframework_header (cpp_reader *pfile, const char *header)
+{
+ const char *fname = header;
+ struct cpp_buffer *b;
+ const char *n;
+
+ for (b = cpp_get_buffer (pfile);
+ b && cpp_get_file (b) && cpp_get_path (cpp_get_file (b));
+ b = cpp_get_prev (b))
+ {
+ n = find_subframework_file (fname, cpp_get_path (cpp_get_file (b)));
+ if (n)
+ return n;
+ }
+
+ return 0;
+}
+
+struct target_c_incpath_s target_c_incpath = C_INCPATH_INIT;
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 83c7a8c..b5dae39 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -119,6 +119,7 @@ Boston, MA 02111-1307, USA. */
{ "-exported_symbols_list", "-Zexported_symbols_list" }, \
{ "-seg_addr_table_filename", "-Zseg_addr_table_filename" }, \
{ "-filelist", "-Xlinker -filelist -Xlinker" }, \
+ { "-framework", "-Xlinker -framework -Xlinker" }, \
{ "-flat_namespace", "-Zflat_namespace" }, \
{ "-force_cpusubtype_ALL", "-Zforce_cpusubtype_ALL" }, \
{ "-force_flat_namespace", "-Zforce_flat_namespace" }, \
@@ -175,10 +176,13 @@ Boston, MA 02111-1307, USA. */
!strcmp (STR, "dylinker_install_name") ? 1 : \
0)
-/* Machine dependent cpp options. */
+/* Machine dependent cpp options. __APPLE_CC__ is defined as the
+ Apple include files expect it to be defined and won't work if it
+ isn't. */
#undef CPP_SPEC
-#define CPP_SPEC "%{static:%{!dynamic:-D__STATIC__}}%{!static:-D__DYNAMIC__}"
+#define CPP_SPEC "%{static:%{!dynamic:-D__STATIC__}}%{!static:-D__DYNAMIC__}\
+ -D__APPLE_CC__=1"
/* This is mostly a clone of the standard LINK_COMMAND_SPEC, plus
precomp, libtool, and fat build additions. Also we
@@ -834,6 +838,12 @@ enum machopic_addr_class {
#undef ASM_APP_OFF
#define ASM_APP_OFF ""
+void darwin_register_frameworks (int);
+#define TARGET_EXTRA_INCLUDES darwin_register_frameworks
+
+void add_framework_path (char *);
+#define TARGET_OPTF add_framework_path
+
#define TARGET_HAS_F_SETLKW
#endif /* CONFIG_DARWIN_H */
diff --git a/gcc/config/t-darwin b/gcc/config/t-darwin
index a7076ab..f5af52e 100644
--- a/gcc/config/t-darwin
+++ b/gcc/config/t-darwin
@@ -5,7 +5,8 @@ darwin.o: $(srcdir)/config/darwin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/darwin.c
darwin-c.o: $(srcdir)/config/darwin-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(CPPLIB_H) tree.h c-pragma.h $(C_TREE_H) toplev.h $(TM_P_H)
+ $(TM_H) $(CPPLIB_H) tree.h c-pragma.h $(C_TREE_H) toplev.h $(TM_P_H) \
+ c-incpath.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/darwin-c.c
gt-darwin.h : s-gtype ; @true
diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c
index b40521b..d31f61b 100644
--- a/gcc/cppfiles.c
+++ b/gcc/cppfiles.c
@@ -319,23 +319,58 @@ find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
if (CPP_OPTION (pfile, remap) && (path = remap_filename (pfile, file)))
;
else
- path = append_file_to_dir (file->name, file->dir);
+ if (file->dir->construct)
+ path = file->dir->construct (file->name, file->dir);
+ else
+ path = append_file_to_dir (file->name, file->dir);
- file->path = path;
- if (pch_open_file (pfile, file, invalid_pch))
- return true;
+ if (path)
+ {
+ file->path = path;
+ if (pch_open_file (pfile, file, invalid_pch))
+ return true;
- if (open_file (file))
- return true;
+ if (open_file (file))
+ return true;
+
+ if (file->err_no != ENOENT)
+ {
+ open_file_failed (pfile, file);
+ return true;
+ }
+
+ free (path);
+ file->path = file->name;
+ }
+ else
+ {
+ file->err_no = ENOENT;
+ file->path = NULL;
+ }
+
+ return false;
+}
- if (file->err_no != ENOENT)
+/* Return tue iff the missing_header callback found the given HEADER. */
+static bool
+search_path_exhausted (cpp_reader *pfile, const char *header, _cpp_file *file)
+{
+ missing_header_cb func = pfile->cb.missing_header;
+
+ /* When the regular search path doesn't work, try context dependent
+ headers search paths. */
+ if (func
+ && file->dir == NULL)
{
- open_file_failed (pfile, file);
- return true;
+ if ((file->path = func (pfile, header)) != NULL)
+ {
+ if (open_file (file))
+ return true;
+ free ((void *)file->path);
+ }
+ file->path = file->name;
}
- free (path);
- file->path = file->name;
return false;
}
@@ -391,6 +426,9 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
file->dir = file->dir->next;
if (file->dir == NULL)
{
+ if (search_path_exhausted (pfile, fname, file))
+ return file;
+
open_file_failed (pfile, file);
if (invalid_pch)
{
@@ -839,6 +877,7 @@ make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp)
dir->name = (char *) dir_name;
dir->len = strlen (dir_name);
dir->sysp = sysp;
+ dir->construct = 0;
/* Store this new result in the hash table. */
entry = new_file_hash_entry (pfile);
@@ -1265,6 +1304,42 @@ validate_pch (cpp_reader *pfile, _cpp_file *file, const char *pchname)
file->path = saved_path;
return valid;
}
+
+/* Get the path associated with the _cpp_file F. The path includes
+ the base name from the include directive and the directory it was
+ found in via the search path. */
+
+const char *
+cpp_get_path (struct _cpp_file *f)
+{
+ return f->path;
+}
+
+/* Get the cpp_buffer currently associated with the cpp_reader
+ PFILE. */
+
+cpp_buffer *
+cpp_get_buffer (cpp_reader *pfile)
+{
+ return pfile->buffer;
+}
+
+/* Get the _cpp_file associated with the cpp_buffer B. */
+
+_cpp_file *
+cpp_get_file (cpp_buffer *b)
+{
+ return b->file;
+}
+
+/* Get the previous cpp_buffer given a cpp_buffer B. The previous
+ buffer is the buffer that included the given buffer. */
+
+cpp_buffer *
+cpp_get_prev (cpp_buffer *b)
+{
+ return b->prev;
+}
/* This datastructure holds the list of header files that were seen
while the PCH was being built. The 'entries' field is kept sorted
diff --git a/gcc/cpplib.h b/gcc/cpplib.h
index dddbac2..c53375d 100644
--- a/gcc/cpplib.h
+++ b/gcc/cpplib.h
@@ -42,6 +42,7 @@ typedef struct cpp_callbacks cpp_callbacks;
typedef struct cpp_dir cpp_dir;
struct answer;
+struct _cpp_file;
/* The first three groups, apart from '=', can appear in preprocessor
expressions (+= and -= are used to indicate unary + and - resp.).
@@ -378,6 +379,14 @@ struct cpp_options
unsigned char stdc_0_in_system_headers;
};
+/* Callback for header lookup for HEADER, which is the name of a
+ source file. It is used as a method of last resort to find headers
+ that are not otherwise found during the normal include processing.
+ The return value is the malloced name of a header to try and open,
+ if any, or NULL otherwise. This callback is called only if the
+ header is otherwise unfound. */
+typedef const char *(*missing_header_cb)(cpp_reader *, const char *header);
+
/* Call backs to cpplib client. */
struct cpp_callbacks
{
@@ -399,6 +408,7 @@ struct cpp_callbacks
void (*def_pragma) (cpp_reader *, unsigned int);
int (*valid_pch) (cpp_reader *, const char *, int);
void (*read_pch) (cpp_reader *, const char *, int, const char *);
+ missing_header_cb missing_header;
};
/* Chain of directories to look for include files in. */
@@ -419,6 +429,12 @@ struct cpp_dir
platforms. A NULL-terminated array of (from, to) pairs. */
const char **name_map;
+ /* Routine to construct pathname, given the search path name and the
+ HEADER we are trying to find, return a constructed pathname to
+ try and open. If this is NULL, the constructed pathname is as
+ constructed by append_file_to_dir. */
+ char *(*construct) (const char *header, cpp_dir *dir);
+
/* The C front end uses these to recognize duplicated
directories in the search path. */
ino_t ino;
@@ -727,6 +743,10 @@ extern bool cpp_included (cpp_reader *, const char *);
extern void cpp_make_system_header (cpp_reader *, int, int);
extern bool cpp_push_include (cpp_reader *, const char *);
extern void cpp_change_file (cpp_reader *, enum lc_reason, const char *);
+extern const char *cpp_get_path (struct _cpp_file *);
+extern cpp_buffer *cpp_get_buffer (cpp_reader *);
+extern struct _cpp_file *cpp_get_file (cpp_buffer *);
+extern cpp_buffer *cpp_get_prev (cpp_buffer *);
/* In cpppch.c */
struct save_macro_data;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 26b9a12..da42b61 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -461,7 +461,7 @@ in the following sections.
-single_module -static -sub_library -sub_umbrella @gol
-twolevel_namespace -umbrella -undefined @gol
-unexported_symbols_list -weak_reference_mismatches @gol
--whatsloaded}
+-whatsloaded -F}
@emph{MIPS Options}
@gccoptlist{-EL -EB -march=@var{arch} -mtune=@var{arch} @gol
@@ -7562,6 +7562,34 @@ These options are defined for all architectures running the Darwin operating
system. They are useful for compatibility with other Mac OS compilers.
@table @gcctabopt
+@item -F@var{dir}
+@opindex F
+Add the framework directory @var{dir} to the head of the list of
+directories to be searched for header files. These directories are
+interleaved with those specified by @option{-I} options and are
+scanned in a left-to-right order.
+
+A framework directory is a directory with frameworks in it. A
+framework is a directory with a @samp{"Headers"} and/or
+@samp{"PrivateHeaders"} directory contained directly in it that ends
+in @samp{".framework"}. The name of a framework is the name of this
+directory excluding the @samp{".framework"}. Headers associated with
+the framework are found in one of those two directories, with
+@samp{"Headers"} being searched first. A subframework is a framework
+directory that is in a framework's @samp{"Frameworks"} directory.
+Includes of subframework headers can only appear in a header of a
+framework that contains the subframework, or in a sibling subframework
+header. Two subframeworks are siblings if they occur in the same
+framework. A subframework should not have the same name as a
+framework, a warning will be issued if this is violated. Currently a
+subframework cannot have subframeworks, in the future, the mechanism
+may be extended to support this. The standard frameworks can be found
+in @samp{"/System/Library/Frameworks"}, @samp{"/Library/Frameworks"}
+and @samp{"/Local/Library/Frameworks"}. An example include looks like
+@code{#include <Framework/header.h>}, where @samp{Framework} denotes
+the name of the framework and header.h is found in the
+@samp{"PrivateHeaders"} or @samp{"Headers"} directory.
+
@item -all_load
@opindex all_load
Loads all members of static archive libraries.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 79a13f7..3ca5aca 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -9109,3 +9109,16 @@ more than this number of multiplications is implemented by calling the
system library's @code{pow}, @code{powf} or @code{powl} routines.
The default value places no upper bound on the multiplication count.
@end defmac
+
+@deftypefn Macro void TARGET_EXTRA_INCLUDES (int @var{stdinc})
+This target hook should register any extra include files for the
+target. The parameter @var{stdinc} indicates if normal include files
+are present.
+@end deftypefn
+
+@deftypefn Macro void TARGET_OPTF (char *@var{path})
+This target hook should register special include paths for the target.
+The parameter @var{path} is the include to register. On Darwin
+systems, this is used for Framework includes, which have semantics
+that are different from @option{-I}.
+@end deftypefn
diff --git a/gcc/fix-header.c b/gcc/fix-header.c
index 67666b6..7b7aee3 100644
--- a/gcc/fix-header.c
+++ b/gcc/fix-header.c
@@ -84,6 +84,12 @@ static void v_fatal (const char *, va_list)
ATTRIBUTE_PRINTF (1,0) ATTRIBUTE_NORETURN;
static void fatal (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+#ifdef TARGET_EXTRA_INCLUDES
+static void hook_void_int(int u ATTRIBUTE_UNUSED) { }
+
+struct target_c_incpath_s target_c_incpath = { hook_void_int };
+#endif
+
struct line_maps line_table;
sstring buf;
diff --git a/gcc/gcc.c b/gcc/gcc.c
index d69da44..9538c62 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -743,7 +743,7 @@ static const char *trad_capable_cpp =
file that happens to exist is up-to-date. */
static const char *cpp_unique_options =
"%{C|CC:%{!E:%eGCC does not support -C or -CC without -E}}\
- %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*} %{P} %I\
+ %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I\
%{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
%{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
%{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
diff --git a/gcc/hooks.c b/gcc/hooks.c
index ef90ce13..cb6efd4 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -125,11 +125,21 @@ hook_uint_uint_constcharptrptr_0 (unsigned int a ATTRIBUTE_UNUSED,
}
void
+hook_void_int (int b ATTRIBUTE_UNUSED)
+{
+}
+
+void
hook_void_tree (tree a ATTRIBUTE_UNUSED)
{
}
void
+hook_void_charptr (char *a ATTRIBUTE_UNUSED)
+{
+}
+
+void
hook_void_tree_treeptr (tree a ATTRIBUTE_UNUSED, tree *b ATTRIBUTE_UNUSED)
{
}
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 40b5e25..a72f6c8 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -36,6 +36,8 @@ extern bool hook_bool_rtx_int_int_intp_false (rtx, int, int, int *);
extern bool hook_bool_constcharptr_size_t_false (const char *, size_t);
extern void hook_void_void (void);
+extern void hook_void_int (int);
+extern void hook_void_charptr (char *);
extern void hook_void_FILEptr_constcharptr (FILE *, const char *);
extern void hook_void_tree (tree);
extern void hook_void_tree_treeptr (tree, tree *);
diff --git a/gcc/target-def.h b/gcc/target-def.h
index 89af47e..861e9ed 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -361,6 +361,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_PRETEND_OUTGOING_VARARGS_NAMED, \
}
+#ifndef TARGET_OPTF
+#define TARGET_OPTF hook_void_charptr
+#endif
+
/* The whole shebang. */
#define TARGET_INITIALIZER \
{ \
diff --git a/gcc/testsuite/gcc.dg/framework-1.c b/gcc/testsuite/gcc.dg/framework-1.c
new file mode 100644
index 0000000..7e68683
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/framework-1.c
@@ -0,0 +1,4 @@
+/* { dg-do compile { target *-*-darwin* } } */
+/* { dg-options "-F." } */
+
+#include <Carbon/Carbon.h>