]> Git Repo - binutils.git/blob - gas/config/cplus-dem.c
* config/tc-sparc.c (md_parse_option): Accept and ignore -sparc
[binutils.git] / gas / config / cplus-dem.c
1 /* Demangler for GNU C++
2    Copyright (C) 1989, 1992 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 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 /* This file exports one function
23
24    char *cplus_demangle (const char *name)
25
26    If `name' is a mangled function name produced by g++, then
27    a pointer to a malloced string giving a C++ representation
28    of the name will be returned; otherwise NULL will be returned.
29    It is the caller's responsibility to free the string which
30    is returned.
31
32    For example,
33
34    cplus_demangle ("_foo__1Ai")
35
36    returns
37
38    "A::foo(int)"
39
40    This file imports xmalloc and xrealloc, which are like malloc and
41    realloc except that they generate a fatal error if there is no
42    available memory. */
43
44 /* #define nounderscore 1 /* define this is names don't start with _ */
45
46 #include <stdio.h>
47 #include <string.h>
48 #include <ctype.h>
49
50 #if !defined(sequent) && !defined(NeXT)
51 #include <memory.h>
52 #else
53 #define memcpy(s1, s2, n) strncpy(s1, s2, n)
54 #define memcmp(s1, s2, n) strncmp(s1, s2, n)
55 #define strchr(s, c) index(s, c)
56 #endif
57
58 #if __STDC__ != 1
59 #define const
60 #endif
61
62 #if __STDC__ == 1
63 extern char *cplus_demangle (const char *type);
64 #else
65 extern char *cplus_demangle ();
66 #endif
67
68 #if __STDC__ == 1
69 extern char *xmalloc (int);
70 extern char *xrealloc (char *, int);
71 #else
72 extern char *xmalloc ();
73 extern char *xrealloc ();
74 #endif
75
76 static char **typevec = 0;
77 static int ntypes = 0;
78 static int typevec_size = 0;
79
80 static struct
81   {
82     const char *in;
83     const char *out;
84   }
85
86 optable[] =
87 {
88   "new", " new",
89   "delete", " delete",
90   "ne", "!=",
91   "eq", "==",
92   "ge", ">=",
93   "gt", ">",
94   "le", "<=",
95   "lt", "<",
96   "plus", "+",
97   "minus", "-",
98   "mult", "*",
99   "negate", "-",
100   "trunc_mod", "%",
101   "trunc_div", "/",
102   "truth_andif", "&&",
103   "truth_orif", "||",
104   "postincrement", "++",
105   "postdecrement", "--",
106   "bit_ior", "|",
107   "bit_xor", "^",
108   "bit_and", "&",
109   "bit_not", "~",
110   "call", "()",
111   "cond", "?:",
112   "alshift", "<<",
113   "arshift", ">>",
114   "component", "->",
115   "nop", "",                    /* for operator= */
116 };
117
118 /* Beware: these aren't '\0' terminated. */
119
120 typedef struct
121   {
122     char *b;                    /* pointer to start of string */
123     char *p;                    /* pointer after last character */
124     char *e;                    /* pointer after end of allocated space */
125   }
126
127 string;
128
129 #if __STDC__ == 1
130 static void string_need (string * s, int n);
131 static void string_delete (string * s);
132 static void string_init (string * s);
133 static void string_clear (string * s);
134 static int string_empty (string * s);
135 static void string_append (string * p, const char *s);
136 static void string_appends (string * p, string * s);
137 static void string_appendn (string * p, const char *s, int n);
138 static void string_prepend (string * p, const char *s);
139 #if 0
140 static void string_prepends (string * p, string * s);
141 #endif
142 static void string_prependn (string * p, const char *s, int n);
143 static int get_count (const char **type, int *count);
144 static int do_args (const char **type, string * decl);
145 static int do_type (const char **type, string * result);
146 static int do_arg (const char **type, string * result);
147 static int do_args (const char **type, string * decl);
148 static void munge_function_name (string * name);
149 #else
150 static void string_need ();
151 static void string_delete ();
152 static void string_init ();
153 static void string_clear ();
154 static int string_empty ();
155 static void string_append ();
156 static void string_appends ();
157 static void string_appendn ();
158 static void string_prepend ();
159 static void string_prepends ();
160 static void string_prependn ();
161 static int get_count ();
162 static int do_args ();
163 static int do_type ();
164 static int do_arg ();
165 static int do_args ();
166 static void munge_function_name ();
167 #endif
168
169 char *
170 cplus_demangle (type)
171      const char *type;
172 {
173   string decl;
174   int n;
175   int success = 0;
176   int constructor = 0;
177   int const_flag = 0;
178   int i;
179   const char *p;
180
181   if (type == NULL || *type == '\0')
182     return NULL;
183 #ifndef nounderscore
184   if (*type++ != '_')
185     return NULL;
186 #endif
187   p = type;
188   while (*p != '\0' && !(*p == '_' && p[1] == '_'))
189     p++;
190   if (*p == '\0')
191     {
192       /* destructor */
193       if (type[0] == '_' && type[1] == '$' && type[2] == '_')
194         {
195           int n = (strlen (type) - 3) * 2 + 3 + 2 + 1;
196           char *tem = (char *) xmalloc (n);
197           strcpy (tem, type + 3);
198           strcat (tem, "::~");
199           strcat (tem, type + 3);
200           strcat (tem, "()");
201           return tem;
202         }
203       /* static data member */
204       if (*type != '_' && (p = strchr (type, '$')) != '\0')
205         {
206           int n = strlen (type) + 2;
207           char *tem = (char *) xmalloc (n);
208           memcpy (tem, type, p - type);
209           strcpy (tem + (p - type), "::");
210           strcpy (tem + (p - type) + 2, p + 1);
211           return tem;
212         }
213       return NULL;
214     }
215
216   string_init (&decl);
217
218   if (p == type)
219     {
220       if (!isdigit (p[2]))
221         {
222           string_delete (&decl);
223           return NULL;
224         }
225       constructor = 1;
226     }
227   else
228     {
229       string_appendn (&decl, type, p - type);
230       munge_function_name (&decl);
231     }
232   p += 2;
233
234   switch (*p)
235     {
236     case 'C':
237       /* a const member function */
238       if (!isdigit (p[1]))
239         {
240           string_delete (&decl);
241           return NULL;
242         }
243       p += 1;
244       const_flag = 1;
245       /* fall through */
246     case '0':
247     case '1':
248     case '2':
249     case '3':
250     case '4':
251     case '5':
252     case '6':
253     case '7':
254     case '8':
255     case '9':
256       n = 0;
257       do
258         {
259           n *= 10;
260           n += *p - '0';
261           p += 1;
262         }
263       while (isdigit (*p));
264       if (strlen (p) < n)
265         {
266           string_delete (&decl);
267           return NULL;
268         }
269       if (constructor)
270         {
271           string_appendn (&decl, p, n);
272           string_append (&decl, "::");
273           string_appendn (&decl, p, n);
274         }
275       else
276         {
277           string_prepend (&decl, "::");
278           string_prependn (&decl, p, n);
279         }
280       p += n;
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
314 static int
315 get_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
346 static int
347 do_type (type, result)
348      const char **type;
349      string *result;
350 {
351   int n;
352   int done;
353   int non_empty;
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
644 static int
645 do_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
682 static int
683 do_args (type, decl)
684      const char **type;
685      string *decl;
686 {
687   string arg;
688   int need_comma = 0;
689
690   string_append (decl, "(");
691
692   while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
693     {
694       if (**type == 'N')
695         {
696           int r;
697           int t;
698           *type += 1;
699           if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
700             return 0;
701           while (--r >= 0)
702             {
703               const char *tem = typevec[t];
704               if (need_comma)
705                 string_append (decl, ", ");
706               if (!do_arg (&tem, &arg))
707                 return 0;
708               string_appends (decl, &arg);
709               string_delete (&arg);
710               need_comma = 1;
711             }
712         }
713       else
714         {
715           if (need_comma)
716             string_append (decl, ", ");
717           if (!do_arg (type, &arg))
718             return 0;
719           string_appends (decl, &arg);
720           string_delete (&arg);
721           need_comma = 1;
722         }
723     }
724
725   if (**type == 'v')
726     *type += 1;
727   else if (**type == 'e')
728     {
729       *type += 1;
730       if (need_comma)
731         string_append (decl, ",");
732       string_append (decl, "...");
733     }
734
735   string_append (decl, ")");
736   return 1;
737 }
738
739 static void
740 munge_function_name (name)
741      string *name;
742 {
743   if (!string_empty (name) && name->p - name->b >= 3
744       && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
745     {
746       int i;
747       /* see if it's an assignment expression */
748       if (name->p - name->b >= 10       /* op$assign_ */
749           && memcmp (name->b + 3, "assign_", 7) == 0)
750         {
751           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
752             {
753               int len = name->p - name->b - 10;
754               if (strlen (optable[i].in) == len
755                   && memcmp (optable[i].in, name->b + 10, len) == 0)
756                 {
757                   string_clear (name);
758                   string_append (name, "operator");
759                   string_append (name, optable[i].out);
760                   string_append (name, "=");
761                   return;
762                 }
763             }
764         }
765       else
766         {
767           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
768             {
769               int len = name->p - name->b - 3;
770               if (strlen (optable[i].in) == len
771                   && memcmp (optable[i].in, name->b + 3, len) == 0)
772                 {
773                   string_clear (name);
774                   string_append (name, "operator");
775                   string_append (name, optable[i].out);
776                   return;
777                 }
778             }
779         }
780       return;
781     }
782   else if (!string_empty (name) && name->p - name->b >= 5
783            && memcmp (name->b, "type$", 5) == 0)
784     {
785       /* type conversion operator */
786       string type;
787       const char *tem = name->b + 5;
788       if (do_type (&tem, &type))
789         {
790           string_clear (name);
791           string_append (name, "operator ");
792           string_appends (name, &type);
793           string_delete (&type);
794           return;
795         }
796     }
797 }
798
799 /* a mini string-handling package */
800
801 static void
802 string_need (s, n)
803      string *s;
804      int n;
805 {
806   if (s->b == NULL)
807     {
808       if (n < 32)
809         n = 32;
810       s->p = s->b = (char *) xmalloc (n);
811       s->e = s->b + n;
812     }
813   else if (s->e - s->p < n)
814     {
815       int tem = s->p - s->b;
816       n += tem;
817       n *= 2;
818       s->b = (char *) xrealloc (s->b, n);
819       s->p = s->b + tem;
820       s->e = s->b + n;
821     }
822 }
823
824 static void
825 string_delete (s)
826      string *s;
827 {
828   if (s->b != NULL)
829     {
830       free (s->b);
831       s->b = s->e = s->p = NULL;
832     }
833 }
834
835 static void
836 string_init (s)
837      string *s;
838 {
839   s->b = s->p = s->e = NULL;
840 }
841
842 static void
843 string_clear (s)
844      string *s;
845 {
846   s->p = s->b;
847 }
848
849 static int
850 string_empty (s)
851      string *s;
852 {
853   return s->b == s->p;
854 }
855
856 static void
857 string_append (p, s)
858      string *p;
859      const char *s;
860 {
861   int n;
862   if (s == NULL || *s == '\0')
863     return;
864   n = strlen (s);
865   string_need (p, n);
866   memcpy (p->p, s, n);
867   p->p += n;
868 }
869
870 static void
871 string_appends (p, s)
872      string *p, *s;
873 {
874   int n;
875   if (s->b == s->p)
876     return;
877   n = s->p - s->b;
878   string_need (p, n);
879   memcpy (p->p, s->b, n);
880   p->p += n;
881 }
882
883 static void
884 string_appendn (p, s, n)
885      string *p;
886      const char *s;
887      int n;
888 {
889   if (n == 0)
890     return;
891   string_need (p, n);
892   memcpy (p->p, s, n);
893   p->p += n;
894 }
895
896 static void
897 string_prepend (p, s)
898      string *p;
899      const char *s;
900 {
901   if (s == NULL || *s == '\0')
902     return;
903   string_prependn (p, s, strlen (s));
904 }
905
906 #if 0
907 static void
908 string_prepends (p, s)
909      string *p, *s;
910 {
911   if (s->b == s->p)
912     return;
913   string_prependn (p, s->b, s->p - s->b);
914 }
915
916 #endif
917
918 static void
919 string_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 }
934
935 /* end of cplus-dem.c */
This page took 0.078963 seconds and 4 git commands to generate.