OSDN Git Service

contrib:
[pf3gnuchains/gcc-fork.git] / gcc / java / mangle.c
1 /* Functions related to mangling class names for the GNU compiler
2    for the Java(TM) language.
3    Copyright (C) 1998, 1999, 2001, 2002, 2003, 2006, 2007
4    Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>. 
21
22 Java and all Java-based marks are trademarks or registered trademarks
23 of Sun Microsystems, Inc. in the United States and other countries.
24 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
25
26 /* Written by Per Bothner <bothner@cygnus.com> */
27
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "jcf.h"
33 #include "tree.h"
34 #include "java-tree.h"
35 #include "obstack.h"
36 #include "toplev.h"
37 #include "ggc.h"
38 #include "langhooks-def.h"
39
40 static void mangle_class_field (tree);
41 static void mangle_vtable (tree);
42 static void mangle_field_decl (tree);
43 static void mangle_method_decl (tree);
44 static void mangle_local_cni_method_decl (tree);
45
46 static void mangle_type (tree);
47 static void mangle_pointer_type (tree);
48 static void mangle_array_type (tree);
49 static int  mangle_record_type (tree, int);
50
51 static int find_compression_pointer_match (tree);
52 static int find_compression_array_match (tree);
53 static int find_compression_record_match (tree, tree *);
54 static int find_compression_array_template_match (tree);
55
56 static void set_type_package_list (tree);
57 static int  entry_match_pointer_p (tree, int);
58 static void emit_compression_string (int);
59
60 static void init_mangling (void);
61 static tree finish_mangling (void);
62 static void compression_table_add (tree);
63
64 static void mangle_member_name (tree);
65
66 static struct obstack mangle_obstack_1;
67 struct obstack *mangle_obstack;
68
69 #define MANGLE_RAW_STRING(S) \
70   obstack_grow (mangle_obstack, (S), sizeof (S)-1)
71
72 /* atms: array template mangled string. */
73 static GTY(()) tree atms;
74
75 static int
76 utf8_cmp (const unsigned char *str, int length, const char *name)
77 {
78   const unsigned char *limit = str + length;
79   int i;
80
81   for (i = 0; name[i]; ++i)
82     {
83       int ch = UTF8_GET (str, limit);
84       if (ch != name[i])
85         return ch - name[i];
86     }
87
88   return str == limit ? 0 : 1;
89 }
90
91 /* A sorted list of all C++ keywords.  */
92 static const char *const cxx_keywords[] =
93 {
94   "_Complex",
95   "__alignof",
96   "__alignof__",
97   "__asm",
98   "__asm__",
99   "__attribute",
100   "__attribute__",
101   "__builtin_va_arg",
102   "__complex",
103   "__complex__",
104   "__const",
105   "__const__",
106   "__extension__",
107   "__imag",
108   "__imag__",
109   "__inline",
110   "__inline__",
111   "__label__",
112   "__null",
113   "__real",
114   "__real__",
115   "__restrict",
116   "__restrict__",
117   "__signed",
118   "__signed__",
119   "__typeof",
120   "__typeof__",
121   "__volatile",
122   "__volatile__",
123   "and",
124   "and_eq",
125   "asm",
126   "auto",
127   "bitand",
128   "bitor",
129   "bool",
130   "break",
131   "case",
132   "catch",
133   "char",
134   "class",
135   "compl",
136   "const",
137   "const_cast",
138   "continue",
139   "default",
140   "delete",
141   "do",
142   "double",
143   "dynamic_cast",
144   "else",
145   "enum",
146   "explicit",
147   "export",
148   "extern",
149   "false",
150   "float",
151   "for",
152   "friend",
153   "goto",
154   "if",
155   "inline",
156   "int",
157   "long",
158   "mutable",
159   "namespace",
160   "new",
161   "not",
162   "not_eq",
163   "operator",
164   "or",
165   "or_eq",
166   "private",
167   "protected",
168   "public",
169   "register",
170   "reinterpret_cast",
171   "return",
172   "short",
173   "signed",
174   "sizeof",
175   "static",
176   "static_cast",
177   "struct",
178   "switch",
179   "template",
180   "this",      
181   "throw",
182   "true",
183   "try",
184   "typedef",
185   "typeid",
186   "typename",
187   "typeof",
188   "union",
189   "unsigned",
190   "using",
191   "virtual",
192   "void",
193   "volatile",
194   "wchar_t",
195   "while",
196   "xor",
197   "xor_eq"
198 };
199
200 /* Return true if NAME is a C++ keyword.  */
201 static int
202 cxx_keyword_p (const char *name, int length)
203 {
204   int last = ARRAY_SIZE (cxx_keywords);
205   int first = 0;
206   int mid = (last + first) / 2;
207   int old = -1;
208
209   for (mid = (last + first) / 2;
210        mid != old;
211        old = mid, mid = (last + first) / 2)
212     {
213       int kwl = strlen (cxx_keywords[mid]);
214       int min_length = kwl > length ? length : kwl;
215       int r = utf8_cmp ((const unsigned char *) name, min_length, cxx_keywords[mid]);
216
217       if (r == 0)
218         {
219           int i;
220           /* We've found a match if all the remaining characters are `$'.  */
221           for (i = min_length; i < length && name[i] == '$'; ++i)
222             ;
223           if (i == length)
224             return 1;
225           r = 1;
226         }
227
228       if (r < 0)
229         last = mid;
230       else
231         first = mid;
232     }
233   return 0;
234 }
235
236 /* This is the mangling interface: a decl, a class field (.class) and
237    the vtable. */
238
239 void
240 java_mangle_decl (tree decl)
241 {
242   /* A copy of the check from the beginning of lhd_set_decl_assembler_name.
243      Only FUNCTION_DECLs and VAR_DECLs for variables with static storage
244      duration need a real DECL_ASSEMBLER_NAME.  */
245   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
246               || (TREE_CODE (decl) == VAR_DECL
247                   && (TREE_STATIC (decl)
248                       || DECL_EXTERNAL (decl)
249                       || TREE_PUBLIC (decl))));
250   
251   /* Mangling only applies to class members.  */
252   if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
253     {
254       init_mangling ();
255       switch (TREE_CODE (decl))
256         {
257         case VAR_DECL:
258           if (DECL_LANG_SPECIFIC (decl))
259             {
260               if (DECL_CLASS_FIELD_P (decl))
261                 {
262                   mangle_class_field (decl);
263                   break;
264                 }
265               else if (DECL_VTABLE_P (decl))
266                 {
267                   mangle_vtable (DECL_CONTEXT (decl));
268                   break;
269                 }
270             }
271           mangle_field_decl (decl);
272           break;
273
274         case FUNCTION_DECL:
275           if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_CNI_METHOD_P (decl))
276             mangle_local_cni_method_decl (decl);
277           else
278             mangle_method_decl (decl);
279           break;
280
281         default:
282           gcc_unreachable ();
283         }
284       SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ());
285     }
286   else
287     lhd_set_decl_assembler_name (decl);
288 }
289
290 /* Beginning of the helper functions */
291
292 static void
293 mangle_class_field (tree decl)
294 {
295   tree type = DECL_CONTEXT (decl);
296   mangle_record_type (type, /* for_pointer = */ 0);
297   if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
298     MANGLE_RAW_STRING ("6class$");
299   else
300     MANGLE_RAW_STRING ("7class$$");
301   obstack_1grow (mangle_obstack, 'E');
302 }
303
304 static void
305 mangle_vtable (tree type)
306 {
307   MANGLE_RAW_STRING ("TV");
308   mangle_record_type (type, /* for_pointer = */ 0);
309   obstack_1grow (mangle_obstack, 'E');
310 }
311
312 /* This mangles a field decl */
313
314 static void
315 mangle_field_decl (tree decl)
316 {
317   /* Mangle the name of the this the field belongs to */
318   mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
319   
320   /* Mangle the name of the field */
321   mangle_member_name (DECL_NAME (decl));
322
323   /* Terminate the mangled name */
324   obstack_1grow (mangle_obstack, 'E');
325 }
326
327 /* This mangles a method decl, first mangling its name and then all
328    its arguments. */
329
330 static void
331 mangle_method_decl (tree mdecl)
332 {
333   tree method_name = DECL_NAME (mdecl);
334   tree arglist;
335
336   /* Mangle the name of the type that contains mdecl */
337   mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
338
339   /* Mangle the function name.  There are two cases:
340        - mdecl is a constructor, use `C1' for its name, (denotes a
341          complete object constructor.)
342        - mdecl is not a constructor, standard mangling is performed.
343      We terminate the mangled function name with a `E'. */
344   if (ID_INIT_P (method_name))
345     obstack_grow (mangle_obstack, "C1", 2);
346   else
347     mangle_member_name (method_name);
348   obstack_1grow (mangle_obstack, 'E');
349
350   /* We mangled type.methodName. Now onto the arguments. */
351   arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
352   if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
353     arglist = TREE_CHAIN (arglist);
354   
355   /* Output literal 'J' and mangle the return type IF not a 
356      constructor.  */
357   if (!ID_INIT_P (method_name))
358     {
359       obstack_1grow (mangle_obstack, 'J');
360       mangle_type(TREE_TYPE(TREE_TYPE(mdecl)));
361     }
362   
363   /* No arguments is easy. We shortcut it. */
364   if (arglist == end_params_node)
365     obstack_1grow (mangle_obstack, 'v');
366   else
367     {
368       tree arg;
369       for (arg = arglist; arg != end_params_node;  arg = TREE_CHAIN (arg))
370         mangle_type (TREE_VALUE (arg));
371     }
372 }
373
374 /* This mangles a CNI method for a local class.  If the target supports
375    hidden aliases, then G++ will have generated one for us.  It is the
376    responsibility of java_mark_class_local to check target support, since
377    we need to set DECL_VISIBILITY (or not) much earlier.  */
378
379 static void
380 mangle_local_cni_method_decl (tree decl)
381 {
382   MANGLE_RAW_STRING ("GA");
383   mangle_method_decl (decl);
384 }
385
386 /* This mangles a member name, like a function name or a field
387    name. Handle cases were `name' is a C++ keyword.  Return a nonzero
388    value if unicode encoding was required.  */
389
390 static void
391 mangle_member_name (tree name)
392 {
393   append_gpp_mangled_name (IDENTIFIER_POINTER (name),
394                            IDENTIFIER_LENGTH (name));
395
396   /* If NAME happens to be a C++ keyword, add `$'.  */
397   if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
398     obstack_1grow (mangle_obstack, '$');
399 }
400
401 /* Append the mangled name of TYPE onto OBSTACK.  */
402
403 static void
404 mangle_type (tree type)
405 {
406   switch (TREE_CODE (type))
407     {
408       char code;
409     case BOOLEAN_TYPE: code = 'b';  goto primitive;
410     case VOID_TYPE:    code = 'v';  goto primitive;
411     case INTEGER_TYPE:
412       if (type == char_type_node || type == promoted_char_type_node)
413         {
414           code = 'w';
415           goto primitive;
416         }
417       /* Get the original type instead of the arguments promoted type.
418          Avoid symbol name clashes. Should call a function to do that.
419          FIXME.  */
420       if (type == promoted_short_type_node)
421         type = short_type_node;
422       if (type == promoted_byte_type_node)
423         type = byte_type_node;
424       switch (TYPE_PRECISION (type))
425         {
426         case  8:       code = 'c';  goto primitive;
427         case 16:       code = 's';  goto primitive;
428         case 32:       code = 'i';  goto primitive;
429         case 64:       code = 'x';  goto primitive;
430         default:  goto bad_type;
431         }
432     primitive:
433       obstack_1grow (mangle_obstack, code);
434       break;
435
436     case REAL_TYPE:
437       switch (TYPE_PRECISION (type))
438         {
439         case 32:       code = 'f';  goto primitive;
440         case 64:       code = 'd';  goto primitive;
441         default:  goto bad_type;
442         }
443     case POINTER_TYPE:
444       if (TYPE_ARRAY_P (TREE_TYPE (type)))
445         mangle_array_type (type);
446       else
447         mangle_pointer_type (type);
448       break;
449     bad_type:
450     default:
451       gcc_unreachable ();
452     }
453 }
454
455 /* The compression table is a vector that keeps track of things we've
456    already seen, so they can be reused. For example, java.lang.Object
457    would generate three entries: two package names and a type. If
458    java.lang.String is presented next, the java.lang will be matched
459    against the first two entries (and kept for compression as S0_), and
460    type String would be added to the table. See mangle_record_type.
461    COMPRESSION_NEXT is the index to the location of the next insertion
462    of an element.  */
463
464 static GTY(()) tree compression_table;
465 static int  compression_next;
466
467 /* Find a POINTER_TYPE in the compression table. Use a special
468    function to match pointer entries and start from the end */
469
470 static int
471 find_compression_pointer_match (tree type)
472 {
473   int i;
474
475   for (i = compression_next-1; i >= 0; i--)
476     if (entry_match_pointer_p (type, i))
477       return i;
478   return -1;
479 }
480
481 /* Already recorder arrays are handled like pointer as they're always
482    associated with it.  */
483
484 static int
485 find_compression_array_match (tree type)
486 {
487   return find_compression_pointer_match (type);
488 }
489
490 /* Match the table of type against STRING.  */
491
492 static int
493 find_compression_array_template_match (tree string)
494 {
495   int i;
496   for (i = 0; i < compression_next; i++)
497     if (TREE_VEC_ELT (compression_table, i) == string) 
498       return i;
499   return -1;
500 }
501
502 /* We go through the compression table and try to find a complete or
503    partial match. The function returns the compression table entry
504    that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
505    to the rest of TYPE to be mangled. */
506
507 static int
508 find_compression_record_match (tree type, tree *next_current)
509 {
510   int i, match = -1;
511   tree current, saved_current = NULL_TREE;
512
513   current = TYPE_PACKAGE_LIST (type);
514       
515   for (i = 0; i < compression_next; i++)
516     {
517       tree compression_entry = TREE_VEC_ELT (compression_table, i);
518       if (current && compression_entry == TREE_PURPOSE (current))
519         {
520           match = i;
521           saved_current = current;
522           current = TREE_CHAIN (current);
523         }
524       else
525         /* We don't want to match an element that appears in the middle
526            of a package name, so skip forward to the next complete type name.
527            IDENTIFIER_NODEs (except for a "6JArray") are partial package
528            names while RECORD_TYPEs represent complete type names. */
529         while (i < compression_next 
530                && TREE_CODE (compression_entry) == IDENTIFIER_NODE
531                && compression_entry != atms)
532           compression_entry = TREE_VEC_ELT (compression_table, ++i);
533     }
534
535   if (!next_current)
536     return match;
537
538   /* If we have a match, set next_current to the item next to the last
539      matched value. */
540   if (match >= 0)
541     *next_current = TREE_CHAIN (saved_current);
542   /* We had no match: we'll have to start from the beginning. */
543   if (match < 0)
544     *next_current = TYPE_PACKAGE_LIST (type);
545
546   return match;
547 }
548
549 /* Mangle a record type. If a nonzero value is returned, it means
550    that a 'N' was emitted (so that a matching 'E' can be emitted if
551    necessary.)  FOR_POINTER indicates that this element is for a pointer
552    symbol, meaning it was preceded by a 'P'. */
553
554 static int
555 mangle_record_type (tree type, int for_pointer)
556 {
557   tree current;
558   int match;
559   int nadded_p = 0;
560   int qualified;
561   
562   /* Does this name have a package qualifier? */
563   qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
564
565 #define ADD_N() \
566   do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
567
568   gcc_assert (TREE_CODE (type) == RECORD_TYPE);
569
570   if (!TYPE_PACKAGE_LIST (type))
571     set_type_package_list (type);
572
573   match = find_compression_record_match (type, &current);
574   if (match >= 0)
575     {
576       /* If we had a pointer, and there's more, we need to emit
577          'N' after 'P' (for_pointer tells us we already emitted it.) */
578       if (for_pointer && current)
579         ADD_N();
580       emit_compression_string (match);
581     }
582   while (current)
583     {
584       /* Add the new type to the table */
585       compression_table_add (TREE_PURPOSE (current));
586       /* Add 'N' if we never got a chance to, but only if we have a qualified
587          name.  For non-pointer elements, the name is always qualified. */
588       if ((qualified || !for_pointer) && !nadded_p)
589         ADD_N();
590       /* Use the bare type name for the mangle. */
591       append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
592                                IDENTIFIER_LENGTH (TREE_VALUE (current)));
593       current = TREE_CHAIN (current);
594     }
595   return nadded_p;
596 #undef ADD_N
597 }
598
599 /* Mangle a pointer type. There are two cases: the pointer is already
600    in the compression table: the compression is emitted sans 'P'
601    indicator. Otherwise, a 'P' is emitted and, depending on the type,
602    a partial compression or/plus the rest of the mangling. */
603
604 static void
605 mangle_pointer_type (tree type)
606 {
607   int match;
608   tree pointer_type;
609
610   /* Search for the type already in the compression table */
611   if ((match = find_compression_pointer_match (type)) >= 0) 
612     {
613       emit_compression_string (match);
614       return;
615     }
616   
617   /* This didn't work. We start by mangling the pointed-to type */
618   pointer_type = type;
619   type = TREE_TYPE (type);
620   gcc_assert (TREE_CODE (type) == RECORD_TYPE);
621   
622   obstack_1grow (mangle_obstack, 'P');
623   if (mangle_record_type (type, /* for_pointer = */ 1))
624     obstack_1grow (mangle_obstack, 'E');
625
626   /* Don't forget to insert the pointer type in the table */
627   compression_table_add (pointer_type);
628 }
629
630 /* Mangle an array type. Search for an easy solution first, then go
631    through the process of finding out whether the bare array type or even
632    the template indicator were already used and compressed appropriately.
633    It handles pointers. */
634
635 static void
636 mangle_array_type (tree p_type)
637 {
638   tree type, elt_type;
639   int match;
640
641   type = TREE_TYPE (p_type);
642   gcc_assert (type);
643
644   elt_type = TYPE_ARRAY_ELEMENT (type);
645
646   /* We cache a bit of the Jarray <> mangle. */
647   if (!atms)
648     {
649       atms = get_identifier ("6JArray");
650     }
651
652   /* Maybe we have what we're looking for in the compression table. */
653   if ((match = find_compression_array_match (p_type)) >= 0)
654     {
655       emit_compression_string (match);
656       return;
657     }
658
659   /* We know for a fact that all arrays are pointers */
660   obstack_1grow (mangle_obstack, 'P');
661   /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
662   if ((match = find_compression_record_match (type, NULL)) > 0)
663     {
664       emit_compression_string (match);
665       return;
666     }
667
668   /* Maybe we already have just JArray somewhere */
669   if ((match = find_compression_array_template_match (atms)) > 0)
670     emit_compression_string (match);
671   else
672     {
673       /* Start the template mangled name */
674       obstack_grow (mangle_obstack, 
675                     IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
676       /* Insert in the compression table */
677       compression_table_add (atms);
678     } 
679
680   /* Mangle Jarray <elt_type> */
681   obstack_1grow (mangle_obstack, 'I');
682   mangle_type (elt_type);
683   obstack_1grow (mangle_obstack, 'E');
684
685   /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
686   compression_table_add (type);
687   compression_table_add (p_type);
688 }
689
690 /* Write a substitution string for entry I. Substitution string starts a
691    -1 (encoded S_.) The base is 36, and the code shamelessly taken from
692    cp/mangle.c.  */
693
694 static void
695 emit_compression_string (int i)
696 {
697   i -= 1;                       /* Adjust */
698   obstack_1grow (mangle_obstack, 'S');
699   if (i >= 0)
700     {
701       static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
702       unsigned HOST_WIDE_INT n;
703       unsigned HOST_WIDE_INT m=1;
704       /* How many digits for I in base 36? */
705       for (n = i; n >= 36; n /= 36, m *=36);
706       /* Write the digits out */
707       while (m > 0)
708         {
709           int digit = i / m;
710           obstack_1grow (mangle_obstack, digits [digit]);
711           i -= digit * m;
712           m /= 36;
713         }
714     }
715   obstack_1grow (mangle_obstack, '_');
716 }
717
718 /* If search the compression table at index I for a pointer type
719    equivalent to TYPE (meaning that after all the indirection, which
720    might all be unique, we find the same RECORD_TYPE.) */
721
722 static int
723 entry_match_pointer_p (tree type, int i)
724 {
725   tree t = TREE_VEC_ELT (compression_table, i);
726   
727   while (TREE_CODE (type) == POINTER_TYPE
728          && TREE_CODE (t) == POINTER_TYPE)
729     {
730       t = TREE_TYPE (t);
731       type = TREE_TYPE (type);
732     }
733   return (TREE_CODE (type) == RECORD_TYPE
734           && TREE_CODE (t) == RECORD_TYPE
735           && t == type);
736 }
737
738 /* Go through all qualification of type and build a list of list node
739    elements containings as a purpose what should be used for a match and
740    inserted in the compression table; and as it value the raw name of the
741    part. The result is stored in TYPE_PACKAGE_LIST to be reused.  */
742
743 static void
744 set_type_package_list (tree type)
745 {
746   int i;
747   const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
748   const char *ptr;
749   int qualifications;
750   tree list = NULL_TREE, elt;
751
752   for (ptr = type_string, qualifications = 0; *ptr; ptr++)
753     if (*ptr == '.')
754       qualifications += 1;
755
756   for (ptr = type_string, i = 0; i < qualifications; ptr++)
757     {
758       if (ptr [0] == '.')
759         {
760           tree const identifier
761             = get_identifier_with_length (type_string, ptr - type_string);
762
763           elt = build_tree_list (identifier, identifier);
764           TREE_CHAIN (elt) = list;
765           list = elt;
766           type_string = ptr+1;
767           i += 1;
768         }
769     }
770
771   elt = build_tree_list (type, get_identifier (type_string));
772   TREE_CHAIN (elt) = list;
773   list = elt;
774   TYPE_PACKAGE_LIST (type) = nreverse (list);
775 }
776
777 /* Add TYPE as the last element of the compression table. Resize the
778    compression table if necessary.  */
779
780 static void
781 compression_table_add (tree type)
782 {
783   if (compression_next == TREE_VEC_LENGTH (compression_table))
784     {
785       tree new = make_tree_vec (2*compression_next);
786       int i;
787
788       for (i = 0; i < compression_next; i++)
789         TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
790
791       compression_table = new;
792     }
793   TREE_VEC_ELT (compression_table, compression_next++) = type;
794 }
795
796 /* Mangle an embedded resource file name.  "_ZGr" is the prefix.  A
797    '_' is prepended to the name so that names starting with a digit
798    can be demangled.  The length and then the resulting name itself
799    are appended while escaping '$', '.', and '/' to: "$$", "$_", and
800    "$S".  */
801
802 tree
803 java_mangle_resource_name (const char *name)
804 {
805   int len = strlen (name);
806   char *buf = (char *) alloca (2 * len + 1);
807   char *pos;
808   const unsigned char *w1 = (const unsigned char *) name;
809   const unsigned char *w2;
810   const unsigned char *limit = w1 + len;
811
812   pos = buf;
813
814   init_mangling ();
815   MANGLE_RAW_STRING ("Gr");
816
817   *pos++ = '_';
818   while (w1 < limit)
819     {
820       int ch;
821       w2 = w1;
822       ch = UTF8_GET (w1, limit);
823       gcc_assert (ch > 0);
824       switch (ch)
825         {
826         case '$':
827           *pos++ = '$';
828           *pos++ = '$';
829           break;
830         case '.':
831           *pos++ = '$';
832           *pos++ = '_';
833           break;
834         case '/':
835           *pos++ = '$';
836           *pos++ = 'S';
837           break;
838         default:
839           memcpy (pos, w2, w1 - w2);
840           pos += w1 - w2;
841           break;
842         }
843     }
844   append_gpp_mangled_name (buf, pos - buf);
845
846   return finish_mangling ();
847 }
848
849 /* Mangling initialization routine.  */
850
851 static void
852 init_mangling (void)
853 {
854   if (!mangle_obstack)
855     {
856       mangle_obstack = &mangle_obstack_1;
857       gcc_obstack_init (mangle_obstack);
858     }
859
860   gcc_assert (compression_table == NULL);
861   compression_table = make_tree_vec (10);
862
863   /* Mangled name are to be suffixed */
864   MANGLE_RAW_STRING ("_Z");
865 }
866
867 /* Mangling finalization routine. The mangled name is returned as a
868    IDENTIFIER_NODE.  */
869
870 static tree
871 finish_mangling (void)
872 {
873   tree result;
874
875   gcc_assert (compression_table);
876
877   compression_table = NULL_TREE;
878   compression_next = 0;
879   obstack_1grow (mangle_obstack, '\0');
880   result = get_identifier (obstack_base (mangle_obstack));
881   obstack_free (mangle_obstack, obstack_base (mangle_obstack));
882
883   return result;
884 }
885
886 #include "gt-java-mangle.h"