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