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