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