]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/binutils/libiberty/cplus-dem.c
This commit was generated by cvs2svn to compensate for changes in r41227,
[FreeBSD/FreeBSD.git] / contrib / binutils / libiberty / cplus-dem.c
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
5    
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.
11
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.
16
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.  */
21
22 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
23
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.  */
27
28 /* This file lives in both GCC and libiberty.  When making changes, please
29    try not to break either.  */
30
31 #include <ctype.h>
32 #include <string.h>
33 #include <stdio.h>
34
35 #include <demangle.h>
36 #undef CURRENT_DEMANGLING_STYLE
37 #define CURRENT_DEMANGLING_STYLE work->options
38
39 extern char *xmalloc PARAMS((unsigned));
40 extern char *xrealloc PARAMS((char *, unsigned));
41
42 static const char *mystrstr PARAMS ((const char *, const char *));
43
44 static const char *
45 mystrstr (s1, s2)
46      const char *s1, *s2;
47 {
48   register const char *p = s1;
49   register int len = strlen (s2);
50
51   for (; (p = strchr (p, *s2)) != 0; p++)
52     {
53       if (strncmp (p, s2, len) == 0)
54         {
55           return (p);
56         }
57     }
58   return (0);
59 }
60
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 '$'.
71
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).  */
76
77 #if !defined (CPLUS_MARKER)
78 #define CPLUS_MARKER '$'
79 #endif
80
81 enum demangling_styles current_demangling_style = gnu_demangling;
82
83 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
84
85 void
86 set_cplus_marker_for_demangling (ch)
87      int ch;
88 {
89   cplus_markers[0] = ch;
90 }
91
92 /* Stuff that is shared between sub-routines.
93    Using a shared structure allows cplus_demangle to be reentrant.  */
94
95 struct work_stuff
96 {
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. */
107 };
108
109 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
110 #define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
111
112 static const struct optable
113 {
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 */
196 };
197
198
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;
205
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, " ");}
211
212 #define ARM_VTABLE_STRING "__vtbl__"    /* Lucid/ARM virtual table prefix */
213 #define ARM_VTABLE_STRLEN 8             /* strlen (ARM_VTABLE_STRING) */
214
215 /* Prototypes for local functions */
216
217 static char *
218 mop_up PARAMS ((struct work_stuff *, string *, int));
219
220 #if 0
221 static int
222 demangle_method_args PARAMS ((struct work_stuff *work, const char **, string *));
223 #endif
224
225 static int
226 demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
227                            string *, int));
228
229 static int
230 arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **,
231                 const char **));
232
233 static void
234 demangle_arm_pt PARAMS ((struct work_stuff *, const char **, int, string *));
235
236 static int
237 demangle_class_name PARAMS ((struct work_stuff *, const char **, string *));
238
239 static int
240 demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
241                             int, int));
242
243 static int
244 demangle_class PARAMS ((struct work_stuff *, const char **, string *));
245
246 static int
247 demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
248
249 static int
250 demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
251
252 static int
253 demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
254
255 static int
256 gnu_special PARAMS ((struct work_stuff *, const char **, string *));
257
258 static int
259 arm_special PARAMS ((struct work_stuff *, const char **, string *));
260
261 static void
262 string_need PARAMS ((string *, int));
263
264 static void
265 string_delete PARAMS ((string *));
266
267 static void
268 string_init PARAMS ((string *));
269
270 static void
271 string_clear PARAMS ((string *));
272
273 #if 0
274 static int
275 string_empty PARAMS ((string *));
276 #endif
277
278 static void
279 string_append PARAMS ((string *, const char *));
280
281 static void
282 string_appends PARAMS ((string *, string *));
283
284 static void
285 string_appendn PARAMS ((string *, const char *, int));
286
287 static void
288 string_prepend PARAMS ((string *, const char *));
289
290 static void
291 string_prependn PARAMS ((string *, const char *, int));
292
293 static int
294 get_count PARAMS ((const char **, int *));
295
296 static int
297 consume_count PARAMS ((const char **));
298
299 static int 
300 consume_count_with_underscores PARAMS ((const char**));
301
302 static int
303 demangle_args PARAMS ((struct work_stuff *, const char **, string *));
304
305 static int
306 do_type PARAMS ((struct work_stuff *, const char **, string *));
307
308 static int
309 do_arg PARAMS ((struct work_stuff *, const char **, string *));
310
311 static void
312 demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
313                                 const char *));
314
315 static void
316 remember_type PARAMS ((struct work_stuff *, const char *, int));
317
318 static void
319 forget_types PARAMS ((struct work_stuff *));
320
321 static void
322 string_prepends PARAMS ((string *, string *));
323
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.  */
328
329 static int
330 consume_count (type)
331      const char **type;
332 {
333   int count = 0;
334
335   while (isdigit (**type))
336     {
337       count *= 10;
338       count += **type - '0';
339       (*type)++;
340     }
341   return (count);
342 }
343
344
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.  */
348
349 static int
350 consume_count_with_underscores (mangled)
351      const char **mangled;
352 {
353   int idx;
354
355   if (**mangled == '_')
356     {
357       (*mangled)++;
358       if (!isdigit (**mangled))
359         return -1;
360
361       idx = consume_count (mangled);
362       if (**mangled != '_')
363         /* The trailing underscore was missing. */
364         return -1;
365             
366       (*mangled)++;
367     }
368   else
369     {
370       if (**mangled < '0' || **mangled > '9')
371         return -1;
372             
373       idx = **mangled - '0';
374       (*mangled)++;
375     }
376
377   return idx;
378 }
379
380 int
381 cplus_demangle_opname (opname, result, options)
382      const char *opname;
383      char *result;
384      int options;
385 {
386   int len, i, len1, ret;
387   string type;
388   struct work_stuff work[1];
389   const char *tem;
390
391   len = strlen(opname);
392   result[0] = '\0';
393   ret = 0;
394   work->options = options;
395   
396   if (opname[0] == '_' && opname[1] == '_'
397       && opname[2] == 'o' && opname[3] == 'p')
398     {
399       /* ANSI.  */
400       /* type conversion operator.  */
401       tem = opname + 4;
402       if (do_type (work, &tem, &type))
403         {
404           strcat (result, "operator ");
405           strncat (result, type.b, type.p - type.b);
406           string_delete (&type);
407           ret = 1;
408         }
409     }
410   else if (opname[0] == '_' && opname[1] == '_'
411            && opname[2] >= 'a' && opname[2] <= 'z'
412            && opname[3] >= 'a' && opname[3] <= 'z')
413     {
414       if (opname[4] == '\0')
415         {
416           /* Operator.  */
417           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
418             {
419               if (strlen (optable[i].in) == 2
420                   && memcmp (optable[i].in, opname + 2, 2) == 0)
421                 {
422                   strcat (result, "operator");
423                   strcat (result, optable[i].out);
424                   ret = 1;
425                   break;
426                 }
427             }
428         }
429       else
430         {
431           if (opname[2] == 'a' && opname[5] == '\0')
432             {
433               /* Assignment.  */
434               for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
435                 {
436                   if (strlen (optable[i].in) == 3
437                       && memcmp (optable[i].in, opname + 2, 3) == 0)
438                     {
439                       strcat (result, "operator");
440                       strcat (result, optable[i].out);
441                       ret = 1;
442                       break;
443                     }                 
444                 }
445             }
446         }
447     }
448   else if (len >= 3 
449            && opname[0] == 'o'
450            && opname[1] == 'p'
451            && strchr (cplus_markers, opname[2]) != NULL)
452     {
453       /* see if it's an assignment expression */
454       if (len >= 10 /* op$assign_ */
455           && memcmp (opname + 3, "assign_", 7) == 0)
456         {
457           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
458             {
459               len1 = len - 10;
460               if (strlen (optable[i].in) == len1
461                   && memcmp (optable[i].in, opname + 10, len1) == 0)
462                 {
463                   strcat (result, "operator");
464                   strcat (result, optable[i].out);
465                   strcat (result, "=");
466                   ret = 1;
467                   break;
468                 }
469             }
470         }
471       else
472         {
473           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
474             {
475               len1 = len - 3;
476               if (strlen (optable[i].in) == len1 
477                   && memcmp (optable[i].in, opname + 3, len1) == 0)
478                 {
479                   strcat (result, "operator");
480                   strcat (result, optable[i].out);
481                   ret = 1;
482                   break;
483                 }
484             }
485         }
486     }
487   else if (len >= 5 && memcmp (opname, "type", 4) == 0
488            && strchr (cplus_markers, opname[4]) != NULL)
489     {
490       /* type conversion operator */
491       tem = opname + 5;
492       if (do_type (work, &tem, &type))
493         {
494           strcat (result, "operator ");
495           strncat (result, type.b, type.p - type.b);
496           string_delete (&type);
497           ret = 1;
498         }
499     }
500   return ret;
501
502 }
503 /* Takes operator name as e.g. "++" and returns mangled
504    operator name (e.g. "postincrement_expr"), or NULL if not found.
505
506    If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
507    if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
508
509 const char *
510 cplus_mangle_opname (opname, options)
511      const char *opname;
512      int options;
513 {
514   int i;
515   int len;
516
517   len = strlen (opname);
518   for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
519     {
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;
524     }
525   return (0);
526 }
527
528 /* char *cplus_demangle (const char *mangled, int options)
529
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.
535
536    The OPTIONS arg may contain one or more of the following bits:
537
538         DMGL_ANSI       ANSI qualifiers such as `const' and `void' are
539                         included.
540         DMGL_PARAMS     Function parameters are included.
541
542    For example,
543    
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"
547
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"
551
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.  */
555
556 char *
557 cplus_demangle (mangled, options)
558      const char *mangled;
559      int options;
560 {
561   string decl;
562   int success = 0;
563   struct work_stuff work[1];
564   char *demangled = NULL;
565
566   if ((mangled != NULL) && (*mangled != '\0'))
567     {
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;
572       
573       string_init (&decl);
574
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.  */
581
582       if ((AUTO_DEMANGLING || GNU_DEMANGLING))
583         {
584           success = gnu_special (work, &mangled, &decl);
585         }
586       if (!success)
587         {
588           success = demangle_prefix (work, &mangled, &decl);
589         }
590       if (success && (*mangled != '\0'))
591         {
592           success = demangle_signature (work, &mangled, &decl);
593         }
594       if (work->constructor == 2)
595         {
596           string_prepend(&decl, "global constructors keyed to ");
597           work->constructor = 0;
598         }
599       else if (work->destructor == 2)
600         {
601           string_prepend(&decl, "global destructors keyed to ");
602           work->destructor = 0;
603         }
604       demangled = mop_up (work, &decl, success);
605     }
606   return (demangled);
607 }
608
609 static char *
610 mop_up (work, declp, success)
611      struct work_stuff *work;
612      string *declp;
613      int success;
614 {
615   char *demangled = NULL;
616
617   /* Discard the remembered types, if any.  */
618   
619   forget_types (work);
620   if (work -> typevec != NULL)
621     {
622       free ((char *) work -> typevec);
623     }
624   if (work->tmpl_argvec)
625     {
626       int i;
627
628       for (i = 0; i < work->ntmpl_args; i++)
629         if (work->tmpl_argvec[i])
630           free ((char*) work->tmpl_argvec[i]);
631       
632       free ((char*) work->tmpl_argvec);
633     }
634
635   /* If demangling was successful, ensure that the demangled string is null
636      terminated and return it.  Otherwise, free the demangling decl.  */
637   
638   if (!success)
639     {
640       string_delete (declp);
641     }
642   else
643     {
644       string_appendn (declp, "", 1);
645       demangled = declp -> b;
646     }
647   return (demangled);
648 }
649
650 /*
651
652 LOCAL FUNCTION
653
654         demangle_signature -- demangle the signature part of a mangled name
655
656 SYNOPSIS
657
658         static int
659         demangle_signature (struct work_stuff *work, const char **mangled,
660                             string *declp);
661
662 DESCRIPTION
663
664         Consume and demangle the signature portion of the mangled name.
665
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.
670
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.
675
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.  */
679
680 static int
681 demangle_signature (work, mangled, declp)
682      struct work_stuff *work;
683      const char **mangled;
684      string *declp;
685 {
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;
693
694   while (success && (**mangled != '\0'))
695     {
696       switch (**mangled)
697         {
698         case 'Q':
699           oldmangled = *mangled;
700           success = demangle_qualified (work, mangled, declp, 1, 0);
701           if (success)
702             {
703               remember_type (work, oldmangled, *mangled - oldmangled);
704             }
705           if (AUTO_DEMANGLING || GNU_DEMANGLING)
706             {
707               expect_func = 1;
708             }
709           oldmangled = NULL;
710           break;
711           
712         case 'S':
713           /* Static member function */
714           if (oldmangled == NULL)
715             {
716               oldmangled = *mangled;
717             }
718           (*mangled)++;
719           work -> static_type = 1;
720           break;
721
722         case 'C':
723           /* a const member function */
724           if (oldmangled == NULL)
725             {
726               oldmangled = *mangled;
727             }
728           (*mangled)++;
729           work -> const_type = 1;
730           break;
731           
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)
735             {
736               oldmangled = *mangled;
737             }
738           success = demangle_class (work, mangled, declp);
739           if (success)
740             {
741               remember_type (work, oldmangled, *mangled - oldmangled);
742             }
743           if (AUTO_DEMANGLING || GNU_DEMANGLING)
744             {
745               expect_func = 1;
746             }
747           oldmangled = NULL;
748           break;
749           
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.  */
756
757           oldmangled = NULL;
758           func_done = 1;
759           (*mangled)++;
760
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() */
765
766           if (LUCID_DEMANGLING || ARM_DEMANGLING)
767             {
768               forget_types (work);
769             }
770           success = demangle_args (work, mangled, declp);
771           break;
772           
773         case 't':
774           /* G++ Template */
775           string_init(&trawname); 
776           string_init(&tname);
777           if (oldmangled == NULL)
778             {
779               oldmangled = *mangled;
780             }
781           success = demangle_template (work, mangled, &tname, &trawname, 1);
782           if (success)
783             {
784               remember_type (work, oldmangled, *mangled - oldmangled);
785             }
786           string_append(&tname, (work -> options & DMGL_JAVA) ? "." : "::");
787           string_prepends(declp, &tname);
788           if (work -> destructor & 1)
789             {
790               string_prepend (&trawname, "~");
791               string_appends (declp, &trawname);
792               work->destructor -= 1;
793             }
794           if ((work->constructor & 1) || (work->destructor & 1))
795             {
796               string_appends (declp, &trawname);
797               work->constructor -= 1;
798             }
799           string_delete(&trawname);
800           string_delete(&tname);
801           oldmangled = NULL;
802           expect_func = 1;
803           break;
804
805         case '_':
806           if (GNU_DEMANGLING && expect_return_type) 
807             {
808               /* Read the return type. */
809               string return_type;
810               string_init (&return_type);
811
812               (*mangled)++;
813               success = do_type (work, mangled, &return_type);
814               APPEND_BLANK (&return_type);
815
816               string_prepends (declp, &return_type);
817               string_delete (&return_type);
818               break;
819             }
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;
828
829         case 'H':
830           if (GNU_DEMANGLING) 
831             {
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;
838             }
839           else
840             /* fall through */
841             ;
842
843         default:
844           if (AUTO_DEMANGLING || GNU_DEMANGLING)
845             {
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);
850             }
851           else
852             {
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;
858             }
859           break;
860         }
861       /*
862         if (AUTO_DEMANGLING || GNU_DEMANGLING)
863         */
864       {
865         if (success && expect_func)
866           {
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;
873           }
874       }
875     }
876   if (success && !func_done)
877     {
878       if (AUTO_DEMANGLING || GNU_DEMANGLING)
879         {
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);
887         }
888     }
889   if (success && work -> static_type && PRINT_ARG_TYPES)
890     {
891       string_append (declp, " static");
892     }
893   if (success && work -> const_type && PRINT_ARG_TYPES)
894     {
895       string_append (declp, " const");
896     }
897   return (success);
898 }
899
900 #if 0
901
902 static int
903 demangle_method_args (work, mangled, declp)
904      struct work_stuff *work;
905      const char **mangled;
906      string *declp;
907 {
908   int success = 0;
909
910   if (work -> static_type)
911     {
912       string_append (declp, *mangled + 1);
913       *mangled += strlen (*mangled);
914       success = 1;
915     }
916   else
917     {
918       success = demangle_args (work, mangled, declp);
919     }
920   return (success);
921 }
922
923 #endif
924
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;
932 {
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;
948
949   (*mangled)++;
950   if (is_type)
951     {
952       start = *mangled;
953       /* get template name */
954       if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
955         {
956           return (0);
957         }
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)
963         {
964           string_appendn (tname, *mangled, r);
965         }
966       *mangled += r;
967     }
968   if (!is_java_array)
969     string_append (tname, "<");
970   /* get size of template parameter list */
971   if (!get_count (mangled, &r))
972     {
973       return (0);
974     }
975   if (!is_type)
976     {
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;
982     }
983   for (i = 0; i < r; i++)
984     {
985       if (need_comma)
986         {
987           string_append (tname, ", ");
988         }
989       /* Z for type parameters */
990       if (**mangled == 'Z')
991         {
992           (*mangled)++;
993           /* temp is initialized in do_type */
994           success = do_type (work, mangled, &temp);
995           if (success)
996             {
997               string_appends (tname, &temp);
998
999               if (!is_type)
1000                 {
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';
1006                 }
1007             }
1008           string_delete(&temp);
1009           if (!success)
1010             {
1011               break;
1012             }
1013         }
1014       else
1015         {
1016           string  param;
1017           string* s;
1018
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);
1029           /*
1030             if (success)
1031             {
1032             string_appends (s, &temp);
1033             }
1034             */
1035           string_delete(&temp);
1036           if (!success)
1037             {
1038               break;
1039             }
1040           /*
1041             string_append (s, "=");
1042             */
1043
1044           if (!is_type)
1045             {
1046               s = &param;
1047               string_init (s);
1048             }
1049           else
1050             s = tname;
1051
1052           while (*old_p && !done)
1053             {   
1054               switch (*old_p)
1055                 {
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;
1103                 }
1104             }
1105           if (**mangled == 'Y')
1106             {
1107               /* The next argument is a template parameter. */
1108               int idx;
1109
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)
1115                 {
1116                   success = 0;
1117                   if (!is_type)
1118                     string_delete (s);
1119                   break;
1120                 }
1121               if (work->tmpl_argvec)
1122                 string_append (s, work->tmpl_argvec[idx]);
1123               else
1124                 {
1125                   char buf[10];
1126                   sprintf(buf, "T%d", idx);
1127                   string_append (s, buf);
1128                 }
1129             }
1130           else if (is_integral)
1131             {
1132               if (**mangled == 'm')
1133                 {
1134                   string_appendn (s, "-", 1);
1135                   (*mangled)++;
1136                 }
1137               while (isdigit (**mangled))       
1138                 {
1139                   string_appendn (s, *mangled, 1);
1140                   (*mangled)++;
1141                 }
1142             }
1143           else if (is_char)
1144             {
1145               char tmp[2];
1146               int val;
1147               if (**mangled == 'm')
1148                 {
1149                   string_appendn (s, "-", 1);
1150                   (*mangled)++;
1151                 }
1152               string_appendn (s, "'", 1);
1153               val = consume_count(mangled);
1154               if (val == 0)
1155                 {
1156                   success = 0;
1157                   if (!is_type)
1158                     string_delete (s);
1159                   break;
1160                 }
1161               tmp[0] = (char)val;
1162               tmp[1] = '\0';
1163               string_appendn (s, &tmp[0], 1);
1164               string_appendn (s, "'", 1);
1165             }
1166           else if (is_bool)
1167             {
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;
1175             }
1176           else if (is_real)
1177             {
1178               if (**mangled == 'm')
1179                 {
1180                   string_appendn (s, "-", 1);
1181                   (*mangled)++;
1182                 }
1183               while (isdigit (**mangled))       
1184                 {
1185                   string_appendn (s, *mangled, 1);
1186                   (*mangled)++;
1187                 }
1188               if (**mangled == '.') /* fraction */
1189                 {
1190                   string_appendn (s, ".", 1);
1191                   (*mangled)++;
1192                   while (isdigit (**mangled))   
1193                     {
1194                       string_appendn (s, *mangled, 1);
1195                       (*mangled)++;
1196                     }
1197                 }
1198               if (**mangled == 'e') /* exponent */
1199                 {
1200                   string_appendn (s, "e", 1);
1201                   (*mangled)++;
1202                   while (isdigit (**mangled))   
1203                     {
1204                       string_appendn (s, *mangled, 1);
1205                       (*mangled)++;
1206                     }
1207                 }
1208             }
1209           else if (is_pointer)
1210             {
1211               symbol_len = consume_count (mangled);
1212               if (symbol_len == 0)
1213                 {
1214                   success = 0;
1215                   if (!is_type)
1216                     string_delete (s);
1217                   break;
1218                 }
1219               if (symbol_len == 0)
1220                 string_appendn (s, "0", 1);
1221               else
1222                 {
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)
1229                     {
1230                       string_append (s, q);
1231                       free (q);
1232                     }
1233                   else
1234                     string_append (s, p);
1235                   free (p);
1236                 }
1237               *mangled += symbol_len;
1238             }
1239           if (!is_type)
1240             {
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';
1245               
1246               string_appends (tname, s);
1247               string_delete (s);
1248             }
1249         }
1250       need_comma = 1;
1251     }
1252   if (is_java_array)
1253     {
1254       string_append (tname, "[]");
1255     }
1256   else
1257     {
1258       if (tname->p[-1] == '>')
1259         string_append (tname, " ");
1260       string_append (tname, ">");
1261     }
1262   
1263   /*
1264     if (work -> static_type)
1265     {
1266     string_append (declp, *mangled + 1);
1267     *mangled += strlen (*mangled);
1268     success = 1;
1269     }
1270     else
1271     {
1272     success = demangle_args (work, mangled, declp);
1273     }
1274     }
1275     */
1276   return (success);
1277 }
1278
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;
1285 {
1286   /* ARM template? */
1287   if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
1288     {
1289       int len;
1290       *args = *anchor + 6;
1291       len = consume_count (args);
1292       if (*args + len == mangled + n && **args == '_')
1293         {
1294           ++*args;
1295           return 1;
1296         }
1297     }
1298   return 0;
1299 }
1300
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;
1307 {
1308   const char *p;
1309   const char *args;
1310   const char *e = *mangled + n;
1311
1312   /* ARM template? */
1313   if (arm_pt (work, *mangled, n, &p, &args))
1314     {
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, ",");
1325       }
1326       string_delete (&arg);
1327       --declp->p;
1328       string_append (declp, ">");
1329     }
1330   else
1331     {
1332       string_appendn (declp, *mangled, n);
1333     }
1334   *mangled += n;
1335 }
1336
1337 static int
1338 demangle_class_name (work, mangled, declp)
1339      struct work_stuff *work;
1340      const char **mangled;
1341      string *declp;
1342 {
1343   int n;
1344   int success = 0;
1345
1346   n = consume_count (mangled);
1347   if (strlen (*mangled) >= n)
1348     {
1349       demangle_arm_pt (work, mangled, n, declp);
1350       success = 1;
1351     }
1352
1353   return (success);
1354 }
1355
1356 /*
1357
1358 LOCAL FUNCTION
1359
1360         demangle_class -- demangle a mangled class sequence
1361
1362 SYNOPSIS
1363
1364         static int
1365         demangle_class (struct work_stuff *work, const char **mangled,
1366                         strint *declp)
1367
1368 DESCRIPTION
1369
1370         DECLP points to the buffer into which demangling is being done.
1371
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.
1376
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.
1380
1381         Otherwise, we prepend "class::" to the current DECLP.
1382
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.
1386
1387         Returns 1 if demangling is successful, 0 otherwise.
1388
1389 */
1390
1391 static int
1392 demangle_class (work, mangled, declp)
1393      struct work_stuff *work;
1394      const char **mangled;
1395      string *declp;
1396 {
1397   int success = 0;
1398   string class_name;
1399
1400   string_init (&class_name);
1401   if (demangle_class_name (work, mangled, &class_name))
1402     {
1403       if ((work->constructor & 1) || (work->destructor & 1))
1404         {
1405           string_prepends (declp, &class_name);
1406           if (work -> destructor & 1)
1407             {
1408               string_prepend (declp, "~");
1409               work -> destructor -= 1;
1410             }
1411           else
1412             {
1413               work -> constructor -= 1; 
1414             }
1415         }
1416       string_prepend (declp, (work -> options & DMGL_JAVA) ? "." : "::");
1417       string_prepends (declp, &class_name);
1418       success = 1;
1419     }
1420   string_delete (&class_name);
1421   return (success);
1422 }
1423
1424 /*
1425
1426 LOCAL FUNCTION
1427
1428         demangle_prefix -- consume the mangled name prefix and find signature
1429
1430 SYNOPSIS
1431
1432         static int
1433         demangle_prefix (struct work_stuff *work, const char **mangled,
1434                          string *declp);
1435
1436 DESCRIPTION
1437
1438         Consume and demangle the prefix of the mangled name.
1439
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.
1444
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.
1451         
1452         Returns 1 on success, 0 otherwise.
1453  */
1454
1455 static int
1456 demangle_prefix (work, mangled, declp)
1457      struct work_stuff *work;
1458      const char **mangled;
1459      string *declp;
1460 {
1461   int success = 1;
1462   const char *scan;
1463   int i;
1464
1465   if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
1466     {
1467       char *marker = strchr (cplus_markers, (*mangled)[8]);
1468       if (marker != NULL && *marker == (*mangled)[10])
1469         {
1470           if ((*mangled)[9] == 'D')
1471             {
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;
1477             }
1478           else if ((*mangled)[9] == 'I')
1479             {
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;
1485             }
1486         }
1487     }
1488   else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
1489     {
1490       /* it's a ARM global destructor to be executed at program exit */
1491       (*mangled) += 7;
1492       work->destructor = 2;
1493     }
1494   else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
1495     {
1496       /* it's a ARM global constructor to be executed at program initial */
1497       (*mangled) += 7;
1498       work->constructor = 2;
1499     }
1500
1501   /*  This block of code is a reduction in strength time optimization
1502       of:
1503       scan = mystrstr (*mangled, "__"); */
1504
1505   {
1506     scan = *mangled;
1507
1508     do {
1509       scan = strchr (scan, '_');
1510     } while (scan != NULL && *++scan != '_');
1511
1512     if (scan != NULL) --scan;
1513   }
1514
1515   if (scan != NULL)
1516     {
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)
1521         {
1522           scan += (i - 2); 
1523         }
1524     }
1525  
1526   if (scan == NULL)
1527     {
1528       success = 0;
1529     }
1530   else if (work -> static_type)
1531     {
1532       if (!isdigit (scan[0]) && (scan[0] != 't'))
1533         {
1534           success = 0;
1535         }
1536     }
1537   else if ((scan == *mangled)
1538            && (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')
1539                || (scan[2] == 'H')))
1540     {
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]))
1545         {
1546           *mangled = scan + 2;
1547           consume_count (mangled);
1548           string_append (declp, *mangled);
1549           *mangled += strlen (*mangled);
1550           success = 1; 
1551         }
1552       else
1553         {
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;
1561         }
1562     }
1563   else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
1564     {
1565       /* Mangled name starts with "__".  Skip over any leading '_' characters,
1566          then find the next "__" that separates the prefix from the signature.
1567          */
1568       if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
1569           || (arm_special (work, mangled, declp) == 0))
1570         {
1571           while (*scan == '_')
1572             {
1573               scan++;
1574             }
1575           if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
1576             {
1577               /* No separator (I.E. "__not_mangled"), or empty signature
1578                  (I.E. "__not_mangled_either__") */
1579               success = 0;
1580             }
1581           else
1582             {
1583               demangle_function_name (work, mangled, declp, scan);
1584             }
1585         }
1586     }
1587   else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
1588     {
1589       /* Cfront-style parameterized type.  Handled later as a signature.  */
1590       success = 1;
1591
1592       /* ARM template? */
1593       demangle_arm_pt (work, mangled, strlen (*mangled), declp);
1594     }
1595   else if (*(scan + 2) != '\0')
1596     {
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);
1601     }
1602   else
1603     {
1604       /* Doesn't look like a mangled name */
1605       success = 0;
1606     }
1607
1608   if (!success && (work->constructor == 2 || work->destructor == 2))
1609     {
1610       string_append (declp, *mangled);
1611       *mangled += strlen (*mangled);
1612       success = 1;
1613     } 
1614   return (success);
1615 }
1616
1617 /*
1618
1619 LOCAL FUNCTION
1620
1621         gnu_special -- special handling of gnu mangled strings
1622
1623 SYNOPSIS
1624
1625         static int
1626         gnu_special (struct work_stuff *work, const char **mangled,
1627                      string *declp);
1628
1629
1630 DESCRIPTION
1631
1632         Process some special GNU style mangling forms that don't fit
1633         the normal pattern.  For example:
1634
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)
1643  */
1644
1645 static int
1646 gnu_special (work, mangled, declp)
1647      struct work_stuff *work;
1648      const char **mangled;
1649      string *declp;
1650 {
1651   int n;
1652   int success = 1;
1653   const char *p;
1654
1655   if ((*mangled)[0] == '_'
1656       && strchr (cplus_markers, (*mangled)[1]) != NULL
1657       && (*mangled)[2] == '_')
1658     {
1659       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1660       (*mangled) += 3;
1661       work -> destructor += 1;
1662     }
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)))
1671     {
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')
1681         {
1682           p = strpbrk (*mangled, cplus_markers);
1683           switch (**mangled)
1684             {
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]))
1693                 {
1694                   n = consume_count(mangled);
1695                   /* We may be seeing a too-large size, or else a
1696                      ".<digits>" indicating a static local symbol.  In
1697                      any case, declare victory and move on; *don't* try
1698                      to use n to allocate.  */
1699                   if (n >= strlen (*mangled))
1700                     {
1701                       success = 1;
1702                       break;
1703                     }
1704                 }
1705               else
1706                 {
1707                   n = strcspn (*mangled, cplus_markers);
1708                 }
1709               string_appendn (declp, *mangled, n);
1710               (*mangled) += n;
1711             }
1712
1713           if (success && ((p == NULL) || (p == *mangled)))
1714             {
1715               if (p != NULL)
1716                 {
1717                   string_append (declp,
1718                                  (work -> options & DMGL_JAVA) ? "." : "::");
1719                   (*mangled)++;
1720                 }
1721             }
1722           else
1723             {
1724               success = 0;
1725               break;
1726             }
1727         }
1728       if (success)
1729         string_append (declp, " virtual table");
1730     }
1731   else if ((*mangled)[0] == '_'
1732            && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
1733            && (p = strpbrk (*mangled, cplus_markers)) != NULL)
1734     {
1735       /* static data member, "_3foo$varname" for example */
1736       (*mangled)++;
1737       switch (**mangled)
1738         {
1739         case 'Q':
1740           success = demangle_qualified (work, mangled, declp, 0, 1);
1741           break;
1742         case 't':
1743           success = demangle_template (work, mangled, declp, 0, 1);
1744           break;
1745         default:
1746           n = consume_count (mangled);
1747           string_appendn (declp, *mangled, n);
1748           (*mangled) += n;
1749         }
1750       if (success && (p == *mangled))
1751         {
1752           /* Consumed everything up to the cplus_marker, append the
1753              variable name.  */
1754           (*mangled)++;
1755           string_append (declp, (work -> options & DMGL_JAVA) ? "." : "::");
1756           n = strlen (*mangled);
1757           string_appendn (declp, *mangled, n);
1758           (*mangled) += n;
1759         }
1760       else
1761         {
1762           success = 0;
1763         }
1764     }
1765   else if (strncmp (*mangled, "__thunk_", 8) == 0)
1766     {
1767       int delta = ((*mangled) += 8, consume_count (mangled));
1768       char *method = cplus_demangle (++*mangled, work->options);
1769       if (method)
1770         {
1771           char buf[50];
1772           sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
1773           string_append (declp, buf);
1774           string_append (declp, method);
1775           free (method);
1776           n = strlen (*mangled);
1777           (*mangled) += n;
1778         }
1779       else
1780         {
1781           success = 0;
1782         }
1783     }
1784   else if (strncmp (*mangled, "__t", 3) == 0
1785            && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
1786     {
1787       p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
1788       (*mangled) += 4;
1789       switch (**mangled)
1790         {
1791         case 'Q':
1792           success = demangle_qualified (work, mangled, declp, 0, 1);
1793           break;
1794         case 't':
1795           success = demangle_template (work, mangled, declp, 0, 1);
1796           break;
1797         default:
1798           success = demangle_fund_type (work, mangled, declp);
1799           break;
1800         }
1801       if (success && **mangled != '\0')
1802         success = 0;
1803       if (success)
1804         string_append (declp, p);
1805     }
1806   else
1807     {
1808       success = 0;
1809     }
1810   return (success);
1811 }
1812
1813 /*
1814
1815 LOCAL FUNCTION
1816
1817         arm_special -- special handling of ARM/lucid mangled strings
1818
1819 SYNOPSIS
1820
1821         static int
1822         arm_special (struct work_stuff *work, const char **mangled,
1823                         string *declp);
1824
1825
1826 DESCRIPTION
1827
1828         Process some special ARM style mangling forms that don't fit
1829         the normal pattern.  For example:
1830
1831                 __vtbl__3foo            (foo virtual table)
1832                 __vtbl__3foo__3bar      (bar::foo virtual table)
1833
1834  */
1835
1836 static int
1837 arm_special (work, mangled, declp)
1838      struct work_stuff *work;
1839      const char **mangled;
1840      string *declp;
1841 {
1842   int n;
1843   int success = 1;
1844   const char *scan;
1845
1846   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
1847     {
1848       /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
1849          and create the decl.  Note that we consume the entire mangled
1850          input string, which means that demangle_signature has no work
1851          to do.  */
1852       scan = *mangled + ARM_VTABLE_STRLEN;
1853       while (*scan != '\0')        /* first check it can be demangled */
1854         {
1855           n = consume_count (&scan);
1856           if (n==0)
1857             {
1858               return (0);           /* no good */
1859             }
1860           scan += n;
1861           if (scan[0] == '_' && scan[1] == '_')
1862             {
1863               scan += 2;
1864             }
1865         }
1866       (*mangled) += ARM_VTABLE_STRLEN;
1867       while (**mangled != '\0')
1868         {
1869           n = consume_count (mangled);
1870           string_prependn (declp, *mangled, n);
1871           (*mangled) += n;
1872           if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
1873             {
1874               string_prepend (declp, "::");
1875               (*mangled) += 2;
1876             }
1877         }
1878       string_append (declp, " virtual table");
1879     }
1880   else
1881     {
1882       success = 0;
1883     }
1884   return (success);
1885 }
1886
1887 /*
1888
1889 LOCAL FUNCTION
1890
1891         demangle_qualified -- demangle 'Q' qualified name strings
1892
1893 SYNOPSIS
1894
1895         static int
1896         demangle_qualified (struct work_stuff *, const char *mangled,
1897                             string *result, int isfuncname, int append);
1898
1899 DESCRIPTION
1900
1901         Demangle a qualified name, such as "Q25Outer5Inner" which is
1902         the mangled form of "Outer::Inner".  The demangled output is
1903         prepended or appended to the result string according to the
1904         state of the append flag.
1905
1906         If isfuncname is nonzero, then the qualified name we are building
1907         is going to be used as a member function name, so if it is a
1908         constructor or destructor function, append an appropriate
1909         constructor or destructor name.  I.E. for the above example,
1910         the result for use as a constructor is "Outer::Inner::Inner"
1911         and the result for use as a destructor is "Outer::Inner::~Inner".
1912
1913 BUGS
1914
1915         Numeric conversion is ASCII dependent (FIXME).
1916
1917  */
1918
1919 static int
1920 demangle_qualified (work, mangled, result, isfuncname, append)
1921      struct work_stuff *work;
1922      const char **mangled;
1923      string *result;
1924      int isfuncname;
1925      int append;
1926 {
1927   int qualifiers;
1928   int namelength;
1929   int success = 1;
1930   const char *p;
1931   char num[2];
1932   string temp;
1933
1934   string_init (&temp);
1935   switch ((*mangled)[1])
1936     {
1937     case '_':
1938       /* GNU mangled name with more than 9 classes.  The count is preceded
1939          by an underscore (to distinguish it from the <= 9 case) and followed
1940          by an underscore.  */
1941       p = *mangled + 2;
1942       qualifiers = atoi (p);
1943       if (!isdigit (*p) || *p == '0')
1944         success = 0;
1945
1946       /* Skip the digits.  */
1947       while (isdigit (*p))
1948         ++p;
1949
1950       if (*p != '_')
1951         success = 0;
1952
1953       *mangled = p + 1;
1954       break;
1955
1956     case '1':
1957     case '2':
1958     case '3':
1959     case '4':
1960     case '5':
1961     case '6':
1962     case '7':
1963     case '8':
1964     case '9':
1965       /* The count is in a single digit.  */
1966       num[0] = (*mangled)[1];
1967       num[1] = '\0';
1968       qualifiers = atoi (num);
1969
1970       /* If there is an underscore after the digit, skip it.  This is
1971          said to be for ARM-qualified names, but the ARM makes no
1972          mention of such an underscore.  Perhaps cfront uses one.  */
1973       if ((*mangled)[2] == '_')
1974         {
1975           (*mangled)++;
1976         }
1977       (*mangled) += 2;
1978       break;
1979
1980     case '0':
1981     default:
1982       success = 0;
1983     }
1984
1985   if (!success)
1986     return success;
1987
1988   /* Pick off the names and collect them in the temp buffer in the order
1989      in which they are found, separated by '::'.  */
1990
1991   while (qualifiers-- > 0)
1992     {
1993       if (*mangled[0] == '_') 
1994         *mangled = *mangled + 1;
1995       if (*mangled[0] == 't')
1996         {
1997           success = demangle_template(work, mangled, &temp, 0, 1);
1998           if (!success) break;
1999         }
2000       else if (*mangled[0] == 'X')
2001         {
2002           success = do_type (work, mangled, &temp);
2003           if (!success) break;
2004         }
2005       else
2006         {       
2007           namelength = consume_count (mangled);
2008           if (strlen (*mangled) < namelength)
2009             {
2010               /* Simple sanity check failed */
2011               success = 0;
2012               break;
2013             }
2014           string_appendn (&temp, *mangled, namelength);
2015           *mangled += namelength;
2016         }
2017       if (qualifiers > 0)
2018         {
2019           string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2020         }
2021     }
2022
2023   /* If we are using the result as a function name, we need to append
2024      the appropriate '::' separated constructor or destructor name.
2025      We do this here because this is the most convenient place, where
2026      we already have a pointer to the name and the length of the name.  */
2027
2028   if (isfuncname && (work->constructor & 1 || work->destructor & 1))
2029     {
2030       string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2031       if (work -> destructor & 1)
2032         {
2033           string_append (&temp, "~");
2034         }
2035       string_appendn (&temp, (*mangled) - namelength, namelength);
2036     }
2037
2038   /* Now either prepend the temp buffer to the result, or append it, 
2039      depending upon the state of the append flag.  */
2040
2041   if (append)
2042     {
2043       string_appends (result, &temp);
2044     }
2045   else
2046     {
2047       if (!STRING_EMPTY (result))
2048         {
2049           string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2050         }
2051       string_prepends (result, &temp);
2052     }
2053
2054   string_delete (&temp);
2055   return (success);
2056 }
2057
2058 /*
2059
2060 LOCAL FUNCTION
2061
2062         get_count -- convert an ascii count to integer, consuming tokens
2063
2064 SYNOPSIS
2065
2066         static int
2067         get_count (const char **type, int *count)
2068
2069 DESCRIPTION
2070
2071         Return 0 if no conversion is performed, 1 if a string is converted.
2072 */
2073
2074 static int
2075 get_count (type, count)
2076      const char **type;
2077      int *count;
2078 {
2079   const char *p;
2080   int n;
2081
2082   if (!isdigit (**type))
2083     {
2084       return (0);
2085     }
2086   else
2087     {
2088       *count = **type - '0';
2089       (*type)++;
2090       if (isdigit (**type))
2091         {
2092           p = *type;
2093           n = *count;
2094           do 
2095             {
2096               n *= 10;
2097               n += *p - '0';
2098               p++;
2099             } 
2100           while (isdigit (*p));
2101           if (*p == '_')
2102             {
2103               *type = p + 1;
2104               *count = n;
2105             }
2106         }
2107     }
2108   return (1);
2109 }
2110
2111 /* result will be initialised here; it will be freed on failure */
2112
2113 static int
2114 do_type (work, mangled, result)
2115      struct work_stuff *work;
2116      const char **mangled;
2117      string *result;
2118 {
2119   int n;
2120   int done;
2121   int success;
2122   string decl;
2123   const char *remembered_type;
2124   int constp;
2125   int volatilep;
2126
2127   string_init (&decl);
2128   string_init (result);
2129
2130   done = 0;
2131   success = 1;
2132   while (success && !done)
2133     {
2134       int member;
2135       switch (**mangled)
2136         {
2137
2138           /* A pointer type */
2139         case 'P':
2140         case 'p':
2141           (*mangled)++;
2142           if (! (work -> options & DMGL_JAVA))
2143             string_prepend (&decl, "*");
2144           break;
2145
2146           /* A reference type */
2147         case 'R':
2148           (*mangled)++;
2149           string_prepend (&decl, "&");
2150           break;
2151
2152           /* An array */
2153         case 'A':
2154           {
2155             const char *p = ++(*mangled);
2156
2157             string_prepend (&decl, "(");
2158             string_append (&decl, ")[");
2159             /* Copy anything up until the next underscore (the size of the
2160                array).  */
2161             while (**mangled && **mangled != '_')
2162               ++(*mangled);
2163             if (**mangled == '_')
2164               {
2165                 string_appendn (&decl, p, *mangled - p);
2166                 string_append (&decl, "]");             
2167                 *mangled += 1;
2168               }
2169             else
2170               success = 0;
2171             break;
2172           }
2173
2174         /* A back reference to a previously seen type */
2175         case 'T':
2176           (*mangled)++;
2177           if (!get_count (mangled, &n) || n >= work -> ntypes)
2178             {
2179               success = 0;
2180             }
2181           else
2182             {
2183               remembered_type = work -> typevec[n];
2184               mangled = &remembered_type;
2185             }
2186           break;
2187
2188           /* A function */
2189         case 'F':
2190           (*mangled)++;
2191           if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
2192             {
2193               string_prepend (&decl, "(");
2194               string_append (&decl, ")");
2195             }
2196           /* After picking off the function args, we expect to either find the
2197              function return type (preceded by an '_') or the end of the
2198              string.  */
2199           if (!demangle_args (work, mangled, &decl)
2200               || (**mangled != '_' && **mangled != '\0'))
2201             {
2202               success = 0;
2203             }
2204           if (success && (**mangled == '_'))
2205             {
2206               (*mangled)++;
2207             }
2208           break;
2209
2210         case 'M':
2211         case 'O':
2212           {
2213             constp = 0;
2214             volatilep = 0;
2215
2216             member = **mangled == 'M';
2217             (*mangled)++;
2218             if (!isdigit (**mangled) && **mangled != 't')
2219               {
2220                 success = 0;
2221                 break;
2222               }
2223
2224             string_append (&decl, ")");
2225             string_prepend (&decl, (work -> options & DMGL_JAVA) ? "." : "::");
2226             if (isdigit (**mangled)) 
2227               {
2228                 n = consume_count (mangled);
2229                 if (strlen (*mangled) < n)
2230                   {
2231                     success = 0;
2232                     break;
2233                   }
2234                 string_prependn (&decl, *mangled, n);
2235                 *mangled += n;
2236               }
2237             else
2238               {
2239                 string temp;
2240                 string_init (&temp);
2241                 success = demangle_template (work, mangled, &temp, NULL, 1);
2242                 if (success)
2243                   {
2244                     string_prependn (&decl, temp.b, temp.p - temp.b);
2245                     string_clear (&temp);
2246                   }
2247                 else
2248                   break;
2249               }
2250             string_prepend (&decl, "(");
2251             if (member)
2252               {
2253                 if (**mangled == 'C')
2254                   {
2255                     (*mangled)++;
2256                     constp = 1;
2257                   }
2258                 if (**mangled == 'V')
2259                   {
2260                     (*mangled)++;
2261                     volatilep = 1;
2262                   }
2263                 if (*(*mangled)++ != 'F')
2264                   {
2265                     success = 0;
2266                     break;
2267                   }
2268               }
2269             if ((member && !demangle_args (work, mangled, &decl))
2270                 || **mangled != '_')
2271               {
2272                 success = 0;
2273                 break;
2274               }
2275             (*mangled)++;
2276             if (! PRINT_ANSI_QUALIFIERS)
2277               {
2278                 break;
2279               }
2280             if (constp)
2281               {
2282                 APPEND_BLANK (&decl);
2283                 string_append (&decl, "const");
2284               }
2285             if (volatilep)
2286               {
2287                 APPEND_BLANK (&decl);
2288                 string_append (&decl, "volatile");
2289               }
2290             break;
2291           }
2292         case 'G':
2293           (*mangled)++;
2294           break;
2295
2296         case 'C':
2297           (*mangled)++;
2298           /*
2299             if ((*mangled)[1] == 'P')
2300             {
2301             */
2302           if (PRINT_ANSI_QUALIFIERS)
2303             {
2304               if (!STRING_EMPTY (&decl))
2305                 {
2306                   string_prepend (&decl, " ");
2307                 }
2308               string_prepend (&decl, "const");
2309             }
2310           break;
2311           /*
2312             }
2313             */
2314
2315           /* fall through */
2316         default:
2317           done = 1;
2318           break;
2319         }
2320     }
2321
2322   switch (**mangled)
2323     {
2324       /* A qualified name, such as "Outer::Inner".  */
2325     case 'Q':
2326       success = demangle_qualified (work, mangled, result, 0, 1);
2327       break;
2328
2329     case 'X':
2330     case 'Y':
2331       /* A template parm.  We substitute the corresponding argument. */
2332       {
2333         int idx;
2334         int lvl;
2335
2336         (*mangled)++;
2337         idx = consume_count_with_underscores (mangled);
2338
2339         if (idx == -1 
2340             || (work->tmpl_argvec && idx >= work->ntmpl_args)
2341             || consume_count_with_underscores (mangled) == -1)
2342           {
2343             success = 0;
2344             break;
2345           }
2346
2347         if (work->tmpl_argvec)
2348           string_append (result, work->tmpl_argvec[idx]);
2349         else
2350           {
2351             char buf[10];
2352             sprintf(buf, "T%d", idx);
2353             string_append (result, buf);
2354           }
2355
2356         success = 1;
2357       }
2358     break;
2359
2360     default:
2361       success = demangle_fund_type (work, mangled, result);
2362       break;
2363     }
2364
2365   if (success)
2366     {
2367       if (!STRING_EMPTY (&decl))
2368         {
2369           string_append (result, " ");
2370           string_appends (result, &decl);
2371         }
2372     }
2373   else
2374     {
2375       string_delete (result);
2376     }
2377   string_delete (&decl);
2378   return (success);
2379 }
2380
2381 /* Given a pointer to a type string that represents a fundamental type
2382    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2383    string in which the demangled output is being built in RESULT, and
2384    the WORK structure, decode the types and add them to the result.
2385
2386    For example:
2387
2388         "Ci"    =>      "const int"
2389         "Sl"    =>      "signed long"
2390         "CUs"   =>      "const unsigned short"
2391
2392    */
2393
2394 static int
2395 demangle_fund_type (work, mangled, result)
2396      struct work_stuff *work;
2397      const char **mangled;
2398      string *result;
2399 {
2400   int done = 0;
2401   int success = 1;
2402
2403   /* First pick off any type qualifiers.  There can be more than one.  */
2404
2405   while (!done)
2406     {
2407       switch (**mangled)
2408         {
2409         case 'C':
2410           (*mangled)++;
2411           if (PRINT_ANSI_QUALIFIERS)
2412             {
2413               APPEND_BLANK (result);
2414               string_append (result, "const");
2415             }
2416           break;
2417         case 'U':
2418           (*mangled)++;
2419           APPEND_BLANK (result);
2420           string_append (result, "unsigned");
2421           break;
2422         case 'S': /* signed char only */
2423           (*mangled)++;
2424           APPEND_BLANK (result);
2425           string_append (result, "signed");
2426           break;
2427         case 'V':
2428           (*mangled)++;
2429           if (PRINT_ANSI_QUALIFIERS)
2430             {
2431               APPEND_BLANK (result);
2432               string_append (result, "volatile");
2433             }
2434           break;
2435         case 'J':
2436           (*mangled)++;
2437           APPEND_BLANK (result);
2438           string_append (result, "__complex");
2439           break;
2440         default:
2441           done = 1;
2442           break;
2443         }
2444     }
2445
2446   /* Now pick off the fundamental type.  There can be only one.  */
2447
2448   switch (**mangled)
2449     {
2450     case '\0':
2451     case '_':
2452       break;
2453     case 'v':
2454       (*mangled)++;
2455       APPEND_BLANK (result);
2456       string_append (result, "void");
2457       break;
2458     case 'x':
2459       (*mangled)++;
2460       APPEND_BLANK (result);
2461       string_append (result, "long long");
2462       break;
2463     case 'l':
2464       (*mangled)++;
2465       APPEND_BLANK (result);
2466       string_append (result, "long");
2467       break;
2468     case 'i':
2469       (*mangled)++;
2470       APPEND_BLANK (result);
2471       string_append (result, "int");
2472       break;
2473     case 's':
2474       (*mangled)++;
2475       APPEND_BLANK (result);
2476       string_append (result, "short");
2477       break;
2478     case 'b':
2479       (*mangled)++;
2480       APPEND_BLANK (result);
2481       string_append (result, "bool");
2482       break;
2483     case 'c':
2484       (*mangled)++;
2485       APPEND_BLANK (result);
2486       string_append (result, "char");
2487       break;
2488     case 'w':
2489       (*mangled)++;
2490       APPEND_BLANK (result);
2491       string_append (result, "wchar_t");
2492       break;
2493     case 'r':
2494       (*mangled)++;
2495       APPEND_BLANK (result);
2496       string_append (result, "long double");
2497       break;
2498     case 'd':
2499       (*mangled)++;
2500       APPEND_BLANK (result);
2501       string_append (result, "double");
2502       break;
2503     case 'f':
2504       (*mangled)++;
2505       APPEND_BLANK (result);
2506       string_append (result, "float");
2507       break;
2508     case 'G':
2509       (*mangled)++;
2510       if (!isdigit (**mangled))
2511         {
2512           success = 0;
2513           break;
2514         }
2515       /* fall through */
2516       /* An explicit type, such as "6mytype" or "7integer" */
2517     case '0':
2518     case '1':
2519     case '2':
2520     case '3':
2521     case '4':
2522     case '5':
2523     case '6':
2524     case '7':
2525     case '8':
2526     case '9':
2527       APPEND_BLANK (result);
2528       if (!demangle_class_name (work, mangled, result)) {
2529         --result->p;
2530         success = 0;
2531       }
2532       break;
2533     case 't':
2534       success = demangle_template(work,mangled, result, 0, 1);
2535       break;
2536     default:
2537       success = 0;
2538       break;
2539     }
2540
2541   return (success);
2542 }
2543
2544 /* `result' will be initialized in do_type; it will be freed on failure */
2545
2546 static int
2547 do_arg (work, mangled, result)
2548      struct work_stuff *work;
2549      const char **mangled;
2550      string *result;
2551 {
2552   const char *start = *mangled;
2553
2554   if (!do_type (work, mangled, result))
2555     {
2556       return (0);
2557     }
2558   else
2559     {
2560       remember_type (work, start, *mangled - start);
2561       return (1);
2562     }
2563 }
2564
2565 static void
2566 remember_type (work, start, len)
2567      struct work_stuff *work;
2568      const char *start;
2569      int len;
2570 {
2571   char *tem;
2572
2573   if (work -> ntypes >= work -> typevec_size)
2574     {
2575       if (work -> typevec_size == 0)
2576         {
2577           work -> typevec_size = 3;
2578           work -> typevec
2579             = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
2580         }
2581       else
2582         {
2583           work -> typevec_size *= 2;
2584           work -> typevec
2585             = (char **) xrealloc ((char *)work -> typevec,
2586                                   sizeof (char *) * work -> typevec_size);
2587         }
2588     }
2589   tem = xmalloc (len + 1);
2590   memcpy (tem, start, len);
2591   tem[len] = '\0';
2592   work -> typevec[work -> ntypes++] = tem;
2593 }
2594
2595 /* Forget the remembered types, but not the type vector itself.  */
2596
2597 static void
2598 forget_types (work)
2599      struct work_stuff *work;
2600 {
2601   int i;
2602
2603   while (work -> ntypes > 0)
2604     {
2605       i = --(work -> ntypes);
2606       if (work -> typevec[i] != NULL)
2607         {
2608           free (work -> typevec[i]);
2609           work -> typevec[i] = NULL;
2610         }
2611     }
2612 }
2613
2614 /* Process the argument list part of the signature, after any class spec
2615    has been consumed, as well as the first 'F' character (if any).  For
2616    example:
2617
2618    "__als__3fooRT0"             =>      process "RT0"
2619    "complexfunc5__FPFPc_PFl_i"  =>      process "PFPc_PFl_i"
2620
2621    DECLP must be already initialised, usually non-empty.  It won't be freed
2622    on failure.
2623
2624    Note that g++ differs significantly from ARM and lucid style mangling
2625    with regards to references to previously seen types.  For example, given
2626    the source fragment:
2627
2628      class foo {
2629        public:
2630        foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
2631      };
2632
2633      foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2634      void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2635
2636    g++ produces the names:
2637
2638      __3fooiRT0iT2iT2
2639      foo__FiR3fooiT1iT1
2640
2641    while lcc (and presumably other ARM style compilers as well) produces:
2642
2643      foo__FiR3fooT1T2T1T2
2644      __ct__3fooFiR3fooT1T2T1T2
2645
2646    Note that g++ bases it's type numbers starting at zero and counts all
2647    previously seen types, while lucid/ARM bases it's type numbers starting
2648    at one and only considers types after it has seen the 'F' character
2649    indicating the start of the function args.  For lucid/ARM style, we
2650    account for this difference by discarding any previously seen types when
2651    we see the 'F' character, and subtracting one from the type number
2652    reference.
2653
2654  */
2655
2656 static int
2657 demangle_args (work, mangled, declp)
2658      struct work_stuff *work;
2659      const char **mangled;
2660      string *declp;
2661 {
2662   string arg;
2663   int need_comma = 0;
2664   int r;
2665   int t;
2666   const char *tem;
2667   char temptype;
2668
2669   if (PRINT_ARG_TYPES)
2670     {
2671       string_append (declp, "(");
2672       if (**mangled == '\0')
2673         {
2674           string_append (declp, "void");
2675         }
2676     }
2677
2678   while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
2679     {
2680       if ((**mangled == 'N') || (**mangled == 'T'))
2681         {
2682           temptype = *(*mangled)++;
2683           
2684           if (temptype == 'N')
2685             {
2686               if (!get_count (mangled, &r))
2687                 {
2688                   return (0);
2689                 }
2690             }
2691           else
2692             {
2693               r = 1;
2694             }
2695           if (ARM_DEMANGLING && work -> ntypes >= 10)
2696             {
2697               /* If we have 10 or more types we might have more than a 1 digit
2698                  index so we'll have to consume the whole count here. This
2699                  will lose if the next thing is a type name preceded by a
2700                  count but it's impossible to demangle that case properly
2701                  anyway. Eg if we already have 12 types is T12Pc "(..., type1,
2702                  Pc, ...)"  or "(..., type12, char *, ...)" */
2703               if ((t = consume_count(mangled)) == 0)
2704                 {
2705                   return (0);
2706                 }
2707             }
2708           else
2709             {
2710               if (!get_count (mangled, &t))
2711                 {
2712                   return (0);
2713                 }
2714             }
2715           if (LUCID_DEMANGLING || ARM_DEMANGLING)
2716             {
2717               t--;
2718             }
2719           /* Validate the type index.  Protect against illegal indices from
2720              malformed type strings.  */
2721           if ((t < 0) || (t >= work -> ntypes))
2722             {
2723               return (0);
2724             }
2725           while (--r >= 0)
2726             {
2727               tem = work -> typevec[t];
2728               if (need_comma && PRINT_ARG_TYPES)
2729                 {
2730                   string_append (declp, ", ");
2731                 }
2732               if (!do_arg (work, &tem, &arg))
2733                 {
2734                   return (0);
2735                 }
2736               if (PRINT_ARG_TYPES)
2737                 {
2738                   string_appends (declp, &arg);
2739                 }
2740               string_delete (&arg);
2741               need_comma = 1;
2742             }
2743         }
2744       else
2745         {
2746           if (need_comma & PRINT_ARG_TYPES)
2747             {
2748               string_append (declp, ", ");
2749             }
2750           if (!do_arg (work, mangled, &arg))
2751             {
2752               return (0);
2753             }
2754           if (PRINT_ARG_TYPES)
2755             {
2756               string_appends (declp, &arg);
2757             }
2758           string_delete (&arg);
2759           need_comma = 1;
2760         }
2761     }
2762
2763   if (**mangled == 'e')
2764     {
2765       (*mangled)++;
2766       if (PRINT_ARG_TYPES)
2767         {
2768           if (need_comma)
2769             {
2770               string_append (declp, ",");
2771             }
2772           string_append (declp, "...");
2773         }
2774     }
2775
2776   if (PRINT_ARG_TYPES)
2777     {
2778       string_append (declp, ")");
2779     }
2780   return (1);
2781 }
2782
2783 static void
2784 demangle_function_name (work, mangled, declp, scan)
2785      struct work_stuff *work;
2786      const char **mangled;
2787      string *declp;
2788      const char *scan;
2789 {
2790   int i;
2791   int len;
2792   string type;
2793   const char *tem;
2794
2795   string_appendn (declp, (*mangled), scan - (*mangled));
2796   string_need (declp, 1);
2797   *(declp -> p) = '\0';
2798
2799   /* Consume the function name, including the "__" separating the name
2800      from the signature.  We are guaranteed that SCAN points to the
2801      separator.  */
2802
2803   (*mangled) = scan + 2;
2804
2805   if (LUCID_DEMANGLING || ARM_DEMANGLING)
2806     {
2807
2808       /* See if we have an ARM style constructor or destructor operator.
2809          If so, then just record it, clear the decl, and return.
2810          We can't build the actual constructor/destructor decl until later,
2811          when we recover the class name from the signature.  */
2812
2813       if (strcmp (declp -> b, "__ct") == 0)
2814         {
2815           work -> constructor += 1;
2816           string_clear (declp);
2817           return;
2818         }
2819       else if (strcmp (declp -> b, "__dt") == 0)
2820         {
2821           work -> destructor += 1;
2822           string_clear (declp);
2823           return;
2824         }
2825     }
2826
2827   if (declp->p - declp->b >= 3 
2828       && declp->b[0] == 'o'
2829       && declp->b[1] == 'p'
2830       && strchr (cplus_markers, declp->b[2]) != NULL)
2831     {
2832       /* see if it's an assignment expression */
2833       if (declp->p - declp->b >= 10 /* op$assign_ */
2834           && memcmp (declp->b + 3, "assign_", 7) == 0)
2835         {
2836           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2837             {
2838               len = declp->p - declp->b - 10;
2839               if (strlen (optable[i].in) == len
2840                   && memcmp (optable[i].in, declp->b + 10, len) == 0)
2841                 {
2842                   string_clear (declp);
2843                   string_append (declp, "operator");
2844                   string_append (declp, optable[i].out);
2845                   string_append (declp, "=");
2846                   break;
2847                 }
2848             }
2849         }
2850       else
2851         {
2852           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2853             {
2854               int len = declp->p - declp->b - 3;
2855               if (strlen (optable[i].in) == len 
2856                   && memcmp (optable[i].in, declp->b + 3, len) == 0)
2857                 {
2858                   string_clear (declp);
2859                   string_append (declp, "operator");
2860                   string_append (declp, optable[i].out);
2861                   break;
2862                 }
2863             }
2864         }
2865     }
2866   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
2867            && strchr (cplus_markers, declp->b[4]) != NULL)
2868     {
2869       /* type conversion operator */
2870       tem = declp->b + 5;
2871       if (do_type (work, &tem, &type))
2872         {
2873           string_clear (declp);
2874           string_append (declp, "operator ");
2875           string_appends (declp, &type);
2876           string_delete (&type);
2877         }
2878     }
2879   else if (declp->b[0] == '_' && declp->b[1] == '_'
2880            && declp->b[2] == 'o' && declp->b[3] == 'p')
2881     {
2882       /* ANSI.  */
2883       /* type conversion operator.  */
2884       tem = declp->b + 4;
2885       if (do_type (work, &tem, &type))
2886         {
2887           string_clear (declp);
2888           string_append (declp, "operator ");
2889           string_appends (declp, &type);
2890           string_delete (&type);
2891         }
2892     }
2893   else if (declp->b[0] == '_' && declp->b[1] == '_'
2894            && declp->b[2] >= 'a' && declp->b[2] <= 'z'
2895            && declp->b[3] >= 'a' && declp->b[3] <= 'z')
2896     {
2897       if (declp->b[4] == '\0')
2898         {
2899           /* Operator.  */
2900           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2901             {
2902               if (strlen (optable[i].in) == 2
2903                   && memcmp (optable[i].in, declp->b + 2, 2) == 0)
2904                 {
2905                   string_clear (declp);
2906                   string_append (declp, "operator");
2907                   string_append (declp, optable[i].out);
2908                   break;
2909                 }
2910             }
2911         }
2912       else
2913         {
2914           if (declp->b[2] == 'a' && declp->b[5] == '\0')
2915             {
2916               /* Assignment.  */
2917               for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2918                 {
2919                   if (strlen (optable[i].in) == 3
2920                       && memcmp (optable[i].in, declp->b + 2, 3) == 0)
2921                     {
2922                       string_clear (declp);
2923                       string_append (declp, "operator");
2924                       string_append (declp, optable[i].out);
2925                       break;
2926                     }                 
2927                 }
2928             }
2929         }
2930     }
2931 }
2932
2933 /* a mini string-handling package */
2934
2935 static void
2936 string_need (s, n)
2937      string *s;
2938      int n;
2939 {
2940   int tem;
2941
2942   if (s->b == NULL)
2943     {
2944       if (n < 32)
2945         {
2946           n = 32;
2947         }
2948       s->p = s->b = xmalloc (n);
2949       s->e = s->b + n;
2950     }
2951   else if (s->e - s->p < n)
2952     {
2953       tem = s->p - s->b;
2954       n += tem;
2955       n *= 2;
2956       s->b = xrealloc (s->b, n);
2957       s->p = s->b + tem;
2958       s->e = s->b + n;
2959     }
2960 }
2961
2962 static void
2963 string_delete (s)
2964      string *s;
2965 {
2966   if (s->b != NULL)
2967     {
2968       free (s->b);
2969       s->b = s->e = s->p = NULL;
2970     }
2971 }
2972
2973 static void
2974 string_init (s)
2975      string *s;
2976 {
2977   s->b = s->p = s->e = NULL;
2978 }
2979
2980 static void 
2981 string_clear (s)
2982      string *s;
2983 {
2984   s->p = s->b;
2985 }
2986
2987 #if 0
2988
2989 static int
2990 string_empty (s)
2991      string *s;
2992 {
2993   return (s->b == s->p);
2994 }
2995
2996 #endif
2997
2998 static void
2999 string_append (p, s)
3000      string *p;
3001      const char *s;
3002 {
3003   int n;
3004   if (s == NULL || *s == '\0')
3005     return;
3006   n = strlen (s);
3007   string_need (p, n);
3008   memcpy (p->p, s, n);
3009   p->p += n;
3010 }
3011
3012 static void
3013 string_appends (p, s)
3014      string *p, *s;
3015 {
3016   int n;
3017
3018   if (s->b != s->p)
3019     {
3020       n = s->p - s->b;
3021       string_need (p, n);
3022       memcpy (p->p, s->b, n);
3023       p->p += n;
3024     }
3025 }
3026
3027 static void
3028 string_appendn (p, s, n)
3029      string *p;
3030      const char *s;
3031      int n;
3032 {
3033   if (n != 0)
3034     {
3035       string_need (p, n);
3036       memcpy (p->p, s, n);
3037       p->p += n;
3038     }
3039 }
3040
3041 static void
3042 string_prepend (p, s)
3043      string *p;
3044      const char *s;
3045 {
3046   if (s != NULL && *s != '\0')
3047     {
3048       string_prependn (p, s, strlen (s));
3049     }
3050 }
3051
3052 static void
3053 string_prepends (p, s)
3054      string *p, *s;
3055 {
3056   if (s->b != s->p)
3057     {
3058       string_prependn (p, s->b, s->p - s->b);
3059     }
3060 }
3061
3062 static void
3063 string_prependn (p, s, n)
3064      string *p;
3065      const char *s;
3066      int n;
3067 {
3068   char *q;
3069
3070   if (n != 0)
3071     {
3072       string_need (p, n);
3073       for (q = p->p - 1; q >= p->b; q--)
3074         {
3075           q[n] = q[0];
3076         }
3077       memcpy (p->b, s, n);
3078       p->p += n;
3079     }
3080 }
3081
3082 /* To generate a standalone demangler program for testing purposes,
3083    just compile and link this file with -DMAIN and libiberty.a.  When
3084    run, it demangles each command line arg, or each stdin string, and
3085    prints the result on stdout.  */
3086
3087 #ifdef MAIN
3088
3089 #include "getopt.h"
3090
3091 static char *program_name;
3092 static char *program_version = VERSION;
3093 static int flags = DMGL_PARAMS | DMGL_ANSI;
3094
3095 static void demangle_it PARAMS ((char *));
3096 static void usage PARAMS ((FILE *, int));
3097 static void fatal PARAMS ((char *));
3098
3099 static void
3100 demangle_it (mangled_name)
3101      char *mangled_name;
3102 {
3103   char *result;
3104
3105   result = cplus_demangle (mangled_name, flags);
3106   if (result == NULL)
3107     {
3108       printf ("%s\n", mangled_name);
3109     }
3110   else
3111     {
3112       printf ("%s\n", result);
3113       free (result);
3114     }
3115 }
3116
3117 static void
3118 usage (stream, status)
3119      FILE *stream;
3120      int status;
3121 {    
3122   fprintf (stream, "\
3123 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3124       [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3125       [--help] [--version] [arg...]\n",
3126            program_name);
3127   exit (status);
3128 }
3129
3130 #define MBUF_SIZE 512
3131 char mbuffer[MBUF_SIZE];
3132
3133 /* Defined in the automatically-generated underscore.c.  */
3134 extern int prepends_underscore;
3135
3136 int strip_underscore = 0;
3137
3138 static struct option long_options[] = {
3139   {"strip-underscores", no_argument, 0, '_'},
3140   {"format", required_argument, 0, 's'},
3141   {"help", no_argument, 0, 'h'},
3142   {"java", no_argument, 0, 'j'},
3143   {"no-strip-underscores", no_argument, 0, 'n'},
3144   {"version", no_argument, 0, 'v'},
3145   {0, no_argument, 0, 0}
3146 };
3147
3148 int
3149 main (argc, argv)
3150      int argc;
3151      char **argv;
3152 {
3153   char *result;
3154   int c;
3155
3156   program_name = argv[0];
3157
3158   strip_underscore = prepends_underscore;
3159
3160   while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF)
3161     {
3162       switch (c)
3163         {
3164         case '?':
3165           usage (stderr, 1);
3166           break;
3167         case 'h':
3168           usage (stdout, 0);
3169         case 'n':
3170           strip_underscore = 0;
3171           break;
3172         case 'v':
3173           printf ("GNU %s version %s\n", program_name, program_version);
3174           exit (0);
3175         case '_':
3176           strip_underscore = 1;
3177           break;
3178         case 'j':
3179           flags |= DMGL_JAVA;
3180           break;
3181         case 's':
3182           if (strcmp (optarg, "gnu") == 0)
3183             {
3184               current_demangling_style = gnu_demangling;
3185             }
3186           else if (strcmp (optarg, "lucid") == 0)
3187             {
3188               current_demangling_style = lucid_demangling;
3189             }
3190           else if (strcmp (optarg, "arm") == 0)
3191             {
3192               current_demangling_style = arm_demangling;
3193             }
3194           else
3195             {
3196               fprintf (stderr, "%s: unknown demangling style `%s'\n",
3197                        program_name, optarg);
3198               exit (1);
3199             }
3200           break;
3201         }
3202     }
3203
3204   if (optind < argc)
3205     {
3206       for ( ; optind < argc; optind++)
3207         {
3208           demangle_it (argv[optind]);
3209         }
3210     }
3211   else
3212     {
3213       for (;;)
3214         {
3215           int i = 0;
3216           c = getchar ();
3217           /* Try to read a label.  */
3218           while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
3219             {
3220               if (i >= MBUF_SIZE-1)
3221                 break;
3222               mbuffer[i++] = c;
3223               c = getchar ();
3224             }
3225           if (i > 0)
3226             {
3227               int skip_first = 0;
3228
3229               if (mbuffer[0] == '.')
3230                 ++skip_first;
3231               if (strip_underscore && mbuffer[skip_first] == '_')
3232                 ++skip_first;
3233
3234               if (skip_first > i)
3235                 skip_first = i;
3236
3237               mbuffer[i] = 0;
3238               
3239               result = cplus_demangle (mbuffer + skip_first, flags);
3240               if (result)
3241                 {
3242                   if (mbuffer[0] == '.')
3243                     putc ('.', stdout);
3244                   fputs (result, stdout);
3245                   free (result);
3246                 }
3247               else
3248                 fputs (mbuffer, stdout);
3249
3250               fflush (stdout);
3251             }
3252           if (c == EOF)
3253             break;
3254           putchar (c);
3255         }
3256     }
3257
3258   exit (0);
3259 }
3260
3261 static void
3262 fatal (str)
3263      char *str;
3264 {
3265   fprintf (stderr, "%s: %s\n", program_name, str);
3266   exit (1);
3267 }
3268
3269 char * malloc ();
3270 char * realloc ();
3271
3272 char *
3273 xmalloc (size)
3274      unsigned size;
3275 {
3276   register char *value = (char *) malloc (size);
3277   if (value == 0)
3278     fatal ("virtual memory exhausted");
3279   return value;
3280 }
3281
3282 char *
3283 xrealloc (ptr, size)
3284      char *ptr;
3285      unsigned size;
3286 {
3287   register char *value = (char *) realloc (ptr, size);
3288   if (value == 0)
3289     fatal ("virtual memory exhausted");
3290   return value;
3291 }
3292 #endif  /* main */