diff options
-rw-r--r-- | gcc/ChangeLog | 53 | ||||
-rw-r--r-- | gcc/Makefile.in | 10 | ||||
-rw-r--r-- | gcc/c-incpath.c | 27 | ||||
-rw-r--r-- | gcc/c-incpath.h | 10 | ||||
-rw-r--r-- | gcc/c-opts.c | 5 | ||||
-rw-r--r-- | gcc/c.opt | 4 | ||||
-rw-r--r-- | gcc/config/darwin-c.c | 317 | ||||
-rw-r--r-- | gcc/config/darwin.h | 14 | ||||
-rw-r--r-- | gcc/config/t-darwin | 3 | ||||
-rw-r--r-- | gcc/cppfiles.c | 97 | ||||
-rw-r--r-- | gcc/cpplib.h | 20 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 30 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 13 | ||||
-rw-r--r-- | gcc/fix-header.c | 6 | ||||
-rw-r--r-- | gcc/gcc.c | 2 | ||||
-rw-r--r-- | gcc/hooks.c | 10 | ||||
-rw-r--r-- | gcc/hooks.h | 2 | ||||
-rw-r--r-- | gcc/target-def.h | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/framework-1.c | 4 |
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); @@ -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; @@ -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> |