class.c (build_utf8_ref): Pad initializer string to utf8const_type's alignment.
[gcc.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, 2008
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_table = make_tree_vec (2*compression_next);
786 int i;
787
788 for (i = 0; i < compression_next; i++)
789 TREE_VEC_ELT (new_table, i) = TREE_VEC_ELT (compression_table, i);
790
791 compression_table = new_table;
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"