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