OSDN Git Service

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