1 /*-
2 * This code is derived from software copyrighted by the Free Software
3 * Foundation.
4 */
5
6 #ifndef lint
7 static char sccsid[] = "@(#)cplus-dem.c 8.1 (Berkeley) 06/06/93";
8 #endif /* not lint */
9
10 /* Demangler for GNU C++
11 Copyright (C) 1989 Free Software Foundation, Inc.
12 written by James Clark (jjc@jclark.uucp)
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 1, or (at your option)
17 any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
27
28 /* This is for g++ 1.36.1 (November 6 version). It will probably
29 require changes for any other version.
30
31 Modified for g++ 1.36.2 (November 18 version). */
32
33 /* This file exports one function
34
35 char *cplus_demangle (const char *name)
36
37 If `name' is a mangled function name produced by g++, then
38 a pointer to a malloced string giving a C++ representation
39 of the name will be returned; otherwise NULL will be returned.
40 It is the caller's responsibility to free the string which
41 is returned.
42
43 For example,
44
45 cplus_demangle ("_foo__1Ai")
46
47 returns
48
49 "A::foo(int)"
50
51 This file imports xmalloc and xrealloc, which are like malloc and
52 realloc except that they generate a fatal error if there is no
53 available memory. */
54
55 /* #define nounderscore 1 /* define this is names don't start with _ */
56
57 #include <stdio.h>
58 #include <ctype.h>
59
60 #ifdef USG
61 #include <memory.h>
62 #include <string.h>
63 #else
64 #include <strings.h>
65 #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
66 #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
67 #define strchr index
68 #define strrchr rindex
69 #endif
70
71 #ifdef __STDC__
72 extern char *cplus_demangle (const char *type);
73 #else
74 extern char *cplus_demangle ();
75 #endif
76
77 #ifdef __STDC__
78 extern char *xmalloc (int);
79 extern char *xrealloc (char *, int);
80 #else
81 extern char *xmalloc ();
82 extern char *xrealloc ();
83 #endif
84
85 static char **typevec = 0;
86 static int ntypes = 0;
87 static int typevec_size = 0;
88
89 static struct {
90 const char *in;
91 const char *out;
92 } optable[] = {
93 "new", " new",
94 "delete", " delete",
95 "ne", "!=",
96 "eq", "==",
97 "ge", ">=",
98 "gt", ">",
99 "le", "<=",
100 "lt", "<",
101 "plus", "+",
102 "minus", "-",
103 "mult", "*",
104 "convert", "+", /* unary + */
105 "negate", "-", /* unary - */
106 "trunc_mod", "%",
107 "trunc_div", "/",
108 "truth_andif", "&&",
109 "truth_orif", "||",
110 "truth_not", "!",
111 "postincrement", "++",
112 "postdecrement", "--",
113 "bit_ior", "|",
114 "bit_xor", "^",
115 "bit_and", "&",
116 "bit_not", "~",
117 "call", "()",
118 "cond", "?:",
119 "alshift", "<<",
120 "arshift", ">>",
121 "component", "->",
122 "indirect", "*",
123 "method_call", "->()",
124 "addr", "&", /* unary & */
125 "array", "[]",
126 "nop", "", /* for operator= */
127 };
128
129 /* Beware: these aren't '\0' terminated. */
130
131 typedef struct {
132 char *b; /* pointer to start of string */
133 char *p; /* pointer after last character */
134 char *e; /* pointer after end of allocated space */
135 } string;
136
137 #ifdef __STDC__
138 static void string_need (string *s, int n);
139 static void string_delete (string *s);
140 static void string_init (string *s);
141 static void string_clear (string *s);
142 static int string_empty (string *s);
143 static void string_append (string *p, const char *s);
144 static void string_appends (string *p, string *s);
145 static void string_appendn (string *p, const char *s, int n);
146 static void string_prepend (string *p, const char *s);
147 #if 0
148 static void string_prepends (string *p, string *s);
149 #endif
150 static void string_prependn (string *p, const char *s, int n);
151 static int get_count (const char **type, int *count);
152 static int do_args (const char **type, string *decl);
153 static int do_type (const char **type, string *result);
154 static int do_arg (const char **type, string *result);
155 static int do_args (const char **type, string *decl);
156 static void munge_function_name (string *name);
157 static void remember_type (const char *type, int len);
158 #else
159 static void string_need ();
160 static void string_delete ();
161 static void string_init ();
162 static void string_clear ();
163 static int string_empty ();
164 static void string_append ();
165 static void string_appends ();
166 static void string_appendn ();
167 static void string_prepend ();
168 static void string_prepends ();
169 static void string_prependn ();
170 static int get_count ();
171 static int do_args ();
172 static int do_type ();
173 static int do_arg ();
174 static int do_args ();
175 static void munge_function_name ();
176 static void remember_type ();
177 #endif
178
179 char *
cplus_demangle(type)180 cplus_demangle (type)
181 const char *type;
182 {
183 string decl;
184 int n;
185 int success = 0;
186 int constructor = 0;
187 int const_flag = 0;
188 int i;
189 const char *p;
190 #ifndef LONGERNAMES
191 const char *premangle;
192 #endif
193
194 if (type == NULL || *type == '\0')
195 return NULL;
196 #ifndef nounderscore
197 if (*type++ != '_')
198 return NULL;
199 #endif
200 p = type;
201 while (*p != '\0' && !(*p == '_' && p[1] == '_'))
202 p++;
203 if (*p == '\0')
204 {
205 /* destructor */
206 if (type[0] == '_' && type[1] == '$' && type[2] == '_')
207 {
208 int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
209 char *tem = (char *) xmalloc (n);
210 strcpy (tem, type + 3);
211 strcat (tem, "::~");
212 strcat (tem, type + 3);
213 strcat (tem, "()");
214 return tem;
215 }
216 /* static data member */
217 if (*type != '_' && (p = strchr (type, '$')) != NULL)
218 {
219 int n = strlen (type) + 2;
220 char *tem = (char *) xmalloc (n);
221 memcpy (tem, type, p - type);
222 strcpy (tem + (p - type), "::");
223 strcpy (tem + (p - type) + 2, p + 1);
224 return tem;
225 }
226 /* virtual table */
227 if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
228 {
229 int n = strlen (type + 4) + 14 + 1;
230 char *tem = (char *) xmalloc (n);
231 strcpy (tem, type + 4);
232 strcat (tem, " virtual table");
233 return tem;
234 }
235 return NULL;
236 }
237
238 string_init (&decl);
239
240 if (p == type)
241 {
242 if (!isdigit (p[2]))
243 {
244 string_delete (&decl);
245 return NULL;
246 }
247 constructor = 1;
248 }
249 else
250 {
251 string_appendn (&decl, type, p - type);
252 munge_function_name (&decl);
253 }
254 p += 2;
255
256 #ifndef LONGERNAMES
257 premangle = p;
258 #endif
259 switch (*p)
260 {
261 case 'C':
262 /* a const member function */
263 if (!isdigit (p[1]))
264 {
265 string_delete (&decl);
266 return NULL;
267 }
268 p += 1;
269 const_flag = 1;
270 /* fall through */
271 case '0':
272 case '1':
273 case '2':
274 case '3':
275 case '4':
276 case '5':
277 case '6':
278 case '7':
279 case '8':
280 case '9':
281 n = 0;
282 do
283 {
284 n *= 10;
285 n += *p - '0';
286 p += 1;
287 }
288 while (isdigit (*p));
289 if (strlen (p) < n)
290 {
291 string_delete (&decl);
292 return NULL;
293 }
294 if (constructor)
295 {
296 string_appendn (&decl, p, n);
297 string_append (&decl, "::");
298 string_appendn (&decl, p, n);
299 }
300 else
301 {
302 string_prepend (&decl, "::");
303 string_prependn (&decl, p, n);
304 }
305 p += n;
306 #ifndef LONGERNAMES
307 remember_type (premangle, p - premangle);
308 #endif
309 success = do_args (&p, &decl);
310 if (const_flag)
311 string_append (&decl, " const");
312 break;
313 case 'F':
314 p += 1;
315 success = do_args (&p, &decl);
316 break;
317 }
318
319 for (i = 0; i < ntypes; i++)
320 if (typevec[i] != NULL)
321 free (typevec[i]);
322 ntypes = 0;
323 if (typevec != NULL)
324 {
325 free ((char *)typevec);
326 typevec = NULL;
327 typevec_size = 0;
328 }
329
330 if (success)
331 {
332 string_appendn (&decl, "", 1);
333 return decl.b;
334 }
335 else
336 {
337 string_delete (&decl);
338 return NULL;
339 }
340 }
341
342 static int
get_count(type,count)343 get_count (type, count)
344 const char **type;
345 int *count;
346 {
347 if (!isdigit (**type))
348 return 0;
349 *count = **type - '0';
350 *type += 1;
351 /* see flush_repeats in cplus-method.c */
352 if (isdigit (**type))
353 {
354 const char *p = *type;
355 int n = *count;
356 do
357 {
358 n *= 10;
359 n += *p - '0';
360 p += 1;
361 }
362 while (isdigit (*p));
363 if (*p == '_')
364 {
365 *type = p + 1;
366 *count = n;
367 }
368 }
369 return 1;
370 }
371
372 /* result will be initialised here; it will be freed on failure */
373
374 static int
do_type(type,result)375 do_type (type, result)
376 const char **type;
377 string *result;
378 {
379 int n;
380 int done;
381 int non_empty = 0;
382 int success;
383 string decl;
384 const char *remembered_type;
385
386 string_init (&decl);
387 string_init (result);
388
389 done = 0;
390 success = 1;
391 while (success && !done)
392 {
393 int member;
394 switch (**type)
395 {
396 case 'P':
397 *type += 1;
398 string_prepend (&decl, "*");
399 break;
400
401 case 'R':
402 *type += 1;
403 string_prepend (&decl, "&");
404 break;
405
406 case 'T':
407 *type += 1;
408 if (!get_count (type, &n) || n >= ntypes)
409 success = 0;
410 else
411 {
412 remembered_type = typevec[n];
413 type = &remembered_type;
414 }
415 break;
416
417 case 'F':
418 *type += 1;
419 if (!string_empty (&decl) && decl.b[0] == '*')
420 {
421 string_prepend (&decl, "(");
422 string_append (&decl, ")");
423 }
424 if (!do_args (type, &decl) || **type != '_')
425 success = 0;
426 else
427 *type += 1;
428 break;
429
430 case 'M':
431 case 'O':
432 {
433 int constp = 0;
434 int volatilep = 0;
435
436 member = **type == 'M';
437 *type += 1;
438 if (!isdigit (**type))
439 {
440 success = 0;
441 break;
442 }
443 n = 0;
444 do
445 {
446 n *= 10;
447 n += **type - '0';
448 *type += 1;
449 }
450 while (isdigit (**type));
451 if (strlen (*type) < n)
452 {
453 success = 0;
454 break;
455 }
456 string_append (&decl, ")");
457 string_prepend (&decl, "::");
458 string_prependn (&decl, *type, n);
459 string_prepend (&decl, "(");
460 *type += n;
461 if (member)
462 {
463 if (**type == 'C')
464 {
465 *type += 1;
466 constp = 1;
467 }
468 if (**type == 'V')
469 {
470 *type += 1;
471 volatilep = 1;
472 }
473 if (*(*type)++ != 'F')
474 {
475 success = 0;
476 break;
477 }
478 }
479 if ((member && !do_args (type, &decl)) || **type != '_')
480 {
481 success = 0;
482 break;
483 }
484 *type += 1;
485 if (constp)
486 {
487 if (non_empty)
488 string_append (&decl, " ");
489 else
490 non_empty = 1;
491 string_append (&decl, "const");
492 }
493 if (volatilep)
494 {
495 if (non_empty)
496 string_append (&decl, " ");
497 else
498 non_empty = 1;
499 string_append (&decl, "volatilep");
500 }
501 break;
502 }
503
504 case 'C':
505 if ((*type)[1] == 'P')
506 {
507 *type += 1;
508 if (!string_empty (&decl))
509 string_prepend (&decl, " ");
510 string_prepend (&decl, "const");
511 break;
512 }
513
514 /* fall through */
515 default:
516 done = 1;
517 break;
518 }
519 }
520
521 done = 0;
522 non_empty = 0;
523 while (success && !done)
524 {
525 switch (**type)
526 {
527 case 'C':
528 *type += 1;
529 if (non_empty)
530 string_append (result, " ");
531 else
532 non_empty = 1;
533 string_append (result, "const");
534 break;
535 case 'U':
536 *type += 1;
537 if (non_empty)
538 string_append (result, " ");
539 else
540 non_empty = 1;
541 string_append (result, "unsigned");
542 break;
543 case 'V':
544 *type += 1;
545 if (non_empty)
546 string_append (result, " ");
547 else
548 non_empty = 1;
549 string_append (result, "volatile");
550 break;
551 default:
552 done = 1;
553 break;
554 }
555 }
556
557 if (success)
558 switch (**type)
559 {
560 case '\0':
561 case '_':
562 break;
563 case 'v':
564 *type += 1;
565 if (non_empty)
566 string_append (result, " ");
567 string_append (result, "void");
568 break;
569 case 'x':
570 *type += 1;
571 if (non_empty)
572 string_append (result, " ");
573 string_append (result, "long long");
574 break;
575 case 'l':
576 *type += 1;
577 if (non_empty)
578 string_append (result, " ");
579 string_append (result, "long");
580 break;
581 case 'i':
582 *type += 1;
583 if (non_empty)
584 string_append (result, " ");
585 string_append (result, "int");
586 break;
587 case 's':
588 *type += 1;
589 if (non_empty)
590 string_append (result, " ");
591 string_append (result, "short");
592 break;
593 case 'c':
594 *type += 1;
595 if (non_empty)
596 string_append (result, " ");
597 string_append (result, "char");
598 break;
599 case 'r':
600 *type += 1;
601 if (non_empty)
602 string_append (result, " ");
603 string_append (result, "long double");
604 break;
605 case 'd':
606 *type += 1;
607 if (non_empty)
608 string_append (result, " ");
609 string_append (result, "double");
610 break;
611 case 'f':
612 *type += 1;
613 if (non_empty)
614 string_append (result, " ");
615 string_append (result, "float");
616 break;
617 case 'G':
618 *type += 1;
619 if (!isdigit (**type))
620 {
621 success = 0;
622 break;
623 }
624 /* fall through */
625 case '0':
626 case '1':
627 case '2':
628 case '3':
629 case '4':
630 case '5':
631 case '6':
632 case '7':
633 case '8':
634 case '9':
635 n = 0;
636 do
637 {
638 n *= 10;
639 n += **type - '0';
640 *type += 1;
641 }
642 while (isdigit (**type));
643 if (strlen (*type) < n)
644 {
645 success = 0;
646 break;
647 }
648 if (non_empty)
649 string_append (result, " ");
650 string_appendn (result, *type, n);
651 *type += n;
652 break;
653 default:
654 success = 0;
655 break;
656 }
657
658 if (success)
659 {
660 if (!string_empty (&decl))
661 {
662 string_append (result, " ");
663 string_appends (result, &decl);
664 }
665 string_delete (&decl);
666 return 1;
667 }
668 else
669 {
670 string_delete (&decl);
671 string_delete (result);
672 return 0;
673 }
674 }
675
676 /* `result' will be initialised in do_type; it will be freed on failure */
677
678 static int
do_arg(type,result)679 do_arg (type, result)
680 const char **type;
681 string *result;
682 {
683 const char *start = *type;
684
685 if (!do_type (type, result))
686 return 0;
687 remember_type (start, *type - start);
688 return 1;
689 }
690
691 static void
remember_type(start,len)692 remember_type (start, len)
693 const char *start;
694 int len;
695 {
696 char *tem;
697
698 if (ntypes >= typevec_size)
699 {
700 if (typevec_size == 0)
701 {
702 typevec_size = 3;
703 typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
704 }
705 else
706 {
707 typevec_size *= 2;
708 typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
709 }
710 }
711 tem = (char *) xmalloc (len + 1);
712 memcpy (tem, start, len);
713 tem[len] = '\0';
714 typevec[ntypes++] = tem;
715 }
716
717 /* `decl' must be already initialised, usually non-empty;
718 it won't be freed on failure */
719
720 static int
do_args(type,decl)721 do_args (type, decl)
722 const char **type;
723 string *decl;
724 {
725 string arg;
726 int need_comma = 0;
727
728 string_append (decl, "(");
729
730 while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
731 {
732 if (**type == 'N')
733 {
734 int r;
735 int t;
736 *type += 1;
737 if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
738 return 0;
739 while (--r >= 0)
740 {
741 const char *tem = typevec[t];
742 if (need_comma)
743 string_append (decl, ", ");
744 if (!do_arg (&tem, &arg))
745 return 0;
746 string_appends (decl, &arg);
747 string_delete (&arg);
748 need_comma = 1;
749 }
750 }
751 else
752 {
753 if (need_comma)
754 string_append (decl, ", ");
755 if (!do_arg (type, &arg))
756 return 0;
757 string_appends (decl, &arg);
758 string_delete (&arg);
759 need_comma = 1;
760 }
761 }
762
763 if (**type == 'v')
764 *type += 1;
765 else if (**type == 'e')
766 {
767 *type += 1;
768 if (need_comma)
769 string_append (decl, ",");
770 string_append (decl, "...");
771 }
772
773 string_append (decl, ")");
774 return 1;
775 }
776
777 static void
munge_function_name(name)778 munge_function_name (name)
779 string *name;
780 {
781 if (!string_empty (name) && name->p - name->b >= 3
782 && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
783 {
784 int i;
785 /* see if it's an assignment expression */
786 if (name->p - name->b >= 10 /* op$assign_ */
787 && memcmp (name->b + 3, "assign_", 7) == 0)
788 {
789 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
790 {
791 int len = name->p - name->b - 10;
792 if (strlen (optable[i].in) == len
793 && memcmp (optable[i].in, name->b + 10, len) == 0)
794 {
795 string_clear (name);
796 string_append (name, "operator");
797 string_append (name, optable[i].out);
798 string_append (name, "=");
799 return;
800 }
801 }
802 }
803 else
804 {
805 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
806 {
807 int len = name->p - name->b - 3;
808 if (strlen (optable[i].in) == len
809 && memcmp (optable[i].in, name->b + 3, len) == 0)
810 {
811 string_clear (name);
812 string_append (name, "operator");
813 string_append (name, optable[i].out);
814 return;
815 }
816 }
817 }
818 return;
819 }
820 else if (!string_empty (name) && name->p - name->b >= 5
821 && memcmp (name->b, "type$", 5) == 0)
822 {
823 /* type conversion operator */
824 string type;
825 const char *tem = name->b + 5;
826 if (do_type (&tem, &type))
827 {
828 string_clear (name);
829 string_append (name, "operator ");
830 string_appends (name, &type);
831 string_delete (&type);
832 return;
833 }
834 }
835 }
836
837 /* a mini string-handling package */
838
839 static void
string_need(s,n)840 string_need (s, n)
841 string *s;
842 int n;
843 {
844 if (s->b == NULL)
845 {
846 if (n < 32)
847 n = 32;
848 s->p = s->b = (char *) xmalloc (n);
849 s->e = s->b + n;
850 }
851 else if (s->e - s->p < n)
852 {
853 int tem = s->p - s->b;
854 n += tem;
855 n *= 2;
856 s->b = (char *) xrealloc (s->b, n);
857 s->p = s->b + tem;
858 s->e = s->b + n;
859 }
860 }
861
862 static void
string_delete(s)863 string_delete (s)
864 string *s;
865 {
866 if (s->b != NULL)
867 {
868 free (s->b);
869 s->b = s->e = s->p = NULL;
870 }
871 }
872
873 static void
string_init(s)874 string_init (s)
875 string *s;
876 {
877 s->b = s->p = s->e = NULL;
878 }
879
880 static void
string_clear(s)881 string_clear (s)
882 string *s;
883 {
884 s->p = s->b;
885 }
886
887 static int
string_empty(s)888 string_empty (s)
889 string *s;
890 {
891 return s->b == s->p;
892 }
893
894 static void
string_append(p,s)895 string_append (p, s)
896 string *p;
897 const char *s;
898 {
899 int n;
900 if (s == NULL || *s == '\0')
901 return;
902 n = strlen (s);
903 string_need (p, n);
904 memcpy (p->p, s, n);
905 p->p += n;
906 }
907
908 static void
string_appends(p,s)909 string_appends (p, s)
910 string *p, *s;
911 {
912 int n;
913 if (s->b == s->p)
914 return;
915 n = s->p - s->b;
916 string_need (p, n);
917 memcpy (p->p, s->b, n);
918 p->p += n;
919 }
920
921 static void
string_appendn(p,s,n)922 string_appendn (p, s, n)
923 string *p;
924 const char *s;
925 int n;
926 {
927 if (n == 0)
928 return;
929 string_need (p, n);
930 memcpy (p->p, s, n);
931 p->p += n;
932 }
933
934 static void
string_prepend(p,s)935 string_prepend (p, s)
936 string *p;
937 const char *s;
938 {
939 if (s == NULL || *s == '\0')
940 return;
941 string_prependn (p, s, strlen (s));
942 }
943
944 #if 0
945 static void
946 string_prepends (p, s)
947 string *p, *s;
948 {
949 if (s->b == s->p)
950 return;
951 string_prependn (p, s->b, s->p - s->b);
952 }
953 #endif
954
955 static void
string_prependn(p,s,n)956 string_prependn (p, s, n)
957 string *p;
958 const char *s;
959 int n;
960 {
961 char *q;
962
963 if (n == 0)
964 return;
965 string_need (p, n);
966 for (q = p->p - 1; q >= p->b; q--)
967 q[n] = q[0];
968 memcpy (p->b, s, n);
969 p->p += n;
970 }
971