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