* cp-tree.h (struct lang_decl_flags): Add comdat.
[official-gcc.git] / libiberty / cplus-dem.c
blobed16c8680cd0d06af719623997bdd4de5a3ddb7a
1 /* Demangler for GNU C++
2 Copyright 1989, 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.uucp)
4 Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
6 This file is part of the libiberty library.
7 Libiberty is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 Libiberty is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with libiberty; see the file COPYING.LIB. If
19 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
24 This file imports xmalloc and xrealloc, which are like malloc and
25 realloc except that they generate a fatal error if there is no
26 available memory. */
28 /* This file lives in both GCC and libiberty. When making changes, please
29 try not to break either. */
31 #include <ctype.h>
32 #include <string.h>
33 #include <stdio.h>
35 #include <demangle.h>
36 #undef CURRENT_DEMANGLING_STYLE
37 #define CURRENT_DEMANGLING_STYLE work->options
39 extern char *xmalloc PARAMS((unsigned));
40 extern char *xrealloc PARAMS((char *, unsigned));
42 static const char *mystrstr PARAMS ((const char *, const char *));
44 static const char *
45 mystrstr (s1, s2)
46 const char *s1, *s2;
48 register const char *p = s1;
49 register int len = strlen (s2);
51 for (; (p = strchr (p, *s2)) != 0; p++)
53 if (strncmp (p, s2, len) == 0)
55 return (p);
58 return (0);
61 /* In order to allow a single demangler executable to demangle strings
62 using various common values of CPLUS_MARKER, as well as any specific
63 one set at compile time, we maintain a string containing all the
64 commonly used ones, and check to see if the marker we are looking for
65 is in that string. CPLUS_MARKER is usually '$' on systems where the
66 assembler can deal with that. Where the assembler can't, it's usually
67 '.' (but on many systems '.' is used for other things). We put the
68 current defined CPLUS_MARKER first (which defaults to '$'), followed
69 by the next most common value, followed by an explicit '$' in case
70 the value of CPLUS_MARKER is not '$'.
72 We could avoid this if we could just get g++ to tell us what the actual
73 cplus marker character is as part of the debug information, perhaps by
74 ensuring that it is the character that terminates the gcc<n>_compiled
75 marker symbol (FIXME). */
77 #if !defined (CPLUS_MARKER)
78 #define CPLUS_MARKER '$'
79 #endif
81 enum demangling_styles current_demangling_style = gnu_demangling;
83 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
85 void
86 set_cplus_marker_for_demangling (ch)
87 int ch;
89 cplus_markers[0] = ch;
92 /* Stuff that is shared between sub-routines.
93 Using a shared structure allows cplus_demangle to be reentrant. */
95 struct work_stuff
97 int options;
98 char **typevec;
99 int ntypes;
100 int typevec_size;
101 int constructor;
102 int destructor;
103 int static_type; /* A static member function */
104 int const_type; /* A const member function */
105 char **tmpl_argvec; /* Template function arguments. */
106 int ntmpl_args; /* The number of template function arguments. */
109 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
110 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
112 static const struct optable
114 const char *in;
115 const char *out;
116 int flags;
117 } optable[] = {
118 {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */
119 {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */
120 {"new", " new", 0}, /* old (1.91, and 1.x) */
121 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
122 {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */
123 {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */
124 {"as", "=", DMGL_ANSI}, /* ansi */
125 {"ne", "!=", DMGL_ANSI}, /* old, ansi */
126 {"eq", "==", DMGL_ANSI}, /* old, ansi */
127 {"ge", ">=", DMGL_ANSI}, /* old, ansi */
128 {"gt", ">", DMGL_ANSI}, /* old, ansi */
129 {"le", "<=", DMGL_ANSI}, /* old, ansi */
130 {"lt", "<", DMGL_ANSI}, /* old, ansi */
131 {"plus", "+", 0}, /* old */
132 {"pl", "+", DMGL_ANSI}, /* ansi */
133 {"apl", "+=", DMGL_ANSI}, /* ansi */
134 {"minus", "-", 0}, /* old */
135 {"mi", "-", DMGL_ANSI}, /* ansi */
136 {"ami", "-=", DMGL_ANSI}, /* ansi */
137 {"mult", "*", 0}, /* old */
138 {"ml", "*", DMGL_ANSI}, /* ansi */
139 {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */
140 {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */
141 {"convert", "+", 0}, /* old (unary +) */
142 {"negate", "-", 0}, /* old (unary -) */
143 {"trunc_mod", "%", 0}, /* old */
144 {"md", "%", DMGL_ANSI}, /* ansi */
145 {"amd", "%=", DMGL_ANSI}, /* ansi */
146 {"trunc_div", "/", 0}, /* old */
147 {"dv", "/", DMGL_ANSI}, /* ansi */
148 {"adv", "/=", DMGL_ANSI}, /* ansi */
149 {"truth_andif", "&&", 0}, /* old */
150 {"aa", "&&", DMGL_ANSI}, /* ansi */
151 {"truth_orif", "||", 0}, /* old */
152 {"oo", "||", DMGL_ANSI}, /* ansi */
153 {"truth_not", "!", 0}, /* old */
154 {"nt", "!", DMGL_ANSI}, /* ansi */
155 {"postincrement","++", 0}, /* old */
156 {"pp", "++", DMGL_ANSI}, /* ansi */
157 {"postdecrement","--", 0}, /* old */
158 {"mm", "--", DMGL_ANSI}, /* ansi */
159 {"bit_ior", "|", 0}, /* old */
160 {"or", "|", DMGL_ANSI}, /* ansi */
161 {"aor", "|=", DMGL_ANSI}, /* ansi */
162 {"bit_xor", "^", 0}, /* old */
163 {"er", "^", DMGL_ANSI}, /* ansi */
164 {"aer", "^=", DMGL_ANSI}, /* ansi */
165 {"bit_and", "&", 0}, /* old */
166 {"ad", "&", DMGL_ANSI}, /* ansi */
167 {"aad", "&=", DMGL_ANSI}, /* ansi */
168 {"bit_not", "~", 0}, /* old */
169 {"co", "~", DMGL_ANSI}, /* ansi */
170 {"call", "()", 0}, /* old */
171 {"cl", "()", DMGL_ANSI}, /* ansi */
172 {"alshift", "<<", 0}, /* old */
173 {"ls", "<<", DMGL_ANSI}, /* ansi */
174 {"als", "<<=", DMGL_ANSI}, /* ansi */
175 {"arshift", ">>", 0}, /* old */
176 {"rs", ">>", DMGL_ANSI}, /* ansi */
177 {"ars", ">>=", DMGL_ANSI}, /* ansi */
178 {"component", "->", 0}, /* old */
179 {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */
180 {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */
181 {"indirect", "*", 0}, /* old */
182 {"method_call", "->()", 0}, /* old */
183 {"addr", "&", 0}, /* old (unary &) */
184 {"array", "[]", 0}, /* old */
185 {"vc", "[]", DMGL_ANSI}, /* ansi */
186 {"compound", ", ", 0}, /* old */
187 {"cm", ", ", DMGL_ANSI}, /* ansi */
188 {"cond", "?:", 0}, /* old */
189 {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */
190 {"max", ">?", 0}, /* old */
191 {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */
192 {"min", "<?", 0}, /* old */
193 {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
194 {"nop", "", 0}, /* old (for operator=) */
195 {"rm", "->*", DMGL_ANSI} /* ansi */
199 typedef struct string /* Beware: these aren't required to be */
200 { /* '\0' terminated. */
201 char *b; /* pointer to start of string */
202 char *p; /* pointer after last character */
203 char *e; /* pointer after end of allocated space */
204 } string;
206 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
207 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
208 string_prepend(str, " ");}
209 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
210 string_append(str, " ");}
212 #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
213 #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
215 /* Prototypes for local functions */
217 static char *
218 mop_up PARAMS ((struct work_stuff *, string *, int));
220 #if 0
221 static int
222 demangle_method_args PARAMS ((struct work_stuff *work, const char **, string *));
223 #endif
225 static int
226 demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
227 string *, int));
229 static int
230 arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **,
231 const char **));
233 static void
234 demangle_arm_pt PARAMS ((struct work_stuff *, const char **, int, string *));
236 static int
237 demangle_class_name PARAMS ((struct work_stuff *, const char **, string *));
239 static int
240 demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
241 int, int));
243 static int
244 demangle_class PARAMS ((struct work_stuff *, const char **, string *));
246 static int
247 demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
249 static int
250 demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
252 static int
253 demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
255 static int
256 gnu_special PARAMS ((struct work_stuff *, const char **, string *));
258 static int
259 arm_special PARAMS ((struct work_stuff *, const char **, string *));
261 static void
262 string_need PARAMS ((string *, int));
264 static void
265 string_delete PARAMS ((string *));
267 static void
268 string_init PARAMS ((string *));
270 static void
271 string_clear PARAMS ((string *));
273 #if 0
274 static int
275 string_empty PARAMS ((string *));
276 #endif
278 static void
279 string_append PARAMS ((string *, const char *));
281 static void
282 string_appends PARAMS ((string *, string *));
284 static void
285 string_appendn PARAMS ((string *, const char *, int));
287 static void
288 string_prepend PARAMS ((string *, const char *));
290 static void
291 string_prependn PARAMS ((string *, const char *, int));
293 static int
294 get_count PARAMS ((const char **, int *));
296 static int
297 consume_count PARAMS ((const char **));
299 static int
300 consume_count_with_underscores PARAMS ((const char**));
302 static int
303 demangle_args PARAMS ((struct work_stuff *, const char **, string *));
305 static int
306 do_type PARAMS ((struct work_stuff *, const char **, string *));
308 static int
309 do_arg PARAMS ((struct work_stuff *, const char **, string *));
311 static void
312 demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
313 const char *));
315 static void
316 remember_type PARAMS ((struct work_stuff *, const char *, int));
318 static void
319 forget_types PARAMS ((struct work_stuff *));
321 static void
322 string_prepends PARAMS ((string *, string *));
324 /* Translate count to integer, consuming tokens in the process.
325 Conversion terminates on the first non-digit character.
326 Trying to consume something that isn't a count results in
327 no consumption of input and a return of 0. */
329 static int
330 consume_count (type)
331 const char **type;
333 int count = 0;
335 while (isdigit (**type))
337 count *= 10;
338 count += **type - '0';
339 (*type)++;
341 return (count);
345 /* Like consume_count, but for counts that are preceeded and followed
346 by '_' if they are greater than 10. Also, -1 is returned for
347 failure, since 0 can be a valid value. */
349 static int
350 consume_count_with_underscores (mangled)
351 const char **mangled;
353 int idx;
355 if (**mangled == '_')
357 (*mangled)++;
358 if (!isdigit (**mangled))
359 return -1;
361 idx = consume_count (mangled);
362 if (**mangled != '_')
363 /* The trailing underscore was missing. */
364 return -1;
366 (*mangled)++;
368 else
370 if (**mangled < '0' || **mangled > '9')
371 return -1;
373 idx = **mangled - '0';
374 (*mangled)++;
377 return idx;
381 cplus_demangle_opname (opname, result, options)
382 const char *opname;
383 char *result;
384 int options;
386 int len, i, len1, ret;
387 string type;
388 struct work_stuff work[1];
389 const char *tem;
391 len = strlen(opname);
392 result[0] = '\0';
393 ret = 0;
394 work->options = options;
396 if (opname[0] == '_' && opname[1] == '_'
397 && opname[2] == 'o' && opname[3] == 'p')
399 /* ANSI. */
400 /* type conversion operator. */
401 tem = opname + 4;
402 if (do_type (work, &tem, &type))
404 strcat (result, "operator ");
405 strncat (result, type.b, type.p - type.b);
406 string_delete (&type);
407 ret = 1;
410 else if (opname[0] == '_' && opname[1] == '_'
411 && opname[2] >= 'a' && opname[2] <= 'z'
412 && opname[3] >= 'a' && opname[3] <= 'z')
414 if (opname[4] == '\0')
416 /* Operator. */
417 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
419 if (strlen (optable[i].in) == 2
420 && memcmp (optable[i].in, opname + 2, 2) == 0)
422 strcat (result, "operator");
423 strcat (result, optable[i].out);
424 ret = 1;
425 break;
429 else
431 if (opname[2] == 'a' && opname[5] == '\0')
433 /* Assignment. */
434 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
436 if (strlen (optable[i].in) == 3
437 && memcmp (optable[i].in, opname + 2, 3) == 0)
439 strcat (result, "operator");
440 strcat (result, optable[i].out);
441 ret = 1;
442 break;
448 else if (len >= 3
449 && opname[0] == 'o'
450 && opname[1] == 'p'
451 && strchr (cplus_markers, opname[2]) != NULL)
453 /* see if it's an assignment expression */
454 if (len >= 10 /* op$assign_ */
455 && memcmp (opname + 3, "assign_", 7) == 0)
457 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
459 len1 = len - 10;
460 if (strlen (optable[i].in) == len1
461 && memcmp (optable[i].in, opname + 10, len1) == 0)
463 strcat (result, "operator");
464 strcat (result, optable[i].out);
465 strcat (result, "=");
466 ret = 1;
467 break;
471 else
473 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
475 len1 = len - 3;
476 if (strlen (optable[i].in) == len1
477 && memcmp (optable[i].in, opname + 3, len1) == 0)
479 strcat (result, "operator");
480 strcat (result, optable[i].out);
481 ret = 1;
482 break;
487 else if (len >= 5 && memcmp (opname, "type", 4) == 0
488 && strchr (cplus_markers, opname[4]) != NULL)
490 /* type conversion operator */
491 tem = opname + 5;
492 if (do_type (work, &tem, &type))
494 strcat (result, "operator ");
495 strncat (result, type.b, type.p - type.b);
496 string_delete (&type);
497 ret = 1;
500 return ret;
503 /* Takes operator name as e.g. "++" and returns mangled
504 operator name (e.g. "postincrement_expr"), or NULL if not found.
506 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
507 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
509 const char *
510 cplus_mangle_opname (opname, options)
511 const char *opname;
512 int options;
514 int i;
515 int len;
517 len = strlen (opname);
518 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
520 if (strlen (optable[i].out) == len
521 && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
522 && memcmp (optable[i].out, opname, len) == 0)
523 return optable[i].in;
525 return (0);
528 /* char *cplus_demangle (const char *mangled, int options)
530 If MANGLED is a mangled function name produced by GNU C++, then
531 a pointer to a malloced string giving a C++ representation
532 of the name will be returned; otherwise NULL will be returned.
533 It is the caller's responsibility to free the string which
534 is returned.
536 The OPTIONS arg may contain one or more of the following bits:
538 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
539 included.
540 DMGL_PARAMS Function parameters are included.
542 For example,
544 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
545 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
546 cplus_demangle ("foo__1Ai", 0) => "A::foo"
548 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
549 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
550 cplus_demangle ("foo__1Afe", 0) => "A::foo"
552 Note that any leading underscores, or other such characters prepended by
553 the compilation system, are presumed to have already been stripped from
554 MANGLED. */
556 char *
557 cplus_demangle (mangled, options)
558 const char *mangled;
559 int options;
561 string decl;
562 int success = 0;
563 struct work_stuff work[1];
564 char *demangled = NULL;
566 if ((mangled != NULL) && (*mangled != '\0'))
568 memset ((char *) work, 0, sizeof (work));
569 work -> options = options;
570 if ((work->options & DMGL_STYLE_MASK) == 0)
571 work->options |= (int)current_demangling_style & DMGL_STYLE_MASK;
573 string_init (&decl);
575 /* First check to see if gnu style demangling is active and if the
576 string to be demangled contains a CPLUS_MARKER. If so, attempt to
577 recognize one of the gnu special forms rather than looking for a
578 standard prefix. In particular, don't worry about whether there
579 is a "__" string in the mangled string. Consider "_$_5__foo" for
580 example. */
582 if ((AUTO_DEMANGLING || GNU_DEMANGLING))
584 success = gnu_special (work, &mangled, &decl);
586 if (!success)
588 success = demangle_prefix (work, &mangled, &decl);
590 if (success && (*mangled != '\0'))
592 success = demangle_signature (work, &mangled, &decl);
594 if (work->constructor == 2)
596 string_prepend(&decl, "global constructors keyed to ");
597 work->constructor = 0;
599 else if (work->destructor == 2)
601 string_prepend(&decl, "global destructors keyed to ");
602 work->destructor = 0;
604 demangled = mop_up (work, &decl, success);
606 return (demangled);
609 static char *
610 mop_up (work, declp, success)
611 struct work_stuff *work;
612 string *declp;
613 int success;
615 char *demangled = NULL;
617 /* Discard the remembered types, if any. */
619 forget_types (work);
620 if (work -> typevec != NULL)
622 free ((char *) work -> typevec);
624 if (work->tmpl_argvec)
626 int i;
628 for (i = 0; i < work->ntmpl_args; i++)
629 if (work->tmpl_argvec[i])
630 free ((char*) work->tmpl_argvec[i]);
632 free ((char*) work->tmpl_argvec);
635 /* If demangling was successful, ensure that the demangled string is null
636 terminated and return it. Otherwise, free the demangling decl. */
638 if (!success)
640 string_delete (declp);
642 else
644 string_appendn (declp, "", 1);
645 demangled = declp -> b;
647 return (demangled);
652 LOCAL FUNCTION
654 demangle_signature -- demangle the signature part of a mangled name
656 SYNOPSIS
658 static int
659 demangle_signature (struct work_stuff *work, const char **mangled,
660 string *declp);
662 DESCRIPTION
664 Consume and demangle the signature portion of the mangled name.
666 DECLP is the string where demangled output is being built. At
667 entry it contains the demangled root name from the mangled name
668 prefix. I.E. either a demangled operator name or the root function
669 name. In some special cases, it may contain nothing.
671 *MANGLED points to the current unconsumed location in the mangled
672 name. As tokens are consumed and demangling is performed, the
673 pointer is updated to continuously point at the next token to
674 be consumed.
676 Demangling GNU style mangled names is nasty because there is no
677 explicit token that marks the start of the outermost function
678 argument list. */
680 static int
681 demangle_signature (work, mangled, declp)
682 struct work_stuff *work;
683 const char **mangled;
684 string *declp;
686 int success = 1;
687 int func_done = 0;
688 int expect_func = 0;
689 int expect_return_type = 0;
690 const char *oldmangled = NULL;
691 string trawname;
692 string tname;
694 while (success && (**mangled != '\0'))
696 switch (**mangled)
698 case 'Q':
699 oldmangled = *mangled;
700 success = demangle_qualified (work, mangled, declp, 1, 0);
701 if (success)
703 remember_type (work, oldmangled, *mangled - oldmangled);
705 if (AUTO_DEMANGLING || GNU_DEMANGLING)
707 expect_func = 1;
709 oldmangled = NULL;
710 break;
712 case 'S':
713 /* Static member function */
714 if (oldmangled == NULL)
716 oldmangled = *mangled;
718 (*mangled)++;
719 work -> static_type = 1;
720 break;
722 case 'C':
723 /* a const member function */
724 if (oldmangled == NULL)
726 oldmangled = *mangled;
728 (*mangled)++;
729 work -> const_type = 1;
730 break;
732 case '0': case '1': case '2': case '3': case '4':
733 case '5': case '6': case '7': case '8': case '9':
734 if (oldmangled == NULL)
736 oldmangled = *mangled;
738 success = demangle_class (work, mangled, declp);
739 if (success)
741 remember_type (work, oldmangled, *mangled - oldmangled);
743 if (AUTO_DEMANGLING || GNU_DEMANGLING)
745 expect_func = 1;
747 oldmangled = NULL;
748 break;
750 case 'F':
751 /* Function */
752 /* ARM style demangling includes a specific 'F' character after
753 the class name. For GNU style, it is just implied. So we can
754 safely just consume any 'F' at this point and be compatible
755 with either style. */
757 oldmangled = NULL;
758 func_done = 1;
759 (*mangled)++;
761 /* For lucid/ARM style we have to forget any types we might
762 have remembered up to this point, since they were not argument
763 types. GNU style considers all types seen as available for
764 back references. See comment in demangle_args() */
766 if (LUCID_DEMANGLING || ARM_DEMANGLING)
768 forget_types (work);
770 success = demangle_args (work, mangled, declp);
771 break;
773 case 't':
774 /* G++ Template */
775 string_init(&trawname);
776 string_init(&tname);
777 if (oldmangled == NULL)
779 oldmangled = *mangled;
781 success = demangle_template (work, mangled, &tname, &trawname, 1);
782 if (success)
784 remember_type (work, oldmangled, *mangled - oldmangled);
786 string_append(&tname, (work -> options & DMGL_JAVA) ? "." : "::");
787 string_prepends(declp, &tname);
788 if (work -> destructor & 1)
790 string_prepend (&trawname, "~");
791 string_appends (declp, &trawname);
792 work->destructor -= 1;
794 if ((work->constructor & 1) || (work->destructor & 1))
796 string_appends (declp, &trawname);
797 work->constructor -= 1;
799 string_delete(&trawname);
800 string_delete(&tname);
801 oldmangled = NULL;
802 expect_func = 1;
803 break;
805 case '_':
806 if (GNU_DEMANGLING && expect_return_type)
808 /* Read the return type. */
809 string return_type;
810 string_init (&return_type);
812 (*mangled)++;
813 success = do_type (work, mangled, &return_type);
814 APPEND_BLANK (&return_type);
816 string_prepends (declp, &return_type);
817 string_delete (&return_type);
818 break;
820 else
821 /* At the outermost level, we cannot have a return type specified,
822 so if we run into another '_' at this point we are dealing with
823 a mangled name that is either bogus, or has been mangled by
824 some algorithm we don't know how to deal with. So just
825 reject the entire demangling. */
826 success = 0;
827 break;
829 case 'H':
830 if (GNU_DEMANGLING)
832 /* A G++ template function. Read the template arguments. */
833 success = demangle_template (work, mangled, declp, 0, 0);
834 if (!(work->constructor & 1))
835 expect_return_type = 1;
836 (*mangled)++;
837 break;
839 else
840 /* fall through */
843 default:
844 if (AUTO_DEMANGLING || GNU_DEMANGLING)
846 /* Assume we have stumbled onto the first outermost function
847 argument token, and start processing args. */
848 func_done = 1;
849 success = demangle_args (work, mangled, declp);
851 else
853 /* Non-GNU demanglers use a specific token to mark the start
854 of the outermost function argument tokens. Typically 'F',
855 for ARM-demangling, for example. So if we find something
856 we are not prepared for, it must be an error. */
857 success = 0;
859 break;
862 if (AUTO_DEMANGLING || GNU_DEMANGLING)
865 if (success && expect_func)
867 func_done = 1;
868 success = demangle_args (work, mangled, declp);
869 /* Since template include the mangling of their return types,
870 we must set expect_func to 0 so that we don't try do
871 demangle more arguments the next time we get here. */
872 expect_func = 0;
876 if (success && !func_done)
878 if (AUTO_DEMANGLING || GNU_DEMANGLING)
880 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
881 bar__3fooi is 'foo::bar(int)'. We get here when we find the
882 first case, and need to ensure that the '(void)' gets added to
883 the current declp. Note that with ARM, the first case
884 represents the name of a static data member 'foo::bar',
885 which is in the current declp, so we leave it alone. */
886 success = demangle_args (work, mangled, declp);
889 if (success && work -> static_type && PRINT_ARG_TYPES)
891 string_append (declp, " static");
893 if (success && work -> const_type && PRINT_ARG_TYPES)
895 string_append (declp, " const");
897 return (success);
900 #if 0
902 static int
903 demangle_method_args (work, mangled, declp)
904 struct work_stuff *work;
905 const char **mangled;
906 string *declp;
908 int success = 0;
910 if (work -> static_type)
912 string_append (declp, *mangled + 1);
913 *mangled += strlen (*mangled);
914 success = 1;
916 else
918 success = demangle_args (work, mangled, declp);
920 return (success);
923 #endif
925 static int
926 demangle_template (work, mangled, tname, trawname, is_type)
927 struct work_stuff *work;
928 const char **mangled;
929 string *tname;
930 string *trawname;
931 int is_type;
933 int i;
934 int is_pointer;
935 int is_real;
936 int is_integral;
937 int is_char;
938 int is_bool;
939 int r;
940 int need_comma = 0;
941 int success = 0;
942 int done;
943 const char *old_p;
944 const char *start;
945 int symbol_len;
946 int is_java_array = 0;
947 string temp;
949 (*mangled)++;
950 if (is_type)
952 start = *mangled;
953 /* get template name */
954 if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
956 return (0);
958 if (trawname)
959 string_appendn (trawname, *mangled, r);
960 is_java_array = (work -> options & DMGL_JAVA)
961 && strncmp (*mangled, "JArray1Z", 8) == 0;
962 if (! is_java_array)
964 string_appendn (tname, *mangled, r);
966 *mangled += r;
968 if (!is_java_array)
969 string_append (tname, "<");
970 /* get size of template parameter list */
971 if (!get_count (mangled, &r))
973 return (0);
975 if (!is_type)
977 /* Create an array for saving the template argument values. */
978 work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
979 work->ntmpl_args = r;
980 for (i = 0; i < r; i++)
981 work->tmpl_argvec[i] = 0;
983 for (i = 0; i < r; i++)
985 if (need_comma)
987 string_append (tname, ", ");
989 /* Z for type parameters */
990 if (**mangled == 'Z')
992 (*mangled)++;
993 /* temp is initialized in do_type */
994 success = do_type (work, mangled, &temp);
995 if (success)
997 string_appends (tname, &temp);
999 if (!is_type)
1001 /* Save the template argument. */
1002 int len = temp.p - temp.b;
1003 work->tmpl_argvec[i] = xmalloc (len + 1);
1004 memcpy (work->tmpl_argvec[i], temp.b, len);
1005 work->tmpl_argvec[i][len] = '\0';
1008 string_delete(&temp);
1009 if (!success)
1011 break;
1014 else
1016 string param;
1017 string* s;
1019 /* otherwise, value parameter */
1020 old_p = *mangled;
1021 is_pointer = 0;
1022 is_real = 0;
1023 is_integral = 0;
1024 is_char = 0;
1025 is_bool = 0;
1026 done = 0;
1027 /* temp is initialized in do_type */
1028 success = do_type (work, mangled, &temp);
1030 if (success)
1032 string_appends (s, &temp);
1035 string_delete(&temp);
1036 if (!success)
1038 break;
1041 string_append (s, "=");
1044 if (!is_type)
1046 s = &param;
1047 string_init (s);
1049 else
1050 s = tname;
1052 while (*old_p && !done)
1054 switch (*old_p)
1056 case 'P':
1057 case 'p':
1058 case 'R':
1059 done = is_pointer = 1;
1060 break;
1061 case 'C': /* const */
1062 case 'S': /* explicitly signed [char] */
1063 case 'U': /* unsigned */
1064 case 'V': /* volatile */
1065 case 'F': /* function */
1066 case 'M': /* member function */
1067 case 'O': /* ??? */
1068 case 'J': /* complex */
1069 old_p++;
1070 continue;
1071 case 'Q': /* qualified name */
1072 done = is_integral = 1;
1073 break;
1074 case 'T': /* remembered type */
1075 abort ();
1076 break;
1077 case 'v': /* void */
1078 abort ();
1079 break;
1080 case 'x': /* long long */
1081 case 'l': /* long */
1082 case 'i': /* int */
1083 case 's': /* short */
1084 case 'w': /* wchar_t */
1085 done = is_integral = 1;
1086 break;
1087 case 'b': /* bool */
1088 done = is_bool = 1;
1089 break;
1090 case 'c': /* char */
1091 done = is_char = 1;
1092 break;
1093 case 'r': /* long double */
1094 case 'd': /* double */
1095 case 'f': /* float */
1096 done = is_real = 1;
1097 break;
1098 default:
1099 /* it's probably user defined type, let's assume
1100 it's integral, it seems hard to figure out
1101 what it really is */
1102 done = is_integral = 1;
1105 if (**mangled == 'Y')
1107 /* The next argument is a template parameter. */
1108 int idx;
1110 (*mangled)++;
1111 idx = consume_count_with_underscores (mangled);
1112 if (idx == -1
1113 || (work->tmpl_argvec && idx >= work->ntmpl_args)
1114 || consume_count_with_underscores (mangled) == -1)
1116 success = 0;
1117 if (!is_type)
1118 string_delete (s);
1119 break;
1121 if (work->tmpl_argvec)
1122 string_append (s, work->tmpl_argvec[idx]);
1123 else
1125 char buf[10];
1126 sprintf(buf, "T%d", idx);
1127 string_append (s, buf);
1130 else if (is_integral)
1132 if (**mangled == 'm')
1134 string_appendn (s, "-", 1);
1135 (*mangled)++;
1137 while (isdigit (**mangled))
1139 string_appendn (s, *mangled, 1);
1140 (*mangled)++;
1143 else if (is_char)
1145 char tmp[2];
1146 int val;
1147 if (**mangled == 'm')
1149 string_appendn (s, "-", 1);
1150 (*mangled)++;
1152 string_appendn (s, "'", 1);
1153 val = consume_count(mangled);
1154 if (val == 0)
1156 success = 0;
1157 if (!is_type)
1158 string_delete (s);
1159 break;
1161 tmp[0] = (char)val;
1162 tmp[1] = '\0';
1163 string_appendn (s, &tmp[0], 1);
1164 string_appendn (s, "'", 1);
1166 else if (is_bool)
1168 int val = consume_count (mangled);
1169 if (val == 0)
1170 string_appendn (s, "false", 5);
1171 else if (val == 1)
1172 string_appendn (s, "true", 4);
1173 else
1174 success = 0;
1176 else if (is_real)
1178 if (**mangled == 'm')
1180 string_appendn (s, "-", 1);
1181 (*mangled)++;
1183 while (isdigit (**mangled))
1185 string_appendn (s, *mangled, 1);
1186 (*mangled)++;
1188 if (**mangled == '.') /* fraction */
1190 string_appendn (s, ".", 1);
1191 (*mangled)++;
1192 while (isdigit (**mangled))
1194 string_appendn (s, *mangled, 1);
1195 (*mangled)++;
1198 if (**mangled == 'e') /* exponent */
1200 string_appendn (s, "e", 1);
1201 (*mangled)++;
1202 while (isdigit (**mangled))
1204 string_appendn (s, *mangled, 1);
1205 (*mangled)++;
1209 else if (is_pointer)
1211 symbol_len = consume_count (mangled);
1212 if (symbol_len == 0)
1214 success = 0;
1215 if (!is_type)
1216 string_delete (s);
1217 break;
1219 if (symbol_len == 0)
1220 string_appendn (s, "0", 1);
1221 else
1223 char *p = xmalloc (symbol_len + 1), *q;
1224 strncpy (p, *mangled, symbol_len);
1225 p [symbol_len] = '\0';
1226 q = cplus_demangle (p, work->options);
1227 string_appendn (s, "&", 1);
1228 if (q)
1230 string_append (s, q);
1231 free (q);
1233 else
1234 string_append (s, p);
1235 free (p);
1237 *mangled += symbol_len;
1239 if (!is_type)
1241 int len = s->p - s->b;
1242 work->tmpl_argvec[i] = xmalloc (len + 1);
1243 memcpy (work->tmpl_argvec[i], s->b, len);
1244 work->tmpl_argvec[i][len] = '\0';
1246 string_appends (tname, s);
1247 string_delete (s);
1250 need_comma = 1;
1252 if (is_java_array)
1254 string_append (tname, "[]");
1256 else
1258 if (tname->p[-1] == '>')
1259 string_append (tname, " ");
1260 string_append (tname, ">");
1264 if (work -> static_type)
1266 string_append (declp, *mangled + 1);
1267 *mangled += strlen (*mangled);
1268 success = 1;
1270 else
1272 success = demangle_args (work, mangled, declp);
1276 return (success);
1279 static int
1280 arm_pt (work, mangled, n, anchor, args)
1281 struct work_stuff *work;
1282 const char *mangled;
1283 int n;
1284 const char **anchor, **args;
1286 /* ARM template? */
1287 if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
1289 int len;
1290 *args = *anchor + 6;
1291 len = consume_count (args);
1292 if (*args + len == mangled + n && **args == '_')
1294 ++*args;
1295 return 1;
1298 return 0;
1301 static void
1302 demangle_arm_pt (work, mangled, n, declp)
1303 struct work_stuff *work;
1304 const char **mangled;
1305 int n;
1306 string *declp;
1308 const char *p;
1309 const char *args;
1310 const char *e = *mangled + n;
1312 /* ARM template? */
1313 if (arm_pt (work, *mangled, n, &p, &args))
1315 string arg;
1316 string_init (&arg);
1317 string_appendn (declp, *mangled, p - *mangled);
1318 string_append (declp, "<");
1319 /* should do error checking here */
1320 while (args < e) {
1321 string_clear (&arg);
1322 do_type (work, &args, &arg);
1323 string_appends (declp, &arg);
1324 string_append (declp, ",");
1326 string_delete (&arg);
1327 --declp->p;
1328 string_append (declp, ">");
1330 else
1332 string_appendn (declp, *mangled, n);
1334 *mangled += n;
1337 static int
1338 demangle_class_name (work, mangled, declp)
1339 struct work_stuff *work;
1340 const char **mangled;
1341 string *declp;
1343 int n;
1344 int success = 0;
1346 n = consume_count (mangled);
1347 if (strlen (*mangled) >= n)
1349 demangle_arm_pt (work, mangled, n, declp);
1350 success = 1;
1353 return (success);
1358 LOCAL FUNCTION
1360 demangle_class -- demangle a mangled class sequence
1362 SYNOPSIS
1364 static int
1365 demangle_class (struct work_stuff *work, const char **mangled,
1366 strint *declp)
1368 DESCRIPTION
1370 DECLP points to the buffer into which demangling is being done.
1372 *MANGLED points to the current token to be demangled. On input,
1373 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1374 On exit, it points to the next token after the mangled class on
1375 success, or the first unconsumed token on failure.
1377 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1378 we are demangling a constructor or destructor. In this case
1379 we prepend "class::class" or "class::~class" to DECLP.
1381 Otherwise, we prepend "class::" to the current DECLP.
1383 Reset the constructor/destructor flags once they have been
1384 "consumed". This allows demangle_class to be called later during
1385 the same demangling, to do normal class demangling.
1387 Returns 1 if demangling is successful, 0 otherwise.
1391 static int
1392 demangle_class (work, mangled, declp)
1393 struct work_stuff *work;
1394 const char **mangled;
1395 string *declp;
1397 int success = 0;
1398 string class_name;
1400 string_init (&class_name);
1401 if (demangle_class_name (work, mangled, &class_name))
1403 if ((work->constructor & 1) || (work->destructor & 1))
1405 string_prepends (declp, &class_name);
1406 if (work -> destructor & 1)
1408 string_prepend (declp, "~");
1409 work -> destructor -= 1;
1411 else
1413 work -> constructor -= 1;
1416 string_prepend (declp, (work -> options & DMGL_JAVA) ? "." : "::");
1417 string_prepends (declp, &class_name);
1418 success = 1;
1420 string_delete (&class_name);
1421 return (success);
1426 LOCAL FUNCTION
1428 demangle_prefix -- consume the mangled name prefix and find signature
1430 SYNOPSIS
1432 static int
1433 demangle_prefix (struct work_stuff *work, const char **mangled,
1434 string *declp);
1436 DESCRIPTION
1438 Consume and demangle the prefix of the mangled name.
1440 DECLP points to the string buffer into which demangled output is
1441 placed. On entry, the buffer is empty. On exit it contains
1442 the root function name, the demangled operator name, or in some
1443 special cases either nothing or the completely demangled result.
1445 MANGLED points to the current pointer into the mangled name. As each
1446 token of the mangled name is consumed, it is updated. Upon entry
1447 the current mangled name pointer points to the first character of
1448 the mangled name. Upon exit, it should point to the first character
1449 of the signature if demangling was successful, or to the first
1450 unconsumed character if demangling of the prefix was unsuccessful.
1452 Returns 1 on success, 0 otherwise.
1455 static int
1456 demangle_prefix (work, mangled, declp)
1457 struct work_stuff *work;
1458 const char **mangled;
1459 string *declp;
1461 int success = 1;
1462 const char *scan;
1463 int i;
1465 if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
1467 char *marker = strchr (cplus_markers, (*mangled)[8]);
1468 if (marker != NULL && *marker == (*mangled)[10])
1470 if ((*mangled)[9] == 'D')
1472 /* it's a GNU global destructor to be executed at program exit */
1473 (*mangled) += 11;
1474 work->destructor = 2;
1475 if (gnu_special (work, mangled, declp))
1476 return success;
1478 else if ((*mangled)[9] == 'I')
1480 /* it's a GNU global constructor to be executed at program init */
1481 (*mangled) += 11;
1482 work->constructor = 2;
1483 if (gnu_special (work, mangled, declp))
1484 return success;
1488 else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
1490 /* it's a ARM global destructor to be executed at program exit */
1491 (*mangled) += 7;
1492 work->destructor = 2;
1494 else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
1496 /* it's a ARM global constructor to be executed at program initial */
1497 (*mangled) += 7;
1498 work->constructor = 2;
1501 /* This block of code is a reduction in strength time optimization
1503 scan = mystrstr (*mangled, "__"); */
1506 scan = *mangled;
1508 do {
1509 scan = strchr (scan, '_');
1510 } while (scan != NULL && *++scan != '_');
1512 if (scan != NULL) --scan;
1515 if (scan != NULL)
1517 /* We found a sequence of two or more '_', ensure that we start at
1518 the last pair in the sequence. */
1519 i = strspn (scan, "_");
1520 if (i > 2)
1522 scan += (i - 2);
1526 if (scan == NULL)
1528 success = 0;
1530 else if (work -> static_type)
1532 if (!isdigit (scan[0]) && (scan[0] != 't'))
1534 success = 0;
1537 else if ((scan == *mangled)
1538 && (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')
1539 || (scan[2] == 'H')))
1541 /* The ARM says nothing about the mangling of local variables.
1542 But cfront mangles local variables by prepending __<nesting_level>
1543 to them. As an extension to ARM demangling we handle this case. */
1544 if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
1546 *mangled = scan + 2;
1547 consume_count (mangled);
1548 string_append (declp, *mangled);
1549 *mangled += strlen (*mangled);
1550 success = 1;
1552 else
1554 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1555 names like __Q2_3foo3bar for nested type names. So don't accept
1556 this style of constructor for cfront demangling. A GNU
1557 style member-template constructor starts with 'H'. */
1558 if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
1559 work -> constructor += 1;
1560 *mangled = scan + 2;
1563 else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
1565 /* Mangled name starts with "__". Skip over any leading '_' characters,
1566 then find the next "__" that separates the prefix from the signature.
1568 if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
1569 || (arm_special (work, mangled, declp) == 0))
1571 while (*scan == '_')
1573 scan++;
1575 if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
1577 /* No separator (I.E. "__not_mangled"), or empty signature
1578 (I.E. "__not_mangled_either__") */
1579 success = 0;
1581 else
1583 demangle_function_name (work, mangled, declp, scan);
1587 else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
1589 /* Cfront-style parameterized type. Handled later as a signature. */
1590 success = 1;
1592 /* ARM template? */
1593 demangle_arm_pt (work, mangled, strlen (*mangled), declp);
1595 else if (*(scan + 2) != '\0')
1597 /* Mangled name does not start with "__" but does have one somewhere
1598 in there with non empty stuff after it. Looks like a global
1599 function name. */
1600 demangle_function_name (work, mangled, declp, scan);
1602 else
1604 /* Doesn't look like a mangled name */
1605 success = 0;
1608 if (!success && (work->constructor == 2 || work->destructor == 2))
1610 string_append (declp, *mangled);
1611 *mangled += strlen (*mangled);
1612 success = 1;
1614 return (success);
1619 LOCAL FUNCTION
1621 gnu_special -- special handling of gnu mangled strings
1623 SYNOPSIS
1625 static int
1626 gnu_special (struct work_stuff *work, const char **mangled,
1627 string *declp);
1630 DESCRIPTION
1632 Process some special GNU style mangling forms that don't fit
1633 the normal pattern. For example:
1635 _$_3foo (destructor for class foo)
1636 _vt$foo (foo virtual table)
1637 _vt$foo$bar (foo::bar virtual table)
1638 __vt_foo (foo virtual table, new style with thunks)
1639 _3foo$varname (static data member)
1640 _Q22rs2tu$vw (static data member)
1641 __t6vector1Zii (constructor with template)
1642 __thunk_4__$_7ostream (virtual function thunk)
1645 static int
1646 gnu_special (work, mangled, declp)
1647 struct work_stuff *work;
1648 const char **mangled;
1649 string *declp;
1651 int n;
1652 int success = 1;
1653 const char *p;
1655 if ((*mangled)[0] == '_'
1656 && strchr (cplus_markers, (*mangled)[1]) != NULL
1657 && (*mangled)[2] == '_')
1659 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1660 (*mangled) += 3;
1661 work -> destructor += 1;
1663 else if ((*mangled)[0] == '_'
1664 && (((*mangled)[1] == '_'
1665 && (*mangled)[2] == 'v'
1666 && (*mangled)[3] == 't'
1667 && (*mangled)[4] == '_')
1668 || ((*mangled)[1] == 'v'
1669 && (*mangled)[2] == 't'
1670 && strchr (cplus_markers, (*mangled)[3]) != NULL)))
1672 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1673 and create the decl. Note that we consume the entire mangled
1674 input string, which means that demangle_signature has no work
1675 to do. */
1676 if ((*mangled)[2] == 'v')
1677 (*mangled) += 5; /* New style, with thunks: "__vt_" */
1678 else
1679 (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1680 while (**mangled != '\0')
1682 p = strpbrk (*mangled, cplus_markers);
1683 switch (**mangled)
1685 case 'Q':
1686 success = demangle_qualified (work, mangled, declp, 0, 1);
1687 break;
1688 case 't':
1689 success = demangle_template (work, mangled, declp, 0, 1);
1690 break;
1691 default:
1692 if (isdigit(*mangled[0]))
1694 n = consume_count(mangled);
1696 else
1698 n = strcspn (*mangled, cplus_markers);
1700 string_appendn (declp, *mangled, n);
1701 (*mangled) += n;
1704 if (success && ((p == NULL) || (p == *mangled)))
1706 if (p != NULL)
1708 string_append (declp,
1709 (work -> options & DMGL_JAVA) ? "." : "::");
1710 (*mangled)++;
1713 else
1715 success = 0;
1716 break;
1719 if (success)
1720 string_append (declp, " virtual table");
1722 else if ((*mangled)[0] == '_'
1723 && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
1724 && (p = strpbrk (*mangled, cplus_markers)) != NULL)
1726 /* static data member, "_3foo$varname" for example */
1727 (*mangled)++;
1728 switch (**mangled)
1730 case 'Q':
1731 success = demangle_qualified (work, mangled, declp, 0, 1);
1732 break;
1733 case 't':
1734 success = demangle_template (work, mangled, declp, 0, 1);
1735 break;
1736 default:
1737 n = consume_count (mangled);
1738 string_appendn (declp, *mangled, n);
1739 (*mangled) += n;
1741 if (success && (p == *mangled))
1743 /* Consumed everything up to the cplus_marker, append the
1744 variable name. */
1745 (*mangled)++;
1746 string_append (declp, (work -> options & DMGL_JAVA) ? "." : "::");
1747 n = strlen (*mangled);
1748 string_appendn (declp, *mangled, n);
1749 (*mangled) += n;
1751 else
1753 success = 0;
1756 else if (strncmp (*mangled, "__thunk_", 8) == 0)
1758 int delta = ((*mangled) += 8, consume_count (mangled));
1759 char *method = cplus_demangle (++*mangled, work->options);
1760 if (method)
1762 char buf[50];
1763 sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
1764 string_append (declp, buf);
1765 string_append (declp, method);
1766 free (method);
1767 n = strlen (*mangled);
1768 (*mangled) += n;
1770 else
1772 success = 0;
1775 else if (strncmp (*mangled, "__t", 3) == 0
1776 && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
1778 p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
1779 (*mangled) += 4;
1780 switch (**mangled)
1782 case 'Q':
1783 success = demangle_qualified (work, mangled, declp, 0, 1);
1784 break;
1785 case 't':
1786 success = demangle_template (work, mangled, declp, 0, 1);
1787 break;
1788 default:
1789 success = demangle_fund_type (work, mangled, declp);
1790 break;
1792 if (success && **mangled != '\0')
1793 success = 0;
1794 if (success)
1795 string_append (declp, p);
1797 else
1799 success = 0;
1801 return (success);
1806 LOCAL FUNCTION
1808 arm_special -- special handling of ARM/lucid mangled strings
1810 SYNOPSIS
1812 static int
1813 arm_special (struct work_stuff *work, const char **mangled,
1814 string *declp);
1817 DESCRIPTION
1819 Process some special ARM style mangling forms that don't fit
1820 the normal pattern. For example:
1822 __vtbl__3foo (foo virtual table)
1823 __vtbl__3foo__3bar (bar::foo virtual table)
1827 static int
1828 arm_special (work, mangled, declp)
1829 struct work_stuff *work;
1830 const char **mangled;
1831 string *declp;
1833 int n;
1834 int success = 1;
1835 const char *scan;
1837 if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
1839 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
1840 and create the decl. Note that we consume the entire mangled
1841 input string, which means that demangle_signature has no work
1842 to do. */
1843 scan = *mangled + ARM_VTABLE_STRLEN;
1844 while (*scan != '\0') /* first check it can be demangled */
1846 n = consume_count (&scan);
1847 if (n==0)
1849 return (0); /* no good */
1851 scan += n;
1852 if (scan[0] == '_' && scan[1] == '_')
1854 scan += 2;
1857 (*mangled) += ARM_VTABLE_STRLEN;
1858 while (**mangled != '\0')
1860 n = consume_count (mangled);
1861 string_prependn (declp, *mangled, n);
1862 (*mangled) += n;
1863 if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
1865 string_prepend (declp, "::");
1866 (*mangled) += 2;
1869 string_append (declp, " virtual table");
1871 else
1873 success = 0;
1875 return (success);
1880 LOCAL FUNCTION
1882 demangle_qualified -- demangle 'Q' qualified name strings
1884 SYNOPSIS
1886 static int
1887 demangle_qualified (struct work_stuff *, const char *mangled,
1888 string *result, int isfuncname, int append);
1890 DESCRIPTION
1892 Demangle a qualified name, such as "Q25Outer5Inner" which is
1893 the mangled form of "Outer::Inner". The demangled output is
1894 prepended or appended to the result string according to the
1895 state of the append flag.
1897 If isfuncname is nonzero, then the qualified name we are building
1898 is going to be used as a member function name, so if it is a
1899 constructor or destructor function, append an appropriate
1900 constructor or destructor name. I.E. for the above example,
1901 the result for use as a constructor is "Outer::Inner::Inner"
1902 and the result for use as a destructor is "Outer::Inner::~Inner".
1904 BUGS
1906 Numeric conversion is ASCII dependent (FIXME).
1910 static int
1911 demangle_qualified (work, mangled, result, isfuncname, append)
1912 struct work_stuff *work;
1913 const char **mangled;
1914 string *result;
1915 int isfuncname;
1916 int append;
1918 int qualifiers;
1919 int namelength;
1920 int success = 1;
1921 const char *p;
1922 char num[2];
1923 string temp;
1925 string_init (&temp);
1926 switch ((*mangled)[1])
1928 case '_':
1929 /* GNU mangled name with more than 9 classes. The count is preceded
1930 by an underscore (to distinguish it from the <= 9 case) and followed
1931 by an underscore. */
1932 p = *mangled + 2;
1933 qualifiers = atoi (p);
1934 if (!isdigit (*p) || *p == '0')
1935 success = 0;
1937 /* Skip the digits. */
1938 while (isdigit (*p))
1939 ++p;
1941 if (*p != '_')
1942 success = 0;
1944 *mangled = p + 1;
1945 break;
1947 case '1':
1948 case '2':
1949 case '3':
1950 case '4':
1951 case '5':
1952 case '6':
1953 case '7':
1954 case '8':
1955 case '9':
1956 /* The count is in a single digit. */
1957 num[0] = (*mangled)[1];
1958 num[1] = '\0';
1959 qualifiers = atoi (num);
1961 /* If there is an underscore after the digit, skip it. This is
1962 said to be for ARM-qualified names, but the ARM makes no
1963 mention of such an underscore. Perhaps cfront uses one. */
1964 if ((*mangled)[2] == '_')
1966 (*mangled)++;
1968 (*mangled) += 2;
1969 break;
1971 case '0':
1972 default:
1973 success = 0;
1976 if (!success)
1977 return success;
1979 /* Pick off the names and collect them in the temp buffer in the order
1980 in which they are found, separated by '::'. */
1982 while (qualifiers-- > 0)
1984 if (*mangled[0] == '_')
1985 *mangled = *mangled + 1;
1986 if (*mangled[0] == 't')
1988 success = demangle_template(work, mangled, &temp, 0, 1);
1989 if (!success) break;
1991 else if (*mangled[0] == 'X')
1993 success = do_type (work, mangled, &temp);
1994 if (!success) break;
1996 else
1998 namelength = consume_count (mangled);
1999 if (strlen (*mangled) < namelength)
2001 /* Simple sanity check failed */
2002 success = 0;
2003 break;
2005 string_appendn (&temp, *mangled, namelength);
2006 *mangled += namelength;
2008 if (qualifiers > 0)
2010 string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2014 /* If we are using the result as a function name, we need to append
2015 the appropriate '::' separated constructor or destructor name.
2016 We do this here because this is the most convenient place, where
2017 we already have a pointer to the name and the length of the name. */
2019 if (isfuncname && (work->constructor & 1 || work->destructor & 1))
2021 string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2022 if (work -> destructor & 1)
2024 string_append (&temp, "~");
2026 string_appendn (&temp, (*mangled) - namelength, namelength);
2029 /* Now either prepend the temp buffer to the result, or append it,
2030 depending upon the state of the append flag. */
2032 if (append)
2034 string_appends (result, &temp);
2036 else
2038 if (!STRING_EMPTY (result))
2040 string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2042 string_prepends (result, &temp);
2045 string_delete (&temp);
2046 return (success);
2051 LOCAL FUNCTION
2053 get_count -- convert an ascii count to integer, consuming tokens
2055 SYNOPSIS
2057 static int
2058 get_count (const char **type, int *count)
2060 DESCRIPTION
2062 Return 0 if no conversion is performed, 1 if a string is converted.
2065 static int
2066 get_count (type, count)
2067 const char **type;
2068 int *count;
2070 const char *p;
2071 int n;
2073 if (!isdigit (**type))
2075 return (0);
2077 else
2079 *count = **type - '0';
2080 (*type)++;
2081 if (isdigit (**type))
2083 p = *type;
2084 n = *count;
2087 n *= 10;
2088 n += *p - '0';
2089 p++;
2091 while (isdigit (*p));
2092 if (*p == '_')
2094 *type = p + 1;
2095 *count = n;
2099 return (1);
2102 /* result will be initialised here; it will be freed on failure */
2104 static int
2105 do_type (work, mangled, result)
2106 struct work_stuff *work;
2107 const char **mangled;
2108 string *result;
2110 int n;
2111 int done;
2112 int success;
2113 string decl;
2114 const char *remembered_type;
2115 int constp;
2116 int volatilep;
2118 string_init (&decl);
2119 string_init (result);
2121 done = 0;
2122 success = 1;
2123 while (success && !done)
2125 int member;
2126 switch (**mangled)
2129 /* A pointer type */
2130 case 'P':
2131 case 'p':
2132 (*mangled)++;
2133 if (! (work -> options & DMGL_JAVA))
2134 string_prepend (&decl, "*");
2135 break;
2137 /* A reference type */
2138 case 'R':
2139 (*mangled)++;
2140 string_prepend (&decl, "&");
2141 break;
2143 /* An array */
2144 case 'A':
2146 const char *p = ++(*mangled);
2148 string_prepend (&decl, "(");
2149 string_append (&decl, ")[");
2150 /* Copy anything up until the next underscore (the size of the
2151 array). */
2152 while (**mangled && **mangled != '_')
2153 ++(*mangled);
2154 if (**mangled == '_')
2156 string_appendn (&decl, p, *mangled - p);
2157 string_append (&decl, "]");
2158 *mangled += 1;
2160 else
2161 success = 0;
2162 break;
2165 /* A back reference to a previously seen type */
2166 case 'T':
2167 (*mangled)++;
2168 if (!get_count (mangled, &n) || n >= work -> ntypes)
2170 success = 0;
2172 else
2174 remembered_type = work -> typevec[n];
2175 mangled = &remembered_type;
2177 break;
2179 /* A function */
2180 case 'F':
2181 (*mangled)++;
2182 if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
2184 string_prepend (&decl, "(");
2185 string_append (&decl, ")");
2187 /* After picking off the function args, we expect to either find the
2188 function return type (preceded by an '_') or the end of the
2189 string. */
2190 if (!demangle_args (work, mangled, &decl)
2191 || (**mangled != '_' && **mangled != '\0'))
2193 success = 0;
2195 if (success && (**mangled == '_'))
2197 (*mangled)++;
2199 break;
2201 case 'M':
2202 case 'O':
2204 constp = 0;
2205 volatilep = 0;
2207 member = **mangled == 'M';
2208 (*mangled)++;
2209 if (!isdigit (**mangled) && **mangled != 't')
2211 success = 0;
2212 break;
2215 string_append (&decl, ")");
2216 string_prepend (&decl, (work -> options & DMGL_JAVA) ? "." : "::");
2217 if (isdigit (**mangled))
2219 n = consume_count (mangled);
2220 if (strlen (*mangled) < n)
2222 success = 0;
2223 break;
2225 string_prependn (&decl, *mangled, n);
2226 *mangled += n;
2228 else
2230 string temp;
2231 string_init (&temp);
2232 success = demangle_template (work, mangled, &temp, NULL, 1);
2233 if (success)
2235 string_prependn (&decl, temp.b, temp.p - temp.b);
2236 string_clear (&temp);
2238 else
2239 break;
2241 string_prepend (&decl, "(");
2242 if (member)
2244 if (**mangled == 'C')
2246 (*mangled)++;
2247 constp = 1;
2249 if (**mangled == 'V')
2251 (*mangled)++;
2252 volatilep = 1;
2254 if (*(*mangled)++ != 'F')
2256 success = 0;
2257 break;
2260 if ((member && !demangle_args (work, mangled, &decl))
2261 || **mangled != '_')
2263 success = 0;
2264 break;
2266 (*mangled)++;
2267 if (! PRINT_ANSI_QUALIFIERS)
2269 break;
2271 if (constp)
2273 APPEND_BLANK (&decl);
2274 string_append (&decl, "const");
2276 if (volatilep)
2278 APPEND_BLANK (&decl);
2279 string_append (&decl, "volatile");
2281 break;
2283 case 'G':
2284 (*mangled)++;
2285 break;
2287 case 'C':
2288 (*mangled)++;
2290 if ((*mangled)[1] == 'P')
2293 if (PRINT_ANSI_QUALIFIERS)
2295 if (!STRING_EMPTY (&decl))
2297 string_prepend (&decl, " ");
2299 string_prepend (&decl, "const");
2301 break;
2306 /* fall through */
2307 default:
2308 done = 1;
2309 break;
2313 switch (**mangled)
2315 /* A qualified name, such as "Outer::Inner". */
2316 case 'Q':
2317 success = demangle_qualified (work, mangled, result, 0, 1);
2318 break;
2320 case 'X':
2321 case 'Y':
2322 /* A template parm. We substitute the corresponding argument. */
2324 int idx;
2325 int lvl;
2327 (*mangled)++;
2328 idx = consume_count_with_underscores (mangled);
2330 if (idx == -1
2331 || (work->tmpl_argvec && idx >= work->ntmpl_args)
2332 || consume_count_with_underscores (mangled) == -1)
2334 success = 0;
2335 break;
2338 if (work->tmpl_argvec)
2339 string_append (result, work->tmpl_argvec[idx]);
2340 else
2342 char buf[10];
2343 sprintf(buf, "T%d", idx);
2344 string_append (result, buf);
2347 success = 1;
2349 break;
2351 default:
2352 success = demangle_fund_type (work, mangled, result);
2353 break;
2356 if (success)
2358 if (!STRING_EMPTY (&decl))
2360 string_append (result, " ");
2361 string_appends (result, &decl);
2364 else
2366 string_delete (result);
2368 string_delete (&decl);
2369 return (success);
2372 /* Given a pointer to a type string that represents a fundamental type
2373 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2374 string in which the demangled output is being built in RESULT, and
2375 the WORK structure, decode the types and add them to the result.
2377 For example:
2379 "Ci" => "const int"
2380 "Sl" => "signed long"
2381 "CUs" => "const unsigned short"
2385 static int
2386 demangle_fund_type (work, mangled, result)
2387 struct work_stuff *work;
2388 const char **mangled;
2389 string *result;
2391 int done = 0;
2392 int success = 1;
2394 /* First pick off any type qualifiers. There can be more than one. */
2396 while (!done)
2398 switch (**mangled)
2400 case 'C':
2401 (*mangled)++;
2402 if (PRINT_ANSI_QUALIFIERS)
2404 APPEND_BLANK (result);
2405 string_append (result, "const");
2407 break;
2408 case 'U':
2409 (*mangled)++;
2410 APPEND_BLANK (result);
2411 string_append (result, "unsigned");
2412 break;
2413 case 'S': /* signed char only */
2414 (*mangled)++;
2415 APPEND_BLANK (result);
2416 string_append (result, "signed");
2417 break;
2418 case 'V':
2419 (*mangled)++;
2420 if (PRINT_ANSI_QUALIFIERS)
2422 APPEND_BLANK (result);
2423 string_append (result, "volatile");
2425 break;
2426 case 'J':
2427 (*mangled)++;
2428 APPEND_BLANK (result);
2429 string_append (result, "__complex");
2430 break;
2431 default:
2432 done = 1;
2433 break;
2437 /* Now pick off the fundamental type. There can be only one. */
2439 switch (**mangled)
2441 case '\0':
2442 case '_':
2443 break;
2444 case 'v':
2445 (*mangled)++;
2446 APPEND_BLANK (result);
2447 string_append (result, "void");
2448 break;
2449 case 'x':
2450 (*mangled)++;
2451 APPEND_BLANK (result);
2452 string_append (result, "long long");
2453 break;
2454 case 'l':
2455 (*mangled)++;
2456 APPEND_BLANK (result);
2457 string_append (result, "long");
2458 break;
2459 case 'i':
2460 (*mangled)++;
2461 APPEND_BLANK (result);
2462 string_append (result, "int");
2463 break;
2464 case 's':
2465 (*mangled)++;
2466 APPEND_BLANK (result);
2467 string_append (result, "short");
2468 break;
2469 case 'b':
2470 (*mangled)++;
2471 APPEND_BLANK (result);
2472 string_append (result, "bool");
2473 break;
2474 case 'c':
2475 (*mangled)++;
2476 APPEND_BLANK (result);
2477 string_append (result, "char");
2478 break;
2479 case 'w':
2480 (*mangled)++;
2481 APPEND_BLANK (result);
2482 string_append (result, "wchar_t");
2483 break;
2484 case 'r':
2485 (*mangled)++;
2486 APPEND_BLANK (result);
2487 string_append (result, "long double");
2488 break;
2489 case 'd':
2490 (*mangled)++;
2491 APPEND_BLANK (result);
2492 string_append (result, "double");
2493 break;
2494 case 'f':
2495 (*mangled)++;
2496 APPEND_BLANK (result);
2497 string_append (result, "float");
2498 break;
2499 case 'G':
2500 (*mangled)++;
2501 if (!isdigit (**mangled))
2503 success = 0;
2504 break;
2506 /* fall through */
2507 /* An explicit type, such as "6mytype" or "7integer" */
2508 case '0':
2509 case '1':
2510 case '2':
2511 case '3':
2512 case '4':
2513 case '5':
2514 case '6':
2515 case '7':
2516 case '8':
2517 case '9':
2518 APPEND_BLANK (result);
2519 if (!demangle_class_name (work, mangled, result)) {
2520 --result->p;
2521 success = 0;
2523 break;
2524 case 't':
2525 success = demangle_template(work,mangled, result, 0, 1);
2526 break;
2527 default:
2528 success = 0;
2529 break;
2532 return (success);
2535 /* `result' will be initialized in do_type; it will be freed on failure */
2537 static int
2538 do_arg (work, mangled, result)
2539 struct work_stuff *work;
2540 const char **mangled;
2541 string *result;
2543 const char *start = *mangled;
2545 if (!do_type (work, mangled, result))
2547 return (0);
2549 else
2551 remember_type (work, start, *mangled - start);
2552 return (1);
2556 static void
2557 remember_type (work, start, len)
2558 struct work_stuff *work;
2559 const char *start;
2560 int len;
2562 char *tem;
2564 if (work -> ntypes >= work -> typevec_size)
2566 if (work -> typevec_size == 0)
2568 work -> typevec_size = 3;
2569 work -> typevec
2570 = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
2572 else
2574 work -> typevec_size *= 2;
2575 work -> typevec
2576 = (char **) xrealloc ((char *)work -> typevec,
2577 sizeof (char *) * work -> typevec_size);
2580 tem = xmalloc (len + 1);
2581 memcpy (tem, start, len);
2582 tem[len] = '\0';
2583 work -> typevec[work -> ntypes++] = tem;
2586 /* Forget the remembered types, but not the type vector itself. */
2588 static void
2589 forget_types (work)
2590 struct work_stuff *work;
2592 int i;
2594 while (work -> ntypes > 0)
2596 i = --(work -> ntypes);
2597 if (work -> typevec[i] != NULL)
2599 free (work -> typevec[i]);
2600 work -> typevec[i] = NULL;
2605 /* Process the argument list part of the signature, after any class spec
2606 has been consumed, as well as the first 'F' character (if any). For
2607 example:
2609 "__als__3fooRT0" => process "RT0"
2610 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
2612 DECLP must be already initialised, usually non-empty. It won't be freed
2613 on failure.
2615 Note that g++ differs significantly from ARM and lucid style mangling
2616 with regards to references to previously seen types. For example, given
2617 the source fragment:
2619 class foo {
2620 public:
2621 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
2624 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2625 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2627 g++ produces the names:
2629 __3fooiRT0iT2iT2
2630 foo__FiR3fooiT1iT1
2632 while lcc (and presumably other ARM style compilers as well) produces:
2634 foo__FiR3fooT1T2T1T2
2635 __ct__3fooFiR3fooT1T2T1T2
2637 Note that g++ bases it's type numbers starting at zero and counts all
2638 previously seen types, while lucid/ARM bases it's type numbers starting
2639 at one and only considers types after it has seen the 'F' character
2640 indicating the start of the function args. For lucid/ARM style, we
2641 account for this difference by discarding any previously seen types when
2642 we see the 'F' character, and subtracting one from the type number
2643 reference.
2647 static int
2648 demangle_args (work, mangled, declp)
2649 struct work_stuff *work;
2650 const char **mangled;
2651 string *declp;
2653 string arg;
2654 int need_comma = 0;
2655 int r;
2656 int t;
2657 const char *tem;
2658 char temptype;
2660 if (PRINT_ARG_TYPES)
2662 string_append (declp, "(");
2663 if (**mangled == '\0')
2665 string_append (declp, "void");
2669 while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
2671 if ((**mangled == 'N') || (**mangled == 'T'))
2673 temptype = *(*mangled)++;
2675 if (temptype == 'N')
2677 if (!get_count (mangled, &r))
2679 return (0);
2682 else
2684 r = 1;
2686 if (ARM_DEMANGLING && work -> ntypes >= 10)
2688 /* If we have 10 or more types we might have more than a 1 digit
2689 index so we'll have to consume the whole count here. This
2690 will lose if the next thing is a type name preceded by a
2691 count but it's impossible to demangle that case properly
2692 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
2693 Pc, ...)" or "(..., type12, char *, ...)" */
2694 if ((t = consume_count(mangled)) == 0)
2696 return (0);
2699 else
2701 if (!get_count (mangled, &t))
2703 return (0);
2706 if (LUCID_DEMANGLING || ARM_DEMANGLING)
2708 t--;
2710 /* Validate the type index. Protect against illegal indices from
2711 malformed type strings. */
2712 if ((t < 0) || (t >= work -> ntypes))
2714 return (0);
2716 while (--r >= 0)
2718 tem = work -> typevec[t];
2719 if (need_comma && PRINT_ARG_TYPES)
2721 string_append (declp, ", ");
2723 if (!do_arg (work, &tem, &arg))
2725 return (0);
2727 if (PRINT_ARG_TYPES)
2729 string_appends (declp, &arg);
2731 string_delete (&arg);
2732 need_comma = 1;
2735 else
2737 if (need_comma & PRINT_ARG_TYPES)
2739 string_append (declp, ", ");
2741 if (!do_arg (work, mangled, &arg))
2743 return (0);
2745 if (PRINT_ARG_TYPES)
2747 string_appends (declp, &arg);
2749 string_delete (&arg);
2750 need_comma = 1;
2754 if (**mangled == 'e')
2756 (*mangled)++;
2757 if (PRINT_ARG_TYPES)
2759 if (need_comma)
2761 string_append (declp, ",");
2763 string_append (declp, "...");
2767 if (PRINT_ARG_TYPES)
2769 string_append (declp, ")");
2771 return (1);
2774 static void
2775 demangle_function_name (work, mangled, declp, scan)
2776 struct work_stuff *work;
2777 const char **mangled;
2778 string *declp;
2779 const char *scan;
2781 int i;
2782 int len;
2783 string type;
2784 const char *tem;
2786 string_appendn (declp, (*mangled), scan - (*mangled));
2787 string_need (declp, 1);
2788 *(declp -> p) = '\0';
2790 /* Consume the function name, including the "__" separating the name
2791 from the signature. We are guaranteed that SCAN points to the
2792 separator. */
2794 (*mangled) = scan + 2;
2796 if (LUCID_DEMANGLING || ARM_DEMANGLING)
2799 /* See if we have an ARM style constructor or destructor operator.
2800 If so, then just record it, clear the decl, and return.
2801 We can't build the actual constructor/destructor decl until later,
2802 when we recover the class name from the signature. */
2804 if (strcmp (declp -> b, "__ct") == 0)
2806 work -> constructor += 1;
2807 string_clear (declp);
2808 return;
2810 else if (strcmp (declp -> b, "__dt") == 0)
2812 work -> destructor += 1;
2813 string_clear (declp);
2814 return;
2818 if (declp->p - declp->b >= 3
2819 && declp->b[0] == 'o'
2820 && declp->b[1] == 'p'
2821 && strchr (cplus_markers, declp->b[2]) != NULL)
2823 /* see if it's an assignment expression */
2824 if (declp->p - declp->b >= 10 /* op$assign_ */
2825 && memcmp (declp->b + 3, "assign_", 7) == 0)
2827 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2829 len = declp->p - declp->b - 10;
2830 if (strlen (optable[i].in) == len
2831 && memcmp (optable[i].in, declp->b + 10, len) == 0)
2833 string_clear (declp);
2834 string_append (declp, "operator");
2835 string_append (declp, optable[i].out);
2836 string_append (declp, "=");
2837 break;
2841 else
2843 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2845 int len = declp->p - declp->b - 3;
2846 if (strlen (optable[i].in) == len
2847 && memcmp (optable[i].in, declp->b + 3, len) == 0)
2849 string_clear (declp);
2850 string_append (declp, "operator");
2851 string_append (declp, optable[i].out);
2852 break;
2857 else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
2858 && strchr (cplus_markers, declp->b[4]) != NULL)
2860 /* type conversion operator */
2861 tem = declp->b + 5;
2862 if (do_type (work, &tem, &type))
2864 string_clear (declp);
2865 string_append (declp, "operator ");
2866 string_appends (declp, &type);
2867 string_delete (&type);
2870 else if (declp->b[0] == '_' && declp->b[1] == '_'
2871 && declp->b[2] == 'o' && declp->b[3] == 'p')
2873 /* ANSI. */
2874 /* type conversion operator. */
2875 tem = declp->b + 4;
2876 if (do_type (work, &tem, &type))
2878 string_clear (declp);
2879 string_append (declp, "operator ");
2880 string_appends (declp, &type);
2881 string_delete (&type);
2884 else if (declp->b[0] == '_' && declp->b[1] == '_'
2885 && declp->b[2] >= 'a' && declp->b[2] <= 'z'
2886 && declp->b[3] >= 'a' && declp->b[3] <= 'z')
2888 if (declp->b[4] == '\0')
2890 /* Operator. */
2891 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2893 if (strlen (optable[i].in) == 2
2894 && memcmp (optable[i].in, declp->b + 2, 2) == 0)
2896 string_clear (declp);
2897 string_append (declp, "operator");
2898 string_append (declp, optable[i].out);
2899 break;
2903 else
2905 if (declp->b[2] == 'a' && declp->b[5] == '\0')
2907 /* Assignment. */
2908 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2910 if (strlen (optable[i].in) == 3
2911 && memcmp (optable[i].in, declp->b + 2, 3) == 0)
2913 string_clear (declp);
2914 string_append (declp, "operator");
2915 string_append (declp, optable[i].out);
2916 break;
2924 /* a mini string-handling package */
2926 static void
2927 string_need (s, n)
2928 string *s;
2929 int n;
2931 int tem;
2933 if (s->b == NULL)
2935 if (n < 32)
2937 n = 32;
2939 s->p = s->b = xmalloc (n);
2940 s->e = s->b + n;
2942 else if (s->e - s->p < n)
2944 tem = s->p - s->b;
2945 n += tem;
2946 n *= 2;
2947 s->b = xrealloc (s->b, n);
2948 s->p = s->b + tem;
2949 s->e = s->b + n;
2953 static void
2954 string_delete (s)
2955 string *s;
2957 if (s->b != NULL)
2959 free (s->b);
2960 s->b = s->e = s->p = NULL;
2964 static void
2965 string_init (s)
2966 string *s;
2968 s->b = s->p = s->e = NULL;
2971 static void
2972 string_clear (s)
2973 string *s;
2975 s->p = s->b;
2978 #if 0
2980 static int
2981 string_empty (s)
2982 string *s;
2984 return (s->b == s->p);
2987 #endif
2989 static void
2990 string_append (p, s)
2991 string *p;
2992 const char *s;
2994 int n;
2995 if (s == NULL || *s == '\0')
2996 return;
2997 n = strlen (s);
2998 string_need (p, n);
2999 memcpy (p->p, s, n);
3000 p->p += n;
3003 static void
3004 string_appends (p, s)
3005 string *p, *s;
3007 int n;
3009 if (s->b != s->p)
3011 n = s->p - s->b;
3012 string_need (p, n);
3013 memcpy (p->p, s->b, n);
3014 p->p += n;
3018 static void
3019 string_appendn (p, s, n)
3020 string *p;
3021 const char *s;
3022 int n;
3024 if (n != 0)
3026 string_need (p, n);
3027 memcpy (p->p, s, n);
3028 p->p += n;
3032 static void
3033 string_prepend (p, s)
3034 string *p;
3035 const char *s;
3037 if (s != NULL && *s != '\0')
3039 string_prependn (p, s, strlen (s));
3043 static void
3044 string_prepends (p, s)
3045 string *p, *s;
3047 if (s->b != s->p)
3049 string_prependn (p, s->b, s->p - s->b);
3053 static void
3054 string_prependn (p, s, n)
3055 string *p;
3056 const char *s;
3057 int n;
3059 char *q;
3061 if (n != 0)
3063 string_need (p, n);
3064 for (q = p->p - 1; q >= p->b; q--)
3066 q[n] = q[0];
3068 memcpy (p->b, s, n);
3069 p->p += n;
3073 /* To generate a standalone demangler program for testing purposes,
3074 just compile and link this file with -DMAIN and libiberty.a. When
3075 run, it demangles each command line arg, or each stdin string, and
3076 prints the result on stdout. */
3078 #ifdef MAIN
3080 #include "getopt.h"
3082 static char *program_name;
3083 static char *program_version = VERSION;
3084 static int flags = DMGL_PARAMS | DMGL_ANSI;
3086 static void demangle_it PARAMS ((char *));
3087 static void usage PARAMS ((FILE *, int));
3088 static void fatal PARAMS ((char *));
3090 static void
3091 demangle_it (mangled_name)
3092 char *mangled_name;
3094 char *result;
3096 result = cplus_demangle (mangled_name, flags);
3097 if (result == NULL)
3099 printf ("%s\n", mangled_name);
3101 else
3103 printf ("%s\n", result);
3104 free (result);
3108 static void
3109 usage (stream, status)
3110 FILE *stream;
3111 int status;
3113 fprintf (stream, "\
3114 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3115 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3116 [--help] [--version] [arg...]\n",
3117 program_name);
3118 exit (status);
3121 #define MBUF_SIZE 512
3122 char mbuffer[MBUF_SIZE];
3124 /* Defined in the automatically-generated underscore.c. */
3125 extern int prepends_underscore;
3127 int strip_underscore = 0;
3129 static struct option long_options[] = {
3130 {"strip-underscores", no_argument, 0, '_'},
3131 {"format", required_argument, 0, 's'},
3132 {"help", no_argument, 0, 'h'},
3133 {"java", no_argument, 0, 'j'},
3134 {"no-strip-underscores", no_argument, 0, 'n'},
3135 {"version", no_argument, 0, 'v'},
3136 {0, no_argument, 0, 0}
3140 main (argc, argv)
3141 int argc;
3142 char **argv;
3144 char *result;
3145 int c;
3147 program_name = argv[0];
3149 strip_underscore = prepends_underscore;
3151 while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF)
3153 switch (c)
3155 case '?':
3156 usage (stderr, 1);
3157 break;
3158 case 'h':
3159 usage (stdout, 0);
3160 case 'n':
3161 strip_underscore = 0;
3162 break;
3163 case 'v':
3164 printf ("GNU %s version %s\n", program_name, program_version);
3165 exit (0);
3166 case '_':
3167 strip_underscore = 1;
3168 break;
3169 case 'j':
3170 flags |= DMGL_JAVA;
3171 break;
3172 case 's':
3173 if (strcmp (optarg, "gnu") == 0)
3175 current_demangling_style = gnu_demangling;
3177 else if (strcmp (optarg, "lucid") == 0)
3179 current_demangling_style = lucid_demangling;
3181 else if (strcmp (optarg, "arm") == 0)
3183 current_demangling_style = arm_demangling;
3185 else
3187 fprintf (stderr, "%s: unknown demangling style `%s'\n",
3188 program_name, optarg);
3189 exit (1);
3191 break;
3195 if (optind < argc)
3197 for ( ; optind < argc; optind++)
3199 demangle_it (argv[optind]);
3202 else
3204 for (;;)
3206 int i = 0;
3207 c = getchar ();
3208 /* Try to read a label. */
3209 while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
3211 if (i >= MBUF_SIZE-1)
3212 break;
3213 mbuffer[i++] = c;
3214 c = getchar ();
3216 if (i > 0)
3218 int skip_first = 0;
3220 if (mbuffer[0] == '.')
3221 ++skip_first;
3222 if (strip_underscore && mbuffer[skip_first] == '_')
3223 ++skip_first;
3225 if (skip_first > i)
3226 skip_first = i;
3228 mbuffer[i] = 0;
3230 result = cplus_demangle (mbuffer + skip_first, flags);
3231 if (result)
3233 if (mbuffer[0] == '.')
3234 putc ('.', stdout);
3235 fputs (result, stdout);
3236 free (result);
3238 else
3239 fputs (mbuffer, stdout);
3241 fflush (stdout);
3243 if (c == EOF)
3244 break;
3245 putchar (c);
3249 exit (0);
3252 static void
3253 fatal (str)
3254 char *str;
3256 fprintf (stderr, "%s: %s\n", program_name, str);
3257 exit (1);
3260 char * malloc ();
3261 char * realloc ();
3263 char *
3264 xmalloc (size)
3265 unsigned size;
3267 register char *value = (char *) malloc (size);
3268 if (value == 0)
3269 fatal ("virtual memory exhausted");
3270 return value;
3273 char *
3274 xrealloc (ptr, size)
3275 char *ptr;
3276 unsigned size;
3278 register char *value = (char *) realloc (ptr, size);
3279 if (value == 0)
3280 fatal ("virtual memory exhausted");
3281 return value;
3283 #endif /* main */