White space and comments only. The devo tree prior to this delta is
[deliverable/binutils-gdb.git] / gas / config / cplus-dem.c
CommitLineData
68a96e53
RP
1/* Demangler for GNU C++
2 Copyright (C) 1989 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
6026cd06 7 the Free Software Foundation; either version 2, or (at your option)
68a96e53 8 any later version.
a39116f1 9
68a96e53
RP
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.
a39116f1 14
68a96e53
RP
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
a39116f1 23
68a96e53
RP
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.
a39116f1 31
68a96e53
RP
32 For example,
33
34 cplus_demangle ("_foo__1Ai")
35
36 returns
a39116f1 37
68a96e53 38 "A::foo(int)"
a39116f1 39
68a96e53
RP
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 _ */
a39116f1 45
68a96e53
RP
46#include <stdio.h>
47#include <string.h>
48#include <ctype.h>
a39116f1 49
68a96e53
RP
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#ifndef __STDC__
59#define const
60#endif
61
62#ifdef __STDC__
63extern char *cplus_demangle (const char *type);
64#else
65extern char *cplus_demangle ();
66#endif
67
68#ifdef __STDC__
69extern char *xmalloc (int);
70extern char *xrealloc (char *, int);
71#else
72extern char *xmalloc ();
73extern char *xrealloc ();
74#endif
75
76static char **typevec = 0;
77static int ntypes = 0;
78static int typevec_size = 0;
79
80static struct {
a39116f1
RP
81 const char *in;
82 const char *out;
68a96e53 83} optable[] = {
a39116f1
RP
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= */
68a96e53
RP
112};
113
114/* Beware: these aren't '\0' terminated. */
115
116typedef struct {
a39116f1
RP
117 char *b; /* pointer to start of string */
118 char *p; /* pointer after last character */
119 char *e; /* pointer after end of allocated space */
68a96e53
RP
120} string;
121
122#ifdef __STDC__
123static void string_need (string *s, int n);
124static void string_delete (string *s);
125static void string_init (string *s);
126static void string_clear (string *s);
127static int string_empty (string *s);
128static void string_append (string *p, const char *s);
129static void string_appends (string *p, string *s);
130static void string_appendn (string *p, const char *s, int n);
131static void string_prepend (string *p, const char *s);
132#if 0
133static void string_prepends (string *p, string *s);
134#endif
135static void string_prependn (string *p, const char *s, int n);
136static int get_count (const char **type, int *count);
137static int do_args (const char **type, string *decl);
138static int do_type (const char **type, string *result);
139static int do_arg (const char **type, string *result);
140static int do_args (const char **type, string *decl);
141static void munge_function_name (string *name);
142#else
143static void string_need ();
144static void string_delete ();
145static void string_init ();
146static void string_clear ();
147static int string_empty ();
148static void string_append ();
149static void string_appends ();
150static void string_appendn ();
151static void string_prepend ();
152static void string_prepends ();
153static void string_prependn ();
154static int get_count ();
155static int do_args ();
156static int do_type ();
157static int do_arg ();
158static int do_args ();
159static void munge_function_name ();
160#endif
161
162char *
a39116f1
RP
163 cplus_demangle (type)
164const char *type;
68a96e53 165{
a39116f1
RP
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;
68a96e53 176#ifndef nounderscore
a39116f1
RP
177 if (*type++ != '_')
178 return NULL;
68a96e53 179#endif
a39116f1
RP
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 }
68a96e53
RP
305}
306
307static int
a39116f1
RP
308 get_count (type, count)
309const char **type;
310int *count;
68a96e53 311{
a39116f1
RP
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;
68a96e53
RP
335}
336
337/* result will be initialised here; it will be freed on failure */
338
339static int
a39116f1
RP
340 do_type (type, result)
341const char **type;
342string *result;
68a96e53 343{
a39116f1
RP
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)
68a96e53 357 {
a39116f1
RP
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 }
68a96e53 484 }
a39116f1
RP
485
486 done = 0;
487 non_empty = 0;
488 while (success && !done)
68a96e53 489 {
a39116f1
RP
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 }
68a96e53 520 }
a39116f1
RP
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)
68a96e53 618 {
a39116f1
RP
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;
68a96e53 632 }
68a96e53
RP
633}
634
635/* `result' will be initialised in do_type; it will be freed on failure */
636
637static int
a39116f1
RP
638 do_arg (type, result)
639const char **type;
640string *result;
68a96e53 641{
a39116f1
RP
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;
68a96e53
RP
670}
671
672/* `decl' must be already initialised, usually non-empty;
673 it won't be freed on failure */
674
675static int
a39116f1
RP
676 do_args (type, decl)
677const char **type;
678string *decl;
68a96e53 679{
a39116f1
RP
680 string arg;
681 int need_comma = 0;
682
683 string_append (decl, "(");
684
685 while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
68a96e53 686 {
a39116f1
RP
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 }
68a96e53 716 }
a39116f1
RP
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;
68a96e53
RP
730}
731
732static void
a39116f1
RP
733 munge_function_name (name)
734string *name;
68a96e53 735{
a39116f1
RP
736 if (!string_empty (name) && name->p - name->b >= 3
737 && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
68a96e53 738 {
a39116f1
RP
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;
68a96e53 774 }
a39116f1
RP
775 else if (!string_empty (name) && name->p - name->b >= 5
776 && memcmp (name->b, "type$", 5) == 0)
68a96e53 777 {
a39116f1
RP
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 }
68a96e53 789 }
68a96e53
RP
790}
791
792/* a mini string-handling package */
793
794static void
a39116f1
RP
795 string_need (s, n)
796string *s;
797int n;
68a96e53 798{
a39116f1
RP
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 }
68a96e53
RP
815}
816
817static void
a39116f1
RP
818 string_delete (s)
819string *s;
68a96e53 820{
a39116f1
RP
821 if (s->b != NULL)
822 {
823 free (s->b);
824 s->b = s->e = s->p = NULL;
825 }
68a96e53
RP
826}
827
828static void
a39116f1
RP
829 string_init (s)
830string *s;
68a96e53 831{
a39116f1 832 s->b = s->p = s->e = NULL;
68a96e53
RP
833}
834
835static void
a39116f1
RP
836 string_clear (s)
837string *s;
68a96e53 838{
a39116f1 839 s->p = s->b;
68a96e53
RP
840}
841
842static int
a39116f1
RP
843 string_empty (s)
844string *s;
68a96e53 845{
a39116f1 846 return s->b == s->p;
68a96e53
RP
847}
848
849static void
a39116f1
RP
850 string_append (p, s)
851string *p;
852const char *s;
68a96e53 853{
a39116f1
RP
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;
68a96e53
RP
861}
862
863static void
a39116f1
RP
864 string_appends (p, s)
865string *p, *s;
68a96e53 866{
a39116f1
RP
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;
68a96e53
RP
874}
875
876static void
a39116f1
RP
877 string_appendn (p, s, n)
878string *p;
879const char *s;
880int n;
68a96e53 881{
a39116f1
RP
882 if (n == 0)
883 return;
884 string_need (p, n);
885 memcpy (p->p, s, n);
886 p->p += n;
68a96e53
RP
887}
888
889static void
a39116f1
RP
890 string_prepend (p, s)
891string *p;
892const char *s;
68a96e53 893{
a39116f1
RP
894 if (s == NULL || *s == '\0')
895 return;
896 string_prependn (p, s, strlen (s));
68a96e53
RP
897}
898
899#if 0
900static void
a39116f1
RP
901 string_prepends (p, s)
902string *p, *s;
68a96e53 903{
a39116f1
RP
904 if (s->b == s->p)
905 return;
906 string_prependn (p, s->b, s->p - s->b);
68a96e53
RP
907}
908#endif
909
910static void
a39116f1
RP
911 string_prependn (p, s, n)
912string *p;
913const char *s;
914int n;
68a96e53 915{
a39116f1
RP
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;
68a96e53 925}
a39116f1
RP
926
927/* end of cplus-dem.c */
This page took 0.077058 seconds and 4 git commands to generate.