fixup in BIG_ENDIAN macro
[unix-history] / usr / src / usr.bin / ld / cplus-dem.c
CommitLineData
2a8bffe0
KB
1/*-
2 * This code is derived from software copyrighted by the Free Software
3 * Foundation.
2a8bffe0
KB
4 */
5
61ff33b7 6#ifndef lint
0a883b6b 7static char sccsid[] = "@(#)cplus-dem.c 5.5 (Berkeley) %G%";
61ff33b7
KB
8#endif /* not lint */
9
81364d41
KB
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
81364d41
KB
71#ifdef __STDC__
72extern char *cplus_demangle (const char *type);
73#else
74extern char *cplus_demangle ();
75#endif
76
77#ifdef __STDC__
78extern char *xmalloc (int);
79extern char *xrealloc (char *, int);
80#else
81extern char *xmalloc ();
82extern char *xrealloc ();
83#endif
84
85static char **typevec = 0;
86static int ntypes = 0;
87static int typevec_size = 0;
88
89static 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
131typedef 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__
138static void string_need (string *s, int n);
139static void string_delete (string *s);
140static void string_init (string *s);
141static void string_clear (string *s);
142static int string_empty (string *s);
143static void string_append (string *p, const char *s);
144static void string_appends (string *p, string *s);
145static void string_appendn (string *p, const char *s, int n);
146static void string_prepend (string *p, const char *s);
147#if 0
148static void string_prepends (string *p, string *s);
149#endif
150static void string_prependn (string *p, const char *s, int n);
151static int get_count (const char **type, int *count);
152static int do_args (const char **type, string *decl);
153static int do_type (const char **type, string *result);
154static int do_arg (const char **type, string *result);
155static int do_args (const char **type, string *decl);
156static void munge_function_name (string *name);
157static void remember_type (const char *type, int len);
158#else
159static void string_need ();
160static void string_delete ();
161static void string_init ();
162static void string_clear ();
163static int string_empty ();
164static void string_append ();
165static void string_appends ();
166static void string_appendn ();
167static void string_prepend ();
168static void string_prepends ();
169static void string_prependn ();
170static int get_count ();
171static int do_args ();
172static int do_type ();
173static int do_arg ();
174static int do_args ();
175static void munge_function_name ();
176static void remember_type ();
177#endif
178
179char *
180cplus_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
342static int
343get_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
374static int
375do_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
678static int
679do_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
691static void
692remember_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
720static int
721do_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
777static void
778munge_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
839static void
840string_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
862static void
863string_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
873static void
874string_init (s)
875 string *s;
876{
877 s->b = s->p = s->e = NULL;
878}
879
880static void
881string_clear (s)
882 string *s;
883{
884 s->p = s->b;
885}
886
887static int
888string_empty (s)
889 string *s;
890{
891 return s->b == s->p;
892}
893
894static void
895string_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
908static void
909string_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
921static void
922string_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
934static void
935string_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
945static void
946string_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
955static void
956string_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}