OSDN Git Service

Add framework support for darwin.
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 4 Mar 2004 00:18:54 +0000 (00:18 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 4 Mar 2004 00:18:54 +0000 (00:18 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@78875 138bc75d-0d04-0410-961f-82ee72b054a4

19 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/c-incpath.c
gcc/c-incpath.h
gcc/c-opts.c
gcc/c.opt
gcc/config/darwin-c.c
gcc/config/darwin.h
gcc/config/t-darwin
gcc/cppfiles.c
gcc/cpplib.h
gcc/doc/invoke.texi
gcc/doc/tm.texi
gcc/fix-header.c
gcc/gcc.c
gcc/hooks.c
gcc/hooks.h
gcc/target-def.h
gcc/testsuite/gcc.dg/framework-1.c [new file with mode: 0644]

index d538709..fd13ce7 100644 (file)
@@ -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
index 416e230..994f0e8 100644 (file)
@@ -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@
 
index 7b08c1a..7f6cbdf 100644 (file)
@@ -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
index 31ed657..80b4130 100644 (file)
@@ -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 };
index b4f3851..6d9696a 100644 (file)
@@ -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);
index 0674627..151c2de 100644 (file)
--- 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
index fb51455..a4c6d8b 100644 (file)
@@ -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;
index 83c7a8c..b5dae39 100644 (file)
@@ -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 */
index a7076ab..f5af52e 100644 (file)
@@ -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
index b40521b..d31f61b 100644 (file)
@@ -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;
+}
 \f
 /* This datastructure holds the list of header files that were seen
    while the PCH was being built.  The 'entries' field is kept sorted
index dddbac2..c53375d 100644 (file)
@@ -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;
index 26b9a12..da42b61 100644 (file)
@@ -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.
index 79a13f7..3ca5aca 100644 (file)
@@ -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
index 67666b6..7b7aee3 100644 (file)
@@ -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;
index d69da44..9538c62 100644 (file)
--- 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*}\
index ef90ce1..cb6efd4 100644 (file)
@@ -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)
 {
 }
index 40b5e25..a72f6c8 100644 (file)
@@ -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 *);
index 89af47e..861e9ed 100644 (file)
@@ -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 (file)
index 0000000..7e68683
--- /dev/null
@@ -0,0 +1,4 @@
+/* { dg-do compile { target *-*-darwin* } } */
+/* { dg-options "-F." } */
+
+#include <Carbon/Carbon.h>