OSDN Git Service

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