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