OSDN Git Service

* cplus-dem.c (gnu_special): Fix off-by-one bug when checking the
[pf3gnuchains/gcc-fork.git] / 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 <sys/types.h>
33 #include <string.h>
34 #include <stdio.h>
35
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39
40 #include <demangle.h>
41 #undef CURRENT_DEMANGLING_STYLE
42 #define CURRENT_DEMANGLING_STYLE work->options
43
44 extern char *xmalloc PARAMS((unsigned));
45 extern char *xrealloc PARAMS((char *, unsigned));
46
47 static const char *mystrstr PARAMS ((const char *, const char *));
48
49 static const char *
50 mystrstr (s1, s2)
51      const char *s1, *s2;
52 {
53   register const char *p = s1;
54   register int len = strlen (s2);
55
56   for (; (p = strchr (p, *s2)) != 0; p++)
57     {
58       if (strncmp (p, s2, len) == 0)
59         {
60           return (p);
61         }
62     }
63   return (0);
64 }
65
66 /* In order to allow a single demangler executable to demangle strings
67    using various common values of CPLUS_MARKER, as well as any specific
68    one set at compile time, we maintain a string containing all the
69    commonly used ones, and check to see if the marker we are looking for
70    is in that string.  CPLUS_MARKER is usually '$' on systems where the
71    assembler can deal with that.  Where the assembler can't, it's usually
72    '.' (but on many systems '.' is used for other things).  We put the
73    current defined CPLUS_MARKER first (which defaults to '$'), followed
74    by the next most common value, followed by an explicit '$' in case
75    the value of CPLUS_MARKER is not '$'.
76
77    We could avoid this if we could just get g++ to tell us what the actual
78    cplus marker character is as part of the debug information, perhaps by
79    ensuring that it is the character that terminates the gcc<n>_compiled
80    marker symbol (FIXME).  */
81
82 #if !defined (CPLUS_MARKER)
83 #define CPLUS_MARKER '$'
84 #endif
85
86 enum demangling_styles current_demangling_style = gnu_demangling;
87
88 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
89
90 void
91 set_cplus_marker_for_demangling (ch)
92      int ch;
93 {
94   cplus_markers[0] = ch;
95 }
96
97 /* Stuff that is shared between sub-routines.
98    Using a shared structure allows cplus_demangle to be reentrant.  */
99
100 struct work_stuff
101 {
102   int options;
103   char **typevec;
104   char **ktypevec;
105   char **btypevec;
106   int numk;
107   int numb;
108   int ksize;
109   int bsize;
110   int ntypes;
111   int typevec_size;
112   int constructor;
113   int destructor;
114   int static_type;      /* A static member function */
115   int const_type;       /* A const member function */
116   char **tmpl_argvec;   /* Template function arguments. */
117   int ntmpl_args;       /* The number of template function arguments. */
118 };
119
120 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
121 #define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
122
123 static const struct optable
124 {
125   const char *in;
126   const char *out;
127   int flags;
128 } optable[] = {
129   {"nw",          " new",       DMGL_ANSI},     /* new (1.92,    ansi) */
130   {"dl",          " delete",    DMGL_ANSI},     /* new (1.92,    ansi) */
131   {"new",         " new",       0},             /* old (1.91,    and 1.x) */
132   {"delete",      " delete",    0},             /* old (1.91,    and 1.x) */
133   {"vn",          " new []",    DMGL_ANSI},     /* GNU, pending ansi */
134   {"vd",          " delete []", DMGL_ANSI},     /* GNU, pending ansi */
135   {"as",          "=",          DMGL_ANSI},     /* ansi */
136   {"ne",          "!=",         DMGL_ANSI},     /* old, ansi */
137   {"eq",          "==",         DMGL_ANSI},     /* old, ansi */
138   {"ge",          ">=",         DMGL_ANSI},     /* old, ansi */
139   {"gt",          ">",          DMGL_ANSI},     /* old, ansi */
140   {"le",          "<=",         DMGL_ANSI},     /* old, ansi */
141   {"lt",          "<",          DMGL_ANSI},     /* old, ansi */
142   {"plus",        "+",          0},             /* old */
143   {"pl",          "+",          DMGL_ANSI},     /* ansi */
144   {"apl",         "+=",         DMGL_ANSI},     /* ansi */
145   {"minus",       "-",          0},             /* old */
146   {"mi",          "-",          DMGL_ANSI},     /* ansi */
147   {"ami",         "-=",         DMGL_ANSI},     /* ansi */
148   {"mult",        "*",          0},             /* old */
149   {"ml",          "*",          DMGL_ANSI},     /* ansi */
150   {"amu",         "*=",         DMGL_ANSI},     /* ansi (ARM/Lucid) */
151   {"aml",         "*=",         DMGL_ANSI},     /* ansi (GNU/g++) */
152   {"convert",     "+",          0},             /* old (unary +) */
153   {"negate",      "-",          0},             /* old (unary -) */
154   {"trunc_mod",   "%",          0},             /* old */
155   {"md",          "%",          DMGL_ANSI},     /* ansi */
156   {"amd",         "%=",         DMGL_ANSI},     /* ansi */
157   {"trunc_div",   "/",          0},             /* old */
158   {"dv",          "/",          DMGL_ANSI},     /* ansi */
159   {"adv",         "/=",         DMGL_ANSI},     /* ansi */
160   {"truth_andif", "&&",         0},             /* old */
161   {"aa",          "&&",         DMGL_ANSI},     /* ansi */
162   {"truth_orif",  "||",         0},             /* old */
163   {"oo",          "||",         DMGL_ANSI},     /* ansi */
164   {"truth_not",   "!",          0},             /* old */
165   {"nt",          "!",          DMGL_ANSI},     /* ansi */
166   {"postincrement","++",        0},             /* old */
167   {"pp",          "++",         DMGL_ANSI},     /* ansi */
168   {"postdecrement","--",        0},             /* old */
169   {"mm",          "--",         DMGL_ANSI},     /* ansi */
170   {"bit_ior",     "|",          0},             /* old */
171   {"or",          "|",          DMGL_ANSI},     /* ansi */
172   {"aor",         "|=",         DMGL_ANSI},     /* ansi */
173   {"bit_xor",     "^",          0},             /* old */
174   {"er",          "^",          DMGL_ANSI},     /* ansi */
175   {"aer",         "^=",         DMGL_ANSI},     /* ansi */
176   {"bit_and",     "&",          0},             /* old */
177   {"ad",          "&",          DMGL_ANSI},     /* ansi */
178   {"aad",         "&=",         DMGL_ANSI},     /* ansi */
179   {"bit_not",     "~",          0},             /* old */
180   {"co",          "~",          DMGL_ANSI},     /* ansi */
181   {"call",        "()",         0},             /* old */
182   {"cl",          "()",         DMGL_ANSI},     /* ansi */
183   {"alshift",     "<<",         0},             /* old */
184   {"ls",          "<<",         DMGL_ANSI},     /* ansi */
185   {"als",         "<<=",        DMGL_ANSI},     /* ansi */
186   {"arshift",     ">>",         0},             /* old */
187   {"rs",          ">>",         DMGL_ANSI},     /* ansi */
188   {"ars",         ">>=",        DMGL_ANSI},     /* ansi */
189   {"component",   "->",         0},             /* old */
190   {"pt",          "->",         DMGL_ANSI},     /* ansi; Lucid C++ form */
191   {"rf",          "->",         DMGL_ANSI},     /* ansi; ARM/GNU form */
192   {"indirect",    "*",          0},             /* old */
193   {"method_call",  "->()",      0},             /* old */
194   {"addr",        "&",          0},             /* old (unary &) */
195   {"array",       "[]",         0},             /* old */
196   {"vc",          "[]",         DMGL_ANSI},     /* ansi */
197   {"compound",    ", ",         0},             /* old */
198   {"cm",          ", ",         DMGL_ANSI},     /* ansi */
199   {"cond",        "?:",         0},             /* old */
200   {"cn",          "?:",         DMGL_ANSI},     /* pseudo-ansi */
201   {"max",         ">?",         0},             /* old */
202   {"mx",          ">?",         DMGL_ANSI},     /* pseudo-ansi */
203   {"min",         "<?",         0},             /* old */
204   {"mn",          "<?",         DMGL_ANSI},     /* pseudo-ansi */
205   {"nop",         "",           0},             /* old (for operator=) */
206   {"rm",          "->*",        DMGL_ANSI},     /* ansi */
207   {"sz",          "sizeof ",    DMGL_ANSI}      /* pseudo-ansi */
208 };
209
210
211 typedef struct string           /* Beware: these aren't required to be */
212 {                               /*  '\0' terminated.  */
213   char *b;                      /* pointer to start of string */
214   char *p;                      /* pointer after last character */
215   char *e;                      /* pointer after end of allocated space */
216 } string;
217
218 #define STRING_EMPTY(str)       ((str) -> b == (str) -> p)
219 #define PREPEND_BLANK(str)      {if (!STRING_EMPTY(str)) \
220     string_prepend(str, " ");}
221 #define APPEND_BLANK(str)       {if (!STRING_EMPTY(str)) \
222     string_append(str, " ");}
223 #define LEN_STRING(str)         ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
224
225 #define ARM_VTABLE_STRING "__vtbl__"    /* Lucid/ARM virtual table prefix */
226 #define ARM_VTABLE_STRLEN 8             /* strlen (ARM_VTABLE_STRING) */
227
228 /* Prototypes for local functions */
229
230 static char *
231 mop_up PARAMS ((struct work_stuff *, string *, int));
232
233 static char *
234 squangle_mop_up PARAMS ((struct work_stuff *));
235
236 #if 0
237 static int
238 demangle_method_args PARAMS ((struct work_stuff *, const char **, string *));
239 #endif
240
241 static char *
242 internal_cplus_demangle PARAMS ((struct work_stuff *, const char *, int));
243
244 static int
245 demangle_template_template_parm PARAMS ((struct work_stuff *work, 
246                                          const char **, string *));
247
248 static int
249 demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
250                            string *, int));
251
252 static int
253 arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **,
254                 const char **));
255
256 static void
257 demangle_arm_pt PARAMS ((struct work_stuff *, const char **, int, string *));
258
259 static int
260 demangle_class_name PARAMS ((struct work_stuff *, const char **, string *));
261
262 static int
263 demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
264                             int, int));
265
266 static int
267 demangle_class PARAMS ((struct work_stuff *, const char **, string *));
268
269 static int
270 demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
271
272 static int
273 demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
274
275 static int
276 demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
277
278 static int
279 gnu_special PARAMS ((struct work_stuff *, const char **, string *));
280
281 static int
282 arm_special PARAMS ((const char **, string *));
283
284 static void
285 string_need PARAMS ((string *, int));
286
287 static void
288 string_delete PARAMS ((string *));
289
290 static void
291 string_init PARAMS ((string *));
292
293 static void
294 string_clear PARAMS ((string *));
295
296 #if 0
297 static int
298 string_empty PARAMS ((string *));
299 #endif
300
301 static void
302 string_append PARAMS ((string *, const char *));
303
304 static void
305 string_appends PARAMS ((string *, string *));
306
307 static void
308 string_appendn PARAMS ((string *, const char *, int));
309
310 static void
311 string_prepend PARAMS ((string *, const char *));
312
313 static void
314 string_prependn PARAMS ((string *, const char *, int));
315
316 static int
317 get_count PARAMS ((const char **, int *));
318
319 static int
320 consume_count PARAMS ((const char **));
321
322 static int 
323 consume_count_with_underscores PARAMS ((const char**));
324
325 static int
326 demangle_args PARAMS ((struct work_stuff *, const char **, string *));
327
328 static int
329 do_type PARAMS ((struct work_stuff *, const char **, string *));
330
331 static int
332 do_arg PARAMS ((struct work_stuff *, const char **, string *));
333
334 static void
335 demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
336                                 const char *));
337
338 static void
339 remember_type PARAMS ((struct work_stuff *, const char *, int));
340
341 static void
342 remember_Btype PARAMS ((struct work_stuff *, const char *, int, int));
343
344 static int
345 register_Btype PARAMS ((struct work_stuff *));
346
347 static void
348 remember_Ktype PARAMS ((struct work_stuff *, const char *, int));
349
350 static void
351 forget_types PARAMS ((struct work_stuff *));
352
353 static void
354 forget_B_and_K_types PARAMS ((struct work_stuff *));
355
356 static void
357 string_prepends PARAMS ((string *, string *));
358
359 static int 
360 demangle_template_value_parm PARAMS ((struct work_stuff*, 
361                                       const char**, string*)); 
362
363 /*  Translate count to integer, consuming tokens in the process.
364     Conversion terminates on the first non-digit character.
365     Trying to consume something that isn't a count results in
366     no consumption of input and a return of 0.  */
367
368 static int
369 consume_count (type)
370      const char **type;
371 {
372   int count = 0;
373
374   while (isdigit (**type))
375     {
376       count *= 10;
377       count += **type - '0';
378       (*type)++;
379     }
380   return (count);
381 }
382
383
384 /* Like consume_count, but for counts that are preceded and followed
385    by '_' if they are greater than 10.  Also, -1 is returned for
386    failure, since 0 can be a valid value.  */
387
388 static int
389 consume_count_with_underscores (mangled)
390      const char **mangled;
391 {
392   int idx;
393
394   if (**mangled == '_')
395     {
396       (*mangled)++;
397       if (!isdigit (**mangled))
398         return -1;
399
400       idx = consume_count (mangled);
401       if (**mangled != '_')
402         /* The trailing underscore was missing. */
403         return -1;
404             
405       (*mangled)++;
406     }
407   else
408     {
409       if (**mangled < '0' || **mangled > '9')
410         return -1;
411             
412       idx = **mangled - '0';
413       (*mangled)++;
414     }
415
416   return idx;
417 }
418
419 int
420 cplus_demangle_opname (opname, result, options)
421      const char *opname;
422      char *result;
423      int options;
424 {
425   int len, i, len1, ret;
426   string type;
427   struct work_stuff work[1];
428   const char *tem;
429
430   len = strlen(opname);
431   result[0] = '\0';
432   ret = 0;
433   work->options = options;
434   
435   if (opname[0] == '_' && opname[1] == '_'
436       && opname[2] == 'o' && opname[3] == 'p')
437     {
438       /* ANSI.  */
439       /* type conversion operator.  */
440       tem = opname + 4;
441       if (do_type (work, &tem, &type))
442         {
443           strcat (result, "operator ");
444           strncat (result, type.b, type.p - type.b);
445           string_delete (&type);
446           ret = 1;
447         }
448     }
449   else if (opname[0] == '_' && opname[1] == '_'
450            && opname[2] >= 'a' && opname[2] <= 'z'
451            && opname[3] >= 'a' && opname[3] <= 'z')
452     {
453       if (opname[4] == '\0')
454         {
455           /* Operator.  */
456           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
457             {
458               if (strlen (optable[i].in) == 2
459                   && memcmp (optable[i].in, opname + 2, 2) == 0)
460                 {
461                   strcat (result, "operator");
462                   strcat (result, optable[i].out);
463                   ret = 1;
464                   break;
465                 }
466             }
467         }
468       else
469         {
470           if (opname[2] == 'a' && opname[5] == '\0')
471             {
472               /* Assignment.  */
473               for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
474                 {
475                   if (strlen (optable[i].in) == 3
476                       && memcmp (optable[i].in, opname + 2, 3) == 0)
477                     {
478                       strcat (result, "operator");
479                       strcat (result, optable[i].out);
480                       ret = 1;
481                       break;
482                     }                 
483                 }
484             }
485         }
486     }
487   else if (len >= 3 
488            && opname[0] == 'o'
489            && opname[1] == 'p'
490            && strchr (cplus_markers, opname[2]) != NULL)
491     {
492       /* see if it's an assignment expression */
493       if (len >= 10 /* op$assign_ */
494           && memcmp (opname + 3, "assign_", 7) == 0)
495         {
496           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
497             {
498               len1 = len - 10;
499               if (strlen (optable[i].in) == len1
500                   && memcmp (optable[i].in, opname + 10, len1) == 0)
501                 {
502                   strcat (result, "operator");
503                   strcat (result, optable[i].out);
504                   strcat (result, "=");
505                   ret = 1;
506                   break;
507                 }
508             }
509         }
510       else
511         {
512           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
513             {
514               len1 = len - 3;
515               if (strlen (optable[i].in) == len1 
516                   && memcmp (optable[i].in, opname + 3, len1) == 0)
517                 {
518                   strcat (result, "operator");
519                   strcat (result, optable[i].out);
520                   ret = 1;
521                   break;
522                 }
523             }
524         }
525     }
526   else if (len >= 5 && memcmp (opname, "type", 4) == 0
527            && strchr (cplus_markers, opname[4]) != NULL)
528     {
529       /* type conversion operator */
530       tem = opname + 5;
531       if (do_type (work, &tem, &type))
532         {
533           strcat (result, "operator ");
534           strncat (result, type.b, type.p - type.b);
535           string_delete (&type);
536           ret = 1;
537         }
538     }
539   squangle_mop_up (work);
540   return ret;
541
542 }
543 /* Takes operator name as e.g. "++" and returns mangled
544    operator name (e.g. "postincrement_expr"), or NULL if not found.
545
546    If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
547    if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
548
549 const char *
550 cplus_mangle_opname (opname, options)
551      const char *opname;
552      int options;
553 {
554   int i;
555   int len;
556
557   len = strlen (opname);
558   for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
559     {
560       if (strlen (optable[i].out) == len
561           && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
562           && memcmp (optable[i].out, opname, len) == 0)
563         return optable[i].in;
564     }
565   return (0);
566 }
567
568 /* char *cplus_demangle (const char *mangled, int options)
569
570    If MANGLED is a mangled function name produced by GNU C++, then
571    a pointer to a malloced string giving a C++ representation
572    of the name will be returned; otherwise NULL will be returned.
573    It is the caller's responsibility to free the string which
574    is returned.
575
576    The OPTIONS arg may contain one or more of the following bits:
577
578         DMGL_ANSI       ANSI qualifiers such as `const' and `void' are
579                         included.
580         DMGL_PARAMS     Function parameters are included.
581
582    For example,
583    
584    cplus_demangle ("foo__1Ai", DMGL_PARAMS)             => "A::foo(int)"
585    cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
586    cplus_demangle ("foo__1Ai", 0)                       => "A::foo"
587
588    cplus_demangle ("foo__1Afe", DMGL_PARAMS)            => "A::foo(float,...)"
589    cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
590    cplus_demangle ("foo__1Afe", 0)                      => "A::foo"
591
592    Note that any leading underscores, or other such characters prepended by
593    the compilation system, are presumed to have already been stripped from
594    MANGLED.  */
595
596 char *
597 cplus_demangle (mangled, options)
598      const char *mangled;
599      int options;
600 {
601   char *ret;
602   struct work_stuff work[1];
603   memset ((char *) work, 0, sizeof (work));
604   work -> options = options;
605   if ((work -> options & DMGL_STYLE_MASK) == 0)
606     work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK;
607
608   ret = internal_cplus_demangle (work, mangled, options);
609   squangle_mop_up (work);
610   return (ret);
611 }
612   
613
614 /* This function performs most of what cplus_demangle use to do, but 
615    to be able to demangle a name with a B, K or n code, we need to
616    have a longer term memory of what types have been seen. The original
617    now intializes and cleans up the squangle code info, while internal
618    calls go directly to this routine to avoid resetting that info. */
619
620 static char *
621 internal_cplus_demangle (work, mangled, options)
622      struct work_stuff *work;
623      const char *mangled;
624      int options;
625 {
626
627   string decl;
628   int success = 0;
629   char *demangled = NULL;
630   int s1,s2,s3,s4;
631   s1 = work->constructor;
632   s2 = work->destructor;
633   s3 = work->static_type;
634   s4 = work->const_type;
635   work->constructor = work->destructor = 0;
636   work->static_type = work->const_type = 0;
637
638   if ((mangled != NULL) && (*mangled != '\0'))
639     {
640       string_init (&decl);
641
642       /* First check to see if gnu style demangling is active and if the
643          string to be demangled contains a CPLUS_MARKER.  If so, attempt to
644          recognize one of the gnu special forms rather than looking for a
645          standard prefix.  In particular, don't worry about whether there
646          is a "__" string in the mangled string.  Consider "_$_5__foo" for
647          example.  */
648
649       if ((AUTO_DEMANGLING || GNU_DEMANGLING))
650         {
651           success = gnu_special (work, &mangled, &decl);
652         }
653       if (!success)
654         {
655           success = demangle_prefix (work, &mangled, &decl);
656         }
657       if (success && (*mangled != '\0'))
658         {
659           success = demangle_signature (work, &mangled, &decl);
660         }
661       if (work->constructor == 2)
662         {
663           string_prepend (&decl, "global constructors keyed to ");
664           work->constructor = 0;
665         }
666       else if (work->destructor == 2)
667         {
668           string_prepend (&decl, "global destructors keyed to ");
669           work->destructor = 0;
670         }
671       demangled = mop_up (work, &decl, success);
672     }
673   work->constructor = s1;
674   work->destructor = s2;
675   work->static_type = s3;
676   work->const_type = s4;
677   return (demangled);
678 }
679
680
681 /* Clear out and squangling related storage */
682 static char *
683 squangle_mop_up (work)
684      struct work_stuff *work;
685 {
686   /* clean up the B and K type mangling types. */
687   forget_B_and_K_types (work);
688   if (work -> btypevec != NULL)
689     {
690       free ((char *) work -> btypevec);
691     }
692   if (work -> ktypevec != NULL)
693     {
694       free ((char *) work -> ktypevec);
695     }
696 }
697
698 /* Clear out any mangled storage */
699
700 static char *
701 mop_up (work, declp, success)
702      struct work_stuff *work;
703      string *declp;
704      int success;
705 {
706   char *demangled = NULL;
707
708   /* Discard the remembered types, if any.  */
709   
710   forget_types (work);
711   if (work -> typevec != NULL)
712     {
713       free ((char *) work -> typevec);
714       work -> typevec = NULL;
715     }
716   if (work->tmpl_argvec)
717     {
718       int i;
719
720       for (i = 0; i < work->ntmpl_args; i++)
721         if (work->tmpl_argvec[i])
722           free ((char*) work->tmpl_argvec[i]);
723       
724       free ((char*) work->tmpl_argvec);
725       work->tmpl_argvec = NULL;
726     }
727
728   /* If demangling was successful, ensure that the demangled string is null
729      terminated and return it.  Otherwise, free the demangling decl.  */
730   
731   if (!success)
732     {
733       string_delete (declp);
734     }
735   else
736     {
737       string_appendn (declp, "", 1);
738       demangled = declp -> b;
739     }
740   return (demangled);
741 }
742
743 /*
744
745 LOCAL FUNCTION
746
747         demangle_signature -- demangle the signature part of a mangled name
748
749 SYNOPSIS
750
751         static int
752         demangle_signature (struct work_stuff *work, const char **mangled,
753                             string *declp);
754
755 DESCRIPTION
756
757         Consume and demangle the signature portion of the mangled name.
758
759         DECLP is the string where demangled output is being built.  At
760         entry it contains the demangled root name from the mangled name
761         prefix.  I.E. either a demangled operator name or the root function
762         name.  In some special cases, it may contain nothing.
763
764         *MANGLED points to the current unconsumed location in the mangled
765         name.  As tokens are consumed and demangling is performed, the
766         pointer is updated to continuously point at the next token to
767         be consumed.
768
769         Demangling GNU style mangled names is nasty because there is no
770         explicit token that marks the start of the outermost function
771         argument list.  */
772
773 static int
774 demangle_signature (work, mangled, declp)
775      struct work_stuff *work;
776      const char **mangled;
777      string *declp;
778 {
779   int success = 1;
780   int func_done = 0;
781   int expect_func = 0;
782   int expect_return_type = 0;
783   const char *oldmangled = NULL;
784   string trawname;
785   string tname;
786
787   while (success && (**mangled != '\0'))
788     {
789       switch (**mangled)
790         {
791         case 'Q':
792           oldmangled = *mangled;
793           success = demangle_qualified (work, mangled, declp, 1, 0);
794           if (success)
795             {
796               remember_type (work, oldmangled, *mangled - oldmangled);
797             }
798           if (AUTO_DEMANGLING || GNU_DEMANGLING)
799             {
800               expect_func = 1;
801             }
802           oldmangled = NULL;
803           break;
804
805         case 'K':
806           oldmangled = *mangled;
807           success = demangle_qualified (work, mangled, declp, 1, 0);
808           if (AUTO_DEMANGLING || GNU_DEMANGLING)
809             {
810               expect_func = 1;
811             }
812           oldmangled = NULL;
813           break;
814           
815         case 'S':
816           /* Static member function */
817           if (oldmangled == NULL)
818             {
819               oldmangled = *mangled;
820             }
821           (*mangled)++;
822           work -> static_type = 1;
823           break;
824
825         case 'C':
826           /* a const member function */
827           if (oldmangled == NULL)
828             {
829               oldmangled = *mangled;
830             }
831           (*mangled)++;
832           work -> const_type = 1;
833           break;
834           
835         case '0': case '1': case '2': case '3': case '4':
836         case '5': case '6': case '7': case '8': case '9':
837           if (oldmangled == NULL)
838             {
839               oldmangled = *mangled;
840             }
841           success = demangle_class (work, mangled, declp);
842           if (success)
843             {
844               remember_type (work, oldmangled, *mangled - oldmangled);
845             }
846           if (AUTO_DEMANGLING || GNU_DEMANGLING)
847             {
848               expect_func = 1;
849             }
850           oldmangled = NULL;
851           break;
852           
853         case 'F':
854           /* Function */
855           /* ARM style demangling includes a specific 'F' character after
856              the class name.  For GNU style, it is just implied.  So we can
857              safely just consume any 'F' at this point and be compatible
858              with either style.  */
859
860           oldmangled = NULL;
861           func_done = 1;
862           (*mangled)++;
863
864           /* For lucid/ARM style we have to forget any types we might
865              have remembered up to this point, since they were not argument
866              types.  GNU style considers all types seen as available for
867              back references.  See comment in demangle_args() */
868
869           if (LUCID_DEMANGLING || ARM_DEMANGLING)
870             {
871               forget_types (work);
872             }
873           success = demangle_args (work, mangled, declp);
874           break;
875           
876         case 't':
877           /* G++ Template */
878           string_init(&trawname); 
879           string_init(&tname);
880           if (oldmangled == NULL)
881             {
882               oldmangled = *mangled;
883             }
884           success = demangle_template (work, mangled, &tname, &trawname, 1);
885           if (success)
886             {
887               remember_type (work, oldmangled, *mangled - oldmangled);
888             }
889           string_append(&tname, (work -> options & DMGL_JAVA) ? "." : "::");
890           string_prepends(declp, &tname);
891           if (work -> destructor & 1)
892             {
893               string_prepend (&trawname, "~");
894               string_appends (declp, &trawname);
895               work->destructor -= 1;
896             }
897           if ((work->constructor & 1) || (work->destructor & 1))
898             {
899               string_appends (declp, &trawname);
900               work->constructor -= 1;
901             }
902           string_delete(&trawname);
903           string_delete(&tname);
904           oldmangled = NULL;
905           expect_func = 1;
906           break;
907
908         case '_':
909           if (GNU_DEMANGLING && expect_return_type) 
910             {
911               /* Read the return type. */
912               string return_type;
913               string_init (&return_type);
914
915               (*mangled)++;
916               success = do_type (work, mangled, &return_type);
917               APPEND_BLANK (&return_type);
918
919               string_prepends (declp, &return_type);
920               string_delete (&return_type);
921               break;
922             }
923           else
924             /* At the outermost level, we cannot have a return type specified,
925                so if we run into another '_' at this point we are dealing with
926                a mangled name that is either bogus, or has been mangled by
927                some algorithm we don't know how to deal with.  So just
928                reject the entire demangling.  */
929             success = 0;
930           break;
931
932         case 'H':
933           if (GNU_DEMANGLING) 
934             {
935               /* A G++ template function.  Read the template arguments. */
936               success = demangle_template (work, mangled, declp, 0, 0);
937               if (!(work->constructor & 1))
938                 expect_return_type = 1;
939               (*mangled)++;
940               break;
941             }
942           else
943             /* fall through */
944             {;}
945
946         default:
947           if (AUTO_DEMANGLING || GNU_DEMANGLING)
948             {
949               /* Assume we have stumbled onto the first outermost function
950                  argument token, and start processing args.  */
951               func_done = 1;
952               success = demangle_args (work, mangled, declp);
953             }
954           else
955             {
956               /* Non-GNU demanglers use a specific token to mark the start
957                  of the outermost function argument tokens.  Typically 'F',
958                  for ARM-demangling, for example.  So if we find something
959                  we are not prepared for, it must be an error.  */
960               success = 0;
961             }
962           break;
963         }
964       /*
965         if (AUTO_DEMANGLING || GNU_DEMANGLING)
966         */
967       {
968         if (success && expect_func)
969           {
970             func_done = 1;
971             success = demangle_args (work, mangled, declp);
972             /* Since template include the mangling of their return types,
973                we must set expect_func to 0 so that we don't try do
974                demangle more arguments the next time we get here.  */
975             expect_func = 0;
976           }
977       }
978     }
979   if (success && !func_done)
980     {
981       if (AUTO_DEMANGLING || GNU_DEMANGLING)
982         {
983           /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
984              bar__3fooi is 'foo::bar(int)'.  We get here when we find the
985              first case, and need to ensure that the '(void)' gets added to
986              the current declp.  Note that with ARM, the first case
987              represents the name of a static data member 'foo::bar',
988              which is in the current declp, so we leave it alone.  */
989           success = demangle_args (work, mangled, declp);
990         }
991     }
992   if (success && work -> static_type && PRINT_ARG_TYPES)
993     {
994       string_append (declp, " static");
995     }
996   if (success && work -> const_type && PRINT_ARG_TYPES)
997     {
998       string_append (declp, " const");
999     }
1000   return (success);
1001 }
1002
1003 #if 0
1004
1005 static int
1006 demangle_method_args (work, mangled, declp)
1007      struct work_stuff *work;
1008      const char **mangled;
1009      string *declp;
1010 {
1011   int success = 0;
1012
1013   if (work -> static_type)
1014     {
1015       string_append (declp, *mangled + 1);
1016       *mangled += strlen (*mangled);
1017       success = 1;
1018     }
1019   else
1020     {
1021       success = demangle_args (work, mangled, declp);
1022     }
1023   return (success);
1024 }
1025
1026 #endif
1027
1028 static int
1029 demangle_template_template_parm (work, mangled, tname)
1030      struct work_stuff *work;
1031      const char **mangled;
1032      string *tname;
1033 {
1034   int i;
1035   int r;
1036   int need_comma = 0;
1037   int success = 1;
1038   string temp;
1039
1040   string_append (tname, "template <");
1041   /* get size of template parameter list */
1042   if (get_count (mangled, &r))
1043     {
1044       for (i = 0; i < r; i++)
1045         {
1046           if (need_comma)
1047             {
1048               string_append (tname, ", ");
1049             }
1050
1051             /* Z for type parameters */
1052             if (**mangled == 'Z')
1053               {
1054                 (*mangled)++;
1055                 string_append (tname, "class");
1056               }
1057               /* z for template parameters */
1058             else if (**mangled == 'z')
1059               {
1060                 (*mangled)++;
1061                 success = 
1062                   demangle_template_template_parm (work, mangled, tname);
1063                 if (!success)
1064                   {
1065                     break;
1066                   }
1067               }
1068             else
1069               {
1070                 /* temp is initialized in do_type */
1071                 success = do_type (work, mangled, &temp);
1072                 if (success)
1073                   {
1074                     string_appends (tname, &temp);
1075                   }
1076                 string_delete(&temp);
1077                 if (!success)
1078                   {
1079                     break;
1080                   }
1081               }
1082           need_comma = 1;
1083         }
1084
1085     }
1086   if (tname->p[-1] == '>')
1087     string_append (tname, " ");
1088   string_append (tname, "> class");
1089   return (success);
1090 }
1091
1092 static int
1093 demangle_integral_value (work, mangled, s)
1094      struct work_stuff *work;
1095      const char** mangled;
1096      string* s;
1097 {
1098   int success;
1099
1100   if (**mangled == 'E')
1101     {
1102       int need_operator = 0;
1103       
1104       success = 1;
1105       string_appendn (s, "(", 1);
1106       (*mangled)++;
1107       while (success && **mangled != 'W' && **mangled != '\0')
1108         {
1109           if (need_operator)
1110             {
1111               size_t i;
1112               size_t len;
1113
1114               success = 0;
1115
1116               len = strlen (*mangled);
1117
1118               for (i = 0; 
1119                    i < sizeof (optable) / sizeof (optable [0]);
1120                    ++i)
1121                 {
1122                   size_t l = strlen (optable[i].in);
1123
1124                   if (l <= len
1125                       && memcmp (optable[i].in, *mangled, l) == 0)
1126                     {
1127                       string_appendn (s, " ", 1);
1128                       string_append (s, optable[i].out);
1129                       string_appendn (s, " ", 1);
1130                       success = 1;
1131                       (*mangled) += l;
1132                       break;
1133                     }
1134                 }
1135
1136               if (!success)
1137                 break;
1138             }
1139           else
1140             need_operator = 1;
1141
1142           success = demangle_template_value_parm (work, mangled, s);
1143         }
1144
1145       if (**mangled != 'W')
1146           success = 0;
1147       else 
1148         {
1149           string_appendn (s, ")", 1);
1150           (*mangled)++;
1151         }
1152     }
1153   else if (**mangled == 'Q' || **mangled == 'K')
1154     success = demangle_qualified (work, mangled, s, 0, 1);
1155   else
1156     {
1157       success = 0;
1158
1159       if (**mangled == 'm')
1160         {
1161           string_appendn (s, "-", 1);
1162           (*mangled)++;
1163         }
1164       while (isdigit (**mangled))       
1165         {
1166           string_appendn (s, *mangled, 1);
1167           (*mangled)++;
1168           success = 1;
1169         }
1170     }
1171   
1172   return success;
1173 }
1174
1175 static int 
1176 demangle_template_value_parm (work, mangled, s)
1177      struct work_stuff *work;
1178      const char **mangled;
1179      string* s;
1180 {
1181   const char *old_p = *mangled;
1182   int is_pointer = 0;
1183   int is_real = 0;
1184   int is_integral = 0;
1185   int is_char = 0;
1186   int is_bool = 0;
1187   int done = 0;
1188   int success = 1;
1189
1190   while (*old_p && !done)
1191     {   
1192       switch (*old_p)
1193         {
1194         case 'P':
1195         case 'p':
1196         case 'R':
1197           done = is_pointer = 1;
1198           break;
1199         case 'C':       /* const */
1200         case 'S':       /* explicitly signed [char] */
1201         case 'U':       /* unsigned */
1202         case 'V':       /* volatile */
1203         case 'F':       /* function */
1204         case 'M':       /* member function */
1205         case 'O':       /* ??? */
1206         case 'J':       /* complex */
1207           old_p++;
1208           continue;
1209         case 'E':       /* expression */
1210         case 'Q':       /* qualified name */
1211         case 'K':       /* qualified name */
1212           done = is_integral = 1;
1213           break;
1214         case 'B':       /* squangled name */
1215           done = is_integral = 1;
1216           break;
1217         case 'T':       /* remembered type */
1218           abort ();
1219           break;
1220         case 'v':       /* void */
1221           abort ();
1222           break;
1223         case 'x':       /* long long */
1224         case 'l':       /* long */
1225         case 'i':       /* int */
1226         case 's':       /* short */
1227         case 'w':       /* wchar_t */
1228           done = is_integral = 1;
1229           break;
1230         case 'b':       /* bool */
1231           done = is_bool = 1;
1232           break;
1233         case 'c':       /* char */
1234           done = is_char = 1;
1235           break;
1236         case 'r':       /* long double */
1237         case 'd':       /* double */
1238         case 'f':       /* float */
1239           done = is_real = 1;
1240           break;
1241         default:
1242           /* it's probably user defined type, let's assume
1243              it's integral, it seems hard to figure out
1244              what it really is */
1245           done = is_integral = 1;
1246         }
1247     }
1248   if (**mangled == 'Y')
1249     {
1250       /* The next argument is a template parameter. */
1251       int idx;
1252
1253       (*mangled)++;
1254       idx = consume_count_with_underscores (mangled);
1255       if (idx == -1 
1256           || (work->tmpl_argvec && idx >= work->ntmpl_args)
1257           || consume_count_with_underscores (mangled) == -1)
1258         return -1;
1259       if (work->tmpl_argvec)
1260         string_append (s, work->tmpl_argvec[idx]);
1261       else
1262         {
1263           char buf[10];
1264           sprintf(buf, "T%d", idx);
1265           string_append (s, buf);
1266         }
1267     }
1268   else if (is_integral)
1269     success = demangle_integral_value (work, mangled, s);
1270   else if (is_char)
1271     {
1272       char tmp[2];
1273       int val;
1274       if (**mangled == 'm')
1275         {
1276           string_appendn (s, "-", 1);
1277           (*mangled)++;
1278         }
1279       string_appendn (s, "'", 1);
1280       val = consume_count(mangled);
1281       if (val == 0)
1282         return -1;
1283       tmp[0] = (char)val;
1284       tmp[1] = '\0';
1285       string_appendn (s, &tmp[0], 1);
1286       string_appendn (s, "'", 1);
1287     }
1288   else if (is_bool)
1289     {
1290       int val = consume_count (mangled);
1291       if (val == 0)
1292         string_appendn (s, "false", 5);
1293       else if (val == 1)
1294         string_appendn (s, "true", 4);
1295       else
1296         success = 0;
1297     }
1298   else if (is_real)
1299     {
1300       if (**mangled == 'm')
1301         {
1302           string_appendn (s, "-", 1);
1303           (*mangled)++;
1304         }
1305       while (isdigit (**mangled))       
1306         {
1307           string_appendn (s, *mangled, 1);
1308           (*mangled)++;
1309         }
1310       if (**mangled == '.') /* fraction */
1311         {
1312           string_appendn (s, ".", 1);
1313           (*mangled)++;
1314           while (isdigit (**mangled))   
1315             {
1316               string_appendn (s, *mangled, 1);
1317               (*mangled)++;
1318             }
1319         }
1320       if (**mangled == 'e') /* exponent */
1321         {
1322           string_appendn (s, "e", 1);
1323           (*mangled)++;
1324           while (isdigit (**mangled))   
1325             {
1326               string_appendn (s, *mangled, 1);
1327               (*mangled)++;
1328             }
1329         }
1330     }
1331   else if (is_pointer)
1332     {
1333       int symbol_len = consume_count (mangled);
1334       if (symbol_len == 0)
1335         return -1;
1336       if (symbol_len == 0)
1337         string_appendn (s, "0", 1);
1338       else
1339         {
1340           char *p = xmalloc (symbol_len + 1), *q;
1341           strncpy (p, *mangled, symbol_len);
1342           p [symbol_len] = '\0';
1343           q = internal_cplus_demangle (work, p, work->options);
1344           string_appendn (s, "&", 1);
1345           if (q)
1346             {
1347               string_append (s, q);
1348               free (q);
1349             }
1350           else
1351             string_append (s, p);
1352           free (p);
1353         }
1354       *mangled += symbol_len;
1355     }
1356
1357   return success;
1358 }
1359
1360 static int
1361 demangle_template (work, mangled, tname, trawname, is_type)
1362      struct work_stuff *work;
1363      const char **mangled;
1364      string *tname;
1365      string *trawname;
1366      int is_type;
1367 {
1368   int i;
1369   int r;
1370   int need_comma = 0;
1371   int success = 0;
1372   const char *start;
1373   int is_java_array = 0;
1374   string temp;
1375
1376   (*mangled)++;
1377   if (is_type)
1378     {
1379       start = *mangled;
1380       /* get template name */
1381       if (**mangled == 'z')
1382         {
1383           int idx;
1384           (*mangled)++;
1385           (*mangled)++;
1386
1387           idx = consume_count_with_underscores (mangled);
1388           if (idx == -1 
1389               || (work->tmpl_argvec && idx >= work->ntmpl_args)
1390               || consume_count_with_underscores (mangled) == -1)
1391             {
1392               return (0);
1393             }
1394           if (work->tmpl_argvec)
1395             {
1396               string_append (tname, work->tmpl_argvec[idx]);
1397               if (trawname)
1398                 string_append (trawname, work->tmpl_argvec[idx]);
1399             }
1400           else
1401             {
1402               char buf[10];
1403               sprintf(buf, "T%d", idx);
1404               string_append (tname, buf);
1405               if (trawname)
1406                 string_append (trawname, work->tmpl_argvec[idx]);
1407             }
1408         }
1409       else
1410         {
1411           if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
1412             {
1413               return (0);
1414             }
1415           if (trawname)
1416             string_appendn (trawname, *mangled, r);
1417           is_java_array = (work -> options & DMGL_JAVA)
1418             && strncmp (*mangled, "JArray1Z", 8) == 0;
1419           if (! is_java_array)
1420             {
1421               string_appendn (tname, *mangled, r);
1422             }
1423           *mangled += r;
1424         }
1425     }
1426   if (!is_java_array)
1427     string_append (tname, "<");
1428   /* get size of template parameter list */
1429   if (!get_count (mangled, &r))
1430     {
1431       return (0);
1432     }
1433   if (!is_type)
1434     {
1435       /* Create an array for saving the template argument values. */
1436       work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
1437       work->ntmpl_args = r;
1438       for (i = 0; i < r; i++)
1439         work->tmpl_argvec[i] = 0;
1440     }
1441   for (i = 0; i < r; i++)
1442     {
1443       if (need_comma)
1444         {
1445           string_append (tname, ", ");
1446         }
1447       /* Z for type parameters */
1448       if (**mangled == 'Z')
1449         {
1450           (*mangled)++;
1451           /* temp is initialized in do_type */
1452           success = do_type (work, mangled, &temp);
1453           if (success)
1454             {
1455               string_appends (tname, &temp);
1456
1457               if (!is_type)
1458                 {
1459                   /* Save the template argument. */
1460                   int len = temp.p - temp.b;
1461                   work->tmpl_argvec[i] = xmalloc (len + 1);
1462                   memcpy (work->tmpl_argvec[i], temp.b, len);
1463                   work->tmpl_argvec[i][len] = '\0';
1464                 }
1465             }
1466           string_delete(&temp);
1467           if (!success)
1468             {
1469               break;
1470             }
1471         }
1472       /* z for template parameters */
1473       else if (**mangled == 'z')
1474         {
1475           int r2;
1476           (*mangled)++;
1477           success = demangle_template_template_parm (work, mangled, tname);
1478           
1479           if (success
1480               && (r2 = consume_count (mangled)) > 0 && strlen (*mangled) >= r2)
1481             {
1482               string_append (tname, " ");
1483               string_appendn (tname, *mangled, r2);
1484               if (!is_type)
1485                 {
1486                   /* Save the template argument. */
1487                   int len = r2;
1488                   work->tmpl_argvec[i] = xmalloc (len + 1);
1489                   memcpy (work->tmpl_argvec[i], *mangled, len);
1490                   work->tmpl_argvec[i][len] = '\0';
1491                 }
1492               *mangled += r2;
1493             }
1494           if (!success)
1495             {
1496               break;
1497             }
1498         }
1499       else
1500         {
1501           string  param;
1502           string* s;
1503
1504           /* otherwise, value parameter */
1505
1506           /* temp is initialized in do_type */
1507           success = do_type (work, mangled, &temp);
1508           /*
1509             if (success)
1510             {
1511             string_appends (s, &temp);
1512             }
1513             */
1514           string_delete(&temp);
1515           if (!success)
1516             {
1517               break;
1518             }
1519           /*
1520             string_append (s, "=");
1521             */
1522
1523           if (!is_type)
1524             {
1525               s = &param;
1526               string_init (s);
1527             }
1528           else
1529             s = tname;
1530
1531           success = demangle_template_value_parm (work, mangled, s);
1532
1533           if (!success)
1534             {
1535               if (!is_type)
1536                 string_delete (s);
1537               success = 0;
1538               break;
1539             }
1540
1541           if (!is_type)
1542             {
1543               int len = s->p - s->b;
1544               work->tmpl_argvec[i] = xmalloc (len + 1);
1545               memcpy (work->tmpl_argvec[i], s->b, len);
1546               work->tmpl_argvec[i][len] = '\0';
1547               
1548               string_appends (tname, s);
1549               string_delete (s);
1550             }
1551         }
1552       need_comma = 1;
1553     }
1554   if (is_java_array)
1555     {
1556       string_append (tname, "[]");
1557     }
1558   else
1559     {
1560       if (tname->p[-1] == '>')
1561         string_append (tname, " ");
1562       string_append (tname, ">");
1563     }
1564   
1565   /*
1566     if (work -> static_type)
1567     {
1568     string_append (declp, *mangled + 1);
1569     *mangled += strlen (*mangled);
1570     success = 1;
1571     }
1572     else
1573     {
1574     success = demangle_args (work, mangled, declp);
1575     }
1576     }
1577     */
1578   return (success);
1579 }
1580
1581 static int
1582 arm_pt (work, mangled, n, anchor, args)
1583      struct work_stuff *work;
1584      const char *mangled;
1585      int n;
1586      const char **anchor, **args;
1587 {
1588   /* ARM template? */
1589   if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
1590     {
1591       int len;
1592       *args = *anchor + 6;
1593       len = consume_count (args);
1594       if (*args + len == mangled + n && **args == '_')
1595         {
1596           ++*args;
1597           return 1;
1598         }
1599     }
1600   return 0;
1601 }
1602
1603 static void
1604 demangle_arm_pt (work, mangled, n, declp)
1605      struct work_stuff *work;
1606      const char **mangled;
1607      int n;
1608      string *declp;
1609 {
1610   const char *p;
1611   const char *args;
1612   const char *e = *mangled + n;
1613
1614   /* ARM template? */
1615   if (arm_pt (work, *mangled, n, &p, &args))
1616     {
1617       string arg;
1618       string_init (&arg);
1619       string_appendn (declp, *mangled, p - *mangled);
1620       string_append (declp, "<");
1621       /* should do error checking here */
1622       while (args < e) {
1623         string_clear (&arg);
1624         do_type (work, &args, &arg);
1625         string_appends (declp, &arg);
1626         string_append (declp, ",");
1627       }
1628       string_delete (&arg);
1629       --declp->p;
1630       string_append (declp, ">");
1631     }
1632   else
1633     {
1634       string_appendn (declp, *mangled, n);
1635     }
1636   *mangled += n;
1637 }
1638
1639 static int
1640 demangle_class_name (work, mangled, declp)
1641      struct work_stuff *work;
1642      const char **mangled;
1643      string *declp;
1644 {
1645   int n;
1646   int success = 0;
1647
1648   n = consume_count (mangled);
1649   if (strlen (*mangled) >= n)
1650     {
1651       demangle_arm_pt (work, mangled, n, declp);
1652       success = 1;
1653     }
1654
1655   return (success);
1656 }
1657
1658 /*
1659
1660 LOCAL FUNCTION
1661
1662         demangle_class -- demangle a mangled class sequence
1663
1664 SYNOPSIS
1665
1666         static int
1667         demangle_class (struct work_stuff *work, const char **mangled,
1668                         strint *declp)
1669
1670 DESCRIPTION
1671
1672         DECLP points to the buffer into which demangling is being done.
1673
1674         *MANGLED points to the current token to be demangled.  On input,
1675         it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1676         On exit, it points to the next token after the mangled class on
1677         success, or the first unconsumed token on failure.
1678
1679         If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1680         we are demangling a constructor or destructor.  In this case
1681         we prepend "class::class" or "class::~class" to DECLP.
1682
1683         Otherwise, we prepend "class::" to the current DECLP.
1684
1685         Reset the constructor/destructor flags once they have been
1686         "consumed".  This allows demangle_class to be called later during
1687         the same demangling, to do normal class demangling.
1688
1689         Returns 1 if demangling is successful, 0 otherwise.
1690
1691 */
1692
1693 static int
1694 demangle_class (work, mangled, declp)
1695      struct work_stuff *work;
1696      const char **mangled;
1697      string *declp;
1698 {
1699   int success = 0;
1700   int btype;
1701   string class_name;
1702
1703   string_init (&class_name);
1704   btype = register_Btype (work);
1705   if (demangle_class_name (work, mangled, &class_name))
1706     {
1707       if ((work->constructor & 1) || (work->destructor & 1))
1708         {
1709           string_prepends (declp, &class_name);
1710           if (work -> destructor & 1)
1711             {
1712               string_prepend (declp, "~");
1713               work -> destructor -= 1;
1714             }
1715           else
1716             {
1717               work -> constructor -= 1; 
1718             }
1719         }
1720       remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
1721       remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
1722       string_prepend (declp, (work -> options & DMGL_JAVA) ? "." : "::");
1723       string_prepends (declp, &class_name);
1724       success = 1;
1725     }
1726   string_delete (&class_name);
1727   return (success);
1728 }
1729
1730 /*
1731
1732 LOCAL FUNCTION
1733
1734         demangle_prefix -- consume the mangled name prefix and find signature
1735
1736 SYNOPSIS
1737
1738         static int
1739         demangle_prefix (struct work_stuff *work, const char **mangled,
1740                          string *declp);
1741
1742 DESCRIPTION
1743
1744         Consume and demangle the prefix of the mangled name.
1745
1746         DECLP points to the string buffer into which demangled output is
1747         placed.  On entry, the buffer is empty.  On exit it contains
1748         the root function name, the demangled operator name, or in some
1749         special cases either nothing or the completely demangled result.
1750
1751         MANGLED points to the current pointer into the mangled name.  As each
1752         token of the mangled name is consumed, it is updated.  Upon entry
1753         the current mangled name pointer points to the first character of
1754         the mangled name.  Upon exit, it should point to the first character
1755         of the signature if demangling was successful, or to the first
1756         unconsumed character if demangling of the prefix was unsuccessful.
1757         
1758         Returns 1 on success, 0 otherwise.
1759  */
1760
1761 static int
1762 demangle_prefix (work, mangled, declp)
1763      struct work_stuff *work;
1764      const char **mangled;
1765      string *declp;
1766 {
1767   int success = 1;
1768   const char *scan;
1769   int i;
1770
1771   if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
1772     {
1773       char *marker = strchr (cplus_markers, (*mangled)[8]);
1774       if (marker != NULL && *marker == (*mangled)[10])
1775         {
1776           if ((*mangled)[9] == 'D')
1777             {
1778               /* it's a GNU global destructor to be executed at program exit */
1779               (*mangled) += 11;
1780               work->destructor = 2;
1781               if (gnu_special (work, mangled, declp))
1782                 return success;
1783             }
1784           else if ((*mangled)[9] == 'I')
1785             {
1786               /* it's a GNU global constructor to be executed at program init */
1787               (*mangled) += 11;
1788               work->constructor = 2;
1789               if (gnu_special (work, mangled, declp))
1790                 return success;
1791             }
1792         }
1793     }
1794   else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
1795     {
1796       /* it's a ARM global destructor to be executed at program exit */
1797       (*mangled) += 7;
1798       work->destructor = 2;
1799     }
1800   else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
1801     {
1802       /* it's a ARM global constructor to be executed at program initial */
1803       (*mangled) += 7;
1804       work->constructor = 2;
1805     }
1806
1807   /*  This block of code is a reduction in strength time optimization
1808       of:
1809       scan = mystrstr (*mangled, "__"); */
1810
1811   {
1812     scan = *mangled;
1813
1814     do {
1815       scan = strchr (scan, '_');
1816     } while (scan != NULL && *++scan != '_');
1817
1818     if (scan != NULL) --scan;
1819   }
1820
1821   if (scan != NULL)
1822     {
1823       /* We found a sequence of two or more '_', ensure that we start at
1824          the last pair in the sequence.  */
1825       i = strspn (scan, "_");
1826       if (i > 2)
1827         {
1828           scan += (i - 2); 
1829         }
1830     }
1831  
1832   if (scan == NULL)
1833     {
1834       success = 0;
1835     }
1836   else if (work -> static_type)
1837     {
1838       if (!isdigit (scan[0]) && (scan[0] != 't'))
1839         {
1840           success = 0;
1841         }
1842     }
1843   else if ((scan == *mangled)
1844            && (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')
1845                || (scan[2] == 'K') || (scan[2] == 'H')))
1846     {
1847       /* The ARM says nothing about the mangling of local variables.
1848          But cfront mangles local variables by prepending __<nesting_level>
1849          to them. As an extension to ARM demangling we handle this case.  */
1850       if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
1851         {
1852           *mangled = scan + 2;
1853           consume_count (mangled);
1854           string_append (declp, *mangled);
1855           *mangled += strlen (*mangled);
1856           success = 1; 
1857         }
1858       else
1859         {
1860           /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
1861              names like __Q2_3foo3bar for nested type names.  So don't accept
1862              this style of constructor for cfront demangling.  A GNU
1863              style member-template constructor starts with 'H'. */
1864           if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
1865             work -> constructor += 1;
1866           *mangled = scan + 2;
1867         }
1868     }
1869   else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
1870     {
1871       /* Mangled name starts with "__".  Skip over any leading '_' characters,
1872          then find the next "__" that separates the prefix from the signature.
1873          */
1874       if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
1875           || (arm_special (mangled, declp) == 0))
1876         {
1877           while (*scan == '_')
1878             {
1879               scan++;
1880             }
1881           if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
1882             {
1883               /* No separator (I.E. "__not_mangled"), or empty signature
1884                  (I.E. "__not_mangled_either__") */
1885               success = 0;
1886             }
1887           else
1888             {
1889               demangle_function_name (work, mangled, declp, scan);
1890             }
1891         }
1892     }
1893   else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
1894     {
1895       /* Cfront-style parameterized type.  Handled later as a signature.  */
1896       success = 1;
1897
1898       /* ARM template? */
1899       demangle_arm_pt (work, mangled, strlen (*mangled), declp);
1900     }
1901   else if (*(scan + 2) != '\0')
1902     {
1903       /* Mangled name does not start with "__" but does have one somewhere
1904          in there with non empty stuff after it.  Looks like a global
1905          function name.  */
1906       demangle_function_name (work, mangled, declp, scan);
1907     }
1908   else
1909     {
1910       /* Doesn't look like a mangled name */
1911       success = 0;
1912     }
1913
1914   if (!success && (work->constructor == 2 || work->destructor == 2))
1915     {
1916       string_append (declp, *mangled);
1917       *mangled += strlen (*mangled);
1918       success = 1;
1919     } 
1920   return (success);
1921 }
1922
1923 /*
1924
1925 LOCAL FUNCTION
1926
1927         gnu_special -- special handling of gnu mangled strings
1928
1929 SYNOPSIS
1930
1931         static int
1932         gnu_special (struct work_stuff *work, const char **mangled,
1933                      string *declp);
1934
1935
1936 DESCRIPTION
1937
1938         Process some special GNU style mangling forms that don't fit
1939         the normal pattern.  For example:
1940
1941                 _$_3foo         (destructor for class foo)
1942                 _vt$foo         (foo virtual table)
1943                 _vt$foo$bar     (foo::bar virtual table)
1944                 __vt_foo        (foo virtual table, new style with thunks)
1945                 _3foo$varname   (static data member)
1946                 _Q22rs2tu$vw    (static data member)
1947                 __t6vector1Zii  (constructor with template)
1948                 __thunk_4__$_7ostream (virtual function thunk)
1949  */
1950
1951 static int
1952 gnu_special (work, mangled, declp)
1953      struct work_stuff *work;
1954      const char **mangled;
1955      string *declp;
1956 {
1957   int n;
1958   int success = 1;
1959   const char *p;
1960
1961   if ((*mangled)[0] == '_'
1962       && strchr (cplus_markers, (*mangled)[1]) != NULL
1963       && (*mangled)[2] == '_')
1964     {
1965       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1966       (*mangled) += 3;
1967       work -> destructor += 1;
1968     }
1969   else if ((*mangled)[0] == '_'
1970            && (((*mangled)[1] == '_'
1971                 && (*mangled)[2] == 'v'
1972                 && (*mangled)[3] == 't'
1973                 && (*mangled)[4] == '_')
1974                || ((*mangled)[1] == 'v'
1975                    && (*mangled)[2] == 't'
1976                    && strchr (cplus_markers, (*mangled)[3]) != NULL)))
1977     {
1978       /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1979          and create the decl.  Note that we consume the entire mangled
1980          input string, which means that demangle_signature has no work
1981          to do.  */
1982       if ((*mangled)[2] == 'v')
1983         (*mangled) += 5; /* New style, with thunks: "__vt_" */
1984       else
1985         (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1986       while (**mangled != '\0')
1987         {
1988           p = strpbrk (*mangled, cplus_markers);
1989           switch (**mangled)
1990             {
1991             case 'Q':
1992             case 'K':
1993               success = demangle_qualified (work, mangled, declp, 0, 1);
1994               break;
1995             case 't':
1996               success = demangle_template (work, mangled, declp, 0, 1);
1997               break;
1998             default:
1999               if (isdigit(*mangled[0]))
2000                 {
2001                   n = consume_count(mangled);
2002                   /* We may be seeing a too-large size, or else a
2003                      ".<digits>" indicating a static local symbol.  In
2004                      any case, declare victory and move on; *don't* try
2005                      to use n to allocate.  */
2006                   if (n > strlen (*mangled))
2007                     {
2008                       success = 1;
2009                       break;
2010                     }
2011                 }
2012               else
2013                 {
2014                   n = strcspn (*mangled, cplus_markers);
2015                 }
2016               string_appendn (declp, *mangled, n);
2017               (*mangled) += n;
2018             }
2019
2020           if (success && ((p == NULL) || (p == *mangled)))
2021             {
2022               if (p != NULL)
2023                 {
2024                   string_append (declp,
2025                                  (work -> options & DMGL_JAVA) ? "." : "::");
2026                   (*mangled)++;
2027                 }
2028             }
2029           else
2030             {
2031               success = 0;
2032               break;
2033             }
2034         }
2035       if (success)
2036         string_append (declp, " virtual table");
2037     }
2038   else if ((*mangled)[0] == '_'
2039            && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
2040            && (p = strpbrk (*mangled, cplus_markers)) != NULL)
2041     {
2042       /* static data member, "_3foo$varname" for example */
2043       (*mangled)++;
2044       switch (**mangled)
2045         {
2046         case 'Q':
2047         case 'K':
2048           success = demangle_qualified (work, mangled, declp, 0, 1);
2049           break;
2050         case 't':
2051           success = demangle_template (work, mangled, declp, 0, 1);
2052           break;
2053         default:
2054           n = consume_count (mangled);
2055           string_appendn (declp, *mangled, n);
2056           (*mangled) += n;
2057         }
2058       if (success && (p == *mangled))
2059         {
2060           /* Consumed everything up to the cplus_marker, append the
2061              variable name.  */
2062           (*mangled)++;
2063           string_append (declp, (work -> options & DMGL_JAVA) ? "." : "::");
2064           n = strlen (*mangled);
2065           string_appendn (declp, *mangled, n);
2066           (*mangled) += n;
2067         }
2068       else
2069         {
2070           success = 0;
2071         }
2072     }
2073   else if (strncmp (*mangled, "__thunk_", 8) == 0)
2074     {
2075       int delta = ((*mangled) += 8, consume_count (mangled));
2076       char *method = internal_cplus_demangle (work, ++*mangled, work->options);
2077       if (method)
2078         {
2079           char buf[50];
2080           sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
2081           string_append (declp, buf);
2082           string_append (declp, method);
2083           free (method);
2084           n = strlen (*mangled);
2085           (*mangled) += n;
2086         }
2087       else
2088         {
2089           success = 0;
2090         }
2091     }
2092   else if (strncmp (*mangled, "__t", 3) == 0
2093            && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
2094     {
2095       p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
2096       (*mangled) += 4;
2097       switch (**mangled)
2098         {
2099         case 'Q':
2100         case 'K':
2101           success = demangle_qualified (work, mangled, declp, 0, 1);
2102           break;
2103         case 't':
2104           success = demangle_template (work, mangled, declp, 0, 1);
2105           break;
2106         default:
2107           success = demangle_fund_type (work, mangled, declp);
2108           break;
2109         }
2110       if (success && **mangled != '\0')
2111         success = 0;
2112       if (success)
2113         string_append (declp, p);
2114     }
2115   else
2116     {
2117       success = 0;
2118     }
2119   return (success);
2120 }
2121
2122 /*
2123
2124 LOCAL FUNCTION
2125
2126         arm_special -- special handling of ARM/lucid mangled strings
2127
2128 SYNOPSIS
2129
2130         static int
2131         arm_special (const char **mangled,
2132                      string *declp);
2133
2134
2135 DESCRIPTION
2136
2137         Process some special ARM style mangling forms that don't fit
2138         the normal pattern.  For example:
2139
2140                 __vtbl__3foo            (foo virtual table)
2141                 __vtbl__3foo__3bar      (bar::foo virtual table)
2142
2143  */
2144
2145 static int
2146 arm_special (mangled, declp)
2147      const char **mangled;
2148      string *declp;
2149 {
2150   int n;
2151   int success = 1;
2152   const char *scan;
2153
2154   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
2155     {
2156       /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2157          and create the decl.  Note that we consume the entire mangled
2158          input string, which means that demangle_signature has no work
2159          to do.  */
2160       scan = *mangled + ARM_VTABLE_STRLEN;
2161       while (*scan != '\0')        /* first check it can be demangled */
2162         {
2163           n = consume_count (&scan);
2164           if (n==0)
2165             {
2166               return (0);           /* no good */
2167             }
2168           scan += n;
2169           if (scan[0] == '_' && scan[1] == '_')
2170             {
2171               scan += 2;
2172             }
2173         }
2174       (*mangled) += ARM_VTABLE_STRLEN;
2175       while (**mangled != '\0')
2176         {
2177           n = consume_count (mangled);
2178           string_prependn (declp, *mangled, n);
2179           (*mangled) += n;
2180           if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
2181             {
2182               string_prepend (declp, "::");
2183               (*mangled) += 2;
2184             }
2185         }
2186       string_append (declp, " virtual table");
2187     }
2188   else
2189     {
2190       success = 0;
2191     }
2192   return (success);
2193 }
2194
2195 /*
2196
2197 LOCAL FUNCTION
2198
2199         demangle_qualified -- demangle 'Q' qualified name strings
2200
2201 SYNOPSIS
2202
2203         static int
2204         demangle_qualified (struct work_stuff *, const char *mangled,
2205                             string *result, int isfuncname, int append);
2206
2207 DESCRIPTION
2208
2209         Demangle a qualified name, such as "Q25Outer5Inner" which is
2210         the mangled form of "Outer::Inner".  The demangled output is
2211         prepended or appended to the result string according to the
2212         state of the append flag.
2213
2214         If isfuncname is nonzero, then the qualified name we are building
2215         is going to be used as a member function name, so if it is a
2216         constructor or destructor function, append an appropriate
2217         constructor or destructor name.  I.E. for the above example,
2218         the result for use as a constructor is "Outer::Inner::Inner"
2219         and the result for use as a destructor is "Outer::Inner::~Inner".
2220
2221 BUGS
2222
2223         Numeric conversion is ASCII dependent (FIXME).
2224
2225  */
2226
2227 static int
2228 demangle_qualified (work, mangled, result, isfuncname, append)
2229      struct work_stuff *work;
2230      const char **mangled;
2231      string *result;
2232      int isfuncname;
2233      int append;
2234 {
2235   int qualifiers = 0;
2236   int namelength;
2237   int success = 1;
2238   const char *p;
2239   char num[2];
2240   string temp;
2241
2242   string_init (&temp);
2243
2244   if ((*mangled)[0] == 'K')
2245     {
2246     /* Squangling qualified name reuse */
2247       int idx;
2248       (*mangled)++;
2249       idx = consume_count_with_underscores (mangled);
2250       if (idx == -1 || idx > work -> numk)
2251         success = 0;
2252       else
2253         string_append (&temp, work -> ktypevec[idx]);
2254     }
2255   else
2256     switch ((*mangled)[1])
2257     {
2258     case '_':
2259       /* GNU mangled name with more than 9 classes.  The count is preceded
2260          by an underscore (to distinguish it from the <= 9 case) and followed
2261          by an underscore.  */
2262       p = *mangled + 2;
2263       qualifiers = atoi (p);
2264       if (!isdigit (*p) || *p == '0')
2265         success = 0;
2266
2267       /* Skip the digits.  */
2268       while (isdigit (*p))
2269         ++p;
2270
2271       if (*p != '_')
2272         success = 0;
2273
2274       *mangled = p + 1;
2275       break;
2276
2277     case '1':
2278     case '2':
2279     case '3':
2280     case '4':
2281     case '5':
2282     case '6':
2283     case '7':
2284     case '8':
2285     case '9':
2286       /* The count is in a single digit.  */
2287       num[0] = (*mangled)[1];
2288       num[1] = '\0';
2289       qualifiers = atoi (num);
2290
2291       /* If there is an underscore after the digit, skip it.  This is
2292          said to be for ARM-qualified names, but the ARM makes no
2293          mention of such an underscore.  Perhaps cfront uses one.  */
2294       if ((*mangled)[2] == '_')
2295         {
2296           (*mangled)++;
2297         }
2298       (*mangled) += 2;
2299       break;
2300
2301     case '0':
2302     default:
2303       success = 0;
2304     }
2305
2306   if (!success)
2307     return success;
2308
2309   /* Pick off the names and collect them in the temp buffer in the order
2310      in which they are found, separated by '::'.  */
2311
2312   while (qualifiers-- > 0)
2313     {
2314       int remember_K = 1;
2315       if (*mangled[0] == '_') 
2316         *mangled = *mangled + 1;
2317       if (*mangled[0] == 't')
2318         {
2319           success = demangle_template(work, mangled, &temp, 0, 1);
2320           if (!success) break;
2321         }
2322       else if (*mangled[0] == 'X')
2323         {
2324           success = do_type (work, mangled, &temp);
2325           if (!success) break;
2326         }
2327       if (*mangled[0] == 'K')
2328         {
2329           int idx;
2330           (*mangled)++;
2331           idx = consume_count_with_underscores (mangled);
2332           if (idx == -1 || idx > work->numk)
2333             success = 0;
2334           else
2335             string_append (&temp, work->ktypevec[idx]);
2336           remember_K = 0;
2337
2338           if (!success) break;
2339         }
2340       else
2341         {       
2342           namelength = consume_count (mangled);
2343           if (strlen (*mangled) < namelength)
2344             {
2345               /* Simple sanity check failed */
2346               success = 0;
2347               break;
2348             }
2349           string_appendn (&temp, *mangled, namelength);
2350           *mangled += namelength;
2351         }
2352
2353       if (remember_K)
2354         {
2355         remember_Ktype (work, temp.b, LEN_STRING (&temp));
2356         }
2357
2358       if (qualifiers > 0)
2359         {
2360           string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2361         }
2362     }
2363
2364   /* If we are using the result as a function name, we need to append
2365      the appropriate '::' separated constructor or destructor name.
2366      We do this here because this is the most convenient place, where
2367      we already have a pointer to the name and the length of the name.  */
2368
2369   if (isfuncname && (work->constructor & 1 || work->destructor & 1))
2370     {
2371       string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2372       if (work -> destructor & 1)
2373         {
2374           string_append (&temp, "~");
2375         }
2376       string_appendn (&temp, (*mangled) - namelength, namelength);
2377     }
2378
2379   /* Now either prepend the temp buffer to the result, or append it, 
2380      depending upon the state of the append flag.  */
2381
2382   if (append)
2383     {
2384       string_appends (result, &temp);
2385     }
2386   else
2387     {
2388       if (!STRING_EMPTY (result))
2389         {
2390           string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2391         }
2392       string_prepends (result, &temp);
2393     }
2394
2395   string_delete (&temp);
2396   return (success);
2397 }
2398
2399 /*
2400
2401 LOCAL FUNCTION
2402
2403         get_count -- convert an ascii count to integer, consuming tokens
2404
2405 SYNOPSIS
2406
2407         static int
2408         get_count (const char **type, int *count)
2409
2410 DESCRIPTION
2411
2412         Return 0 if no conversion is performed, 1 if a string is converted.
2413 */
2414
2415 static int
2416 get_count (type, count)
2417      const char **type;
2418      int *count;
2419 {
2420   const char *p;
2421   int n;
2422
2423   if (!isdigit (**type))
2424     {
2425       return (0);
2426     }
2427   else
2428     {
2429       *count = **type - '0';
2430       (*type)++;
2431       if (isdigit (**type))
2432         {
2433           p = *type;
2434           n = *count;
2435           do 
2436             {
2437               n *= 10;
2438               n += *p - '0';
2439               p++;
2440             } 
2441           while (isdigit (*p));
2442           if (*p == '_')
2443             {
2444               *type = p + 1;
2445               *count = n;
2446             }
2447         }
2448     }
2449   return (1);
2450 }
2451
2452 /* result will be initialised here; it will be freed on failure */
2453
2454 static int
2455 do_type (work, mangled, result)
2456      struct work_stuff *work;
2457      const char **mangled;
2458      string *result;
2459 {
2460   int n;
2461   int done;
2462   int success;
2463   string decl;
2464   const char *remembered_type;
2465   int constp;
2466   int volatilep;
2467   string btype;
2468
2469   string_init (&btype);
2470   string_init (&decl);
2471   string_init (result);
2472
2473   done = 0;
2474   success = 1;
2475   while (success && !done)
2476     {
2477       int member;
2478       switch (**mangled)
2479         {
2480
2481           /* A pointer type */
2482         case 'P':
2483         case 'p':
2484           (*mangled)++;
2485           if (! (work -> options & DMGL_JAVA))
2486             string_prepend (&decl, "*");
2487           break;
2488
2489           /* A reference type */
2490         case 'R':
2491           (*mangled)++;
2492           string_prepend (&decl, "&");
2493           break;
2494
2495           /* An array */
2496         case 'A':
2497           {
2498             const char *p = ++(*mangled);
2499
2500             string_prepend (&decl, "(");
2501             string_append (&decl, ")[");
2502             /* Copy anything up until the next underscore (the size of the
2503                array).  */
2504             while (**mangled && **mangled != '_')
2505               ++(*mangled);
2506             if (**mangled == '_')
2507               {
2508                 string_appendn (&decl, p, *mangled - p);
2509                 string_append (&decl, "]");             
2510                 *mangled += 1;
2511               }
2512             else
2513               success = 0;
2514             break;
2515           }
2516
2517         /* A back reference to a previously seen type */
2518         case 'T':
2519           (*mangled)++;
2520           if (!get_count (mangled, &n) || n >= work -> ntypes)
2521             {
2522               success = 0;
2523             }
2524           else
2525             {
2526               remembered_type = work -> typevec[n];
2527               mangled = &remembered_type;
2528             }
2529           break;
2530
2531           /* A function */
2532         case 'F':
2533           (*mangled)++;
2534           if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
2535             {
2536               string_prepend (&decl, "(");
2537               string_append (&decl, ")");
2538             }
2539           /* After picking off the function args, we expect to either find the
2540              function return type (preceded by an '_') or the end of the
2541              string.  */
2542           if (!demangle_args (work, mangled, &decl)
2543               || (**mangled != '_' && **mangled != '\0'))
2544             {
2545               success = 0;
2546             }
2547           if (success && (**mangled == '_'))
2548             {
2549               (*mangled)++;
2550             }
2551           break;
2552
2553         case 'M':
2554         case 'O':
2555           {
2556             constp = 0;
2557             volatilep = 0;
2558
2559             member = **mangled == 'M';
2560             (*mangled)++;
2561             if (!isdigit (**mangled) && **mangled != 't')
2562               {
2563                 success = 0;
2564                 break;
2565               }
2566
2567             string_append (&decl, ")");
2568             string_prepend (&decl, (work -> options & DMGL_JAVA) ? "." : "::");
2569             if (isdigit (**mangled)) 
2570               {
2571                 n = consume_count (mangled);
2572                 if (strlen (*mangled) < n)
2573                   {
2574                     success = 0;
2575                     break;
2576                   }
2577                 string_prependn (&decl, *mangled, n);
2578                 *mangled += n;
2579               }
2580             else
2581               {
2582                 string temp;
2583                 string_init (&temp);
2584                 success = demangle_template (work, mangled, &temp, NULL, 1);
2585                 if (success)
2586                   {
2587                     string_prependn (&decl, temp.b, temp.p - temp.b);
2588                     string_clear (&temp);
2589                   }
2590                 else
2591                   break;
2592               }
2593             string_prepend (&decl, "(");
2594             if (member)
2595               {
2596                 if (**mangled == 'C')
2597                   {
2598                     (*mangled)++;
2599                     constp = 1;
2600                   }
2601                 if (**mangled == 'V')
2602                   {
2603                     (*mangled)++;
2604                     volatilep = 1;
2605                   }
2606                 if (*(*mangled)++ != 'F')
2607                   {
2608                     success = 0;
2609                     break;
2610                   }
2611               }
2612             if ((member && !demangle_args (work, mangled, &decl))
2613                 || **mangled != '_')
2614               {
2615                 success = 0;
2616                 break;
2617               }
2618             (*mangled)++;
2619             if (! PRINT_ANSI_QUALIFIERS)
2620               {
2621                 break;
2622               }
2623             if (constp)
2624               {
2625                 APPEND_BLANK (&decl);
2626                 string_append (&decl, "const");
2627               }
2628             if (volatilep)
2629               {
2630                 APPEND_BLANK (&decl);
2631                 string_append (&decl, "volatile");
2632               }
2633             break;
2634           }
2635         case 'G':
2636           (*mangled)++;
2637           break;
2638
2639         case 'C':
2640           (*mangled)++;
2641           /*
2642             if ((*mangled)[1] == 'P')
2643             {
2644             */
2645           if (PRINT_ANSI_QUALIFIERS)
2646             {
2647               if (!STRING_EMPTY (&decl))
2648                 {
2649                   string_prepend (&decl, " ");
2650                 }
2651               string_prepend (&decl, "const");
2652             }
2653           break;
2654           /*
2655             }
2656             */
2657
2658           /* fall through */
2659         default:
2660           done = 1;
2661           break;
2662         }
2663     }
2664
2665   switch (**mangled)
2666     {
2667       /* A qualified name, such as "Outer::Inner".  */
2668     case 'Q':
2669     case 'K':
2670       {
2671         int btype = register_Btype (work);
2672         success = demangle_qualified (work, mangled, result, 0, 1);
2673         remember_Btype (work, result->b, LEN_STRING (result), btype);
2674
2675         break;
2676       }
2677
2678     /* A back reference to a previously seen squangled type */
2679     case 'B':
2680       (*mangled)++;
2681       if (!get_count (mangled, &n) || n >= work -> numb)
2682           success = 0;
2683       else
2684         {
2685           string_append (result, work->btypevec[n]);
2686         }
2687       break;
2688
2689     case 'X':
2690     case 'Y':
2691       /* A template parm.  We substitute the corresponding argument. */
2692       {
2693         int idx;
2694
2695         (*mangled)++;
2696         idx = consume_count_with_underscores (mangled);
2697
2698         if (idx == -1 
2699             || (work->tmpl_argvec && idx >= work->ntmpl_args)
2700             || consume_count_with_underscores (mangled) == -1)
2701           {
2702             success = 0;
2703             break;
2704           }
2705
2706         if (work->tmpl_argvec)
2707           string_append (result, work->tmpl_argvec[idx]);
2708         else
2709           {
2710             char buf[10];
2711             sprintf(buf, "T%d", idx);
2712             string_append (result, buf);
2713           }
2714
2715         success = 1;
2716       }
2717     break;
2718
2719     default:
2720       success = demangle_fund_type (work, mangled, result);
2721       break;
2722     }
2723
2724   if (success)
2725     {
2726       if (!STRING_EMPTY (&decl))
2727         {
2728           string_append (result, " ");
2729           string_appends (result, &decl);
2730         }
2731     }
2732   else
2733     {
2734       string_delete (result);
2735     }
2736   string_delete (&decl);
2737   return (success);
2738 }
2739
2740 /* Given a pointer to a type string that represents a fundamental type
2741    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2742    string in which the demangled output is being built in RESULT, and
2743    the WORK structure, decode the types and add them to the result.
2744
2745    For example:
2746
2747         "Ci"    =>      "const int"
2748         "Sl"    =>      "signed long"
2749         "CUs"   =>      "const unsigned short"
2750
2751    */
2752
2753 static int
2754 demangle_fund_type (work, mangled, result)
2755      struct work_stuff *work;
2756      const char **mangled;
2757      string *result;
2758 {
2759   int done = 0;
2760   int success = 1;
2761   string btype;
2762   string_init (&btype);
2763
2764   /* First pick off any type qualifiers.  There can be more than one.  */
2765
2766   while (!done)
2767     {
2768       switch (**mangled)
2769         {
2770         case 'C':
2771           (*mangled)++;
2772           if (PRINT_ANSI_QUALIFIERS)
2773             {
2774               APPEND_BLANK (result);
2775               string_append (result, "const");
2776             }
2777           break;
2778         case 'U':
2779           (*mangled)++;
2780           APPEND_BLANK (result);
2781           string_append (result, "unsigned");
2782           break;
2783         case 'S': /* signed char only */
2784           (*mangled)++;
2785           APPEND_BLANK (result);
2786           string_append (result, "signed");
2787           break;
2788         case 'V':
2789           (*mangled)++;
2790           if (PRINT_ANSI_QUALIFIERS)
2791             {
2792               APPEND_BLANK (result);
2793               string_append (result, "volatile");
2794             }
2795           break;
2796         case 'J':
2797           (*mangled)++;
2798           APPEND_BLANK (result);
2799           string_append (result, "__complex");
2800           break;
2801         default:
2802           done = 1;
2803           break;
2804         }
2805     }
2806
2807   /* Now pick off the fundamental type.  There can be only one.  */
2808
2809   switch (**mangled)
2810     {
2811     case '\0':
2812     case '_':
2813       break;
2814     case 'v':
2815       (*mangled)++;
2816       APPEND_BLANK (result);
2817       string_append (result, "void");
2818       break;
2819     case 'x':
2820       (*mangled)++;
2821       APPEND_BLANK (result);
2822       string_append (result, "long long");
2823       break;
2824     case 'l':
2825       (*mangled)++;
2826       APPEND_BLANK (result);
2827       string_append (result, "long");
2828       break;
2829     case 'i':
2830       (*mangled)++;
2831       APPEND_BLANK (result);
2832       string_append (result, "int");
2833       break;
2834     case 's':
2835       (*mangled)++;
2836       APPEND_BLANK (result);
2837       string_append (result, "short");
2838       break;
2839     case 'b':
2840       (*mangled)++;
2841       APPEND_BLANK (result);
2842       string_append (result, "bool");
2843       break;
2844     case 'c':
2845       (*mangled)++;
2846       APPEND_BLANK (result);
2847       string_append (result, "char");
2848       break;
2849     case 'w':
2850       (*mangled)++;
2851       APPEND_BLANK (result);
2852       string_append (result, "wchar_t");
2853       break;
2854     case 'r':
2855       (*mangled)++;
2856       APPEND_BLANK (result);
2857       string_append (result, "long double");
2858       break;
2859     case 'd':
2860       (*mangled)++;
2861       APPEND_BLANK (result);
2862       string_append (result, "double");
2863       break;
2864     case 'f':
2865       (*mangled)++;
2866       APPEND_BLANK (result);
2867       string_append (result, "float");
2868       break;
2869     case 'G':
2870       (*mangled)++;
2871       if (!isdigit (**mangled))
2872         {
2873           success = 0;
2874           break;
2875         }
2876       /* fall through */
2877       /* An explicit type, such as "6mytype" or "7integer" */
2878     case '0':
2879     case '1':
2880     case '2':
2881     case '3':
2882     case '4':
2883     case '5':
2884     case '6':
2885     case '7':
2886     case '8':
2887     case '9':
2888       {
2889         int bindex = register_Btype (work);
2890         string btype;
2891         string_init (&btype);
2892         if (demangle_class_name (work, mangled, &btype)) {
2893           remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
2894           APPEND_BLANK (result);
2895           string_appends (result, &btype);
2896         }
2897         else 
2898           success = 0;
2899         string_delete (&btype);
2900         break;
2901       }
2902     case 't':
2903       {
2904         int bindex= register_Btype (work);
2905         success = demangle_template (work, mangled, &btype, 0, 1);
2906         remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
2907         string_appends (result, &btype);
2908         break;
2909       }
2910     default:
2911       success = 0;
2912       break;
2913     }
2914
2915   return (success);
2916 }
2917
2918 /* `result' will be initialized in do_type; it will be freed on failure */
2919
2920 static int
2921 do_arg (work, mangled, result)
2922      struct work_stuff *work;
2923      const char **mangled;
2924      string *result;
2925 {
2926   const char *start = *mangled;
2927
2928   if (!do_type (work, mangled, result))
2929     {
2930       return (0);
2931     }
2932   else
2933     {
2934       remember_type (work, start, *mangled - start);
2935       return (1);
2936     }
2937 }
2938
2939 static void
2940 remember_type (work, start, len)
2941      struct work_stuff *work;
2942      const char *start;
2943      int len;
2944 {
2945   char *tem;
2946
2947   if (work -> ntypes >= work -> typevec_size)
2948     {
2949       if (work -> typevec_size == 0)
2950         {
2951           work -> typevec_size = 3;
2952           work -> typevec
2953             = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
2954         }
2955       else
2956         {
2957           work -> typevec_size *= 2;
2958           work -> typevec
2959             = (char **) xrealloc ((char *)work -> typevec,
2960                                   sizeof (char *) * work -> typevec_size);
2961         }
2962     }
2963   tem = xmalloc (len + 1);
2964   memcpy (tem, start, len);
2965   tem[len] = '\0';
2966   work -> typevec[work -> ntypes++] = tem;
2967 }
2968
2969
2970 /* Remember a K type class qualifier. */
2971 static void
2972 remember_Ktype (work, start, len)
2973      struct work_stuff *work;
2974      const char *start;
2975      int len;
2976 {
2977   char *tem;
2978
2979   if (work -> numk >= work -> ksize)
2980     {
2981       if (work -> ksize == 0)
2982         {
2983           work -> ksize = 5;
2984           work -> ktypevec
2985             = (char **) xmalloc (sizeof (char *) * work -> ksize);
2986         }
2987       else
2988         {
2989           work -> ksize *= 2;
2990           work -> ktypevec
2991             = (char **) xrealloc ((char *)work -> ktypevec,
2992                                   sizeof (char *) * work -> ksize);
2993         }
2994     }
2995   tem = xmalloc (len + 1);
2996   memcpy (tem, start, len);
2997   tem[len] = '\0';
2998   work -> ktypevec[work -> numk++] = tem;
2999 }
3000
3001 /* Register a B code, and get an index for it. B codes are registered
3002    as they are seen, rather than as they are completed, so map<temp<char> >  
3003    registers map<temp<char> > as B0, and temp<char> as B1 */
3004
3005 static int
3006 register_Btype (work)
3007      struct work_stuff *work;
3008 {
3009   int ret;
3010  
3011   if (work -> numb >= work -> bsize)
3012     {
3013       if (work -> bsize == 0)
3014         {
3015           work -> bsize = 5;
3016           work -> btypevec
3017             = (char **) xmalloc (sizeof (char *) * work -> bsize);
3018         }
3019       else
3020         {
3021           work -> bsize *= 2;
3022           work -> btypevec
3023             = (char **) xrealloc ((char *)work -> btypevec,
3024                                   sizeof (char *) * work -> bsize);
3025         }
3026     }
3027   ret = work -> numb++;
3028   work -> btypevec[ret] = NULL;
3029   return(ret);
3030 }
3031
3032 /* Store a value into a previously registered B code type. */
3033
3034 static void
3035 remember_Btype (work, start, len, index)
3036      struct work_stuff *work;
3037      const char *start;
3038      int len, index;
3039 {
3040   char *tem;
3041
3042   tem = xmalloc (len + 1);
3043   memcpy (tem, start, len);
3044   tem[len] = '\0';
3045   work -> btypevec[index] = tem;
3046 }
3047
3048 /* Lose all the info related to B and K type codes. */
3049 static void
3050 forget_B_and_K_types (work)
3051      struct work_stuff *work;
3052 {
3053   int i;
3054
3055   while (work -> numk > 0)
3056     {
3057       i = --(work -> numk);
3058       if (work -> ktypevec[i] != NULL)
3059         {
3060           free (work -> ktypevec[i]);
3061           work -> ktypevec[i] = NULL;
3062         }
3063     }
3064
3065   while (work -> numb > 0)
3066     {
3067       i = --(work -> numb);
3068       if (work -> btypevec[i] != NULL)
3069         {
3070           free (work -> btypevec[i]);
3071           work -> btypevec[i] = NULL;
3072         }
3073     }
3074 }
3075 /* Forget the remembered types, but not the type vector itself.  */
3076
3077 static void
3078 forget_types (work)
3079      struct work_stuff *work;
3080 {
3081   int i;
3082
3083   while (work -> ntypes > 0)
3084     {
3085       i = --(work -> ntypes);
3086       if (work -> typevec[i] != NULL)
3087         {
3088           free (work -> typevec[i]);
3089           work -> typevec[i] = NULL;
3090         }
3091     }
3092 }
3093
3094 /* Process the argument list part of the signature, after any class spec
3095    has been consumed, as well as the first 'F' character (if any).  For
3096    example:
3097
3098    "__als__3fooRT0"             =>      process "RT0"
3099    "complexfunc5__FPFPc_PFl_i"  =>      process "PFPc_PFl_i"
3100
3101    DECLP must be already initialised, usually non-empty.  It won't be freed
3102    on failure.
3103
3104    Note that g++ differs significantly from ARM and lucid style mangling
3105    with regards to references to previously seen types.  For example, given
3106    the source fragment:
3107
3108      class foo {
3109        public:
3110        foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3111      };
3112
3113      foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3114      void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3115
3116    g++ produces the names:
3117
3118      __3fooiRT0iT2iT2
3119      foo__FiR3fooiT1iT1
3120
3121    while lcc (and presumably other ARM style compilers as well) produces:
3122
3123      foo__FiR3fooT1T2T1T2
3124      __ct__3fooFiR3fooT1T2T1T2
3125
3126    Note that g++ bases it's type numbers starting at zero and counts all
3127    previously seen types, while lucid/ARM bases it's type numbers starting
3128    at one and only considers types after it has seen the 'F' character
3129    indicating the start of the function args.  For lucid/ARM style, we
3130    account for this difference by discarding any previously seen types when
3131    we see the 'F' character, and subtracting one from the type number
3132    reference.
3133
3134  */
3135
3136 static int
3137 demangle_args (work, mangled, declp)
3138      struct work_stuff *work;
3139      const char **mangled;
3140      string *declp;
3141 {
3142   string arg;
3143   int need_comma = 0;
3144   int r;
3145   int t;
3146   const char *tem;
3147   char temptype;
3148
3149   if (PRINT_ARG_TYPES)
3150     {
3151       string_append (declp, "(");
3152       if (**mangled == '\0')
3153         {
3154           string_append (declp, "void");
3155         }
3156     }
3157
3158   while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
3159     {
3160       if ((**mangled == 'N') || (**mangled == 'T'))
3161         {
3162           temptype = *(*mangled)++;
3163           
3164           if (temptype == 'N')
3165             {
3166               if (!get_count (mangled, &r))
3167                 {
3168                   return (0);
3169                 }
3170             }
3171           else
3172             {
3173               r = 1;
3174             }
3175           if (ARM_DEMANGLING && work -> ntypes >= 10)
3176             {
3177               /* If we have 10 or more types we might have more than a 1 digit
3178                  index so we'll have to consume the whole count here. This
3179                  will lose if the next thing is a type name preceded by a
3180                  count but it's impossible to demangle that case properly
3181                  anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3182                  Pc, ...)"  or "(..., type12, char *, ...)" */
3183               if ((t = consume_count(mangled)) == 0)
3184                 {
3185                   return (0);
3186                 }
3187             }
3188           else
3189             {
3190               if (!get_count (mangled, &t))
3191                 {
3192                   return (0);
3193                 }
3194             }
3195           if (LUCID_DEMANGLING || ARM_DEMANGLING)
3196             {
3197               t--;
3198             }
3199           /* Validate the type index.  Protect against illegal indices from
3200              malformed type strings.  */
3201           if ((t < 0) || (t >= work -> ntypes))
3202             {
3203               return (0);
3204             }
3205           while (--r >= 0)
3206             {
3207               tem = work -> typevec[t];
3208               if (need_comma && PRINT_ARG_TYPES)
3209                 {
3210                   string_append (declp, ", ");
3211                 }
3212               if (!do_arg (work, &tem, &arg))
3213                 {
3214                   return (0);
3215                 }
3216               if (PRINT_ARG_TYPES)
3217                 {
3218                   string_appends (declp, &arg);
3219                 }
3220               string_delete (&arg);
3221               need_comma = 1;
3222             }
3223         }
3224       else
3225         {
3226           if (need_comma & PRINT_ARG_TYPES)
3227             {
3228               string_append (declp, ", ");
3229             }
3230           if (!do_arg (work, mangled, &arg))
3231             {
3232               return (0);
3233             }
3234           if (PRINT_ARG_TYPES)
3235             {
3236               string_appends (declp, &arg);
3237             }
3238           string_delete (&arg);
3239           need_comma = 1;
3240         }
3241     }
3242
3243   if (**mangled == 'e')
3244     {
3245       (*mangled)++;
3246       if (PRINT_ARG_TYPES)
3247         {
3248           if (need_comma)
3249             {
3250               string_append (declp, ",");
3251             }
3252           string_append (declp, "...");
3253         }
3254     }
3255
3256   if (PRINT_ARG_TYPES)
3257     {
3258       string_append (declp, ")");
3259     }
3260   return (1);
3261 }
3262
3263 static void
3264 demangle_function_name (work, mangled, declp, scan)
3265      struct work_stuff *work;
3266      const char **mangled;
3267      string *declp;
3268      const char *scan;
3269 {
3270   size_t i;
3271   string type;
3272   const char *tem;
3273
3274   string_appendn (declp, (*mangled), scan - (*mangled));
3275   string_need (declp, 1);
3276   *(declp -> p) = '\0';
3277
3278   /* Consume the function name, including the "__" separating the name
3279      from the signature.  We are guaranteed that SCAN points to the
3280      separator.  */
3281
3282   (*mangled) = scan + 2;
3283
3284   if (LUCID_DEMANGLING || ARM_DEMANGLING)
3285     {
3286
3287       /* See if we have an ARM style constructor or destructor operator.
3288          If so, then just record it, clear the decl, and return.
3289          We can't build the actual constructor/destructor decl until later,
3290          when we recover the class name from the signature.  */
3291
3292       if (strcmp (declp -> b, "__ct") == 0)
3293         {
3294           work -> constructor += 1;
3295           string_clear (declp);
3296           return;
3297         }
3298       else if (strcmp (declp -> b, "__dt") == 0)
3299         {
3300           work -> destructor += 1;
3301           string_clear (declp);
3302           return;
3303         }
3304     }
3305
3306   if (declp->p - declp->b >= 3 
3307       && declp->b[0] == 'o'
3308       && declp->b[1] == 'p'
3309       && strchr (cplus_markers, declp->b[2]) != NULL)
3310     {
3311       /* see if it's an assignment expression */
3312       if (declp->p - declp->b >= 10 /* op$assign_ */
3313           && memcmp (declp->b + 3, "assign_", 7) == 0)
3314         {
3315           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3316             {
3317               int len = declp->p - declp->b - 10;
3318               if (strlen (optable[i].in) == len
3319                   && memcmp (optable[i].in, declp->b + 10, len) == 0)
3320                 {
3321                   string_clear (declp);
3322                   string_append (declp, "operator");
3323                   string_append (declp, optable[i].out);
3324                   string_append (declp, "=");
3325                   break;
3326                 }
3327             }
3328         }
3329       else
3330         {
3331           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3332             {
3333               int len = declp->p - declp->b - 3;
3334               if (strlen (optable[i].in) == len 
3335                   && memcmp (optable[i].in, declp->b + 3, len) == 0)
3336                 {
3337                   string_clear (declp);
3338                   string_append (declp, "operator");
3339                   string_append (declp, optable[i].out);
3340                   break;
3341                 }
3342             }
3343         }
3344     }
3345   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
3346            && strchr (cplus_markers, declp->b[4]) != NULL)
3347     {
3348       /* type conversion operator */
3349       tem = declp->b + 5;
3350       if (do_type (work, &tem, &type))
3351         {
3352           string_clear (declp);
3353           string_append (declp, "operator ");
3354           string_appends (declp, &type);
3355           string_delete (&type);
3356         }
3357     }
3358   else if (declp->b[0] == '_' && declp->b[1] == '_'
3359            && declp->b[2] == 'o' && declp->b[3] == 'p')
3360     {
3361       /* ANSI.  */
3362       /* type conversion operator.  */
3363       tem = declp->b + 4;
3364       if (do_type (work, &tem, &type))
3365         {
3366           string_clear (declp);
3367           string_append (declp, "operator ");
3368           string_appends (declp, &type);
3369           string_delete (&type);
3370         }
3371     }
3372   else if (declp->b[0] == '_' && declp->b[1] == '_'
3373            && declp->b[2] >= 'a' && declp->b[2] <= 'z'
3374            && declp->b[3] >= 'a' && declp->b[3] <= 'z')
3375     {
3376       if (declp->b[4] == '\0')
3377         {
3378           /* Operator.  */
3379           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3380             {
3381               if (strlen (optable[i].in) == 2
3382                   && memcmp (optable[i].in, declp->b + 2, 2) == 0)
3383                 {
3384                   string_clear (declp);
3385                   string_append (declp, "operator");
3386                   string_append (declp, optable[i].out);
3387                   break;
3388                 }
3389             }
3390         }
3391       else
3392         {
3393           if (declp->b[2] == 'a' && declp->b[5] == '\0')
3394             {
3395               /* Assignment.  */
3396               for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3397                 {
3398                   if (strlen (optable[i].in) == 3
3399                       && memcmp (optable[i].in, declp->b + 2, 3) == 0)
3400                     {
3401                       string_clear (declp);
3402                       string_append (declp, "operator");
3403                       string_append (declp, optable[i].out);
3404                       break;
3405                     }                 
3406                 }
3407             }
3408         }
3409     }
3410 }
3411
3412 /* a mini string-handling package */
3413
3414 static void
3415 string_need (s, n)
3416      string *s;
3417      int n;
3418 {
3419   int tem;
3420
3421   if (s->b == NULL)
3422     {
3423       if (n < 32)
3424         {
3425           n = 32;
3426         }
3427       s->p = s->b = xmalloc (n);
3428       s->e = s->b + n;
3429     }
3430   else if (s->e - s->p < n)
3431     {
3432       tem = s->p - s->b;
3433       n += tem;
3434       n *= 2;
3435       s->b = xrealloc (s->b, n);
3436       s->p = s->b + tem;
3437       s->e = s->b + n;
3438     }
3439 }
3440
3441 static void
3442 string_delete (s)
3443      string *s;
3444 {
3445   if (s->b != NULL)
3446     {
3447       free (s->b);
3448       s->b = s->e = s->p = NULL;
3449     }
3450 }
3451
3452 static void
3453 string_init (s)
3454      string *s;
3455 {
3456   s->b = s->p = s->e = NULL;
3457 }
3458
3459 static void 
3460 string_clear (s)
3461      string *s;
3462 {
3463   s->p = s->b;
3464 }
3465
3466 #if 0
3467
3468 static int
3469 string_empty (s)
3470      string *s;
3471 {
3472   return (s->b == s->p);
3473 }
3474
3475 #endif
3476
3477 static void
3478 string_append (p, s)
3479      string *p;
3480      const char *s;
3481 {
3482   int n;
3483   if (s == NULL || *s == '\0')
3484     return;
3485   n = strlen (s);
3486   string_need (p, n);
3487   memcpy (p->p, s, n);
3488   p->p += n;
3489 }
3490
3491 static void
3492 string_appends (p, s)
3493      string *p, *s;
3494 {
3495   int n;
3496
3497   if (s->b != s->p)
3498     {
3499       n = s->p - s->b;
3500       string_need (p, n);
3501       memcpy (p->p, s->b, n);
3502       p->p += n;
3503     }
3504 }
3505
3506 static void
3507 string_appendn (p, s, n)
3508      string *p;
3509      const char *s;
3510      int n;
3511 {
3512   if (n != 0)
3513     {
3514       string_need (p, n);
3515       memcpy (p->p, s, n);
3516       p->p += n;
3517     }
3518 }
3519
3520 static void
3521 string_prepend (p, s)
3522      string *p;
3523      const char *s;
3524 {
3525   if (s != NULL && *s != '\0')
3526     {
3527       string_prependn (p, s, strlen (s));
3528     }
3529 }
3530
3531 static void
3532 string_prepends (p, s)
3533      string *p, *s;
3534 {
3535   if (s->b != s->p)
3536     {
3537       string_prependn (p, s->b, s->p - s->b);
3538     }
3539 }
3540
3541 static void
3542 string_prependn (p, s, n)
3543      string *p;
3544      const char *s;
3545      int n;
3546 {
3547   char *q;
3548
3549   if (n != 0)
3550     {
3551       string_need (p, n);
3552       for (q = p->p - 1; q >= p->b; q--)
3553         {
3554           q[n] = q[0];
3555         }
3556       memcpy (p->b, s, n);
3557       p->p += n;
3558     }
3559 }
3560
3561 /* To generate a standalone demangler program for testing purposes,
3562    just compile and link this file with -DMAIN and libiberty.a.  When
3563    run, it demangles each command line arg, or each stdin string, and
3564    prints the result on stdout.  */
3565
3566 #ifdef MAIN
3567
3568 #include "getopt.h"
3569
3570 static char *program_name;
3571 static char *program_version = VERSION;
3572 static int flags = DMGL_PARAMS | DMGL_ANSI;
3573
3574 static void demangle_it PARAMS ((char *));
3575 static void usage PARAMS ((FILE *, int));
3576 static void fatal PARAMS ((char *));
3577
3578 static void
3579 demangle_it (mangled_name)
3580      char *mangled_name;
3581 {
3582   char *result;
3583
3584   result = cplus_demangle (mangled_name, flags);
3585   if (result == NULL)
3586     {
3587       printf ("%s\n", mangled_name);
3588     }
3589   else
3590     {
3591       printf ("%s\n", result);
3592       free (result);
3593     }
3594 }
3595
3596 static void
3597 usage (stream, status)
3598      FILE *stream;
3599      int status;
3600 {    
3601   fprintf (stream, "\
3602 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3603       [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3604       [--help] [--version] [arg...]\n",
3605            program_name);
3606   exit (status);
3607 }
3608
3609 #define MBUF_SIZE 512
3610 char mbuffer[MBUF_SIZE];
3611
3612 /* Defined in the automatically-generated underscore.c.  */
3613 extern int prepends_underscore;
3614
3615 int strip_underscore = 0;
3616
3617 static struct option long_options[] = {
3618   {"strip-underscores", no_argument, 0, '_'},
3619   {"format", required_argument, 0, 's'},
3620   {"help", no_argument, 0, 'h'},
3621   {"java", no_argument, 0, 'j'},
3622   {"no-strip-underscores", no_argument, 0, 'n'},
3623   {"version", no_argument, 0, 'v'},
3624   {0, no_argument, 0, 0}
3625 };
3626
3627 /* More 'friendly' abort that prints the line and file.
3628    config.h can #define abort fancy_abort if you like that sort of thing.  */
3629
3630 void
3631 fancy_abort ()
3632 {
3633   fatal ("Internal gcc abort.");
3634 }
3635
3636 int
3637 main (argc, argv)
3638      int argc;
3639      char **argv;
3640 {
3641   char *result;
3642   int c;
3643
3644   program_name = argv[0];
3645
3646   strip_underscore = prepends_underscore;
3647
3648   while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF)
3649     {
3650       switch (c)
3651         {
3652         case '?':
3653           usage (stderr, 1);
3654           break;
3655         case 'h':
3656           usage (stdout, 0);
3657         case 'n':
3658           strip_underscore = 0;
3659           break;
3660         case 'v':
3661           printf ("GNU %s version %s\n", program_name, program_version);
3662           exit (0);
3663         case '_':
3664           strip_underscore = 1;
3665           break;
3666         case 'j':
3667           flags |= DMGL_JAVA;
3668           break;
3669         case 's':
3670           if (strcmp (optarg, "gnu") == 0)
3671             {
3672               current_demangling_style = gnu_demangling;
3673             }
3674           else if (strcmp (optarg, "lucid") == 0)
3675             {
3676               current_demangling_style = lucid_demangling;
3677             }
3678           else if (strcmp (optarg, "arm") == 0)
3679             {
3680               current_demangling_style = arm_demangling;
3681             }
3682           else
3683             {
3684               fprintf (stderr, "%s: unknown demangling style `%s'\n",
3685                        program_name, optarg);
3686               exit (1);
3687             }
3688           break;
3689         }
3690     }
3691
3692   if (optind < argc)
3693     {
3694       for ( ; optind < argc; optind++)
3695         {
3696           demangle_it (argv[optind]);
3697         }
3698     }
3699   else
3700     {
3701       for (;;)
3702         {
3703           int i = 0;
3704           c = getchar ();
3705           /* Try to read a label.  */
3706           while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
3707             {
3708               if (i >= MBUF_SIZE-1)
3709                 break;
3710               mbuffer[i++] = c;
3711               c = getchar ();
3712             }
3713           if (i > 0)
3714             {
3715               int skip_first = 0;
3716
3717               if (mbuffer[0] == '.')
3718                 ++skip_first;
3719               if (strip_underscore && mbuffer[skip_first] == '_')
3720                 ++skip_first;
3721
3722               if (skip_first > i)
3723                 skip_first = i;
3724
3725               mbuffer[i] = 0;
3726               
3727               result = cplus_demangle (mbuffer + skip_first, flags);
3728               if (result)
3729                 {
3730                   if (mbuffer[0] == '.')
3731                     putc ('.', stdout);
3732                   fputs (result, stdout);
3733                   free (result);
3734                 }
3735               else
3736                 fputs (mbuffer, stdout);
3737
3738               fflush (stdout);
3739             }
3740           if (c == EOF)
3741             break;
3742           putchar (c);
3743         }
3744     }
3745
3746   exit (0);
3747 }
3748
3749 static void
3750 fatal (str)
3751      char *str;
3752 {
3753   fprintf (stderr, "%s: %s\n", program_name, str);
3754   exit (1);
3755 }
3756
3757 char * malloc ();
3758 char * realloc ();
3759
3760 char *
3761 xmalloc (size)
3762      unsigned size;
3763 {
3764   register char *value = (char *) malloc (size);
3765   if (value == 0)
3766     fatal ("virtual memory exhausted");
3767   return value;
3768 }
3769
3770 char *
3771 xrealloc (ptr, size)
3772      char *ptr;
3773      unsigned size;
3774 {
3775   register char *value = (char *) realloc (ptr, size);
3776   if (value == 0)
3777     fatal ("virtual memory exhausted");
3778   return value;
3779 }
3780 #endif  /* main */