OSDN Git Service

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