#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 "c-common.h"
#include "toplev.h"
#include "flags.h"
#include "tm_p.h"
#include "cppdefault.h"
#include "prefix.h"
#include "options.h"
#include "flags.h"
#include "opts.h"
#include "varray.h"
#define BAD(gmsgid) do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
#define BAD2(msgid, arg) do { warning (OPT_Wpragmas, msgid, arg); return; } while (0)
static bool using_frameworks = false;
static void push_field_alignment (int, int, int);
static void pop_field_alignment (void);
static const char *find_subframework_file (const char *, const char *);
static const char *find_subframework_header (cpp_reader *pfile, const char *header,
cpp_dir **dirp);
typedef struct align_stack
{
int alignment;
unsigned long mac68k;
unsigned long natural;
struct align_stack * prev;
} align_stack;
static struct align_stack * field_align_stack = NULL;
static void
push_field_alignment (int bit_alignment,
int mac68k_alignment, int natural_alignment)
{
align_stack *entry = XNEW (align_stack);
entry->alignment = maximum_field_alignment;
entry->mac68k = OPTION_ALIGN_MAC68K;
entry->natural = OPTION_ALIGN_NATURAL;
entry->prev = field_align_stack;
field_align_stack = entry;
maximum_field_alignment = bit_alignment;
if (mac68k_alignment)
darwin_alignment_flags |= OPTION_MASK_ALIGN_MAC68K;
else
darwin_alignment_flags &= ~OPTION_MASK_ALIGN_MAC68K;
if (natural_alignment == 1)
darwin_alignment_flags |= OPTION_MASK_ALIGN_NATURAL;
else if (natural_alignment == 0)
darwin_alignment_flags &= ~OPTION_MASK_ALIGN_NATURAL;
}
static void
pop_field_alignment (void)
{
if (field_align_stack)
{
align_stack *entry = field_align_stack;
maximum_field_alignment = entry->alignment;
if (entry->mac68k)
darwin_alignment_flags |= OPTION_MASK_ALIGN_MAC68K;
else
darwin_alignment_flags &= ~OPTION_MASK_ALIGN_MAC68K;
if (entry->natural)
darwin_alignment_flags |= OPTION_MASK_ALIGN_NATURAL;
else
darwin_alignment_flags &= ~OPTION_MASK_ALIGN_NATURAL;
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_fenv (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
flag_trapping_math = 1;
}
void
darwin_pragma_options (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
const char *arg;
tree t, x;
if (pragma_lex (&t) != CPP_NAME)
BAD ("malformed '#pragma options', ignoring");
arg = IDENTIFIER_POINTER (t);
if (strcmp (arg, "align"))
BAD ("malformed '#pragma options', ignoring");
if (pragma_lex (&t) != CPP_EQ)
BAD ("malformed '#pragma options', ignoring");
if (pragma_lex (&t) != CPP_NAME)
BAD ("malformed '#pragma options', ignoring");
if (pragma_lex (&x) != CPP_EOF)
warning (OPT_Wpragmas, "junk at end of '#pragma options'");
arg = IDENTIFIER_POINTER (t);
if (!strcmp (arg, "mac68k"))
{
if (POINTER_SIZE == 64)
warning (OPT_Wpragmas, "mac68k alignment pragma is deprecated for 64-bit Darwin");
push_field_alignment (0, 1, 0);
}
else if (!strcmp (arg, "native"))
push_field_alignment (0, 0, 0);
else if (!strcmp (arg, "natural"))
push_field_alignment (0, 0, 1);
else if (!strcmp (arg, "packed"))
push_field_alignment (8, 0, 0);
else if (!strcmp (arg, "power"))
push_field_alignment (0, 0, 0);
else if (!strcmp (arg, "reset"))
pop_field_alignment ();
else
BAD ("malformed '#pragma options align={mac68k|power|natural|reset}', ignoring");
}
void
darwin_pragma_pack (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
tree x, id = 0;
int align = -1;
enum cpp_ttype token;
enum { set, push, pop } action;
if (pragma_lex (&x) != CPP_OPEN_PAREN)
BAD ("missing '(' after '#pragma pack' - ignored");
token = pragma_lex (&x);
if (token == CPP_CLOSE_PAREN)
{
action = pop;
align = 0;
}
else if (token == CPP_NUMBER)
{
if (TREE_CODE (x) != INTEGER_CST)
BAD ("invalid constant in %<#pragma pack%> - ignored");
align = TREE_INT_CST_LOW (x);
action = push;
if (pragma_lex (&x) != CPP_CLOSE_PAREN)
BAD ("malformed '#pragma pack' - ignored");
}
else if (token == CPP_NAME)
{
#define GCC_BAD_ACTION do { if (action == push) \
BAD ("malformed '#pragma pack(push[, id], <n>)' - ignored"); \
else \
BAD ("malformed '#pragma pack(pop[, id])' - ignored"); \
} while (0)
const char *op = IDENTIFIER_POINTER (x);
if (!strcmp (op, "push"))
action = push;
else if (!strcmp (op, "pop"))
action = pop;
else
BAD2 ("unknown action '%s' for '#pragma pack' - ignored", op);
while ((token = pragma_lex (&x)) == CPP_COMMA)
{
token = pragma_lex (&x);
if (token == CPP_NAME && id == 0)
{
id = x;
}
else if (token == CPP_NUMBER && action == push && align == -1)
{
if (TREE_CODE (x) != INTEGER_CST)
BAD ("invalid constant in %<#pragma pack%> - ignored");
align = TREE_INT_CST_LOW (x);
if (align == -1)
action = set;
}
else
GCC_BAD_ACTION;
}
if (token != CPP_CLOSE_PAREN)
GCC_BAD_ACTION;
#undef GCC_BAD_ACTION
}
else
BAD ("malformed '#pragma pack' - ignored");
if (pragma_lex (&x) != CPP_EOF)
warning (OPT_Wpragmas, "junk at end of '#pragma pack'");
if (action != pop)
{
switch (align)
{
case 0:
case 1:
case 2:
case 4:
case 8:
case 16:
align *= BITS_PER_UNIT;
break;
case -1:
if (action == push)
{
align = maximum_field_alignment;
break;
}
default:
BAD2 ("alignment must be a small power of two, not %d", align);
}
}
switch (action)
{
case pop: pop_field_alignment (); break;
case push: push_field_alignment (align, 0, 2); break;
case set: break;
}
}
void
darwin_pragma_unused (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
tree decl, x;
int tok;
if ((tok=pragma_lex (&x)) != CPP_OPEN_PAREN)
BAD ("missing '(' after '#pragma unused', ignoring");
while (tok != CPP_EOF && tok != CPP_CLOSE_PAREN)
{
tok = pragma_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 = pragma_lex (&x);
if (tok != CPP_COMMA)
break;
}
}
if (tok != CPP_CLOSE_PAREN)
BAD ("missing ')' after '#pragma unused', ignoring");
if (pragma_lex (&x) != CPP_EOF)
BAD ("junk at end of '#pragma unused'");
}
void
darwin_pragma_ms_struct (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
const char *arg;
tree t;
if (pragma_lex (&t) != CPP_NAME)
BAD ("malformed '#pragma ms_struct', ignoring");
arg = IDENTIFIER_POINTER (t);
if (!strcmp (arg, "on"))
darwin_ms_struct = true;
else if (!strcmp (arg, "off") || !strcmp (arg, "reset"))
darwin_ms_struct = false;
else
BAD ("malformed '#pragma ms_struct {on|off|reset}', ignoring");
if (pragma_lex (&t) != CPP_EOF)
BAD ("junk at end of '#pragma ms_struct'");
}
void
darwin_pragma_reverse_bitfields (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
const char* arg;
tree t;
if (pragma_lex (&t) != CPP_NAME)
BAD ("malformed '#pragma reverse_bitfields', ignoring");
arg = IDENTIFIER_POINTER (t);
if (!strcmp (arg, "on"))
darwin_reverse_bitfields = true;
else if (!strcmp (arg, "off") || !strcmp (arg, "reset"))
darwin_reverse_bitfields = false;
else
BAD ("malformed '#pragma reverse_bitfields {on|off|reset}', ignoring");
if (pragma_lex (&t) != CPP_EOF)
BAD ("junk at end of '#pragma reverse_bitfields'");
}
varray_type va_opt;
static void
push_opt_level (int level, int size)
{
if (!va_opt)
VARRAY_INT_INIT (va_opt, 5, "va_opt");
VARRAY_PUSH_INT (va_opt, size << 16 | level);
}
static void
pop_opt_level (void)
{
int level;
if (!va_opt)
VARRAY_INT_INIT (va_opt, 5, "va_opt");
if (!VARRAY_ACTIVE_SIZE (va_opt))
BAD ("optimization pragma stack underflow");
level = VARRAY_TOP_INT (va_opt);
VARRAY_POP (va_opt);
optimize_size = level >> 16;
optimize = level & 0xffff;
}
static void darwin_set_flags_from_pragma (void)
{
set_flags_from_O (false);
#if 0
if (flag_move_loop_invariants
|| flag_unswitch_loops
|| flag_peel_loops
|| flag_unroll_loops
|| flag_branch_on_count_reg)
flag_loop_optimize2 = 1;
#endif
reset_optimization_options (optimize, optimize_size);
if (align_loops <= 0) align_loops = 1;
if (align_loops_max_skip > align_loops || !align_loops)
align_loops_max_skip = align_loops - 1;
if (align_jumps <= 0) align_jumps = 1;
if (align_jumps_max_skip > align_jumps || !align_jumps)
align_jumps_max_skip = align_jumps - 1;
if (align_labels <= 0) align_labels = 1;
}
void
darwin_pragma_opt_level (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
tree t;
enum cpp_ttype argtype = pragma_lex (&t);
if (argtype == CPP_NAME)
{
const char* arg = IDENTIFIER_POINTER (t);
if (strcmp (arg, "reset") != 0)
BAD ("malformed '#pragma optimization_level [GCC] {0|1|2|3|reset}', ignoring");
pop_opt_level ();
}
else if (argtype == CPP_NUMBER)
{
if (TREE_CODE (t) != INTEGER_CST
|| INT_CST_LT (t, integer_zero_node)
|| TREE_INT_CST_HIGH (t) != 0)
BAD ("malformed '#pragma optimization_level [GCC] {0|1|2|3|reset}', ignoring");
push_opt_level (optimize, optimize_size);
optimize = TREE_INT_CST_LOW (t);
if (optimize > 3)
optimize = 3;
optimize_size = 0;
}
else
BAD ("malformed '#pragma optimization_level [GCC] {0|1|2|3|reset}', ignoring");
darwin_set_flags_from_pragma ();
if (pragma_lex (&t) != CPP_EOF)
BAD ("junk at end of '#pragma optimization_level'");
}
void
darwin_pragma_opt_size (cpp_reader *pfile ATTRIBUTE_UNUSED)
{
const char* arg;
tree t;
if (pragma_lex (&t) != CPP_NAME)
BAD ("malformed '#pragma optimize_for_size { on | off | reset}', ignoring");
arg = IDENTIFIER_POINTER (t);
if (!strcmp (arg, "on"))
{
push_opt_level (optimize, optimize_size);
optimize_size = 1;
optimize = 2;
}
else if (!strcmp (arg, "off"))
optimize_size = 0;
else if (!strcmp (arg, "reset"))
pop_opt_level ();
else
BAD ("malformed '#pragma optimize_for_size { on | off | reset }', ignoring");
darwin_set_flags_from_pragma ();
if (pragma_lex (&t) != CPP_EOF)
BAD ("junk at end of '#pragma optimize_for_size'");
}
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 = XNEWVEC (char, 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 = XNEWVEC (char, 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/");
if (fast_dir == 0)
{
frname[frname_len-1] = 0;
if (stat (frname, &st) == 0)
{
add_framework (fname, fname_len, dir);
}
else
{
free (frname);
return 0;
}
frname[frname_len-1] = '/';
}
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)
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 = XNEWVEC (char, 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 (0, "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 = XNEW (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 = XNEW (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;
}
static const char *
macosx_version_as_macro (void)
{
static char result[] = "1000";
if (strncmp (darwin_macosx_version_min, "10.", 3) != 0)
goto fail;
if (! ISDIGIT (darwin_macosx_version_min[3]))
goto fail;
result[2] = darwin_macosx_version_min[3];
if (darwin_macosx_version_min[4] != '\0')
{
if (darwin_macosx_version_min[4] != '.')
goto fail;
if (! ISDIGIT (darwin_macosx_version_min[5]))
goto fail;
if (darwin_macosx_version_min[6] != '\0')
goto fail;
result[3] = darwin_macosx_version_min[5];
}
else
result[3] = '0';
return result;
fail:
error ("Unknown value %qs of -mmacosx-version-min",
darwin_macosx_version_min);
return "1000";
}
static const char *
iphoneos_version_as_macro (void)
{
static char result[sizeof ("99.99.99") + 1];
const char *src_ptr = darwin_iphoneos_version_min;
char *result_ptr = &result[0];
if (! darwin_iphoneos_version_min)
goto fail;
if (! ISDIGIT (*src_ptr))
goto fail;
*result_ptr++ = *src_ptr++;
if (ISDIGIT (*src_ptr))
*result_ptr++ = *src_ptr++;
if (*src_ptr != '.')
goto fail;
src_ptr++;
if (! ISDIGIT (*src_ptr))
goto fail;
*result_ptr++ = ISDIGIT (*(src_ptr + 1)) ? *src_ptr++ : '0';
*result_ptr++ = *src_ptr++;
if (*src_ptr == '\0')
{
*result_ptr++ = '0';
*result_ptr++ = '0';
}
else if (*src_ptr == '.')
{
src_ptr++;
if (! ISDIGIT (*src_ptr))
goto fail;
*result_ptr++ = ISDIGIT (*(src_ptr + 1)) ? *src_ptr++ : '0';
*result_ptr++ = *src_ptr++;
}
else
goto fail;
if (*src_ptr != '\0')
goto fail;
*result_ptr++ = '\0';
return result;
fail:
error ("Unknown value %qs of -miphoneos-version-min",
darwin_iphoneos_version_min);
return "10200";
}
#define builtin_define(TXT) cpp_define (pfile, TXT)
void
darwin_cpp_builtins (cpp_reader *pfile)
{
builtin_define ("__MACH__");
builtin_define ("__APPLE__");
if (darwin_macosx_version_min)
builtin_define_with_value ("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__",
macosx_version_as_macro(), false);
else
builtin_define_with_value ("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
iphoneos_version_as_macro(), false);
if (darwin_constant_cfstrings)
builtin_define ("__CONSTANT_CFSTRINGS__");
if (darwin_pascal_strings)
{
builtin_define ("__PASCAL_STRINGS__");
}
if (flag_objc_gc || flag_objc_gc_only)
{
builtin_define ("__strong=__attribute__((objc_gc(strong)))");
builtin_define ("__weak=__attribute__((objc_gc(weak)))");
builtin_define ("__OBJC_GC__");
}
else
{
builtin_define ("__strong=");
builtin_define ("__weak=__attribute__((objc_gc(weak)))");
}
if (flag_blocks) {
builtin_define ("__block=__attribute__((__blocks__(byref)))");
}
if (flag_objc_abi == 2)
builtin_define ("__OBJC2__");
if (flag_objc_zerocost_exceptions)
builtin_define ("OBJC_ZEROCOST_EXCEPTIONS");
builtin_define ("OBJC_NEW_PROPERTIES");
}
bool
darwin_handle_c_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
{
switch (code)
{
default:
if (cl_options[code].flag_var)
break;
return false;
case OPT_iframework:
add_system_framework_path (xstrdup (arg));
break;
}
return true;
}
bool
objc_check_cfstringref_type (tree type)
{
tree CFStringRef_decl = lookup_name (get_identifier ("CFStringRef"));
if (!CFStringRef_decl || TREE_CODE (CFStringRef_decl) != TYPE_DECL)
return false;
return type == TREE_TYPE (CFStringRef_decl);
}
bool
objc_check_format_cfstring (tree argument,
unsigned HOST_WIDE_INT format_num,
bool *no_add_attrs)
{
unsigned HOST_WIDE_INT i;
if (format_num < 1)
{
error ("argument number of CFString format cannot be less than one");
return false;
}
for (i = 1; i != format_num; i++)
{
if (argument == 0)
break;
argument = TREE_CHAIN (argument);
}
if (!objc_check_cfstringref_type (TREE_VALUE (argument)))
{
error ("format CFString argument not an 'CFStringRef' type");
*no_add_attrs = true;
return false;
}
return true;
}
bool
cvt_utf8_utf16 (const unsigned char *inbuf, size_t length,
unsigned char **uniCharBuf, size_t *numUniChars)
{
return cpp_utf8_utf16 (parse_in, inbuf, length, uniCharBuf, numUniChars);
}
tree
create_init_utf16_var (const unsigned char *inbuf, size_t length, size_t *numUniChars)
{
size_t l;
tree decl, type, init;
tree initlist = NULL_TREE;
tree attribute;
const char *section_name = "__TEXT,__ustring";
int len = strlen (section_name);
unsigned char *uniCharBuf;
static int num;
const char *name_prefix = "__utf16_string_";
char *name;
if (!cvt_utf8_utf16 (inbuf, length, &uniCharBuf, numUniChars))
return NULL_TREE;
for (l = 0; l < *numUniChars; l++)
initlist = tree_cons (NULL_TREE, build_int_cst (char_type_node, uniCharBuf[l]), initlist);
type = build_array_type (char_type_node,
build_index_type (build_int_cst (NULL_TREE, *numUniChars)));
name = (char *)alloca (strlen (name_prefix) + 10);
sprintf (name, "%s%d", name_prefix, ++num);
decl = build_decl (VAR_DECL, get_identifier (name), type);
TREE_STATIC (decl) = 1;
DECL_INITIAL (decl) = error_mark_node;
DECL_IGNORED_P (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_CONTEXT (decl) = NULL_TREE;
attribute = tree_cons (NULL_TREE, build_string (len, section_name), NULL_TREE);
attribute = tree_cons (get_identifier ("section"), attribute, NULL_TREE);
decl_attributes (&decl, attribute, 0);
attribute = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 2), NULL_TREE);
attribute = tree_cons (get_identifier ("aligned"), attribute, NULL_TREE);
decl_attributes (&decl, attribute, 0);
init = build_constructor_from_list (type, nreverse (initlist));
TREE_CONSTANT (init) = 1;
TREE_STATIC (init) = 1;
TREE_READONLY (init) = 1;
if (c_dialect_cxx ())
TREE_TYPE (init) = NULL_TREE;
finish_decl (decl, init, NULL_TREE);
mark_decl_referenced (decl);
TREE_USED (decl) = 1;
return decl;
}