OSDN Git Service

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