#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "cpplib.h"
#include "tree.h"
#include "c-pragma.h"
#include "c-tree.h"
#include "c-incpath.h"
#include "toplev.h"
#include "tm_p.h"
#include "cppdefault.h"
#include "prefix.h"
#define BAD(msgid) do { warning (msgid); return; } while (0)
static bool using_frameworks = false;
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,
cpp_dir **dirp);
typedef struct align_stack
{
int alignment;
struct align_stack * prev;
} align_stack;
static struct align_stack * field_align_stack = NULL;
static void
push_field_alignment (int bit_alignment)
{
align_stack *entry = (align_stack *) xmalloc (sizeof (align_stack));
entry->alignment = maximum_field_alignment;
entry->prev = field_align_stack;
field_align_stack = entry;
maximum_field_alignment = bit_alignment;
}
static void
pop_field_alignment (void)
{
if (field_align_stack)
{
align_stack *entry = field_align_stack;
maximum_field_alignment = entry->alignment;
field_align_stack = entry->prev;
free (entry);
}
else
error ("too many #pragma options align=reset");
}
void
darwin_pragma_ignore (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
}
void
darwin_pragma_options (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
const char *arg;
tree t, x;
if (c_lex (&t) != CPP_NAME)
BAD ("malformed '#pragma options', ignoring");
arg = IDENTIFIER_POINTER (t);
if (strcmp (arg, "align"))
BAD ("malformed '#pragma options', ignoring");
if (c_lex (&t) != CPP_EQ)
BAD ("malformed '#pragma options', ignoring");
if (c_lex (&t) != CPP_NAME)
BAD ("malformed '#pragma options', ignoring");
if (c_lex (&x) != CPP_EOF)
warning ("junk at end of '#pragma options'");
arg = IDENTIFIER_POINTER (t);
if (!strcmp (arg, "mac68k"))
push_field_alignment (16);
else if (!strcmp (arg, "power"))
push_field_alignment (0);
else if (!strcmp (arg, "reset"))
pop_field_alignment ();
else
warning ("malformed '#pragma options align={mac68k|power|reset}', ignoring");
}
void
darwin_pragma_unused (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
tree decl, x;
int tok;
if (c_lex (&x) != CPP_OPEN_PAREN)
BAD ("missing '(' after '#pragma unused', ignoring");
while (1)
{
tok = c_lex (&decl);
if (tok == CPP_NAME && decl)
{
tree local = lookup_name (decl);
if (local && (TREE_CODE (local) == PARM_DECL
|| TREE_CODE (local) == VAR_DECL))
TREE_USED (local) = 1;
tok = c_lex (&x);
if (tok != CPP_COMMA)
break;
}
}
if (tok != CPP_CLOSE_PAREN)
BAD ("missing ')' after '#pragma unused', ignoring");
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;
static void
add_framework (const char *name, size_t len, cpp_dir *dir)
{
char *dir_name;
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;
max_frameworks += i == 0;
frameworks_in_use = xrealloc (frameworks_in_use,
max_frameworks*sizeof(*frameworks_in_use));
}
dir_name = xmalloc (len + 1);
memcpy (dir_name, name, len);
dir_name[len] = '\0';
frameworks_in_use[num_frameworks].name = dir_name;
frameworks_in_use[num_frameworks].len = len;
frameworks_in_use[num_frameworks].dir = dir;
++num_frameworks;
}
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;
}
struct framework_header {const char * dirName; int dirNameLen; };
static struct framework_header framework_header_dirs[] = {
{ "Headers", 7 },
{ "PrivateHeaders", 14 },
{ NULL, 0 }
};
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;
buf = strchr (fname, '/');
if (buf)
fname_len = buf - fname;
else
return 0;
fast_dir = find_framework (fname, fname_len);
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/");
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)
{
if (fast_dir == 0)
add_framework (fname, fname_len, dir);
return frname;
}
}
free (frname);
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, '/');
if (bufptr == 0)
return 0;
fname_len = bufptr - fname;
fast_dir = find_framework (fname, fname_len);
bufptr = strstr (pname, dot_framework);
if (!bufptr)
return 0;
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/");
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;
}
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);
}
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",
};
void
darwin_register_objc_includes (const char *sysroot, const char *iprefix,
int stdinc)
{
const char *fname;
size_t len;
if (!stdinc)
return;
fname = GCC_INCLUDE_DIR "-gnu-runtime";
if (c_dialect_objc () && !flag_next_runtime)
{
char *str;
if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0 && !sysroot
&& !strncmp (fname, cpp_GCC_INCLUDE_DIR, len))
{
str = concat (iprefix, fname + len, NULL);
add_path (str, SYSTEM, false, false);
}
if (sysroot)
str = concat (sysroot, fname, NULL);
else
str = update_path (fname, "");
add_path (str, SYSTEM, false, false);
}
}
void
darwin_register_frameworks (const char *sysroot,
const char *iprefix ATTRIBUTE_UNUSED, int stdinc)
{
if (stdinc)
{
size_t i;
for (i=0; i<sizeof (framework_defaults)/sizeof(const char *); ++i)
{
char *str;
if (sysroot)
str = concat (sysroot, xstrdup (framework_defaults [i]), NULL);
else
str = xstrdup (framework_defaults[i]);
add_system_framework_path (str);
}
}
if (using_frameworks)
cpp_get_callbacks (parse_in)->missing_header = find_subframework_header;
}
static const char*
find_subframework_header (cpp_reader *pfile, const char *header, cpp_dir **dirp)
{
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)
{
*dirp = cpp_get_dir (cpp_get_file (b));
return n;
}
}
return 0;
}