]> Git Repo - binutils.git/blob - binutils/cplus-dem.c
Include bfd.h before sysdep.h, so ansidecl and PROTO() get defined first.
[binutils.git] / binutils / cplus-dem.c
1 /* Demangler for GNU C++ 
2    Copyright (C) 1989 Free Software Foundation, Inc.
3    written by James Clark ([email protected])
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 "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.075103 seconds and 4 git commands to generate.