OSDN Git Service

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