f12c30a8f1
From-SVN: r101309
219 lines
6.0 KiB
C
219 lines
6.0 KiB
C
/* Shared functions related to mangling names for the GNU compiler
|
|
for the Java(TM) language.
|
|
Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
any later version.
|
|
|
|
GCC is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING. If not, write to
|
|
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
Java and all Java-based marks are trademarks or registered trademarks
|
|
of Sun Microsystems, Inc. in the United States and other countries.
|
|
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
|
|
|
/* Written by Alexandre Petit-Bianco <apbianco@cygnus.com> */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "tm.h"
|
|
#include "jcf.h"
|
|
#include "tree.h"
|
|
#include "java-tree.h"
|
|
#include "obstack.h"
|
|
#include "toplev.h"
|
|
|
|
static void append_unicode_mangled_name (const char *, int);
|
|
#ifndef HAVE_AS_UTF8
|
|
static int unicode_mangling_length (const char *, int);
|
|
#endif
|
|
|
|
extern struct obstack *mangle_obstack;
|
|
|
|
/* If the assembler doesn't support UTF8 in symbol names, some
|
|
characters might need to be escaped. */
|
|
|
|
#ifndef HAVE_AS_UTF8
|
|
|
|
/* Assuming (NAME, LEN) is a Utf8-encoding string, emit the string
|
|
appropriately mangled (with Unicode escapes if needed) to
|
|
MANGLE_OBSTACK. Note that `java', `lang' and `Object' are used so
|
|
frequently that they could be cached. */
|
|
|
|
void
|
|
append_gpp_mangled_name (const char *name, int len)
|
|
{
|
|
int encoded_len = unicode_mangling_length (name, len);
|
|
int needs_escapes = encoded_len > 0;
|
|
char buf[6];
|
|
|
|
sprintf (buf, "%d", (needs_escapes ? encoded_len : len));
|
|
obstack_grow (mangle_obstack, buf, strlen (buf));
|
|
|
|
if (needs_escapes)
|
|
append_unicode_mangled_name (name, len);
|
|
else
|
|
obstack_grow (mangle_obstack, name, len);
|
|
}
|
|
|
|
/* Assuming (NAME, LEN) is a Utf8-encoded string, emit the string
|
|
appropriately mangled (with Unicode escapes) to MANGLE_OBSTACK.
|
|
Characters needing an escape are encoded `__UNN_' to `__UNNNN_', in
|
|
which case `__U' will be mangled `__U_'. */
|
|
|
|
static void
|
|
append_unicode_mangled_name (const char *name, int len)
|
|
{
|
|
const unsigned char *ptr;
|
|
const unsigned char *limit = (const unsigned char *)name + len;
|
|
int uuU = 0;
|
|
for (ptr = (const unsigned char *) name; ptr < limit; )
|
|
{
|
|
int ch = UTF8_GET(ptr, limit);
|
|
|
|
if ((ISALNUM (ch) && ch != 'U') || ch == '$')
|
|
obstack_1grow (mangle_obstack, ch);
|
|
/* Everything else needs encoding */
|
|
else
|
|
{
|
|
char buf [9];
|
|
if (ch == '_' || ch == 'U')
|
|
{
|
|
/* Prepare to recognize __U */
|
|
if (ch == '_' && (uuU < 3))
|
|
{
|
|
uuU++;
|
|
obstack_1grow (mangle_obstack, ch);
|
|
}
|
|
/* We recognize __U that we wish to encode
|
|
__U_. Finish the encoding. */
|
|
else if (ch == 'U' && (uuU == 2))
|
|
{
|
|
uuU = 0;
|
|
obstack_grow (mangle_obstack, "U_", 2);
|
|
}
|
|
/* Otherwise, just reset uuU and emit the character we
|
|
have. */
|
|
else
|
|
{
|
|
uuU = 0;
|
|
obstack_1grow (mangle_obstack, ch);
|
|
}
|
|
continue;
|
|
}
|
|
sprintf (buf, "__U%x_", ch);
|
|
obstack_grow (mangle_obstack, buf, strlen (buf));
|
|
uuU = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Assuming (NAME, LEN) is a Utf8-encoding string, calculate the
|
|
length of the string as mangled (a la g++) including Unicode
|
|
escapes. If no escapes are needed, return 0. */
|
|
|
|
static int
|
|
unicode_mangling_length (const char *name, int len)
|
|
{
|
|
const unsigned char *ptr;
|
|
const unsigned char *limit = (const unsigned char *)name + len;
|
|
int need_escapes = 0; /* Whether we need an escape or not */
|
|
int num_chars = 0; /* Number of characters in the mangled name */
|
|
int uuU = 0; /* Help us to find __U. 0: '_', 1: '__' */
|
|
for (ptr = (const unsigned char *) name; ptr < limit; )
|
|
{
|
|
int ch = UTF8_GET(ptr, limit);
|
|
|
|
if (ch < 0)
|
|
error ("internal error - invalid Utf8 name");
|
|
if ((ISALNUM (ch) && ch != 'U') || ch == '$')
|
|
num_chars++;
|
|
/* Everything else needs encoding */
|
|
else
|
|
{
|
|
int encoding_length = 2;
|
|
|
|
if (ch == '_' || ch == 'U')
|
|
{
|
|
/* It's always at least one character. */
|
|
num_chars++;
|
|
|
|
/* Prepare to recognize __U */
|
|
if (ch == '_' && (uuU < 3))
|
|
uuU++;
|
|
|
|
/* We recognize __U that we wish to encode __U_, we
|
|
count one more character. */
|
|
else if (ch == 'U' && (uuU == 2))
|
|
{
|
|
num_chars++;
|
|
need_escapes = 1;
|
|
uuU = 0;
|
|
}
|
|
/* Otherwise, just reset uuU */
|
|
else
|
|
uuU = 0;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (ch > 0xff)
|
|
encoding_length++;
|
|
if (ch > 0xfff)
|
|
encoding_length++;
|
|
|
|
num_chars += (4 + encoding_length);
|
|
need_escapes = 1;
|
|
uuU = 0;
|
|
}
|
|
}
|
|
if (need_escapes)
|
|
return num_chars;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
|
|
/* The assembler supports UTF8, we don't use escapes. Mangling is
|
|
simply <N>NAME. <N> is the number of UTF8 encoded characters that
|
|
are found in NAME. Note that `java', `lang' and `Object' are used
|
|
so frequently that they could be cached. */
|
|
|
|
void
|
|
append_gpp_mangled_name (const char *name, int len)
|
|
{
|
|
const unsigned char *ptr;
|
|
const unsigned char *limit = (const unsigned char *)name + len;
|
|
int encoded_len;
|
|
char buf [6];
|
|
|
|
/* Compute the length of the string we wish to mangle. */
|
|
for (encoded_len = 0, ptr = (const unsigned char *) name;
|
|
ptr < limit; encoded_len++)
|
|
{
|
|
int ch = UTF8_GET(ptr, limit);
|
|
|
|
if (ch < 0)
|
|
error ("internal error - invalid Utf8 name");
|
|
}
|
|
|
|
sprintf (buf, "%d", encoded_len);
|
|
obstack_grow (mangle_obstack, buf, strlen (buf));
|
|
obstack_grow (mangle_obstack, name, len);
|
|
}
|
|
|
|
#endif /* HAVE_AS_UTF8 */
|