]>
Commit | Line | Data |
---|---|---|
0168a849 | 1 | /* Darwin support needed only by C/C++ frontends. |
ca2b05ba | 2 | Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. |
0168a849 SS |
3 | Contributed by Apple Computer Inc. |
4 | ||
7ec022b2 | 5 | This file is part of GCC. |
0168a849 | 6 | |
7ec022b2 | 7 | GCC is free software; you can redistribute it and/or modify |
0168a849 SS |
8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
7ec022b2 | 12 | GCC is distributed in the hope that it will be useful, |
0168a849 SS |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
7ec022b2 | 18 | along with GCC; see the file COPYING. If not, write to |
0168a849 SS |
19 | the Free Software Foundation, 59 Temple Place - Suite 330, |
20 | Boston, MA 02111-1307, USA. */ | |
21 | ||
22 | #include "config.h" | |
23 | #include "system.h" | |
4977bab6 ZW |
24 | #include "coretypes.h" |
25 | #include "tm.h" | |
0168a849 SS |
26 | #include "cpplib.h" |
27 | #include "tree.h" | |
28 | #include "c-pragma.h" | |
0168a849 | 29 | #include "c-tree.h" |
94d1613b | 30 | #include "c-incpath.h" |
0168a849 SS |
31 | #include "toplev.h" |
32 | #include "tm_p.h" | |
3dd53121 AP |
33 | #include "cppdefault.h" |
34 | #include "prefix.h" | |
0168a849 SS |
35 | |
36 | /* Pragmas. */ | |
37 | ||
38 | #define BAD(msgid) do { warning (msgid); return; } while (0) | |
39 | ||
94d1613b MS |
40 | static bool using_frameworks = false; |
41 | ||
0168a849 SS |
42 | /* Maintain a small stack of alignments. This is similar to pragma |
43 | pack's stack, but simpler. */ | |
44 | ||
9c808aad AJ |
45 | static void push_field_alignment (int); |
46 | static void pop_field_alignment (void); | |
94d1613b MS |
47 | static const char *find_subframework_file (const char *, const char *); |
48 | static void add_system_framework_path (char *); | |
e3c287c9 MS |
49 | static const char *find_subframework_header (cpp_reader *pfile, const char *header, |
50 | cpp_dir **dirp); | |
0168a849 SS |
51 | |
52 | typedef struct align_stack | |
53 | { | |
54 | int alignment; | |
55 | struct align_stack * prev; | |
56 | } align_stack; | |
57 | ||
58 | static struct align_stack * field_align_stack = NULL; | |
59 | ||
60 | static void | |
9c808aad | 61 | push_field_alignment (int bit_alignment) |
0168a849 SS |
62 | { |
63 | align_stack *entry = (align_stack *) xmalloc (sizeof (align_stack)); | |
64 | ||
65 | entry->alignment = maximum_field_alignment; | |
66 | entry->prev = field_align_stack; | |
67 | field_align_stack = entry; | |
68 | ||
69 | maximum_field_alignment = bit_alignment; | |
70 | } | |
71 | ||
72 | static void | |
9c808aad | 73 | pop_field_alignment (void) |
0168a849 SS |
74 | { |
75 | if (field_align_stack) | |
76 | { | |
77 | align_stack *entry = field_align_stack; | |
78 | ||
79 | maximum_field_alignment = entry->alignment; | |
80 | field_align_stack = entry->prev; | |
81 | free (entry); | |
82 | } | |
83 | else | |
84 | error ("too many #pragma options align=reset"); | |
85 | } | |
86 | ||
87 | /* Handlers for Darwin-specific pragmas. */ | |
88 | ||
89 | void | |
9c808aad | 90 | darwin_pragma_ignore (cpp_reader *pfile ATTRIBUTE_UNUSED) |
0168a849 SS |
91 | { |
92 | /* Do nothing. */ | |
93 | } | |
94 | ||
95 | /* #pragma options align={mac68k|power|reset} */ | |
96 | ||
97 | void | |
9c808aad | 98 | darwin_pragma_options (cpp_reader *pfile ATTRIBUTE_UNUSED) |
0168a849 | 99 | { |
7ae8cf75 | 100 | const char *arg; |
0168a849 SS |
101 | tree t, x; |
102 | ||
103 | if (c_lex (&t) != CPP_NAME) | |
104 | BAD ("malformed '#pragma options', ignoring"); | |
105 | arg = IDENTIFIER_POINTER (t); | |
106 | if (strcmp (arg, "align")) | |
107 | BAD ("malformed '#pragma options', ignoring"); | |
108 | if (c_lex (&t) != CPP_EQ) | |
109 | BAD ("malformed '#pragma options', ignoring"); | |
110 | if (c_lex (&t) != CPP_NAME) | |
111 | BAD ("malformed '#pragma options', ignoring"); | |
112 | ||
113 | if (c_lex (&x) != CPP_EOF) | |
114 | warning ("junk at end of '#pragma options'"); | |
115 | ||
116 | arg = IDENTIFIER_POINTER (t); | |
117 | if (!strcmp (arg, "mac68k")) | |
118 | push_field_alignment (16); | |
119 | else if (!strcmp (arg, "power")) | |
120 | push_field_alignment (0); | |
121 | else if (!strcmp (arg, "reset")) | |
122 | pop_field_alignment (); | |
123 | else | |
124 | warning ("malformed '#pragma options align={mac68k|power|reset}', ignoring"); | |
125 | } | |
126 | ||
127 | /* #pragma unused ([var {, var}*]) */ | |
128 | ||
129 | void | |
9c808aad | 130 | darwin_pragma_unused (cpp_reader *pfile ATTRIBUTE_UNUSED) |
0168a849 SS |
131 | { |
132 | tree decl, x; | |
133 | int tok; | |
134 | ||
135 | if (c_lex (&x) != CPP_OPEN_PAREN) | |
136 | BAD ("missing '(' after '#pragma unused', ignoring"); | |
137 | ||
138 | while (1) | |
139 | { | |
140 | tok = c_lex (&decl); | |
141 | if (tok == CPP_NAME && decl) | |
142 | { | |
43451169 | 143 | tree local = lookup_name (decl); |
0168a849 SS |
144 | if (local && (TREE_CODE (local) == PARM_DECL |
145 | || TREE_CODE (local) == VAR_DECL)) | |
146 | TREE_USED (local) = 1; | |
147 | tok = c_lex (&x); | |
148 | if (tok != CPP_COMMA) | |
149 | break; | |
150 | } | |
151 | } | |
152 | ||
153 | if (tok != CPP_CLOSE_PAREN) | |
154 | BAD ("missing ')' after '#pragma unused', ignoring"); | |
155 | ||
156 | if (c_lex (&x) != CPP_EOF) | |
157 | warning ("junk at end of '#pragma unused'"); | |
158 | } | |
94d1613b MS |
159 | |
160 | static struct { | |
161 | size_t len; | |
162 | const char *name; | |
163 | cpp_dir* dir; | |
164 | } *frameworks_in_use; | |
165 | static int num_frameworks = 0; | |
166 | static int max_frameworks = 0; | |
167 | ||
168 | ||
169 | /* Remember which frameworks have been seen, so that we can ensure | |
170 | that all uses of that framework come from the same framework. DIR | |
171 | is the place where the named framework NAME, which is of length | |
e3c287c9 MS |
172 | LEN, was found. We copy the directory name from NAME, as it will be |
173 | freed by others. */ | |
94d1613b MS |
174 | |
175 | static void | |
176 | add_framework (const char *name, size_t len, cpp_dir *dir) | |
177 | { | |
e3c287c9 | 178 | char *dir_name; |
94d1613b MS |
179 | int i; |
180 | for (i = 0; i < num_frameworks; ++i) | |
181 | { | |
182 | if (len == frameworks_in_use[i].len | |
183 | && strncmp (name, frameworks_in_use[i].name, len) == 0) | |
184 | { | |
185 | return; | |
186 | } | |
187 | } | |
188 | if (i >= max_frameworks) | |
189 | { | |
190 | max_frameworks = i*2; | |
e3c287c9 | 191 | max_frameworks += i == 0; |
94d1613b MS |
192 | frameworks_in_use = xrealloc (frameworks_in_use, |
193 | max_frameworks*sizeof(*frameworks_in_use)); | |
194 | } | |
e3c287c9 MS |
195 | dir_name = xmalloc (len + 1); |
196 | memcpy (dir_name, name, len); | |
197 | dir_name[len] = '\0'; | |
198 | frameworks_in_use[num_frameworks].name = dir_name; | |
94d1613b MS |
199 | frameworks_in_use[num_frameworks].len = len; |
200 | frameworks_in_use[num_frameworks].dir = dir; | |
201 | ++num_frameworks; | |
202 | } | |
203 | ||
204 | /* Recall if we have seen the named framework NAME, before, and where | |
205 | we saw it. NAME is LEN bytes long. The return value is the place | |
206 | where it was seen before. */ | |
207 | ||
208 | static struct cpp_dir* | |
209 | find_framework (const char *name, size_t len) | |
210 | { | |
211 | int i; | |
212 | for (i = 0; i < num_frameworks; ++i) | |
213 | { | |
214 | if (len == frameworks_in_use[i].len | |
215 | && strncmp (name, frameworks_in_use[i].name, len) == 0) | |
216 | { | |
217 | return frameworks_in_use[i].dir; | |
218 | } | |
219 | } | |
220 | return 0; | |
221 | } | |
222 | ||
223 | /* There are two directories in a framework that contain header files, | |
224 | Headers and PrivateHeaders. We search Headers first as it is more | |
225 | common to upgrade a header from PrivateHeaders to Headers and when | |
226 | that is done, the old one might hang around and be out of data, | |
227 | causing grief. */ | |
228 | ||
229 | struct framework_header {const char * dirName; int dirNameLen; }; | |
230 | static struct framework_header framework_header_dirs[] = { | |
231 | { "Headers", 7 }, | |
232 | { "PrivateHeaders", 14 }, | |
233 | { NULL, 0 } | |
234 | }; | |
235 | ||
236 | /* Returns a pointer to a malloced string that contains the real pathname | |
237 | to the file, given the base name and the name. */ | |
238 | ||
239 | static char * | |
240 | framework_construct_pathname (const char *fname, cpp_dir *dir) | |
241 | { | |
242 | char *buf; | |
243 | size_t fname_len, frname_len; | |
244 | cpp_dir *fast_dir; | |
245 | char *frname; | |
246 | struct stat st; | |
247 | int i; | |
248 | ||
249 | /* Framework names must have a / in them. */ | |
250 | buf = strchr (fname, '/'); | |
251 | if (buf) | |
252 | fname_len = buf - fname; | |
253 | else | |
254 | return 0; | |
255 | ||
256 | fast_dir = find_framework (fname, fname_len); | |
257 | ||
258 | /* Framework includes must all come from one framework. */ | |
259 | if (fast_dir && dir != fast_dir) | |
260 | return 0; | |
261 | ||
262 | frname = xmalloc (strlen (fname) + dir->len + 2 | |
263 | + strlen(".framework/") + strlen("PrivateHeaders")); | |
264 | strncpy (&frname[0], dir->name, dir->len); | |
265 | frname_len = dir->len; | |
266 | if (frname_len && frname[frname_len-1] != '/') | |
267 | frname[frname_len++] = '/'; | |
268 | strncpy (&frname[frname_len], fname, fname_len); | |
269 | frname_len += fname_len; | |
270 | strncpy (&frname[frname_len], ".framework/", strlen (".framework/")); | |
271 | frname_len += strlen (".framework/"); | |
272 | ||
a68bdb0b MS |
273 | if (fast_dir == 0) |
274 | { | |
275 | frname[frname_len-1] = 0; | |
276 | if (stat (frname, &st) == 0) | |
277 | { | |
278 | /* As soon as we find the first instance of the framework, | |
279 | we stop and never use any later instance of that | |
280 | framework. */ | |
281 | add_framework (fname, fname_len, dir); | |
282 | } | |
283 | else | |
284 | { | |
285 | /* If we can't find the parent directory, no point looking | |
286 | further. */ | |
287 | free (frname); | |
288 | return 0; | |
289 | } | |
290 | frname[frname_len-1] = '/'; | |
291 | } | |
292 | ||
94d1613b MS |
293 | /* Append framework_header_dirs and header file name */ |
294 | for (i = 0; framework_header_dirs[i].dirName; i++) | |
295 | { | |
296 | strncpy (&frname[frname_len], | |
297 | framework_header_dirs[i].dirName, | |
298 | framework_header_dirs[i].dirNameLen); | |
299 | strcpy (&frname[frname_len + framework_header_dirs[i].dirNameLen], | |
300 | &fname[fname_len]); | |
301 | ||
302 | if (stat (frname, &st) == 0) | |
a68bdb0b | 303 | return frname; |
94d1613b MS |
304 | } |
305 | ||
306 | free (frname); | |
307 | return 0; | |
308 | } | |
309 | ||
310 | /* Search for FNAME in sub-frameworks. pname is the context that we | |
311 | wish to search in. Return the path the file was found at, | |
312 | otherwise return 0. */ | |
313 | ||
314 | static const char* | |
315 | find_subframework_file (const char *fname, const char *pname) | |
316 | { | |
317 | char *sfrname; | |
318 | const char *dot_framework = ".framework/"; | |
319 | char *bufptr; | |
320 | int sfrname_len, i, fname_len; | |
321 | struct cpp_dir *fast_dir; | |
322 | static struct cpp_dir subframe_dir; | |
323 | struct stat st; | |
324 | ||
325 | bufptr = strchr (fname, '/'); | |
326 | ||
327 | /* Subframework files must have / in the name. */ | |
328 | if (bufptr == 0) | |
329 | return 0; | |
330 | ||
331 | fname_len = bufptr - fname; | |
332 | fast_dir = find_framework (fname, fname_len); | |
333 | ||
334 | /* Sub framework header filename includes parent framework name and | |
335 | header name in the "CarbonCore/OSUtils.h" form. If it does not | |
336 | include slash it is not a sub framework include. */ | |
337 | bufptr = strstr (pname, dot_framework); | |
338 | ||
339 | /* If the parent header is not of any framework, then this header | |
1e5f1716 | 340 | cannot be part of any subframework. */ |
94d1613b MS |
341 | if (!bufptr) |
342 | return 0; | |
343 | ||
344 | /* Now translate. For example, +- bufptr | |
345 | fname = CarbonCore/OSUtils.h | | |
346 | pname = /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h | |
347 | into | |
348 | sfrname = /System/Library/Frameworks/Foundation.framework/Frameworks/CarbonCore.framework/Headers/OSUtils.h */ | |
349 | ||
350 | sfrname = (char *) xmalloc (strlen (pname) + strlen (fname) + 2 + | |
351 | strlen ("Frameworks/") + strlen (".framework/") | |
352 | + strlen ("PrivateHeaders")); | |
353 | ||
354 | bufptr += strlen (dot_framework); | |
355 | ||
356 | sfrname_len = bufptr - pname; | |
357 | ||
358 | strncpy (&sfrname[0], pname, sfrname_len); | |
359 | ||
360 | strncpy (&sfrname[sfrname_len], "Frameworks/", strlen ("Frameworks/")); | |
361 | sfrname_len += strlen("Frameworks/"); | |
362 | ||
363 | strncpy (&sfrname[sfrname_len], fname, fname_len); | |
364 | sfrname_len += fname_len; | |
365 | ||
366 | strncpy (&sfrname[sfrname_len], ".framework/", strlen (".framework/")); | |
367 | sfrname_len += strlen (".framework/"); | |
368 | ||
369 | /* Append framework_header_dirs and header file name */ | |
370 | for (i = 0; framework_header_dirs[i].dirName; i++) | |
371 | { | |
372 | strncpy (&sfrname[sfrname_len], | |
373 | framework_header_dirs[i].dirName, | |
374 | framework_header_dirs[i].dirNameLen); | |
375 | strcpy (&sfrname[sfrname_len + framework_header_dirs[i].dirNameLen], | |
376 | &fname[fname_len]); | |
377 | ||
378 | if (stat (sfrname, &st) == 0) | |
379 | { | |
380 | if (fast_dir != &subframe_dir) | |
381 | { | |
382 | if (fast_dir) | |
383 | warning ("subframework include %s conflicts with framework include", | |
384 | fname); | |
385 | else | |
386 | add_framework (fname, fname_len, &subframe_dir); | |
387 | } | |
388 | ||
389 | return sfrname; | |
390 | } | |
391 | } | |
392 | free (sfrname); | |
393 | ||
394 | return 0; | |
395 | } | |
396 | ||
397 | /* Add PATH to the system includes. PATH must be malloc-ed and | |
398 | NUL-terminated. System framework paths are C++ aware. */ | |
399 | ||
400 | static void | |
401 | add_system_framework_path (char *path) | |
402 | { | |
403 | int cxx_aware = 1; | |
404 | cpp_dir *p; | |
405 | ||
406 | p = xmalloc (sizeof (cpp_dir)); | |
407 | p->next = NULL; | |
408 | p->name = path; | |
409 | p->sysp = 1 + !cxx_aware; | |
410 | p->construct = framework_construct_pathname; | |
411 | using_frameworks = 1; | |
412 | ||
413 | add_cpp_dir_path (p, SYSTEM); | |
414 | } | |
415 | ||
416 | /* Add PATH to the bracket includes. PATH must be malloc-ed and | |
417 | NUL-terminated. */ | |
418 | ||
419 | void | |
420 | add_framework_path (char *path) | |
421 | { | |
422 | cpp_dir *p; | |
423 | ||
424 | p = xmalloc (sizeof (cpp_dir)); | |
425 | p->next = NULL; | |
426 | p->name = path; | |
427 | p->sysp = 0; | |
428 | p->construct = framework_construct_pathname; | |
429 | using_frameworks = 1; | |
430 | ||
431 | add_cpp_dir_path (p, BRACKET); | |
432 | } | |
433 | ||
434 | static const char *framework_defaults [] = | |
435 | { | |
436 | "/System/Library/Frameworks", | |
437 | "/Library/Frameworks", | |
94d1613b MS |
438 | }; |
439 | ||
3dd53121 AP |
440 | /* Register the GNU objective-C runtime include path if STDINC. */ |
441 | ||
442 | void | |
443 | darwin_register_objc_includes (const char *sysroot, const char *iprefix, | |
444 | int stdinc) | |
445 | { | |
446 | const char *fname; | |
447 | size_t len; | |
448 | /* We do not do anything if we do not want the standard includes. */ | |
449 | if (!stdinc) | |
450 | return; | |
451 | ||
452 | fname = GCC_INCLUDE_DIR "-gnu-runtime"; | |
453 | ||
454 | /* Register the GNU OBJC runtime include path if we are compiling OBJC | |
455 | with GNU-runtime. */ | |
456 | ||
457 | if (c_dialect_objc () && !flag_next_runtime) | |
458 | { | |
459 | char *str; | |
460 | /* See if our directory starts with the standard prefix. | |
112cdef5 | 461 | "Translate" them, i.e. replace /usr/local/lib/gcc... with |
3dd53121 AP |
462 | IPREFIX and search them first. */ |
463 | if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0 && !sysroot | |
464 | && !strncmp (fname, cpp_GCC_INCLUDE_DIR, len)) | |
465 | { | |
466 | str = concat (iprefix, fname + len, NULL); | |
467 | /* FIXME: wrap the headers for C++awareness. */ | |
468 | add_path (str, SYSTEM, /*c++aware=*/false, false); | |
469 | } | |
470 | ||
471 | /* Should this directory start with the sysroot? */ | |
472 | if (sysroot) | |
473 | str = concat (sysroot, fname, NULL); | |
474 | else | |
475 | str = update_path (fname, ""); | |
476 | ||
477 | add_path (str, SYSTEM, /*c++aware=*/false, false); | |
478 | } | |
479 | } | |
480 | ||
94d1613b MS |
481 | |
482 | /* Register all the system framework paths if STDINC is true and setup | |
483 | the missing_header callback for subframework searching if any | |
484 | frameworks had been registered. */ | |
485 | ||
486 | void | |
479ec1d1 | 487 | darwin_register_frameworks (const char *sysroot, |
3dd53121 | 488 | const char *iprefix ATTRIBUTE_UNUSED, int stdinc) |
94d1613b MS |
489 | { |
490 | if (stdinc) | |
491 | { | |
492 | size_t i; | |
493 | ||
494 | /* Setup default search path for frameworks. */ | |
495 | for (i=0; i<sizeof (framework_defaults)/sizeof(const char *); ++i) | |
496 | { | |
479ec1d1 DP |
497 | char *str; |
498 | if (sysroot) | |
499 | str = concat (sysroot, xstrdup (framework_defaults [i]), NULL); | |
500 | else | |
501 | str = xstrdup (framework_defaults[i]); | |
94d1613b | 502 | /* System Framework headers are cxx aware. */ |
479ec1d1 | 503 | add_system_framework_path (str); |
94d1613b MS |
504 | } |
505 | } | |
506 | ||
507 | if (using_frameworks) | |
508 | cpp_get_callbacks (parse_in)->missing_header = find_subframework_header; | |
509 | } | |
510 | ||
511 | /* Search for HEADER in context dependent way. The return value is | |
512 | the malloced name of a header to try and open, if any, or NULL | |
513 | otherwise. This is called after normal header lookup processing | |
514 | fails to find a header. We search each file in the include stack, | |
515 | using FUNC, starting from the most deeply nested include and | |
516 | finishing with the main input file. We stop searching when FUNC | |
0e40b5f2 | 517 | returns nonzero. */ |
94d1613b MS |
518 | |
519 | static const char* | |
e3c287c9 | 520 | find_subframework_header (cpp_reader *pfile, const char *header, cpp_dir **dirp) |
94d1613b MS |
521 | { |
522 | const char *fname = header; | |
523 | struct cpp_buffer *b; | |
524 | const char *n; | |
525 | ||
526 | for (b = cpp_get_buffer (pfile); | |
527 | b && cpp_get_file (b) && cpp_get_path (cpp_get_file (b)); | |
528 | b = cpp_get_prev (b)) | |
529 | { | |
530 | n = find_subframework_file (fname, cpp_get_path (cpp_get_file (b))); | |
531 | if (n) | |
e3c287c9 MS |
532 | { |
533 | /* Logically, the place where we found the subframework is | |
534 | the place where we found the Framework that contains the | |
535 | subframework. This is useful for tracking wether or not | |
536 | we are in a system header. */ | |
537 | *dirp = cpp_get_dir (cpp_get_file (b)); | |
538 | return n; | |
539 | } | |
94d1613b MS |
540 | } |
541 | ||
542 | return 0; | |
543 | } |