OSDN Git Service

(strstr, strncmp, strlen): Remove declarations.
[pf3gnuchains/gcc-fork.git] / gcc / cplus-dem.c
1 /* Demangler for GNU C++ 
2    Copyright 1989, 1991, 1994, 1995 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., 675 Mass Ave,
20 Cambridge, MA 02139, 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      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 char *
454 cplus_mangle_opname (opname, options)
455      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 ((char *)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           done = 0;
911           /* temp is initialized in do_type */
912           success = do_type (work, mangled, &temp);
913 /*
914           if (success)
915             {
916               string_appends (tname, &temp);
917             }
918 */
919           string_delete(&temp);
920           if (!success)
921             {
922               break;
923             }
924 /*
925           string_append (tname, "=");
926 */
927           while (*old_p && !done)
928             {   
929               switch (*old_p)
930                 {
931                   case 'P':
932                   case 'p':
933                   case 'R':
934                     done = is_pointer = 1;
935                     break;
936                   case 'C':     /* const */
937                   case 'S':     /* explicitly signed [char] */
938                   case 'U':     /* unsigned */
939                   case 'V':     /* volatile */
940                   case 'F':     /* function */
941                   case 'M':     /* member function */
942                   case 'O':     /* ??? */
943                     old_p++;
944                     continue;
945                   case 'Q':     /* qualified name */
946                     done = is_integral = 1;
947                     break;
948                   case 'T':     /* remembered type */
949                     abort ();
950                     break;
951                   case 'v':     /* void */
952                     abort ();
953                     break;
954                   case 'x':     /* long long */
955                   case 'l':     /* long */
956                   case 'i':     /* int */
957                   case 's':     /* short */
958                   case 'w':     /* wchar_t */
959                     done = is_integral = 1;
960                     break;
961                   case 'b':     /* bool */
962                     done = is_bool = 1;
963                     break;
964                   case 'c':     /* char */
965                     done = is_char = 1;
966                     break;
967                   case 'r':     /* long double */
968                   case 'd':     /* double */
969                   case 'f':     /* float */
970                     done = is_real = 1;
971                     break;
972                   default:
973                     /* it's probably user defined type, let's assume
974                        it's integral, it seems hard to figure out
975                        what it really is */
976                     done = is_integral = 1;
977                 }
978             }
979           if (is_integral)
980             {
981               if (**mangled == 'm')
982                 {
983                   string_appendn (tname, "-", 1);
984                   (*mangled)++;
985                 }
986               while (isdigit (**mangled))       
987                 {
988                   string_appendn (tname, *mangled, 1);
989                   (*mangled)++;
990                 }
991             }
992           else if (is_char)
993             {
994             char tmp[2];
995             int val;
996               if (**mangled == 'm')
997                 {
998                   string_appendn (tname, "-", 1);
999                   (*mangled)++;
1000                 }
1001               string_appendn (tname, "'", 1);
1002               val = consume_count(mangled);
1003               if (val == 0)
1004                 {
1005                   success = 0;
1006                   break;
1007                 }
1008               tmp[0] = (char)val;
1009               tmp[1] = '\0';
1010               string_appendn (tname, &tmp[0], 1);
1011               string_appendn (tname, "'", 1);
1012             }
1013           else if (is_bool)
1014             {
1015               int val = consume_count (mangled);
1016               if (val == 0)
1017                 string_appendn (tname, "false", 5);
1018               else if (val == 1)
1019                 string_appendn (tname, "true", 4);
1020               else
1021                 success = 0;
1022             }
1023           else if (is_real)
1024             {
1025               if (**mangled == 'm')
1026                 {
1027                   string_appendn (tname, "-", 1);
1028                   (*mangled)++;
1029                 }
1030               while (isdigit (**mangled))       
1031                 {
1032                   string_appendn (tname, *mangled, 1);
1033                   (*mangled)++;
1034                 }
1035               if (**mangled == '.') /* fraction */
1036                 {
1037                   string_appendn (tname, ".", 1);
1038                   (*mangled)++;
1039                   while (isdigit (**mangled))   
1040                     {
1041                       string_appendn (tname, *mangled, 1);
1042                       (*mangled)++;
1043                     }
1044                 }
1045               if (**mangled == 'e') /* exponent */
1046                 {
1047                   string_appendn (tname, "e", 1);
1048                   (*mangled)++;
1049                   while (isdigit (**mangled))   
1050                     {
1051                       string_appendn (tname, *mangled, 1);
1052                       (*mangled)++;
1053                     }
1054                 }
1055             }
1056           else if (is_pointer)
1057             {
1058               if (!get_count (mangled, &symbol_len))
1059                 {
1060                   success = 0;
1061                   break;
1062                 }
1063               string_appendn (tname, *mangled, symbol_len);
1064               *mangled += symbol_len;
1065             }
1066         }
1067       need_comma = 1;
1068     }
1069   if (tname->p[-1] == '>')
1070     string_append (tname, " ");
1071   string_append (tname, ">");
1072   
1073 /*
1074       if (work -> static_type)
1075         {
1076           string_append (declp, *mangled + 1);
1077           *mangled += strlen (*mangled);
1078           success = 1;
1079         }
1080       else
1081         {
1082           success = demangle_args (work, mangled, declp);
1083         }
1084     }
1085 */
1086   return (success);
1087 }
1088
1089 static int
1090 arm_pt (work, mangled, n, anchor, args)
1091      struct work_stuff *work;
1092      const char *mangled;
1093      int n;
1094      const char **anchor, **args;
1095 {
1096   /* ARM template? */
1097   if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
1098     {
1099         int len;
1100         *args = *anchor + 6;
1101         len = consume_count (args);
1102         if (*args + len == mangled + n && **args == '_')
1103           {
1104             ++*args;
1105             return 1;
1106           }
1107     }
1108   return 0;
1109 }
1110
1111 static void
1112 demangle_arm_pt (work, mangled, n, declp)
1113      struct work_stuff *work;
1114      const char **mangled;
1115      int n;
1116      string *declp;
1117 {
1118   const char *p;
1119   const char *args;
1120   const char *e = *mangled + n;
1121
1122   /* ARM template? */
1123   if (arm_pt (work, *mangled, n, &p, &args))
1124   {
1125     string arg;
1126     string_init (&arg);
1127     string_appendn (declp, *mangled, p - *mangled);
1128     string_append (declp, "<");
1129     /* should do error checking here */
1130     while (args < e) {
1131       string_clear (&arg);
1132       do_type (work, &args, &arg);
1133       string_appends (declp, &arg);
1134       string_append (declp, ",");
1135     }
1136     string_delete (&arg);
1137     --declp->p;
1138     string_append (declp, ">");
1139   }
1140   else
1141   {
1142     string_appendn (declp, *mangled, n);
1143   }
1144   *mangled += n;
1145 }
1146
1147 static int
1148 demangle_class_name (work, mangled, declp)
1149      struct work_stuff *work;
1150      const char **mangled;
1151      string *declp;
1152 {
1153   int n;
1154   int success = 0;
1155
1156   n = consume_count (mangled);
1157   if (strlen (*mangled) >= n)
1158   {
1159     demangle_arm_pt (work, mangled, n, declp);
1160     success = 1;
1161   }
1162
1163   return (success);
1164 }
1165
1166 /*
1167
1168 LOCAL FUNCTION
1169
1170         demangle_class -- demangle a mangled class sequence
1171
1172 SYNOPSIS
1173
1174         static int
1175         demangle_class (struct work_stuff *work, const char **mangled,
1176                         strint *declp)
1177
1178 DESCRIPTION
1179
1180         DECLP points to the buffer into which demangling is being done.
1181
1182         *MANGLED points to the current token to be demangled.  On input,
1183         it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1184         On exit, it points to the next token after the mangled class on
1185         success, or the first unconsumed token on failure.
1186
1187         If the constRUCTOR or DESTRUCTOR flags are set in WORK, then
1188         we are demangling a constructor or destructor.  In this case
1189         we prepend "class::class" or "class::~class" to DECLP.
1190
1191         Otherwise, we prepend "class::" to the current DECLP.
1192
1193         Reset the constructor/destructor flags once they have been
1194         "consumed".  This allows demangle_class to be called later during
1195         the same demangling, to do normal class demangling.
1196
1197         Returns 1 if demangling is successful, 0 otherwise.
1198
1199 */
1200
1201 static int
1202 demangle_class (work, mangled, declp)
1203      struct work_stuff *work;
1204      const char **mangled;
1205      string *declp;
1206 {
1207   int success = 0;
1208   string class_name;
1209
1210   string_init (&class_name);
1211   if (demangle_class_name (work, mangled, &class_name))
1212     {
1213       if ((work->constructor & 1) || (work->destructor & 1))
1214         {
1215           string_prepends (declp, &class_name);
1216           if (work -> destructor & 1)
1217             {
1218               string_prepend (declp, "~");
1219               work -> destructor -= 1;
1220             }
1221           else
1222             {
1223               work -> constructor -= 1; 
1224             }
1225         }
1226       string_prepend (declp, "::");
1227       string_prepends (declp, &class_name);
1228       success = 1;
1229     }
1230   string_delete (&class_name);
1231   return (success);
1232 }
1233
1234 /*
1235
1236 LOCAL FUNCTION
1237
1238         demangle_prefix -- consume the mangled name prefix and find signature
1239
1240 SYNOPSIS
1241
1242         static int
1243         demangle_prefix (struct work_stuff *work, const char **mangled,
1244                          string *declp);
1245
1246 DESCRIPTION
1247
1248         Consume and demangle the prefix of the mangled name.
1249
1250         DECLP points to the string buffer into which demangled output is
1251         placed.  On entry, the buffer is empty.  On exit it contains
1252         the root function name, the demangled operator name, or in some
1253         special cases either nothing or the completely demangled result.
1254
1255         MANGLED points to the current pointer into the mangled name.  As each
1256         token of the mangled name is consumed, it is updated.  Upon entry
1257         the current mangled name pointer points to the first character of
1258         the mangled name.  Upon exit, it should point to the first character
1259         of the signature if demangling was successful, or to the first
1260         unconsumed character if demangling of the prefix was unsuccessful.
1261         
1262         Returns 1 on success, 0 otherwise.
1263  */
1264
1265 static int
1266 demangle_prefix (work, mangled, declp)
1267      struct work_stuff *work;
1268      const char **mangled;
1269      string *declp;
1270 {
1271   int success = 1;
1272   const char *scan;
1273   int i;
1274
1275   if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
1276     {
1277       char *marker = strchr (cplus_markers, (*mangled)[8]);
1278       if (marker != NULL && *marker == (*mangled)[10])
1279         {
1280           if ((*mangled)[9] == 'D')
1281             {
1282               /* it's a GNU global destructor to be executed at program exit */
1283               (*mangled) += 11;
1284               work->destructor = 2;
1285               if (gnu_special (work, mangled, declp))
1286                 return success;
1287             }
1288           else if ((*mangled)[9] == 'I')
1289             {
1290               /* it's a GNU global constructor to be executed at program init */
1291               (*mangled) += 11;
1292               work->constructor = 2;
1293               if (gnu_special (work, mangled, declp))
1294                 return success;
1295             }
1296         }
1297     }
1298   else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
1299     {
1300       /* it's a ARM global destructor to be executed at program exit */
1301       (*mangled) += 7;
1302       work->destructor = 2;
1303     }
1304   else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
1305     {
1306       /* it's a ARM global constructor to be executed at program initial */
1307       (*mangled) += 7;
1308       work->constructor = 2;
1309     }
1310
1311 /*  This block of code is a reduction in strength time optimization
1312     of:
1313         scan = mystrstr (*mangled, "__"); */
1314
1315   {
1316     scan = *mangled;
1317
1318     do {
1319       scan = strchr (scan, '_');
1320     } while (scan != NULL && *++scan != '_');
1321
1322     if (scan != NULL) --scan;
1323   }
1324
1325   if (scan != NULL)
1326     {
1327       /* We found a sequence of two or more '_', ensure that we start at
1328          the last pair in the sequence. */
1329       i = strspn (scan, "_");
1330       if (i > 2)
1331         {
1332           scan += (i - 2); 
1333         }
1334     }
1335  
1336   if (scan == NULL)
1337     {
1338       success = 0;
1339     }
1340   else if (work -> static_type)
1341     {
1342       if (!isdigit (scan[0]) && (scan[0] != 't'))
1343         {
1344           success = 0;
1345         }
1346     }
1347   else if ((scan == *mangled) &&
1348            (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')))
1349     {
1350       /* The ARM says nothing about the mangling of local variables.
1351          But cfront mangles local variables by prepending __<nesting_level>
1352          to them. As an extension to ARM demangling we handle this case.  */
1353       if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
1354         {
1355           *mangled = scan + 2;
1356           consume_count (mangled);
1357           string_append (declp, *mangled);
1358           *mangled += strlen (*mangled);
1359           success = 1; 
1360         }
1361       else
1362         {
1363           /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
1364              names like __Q2_3foo3bar for nested type names.  So don't accept
1365              this style of constructor for cfront demangling.  */
1366           if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
1367             work -> constructor += 1;
1368           *mangled = scan + 2;
1369         }
1370     }
1371   else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
1372     {
1373       /* Mangled name starts with "__".  Skip over any leading '_' characters,
1374          then find the next "__" that separates the prefix from the signature.
1375          */
1376       if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
1377           || (arm_special (work, mangled, declp) == 0))
1378         {
1379           while (*scan == '_')
1380             {
1381               scan++;
1382             }
1383           if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
1384             {
1385               /* No separator (I.E. "__not_mangled"), or empty signature
1386                  (I.E. "__not_mangled_either__") */
1387               success = 0;
1388             }
1389           else
1390             {
1391               demangle_function_name (work, mangled, declp, scan);
1392             }
1393         }
1394     }
1395   else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
1396     {
1397       /* Cfront-style parameterized type.  Handled later as a signature. */
1398       success = 1;
1399
1400       /* ARM template? */
1401       demangle_arm_pt (work, mangled, strlen (*mangled), declp);
1402     }
1403   else if (*(scan + 2) != '\0')
1404     {
1405       /* Mangled name does not start with "__" but does have one somewhere
1406          in there with non empty stuff after it.  Looks like a global
1407          function name. */
1408       demangle_function_name (work, mangled, declp, scan);
1409     }
1410   else
1411     {
1412       /* Doesn't look like a mangled name */
1413       success = 0;
1414     }
1415
1416   if (!success && (work->constructor == 2 || work->destructor == 2))
1417     {
1418       string_append (declp, *mangled);
1419       *mangled += strlen (*mangled);
1420       success = 1;
1421     } 
1422   return (success);
1423 }
1424
1425 /*
1426
1427 LOCAL FUNCTION
1428
1429         gnu_special -- special handling of gnu mangled strings
1430
1431 SYNOPSIS
1432
1433         static int
1434         gnu_special (struct work_stuff *work, const char **mangled,
1435                      string *declp);
1436
1437
1438 DESCRIPTION
1439
1440         Process some special GNU style mangling forms that don't fit
1441         the normal pattern.  For example:
1442
1443                 _$_3foo         (destructor for class foo)
1444                 _vt$foo         (foo virtual table)
1445                 _vt$foo$bar     (foo::bar virtual table)
1446                 __vt_foo        (foo virtual table, new style with thunks)
1447                 _3foo$varname   (static data member)
1448                 _Q22rs2tu$vw    (static data member)
1449                 __t6vector1Zii  (constructor with template)
1450                 __thunk_4__$_7ostream (virtual function thunk)
1451  */
1452
1453 static int
1454 gnu_special (work, mangled, declp)
1455      struct work_stuff *work;
1456      const char **mangled;
1457      string *declp;
1458 {
1459   int n;
1460   int success = 1;
1461   const char *p;
1462
1463   if ((*mangled)[0] == '_'
1464       && strchr (cplus_markers, (*mangled)[1]) != NULL
1465       && (*mangled)[2] == '_')
1466     {
1467       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1468       (*mangled) += 3;
1469       work -> destructor += 1;
1470     }
1471   else if ((*mangled)[0] == '_'
1472            && (((*mangled)[1] == '_'
1473                 && (*mangled)[2] == 'v'
1474                 && (*mangled)[3] == 't'
1475                 && (*mangled)[4] == '_')
1476              || ((*mangled)[1] == 'v'
1477                  && (*mangled)[2] == 't'
1478                  && strchr (cplus_markers, (*mangled)[3]) != NULL)))
1479     {
1480       /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1481          and create the decl.  Note that we consume the entire mangled
1482          input string, which means that demangle_signature has no work
1483          to do. */
1484       if ((*mangled)[2] == 'v')
1485         (*mangled) += 5; /* New style, with thunks: "__vt_" */
1486       else
1487         (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1488       while (**mangled != '\0')
1489         {
1490           p = strpbrk (*mangled, cplus_markers);
1491           switch (**mangled)
1492             {
1493             case 'Q':
1494               success = demangle_qualified (work, mangled, declp, 0, 1);
1495               break;
1496             case 't':
1497               success = demangle_template (work, mangled, declp, 0);
1498               break;
1499             default:
1500               if (isdigit(*mangled[0]))
1501                 {
1502                   n = consume_count(mangled);
1503                 }
1504               else
1505                 {
1506                   n = strcspn (*mangled, cplus_markers);
1507                 }
1508               string_appendn (declp, *mangled, n);
1509               (*mangled) += n;
1510             }
1511
1512           if (success && ((p == NULL) || (p == *mangled)))
1513             {
1514               if (p != NULL)
1515                 {
1516                   string_append (declp, "::");
1517                   (*mangled)++;
1518                 }
1519             }
1520           else
1521             {
1522               success = 0;
1523               break;
1524             }
1525         }
1526       if (success)
1527         string_append (declp, " virtual table");
1528     }
1529   else if ((*mangled)[0] == '_'
1530            && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
1531            && (p = strpbrk (*mangled, cplus_markers)) != NULL)
1532     {
1533       /* static data member, "_3foo$varname" for example */
1534       (*mangled)++;
1535       switch (**mangled)
1536         {
1537           case 'Q':
1538             success = demangle_qualified (work, mangled, declp, 0, 1);
1539             break;
1540           case 't':
1541             success = demangle_template (work, mangled, declp, 0);
1542             break;
1543           default:
1544             n = consume_count (mangled);
1545             string_appendn (declp, *mangled, n);
1546             (*mangled) += n;
1547         }
1548       if (success && (p == *mangled))
1549         {
1550           /* Consumed everything up to the cplus_marker, append the
1551              variable name. */
1552           (*mangled)++;
1553           string_append (declp, "::");
1554           n = strlen (*mangled);
1555           string_appendn (declp, *mangled, n);
1556           (*mangled) += n;
1557         }
1558       else
1559         {
1560           success = 0;
1561         }
1562     }
1563   else if (strncmp (*mangled, "__thunk_", 8) == 0)
1564     {
1565       int delta = ((*mangled) += 8, consume_count (mangled));
1566       char *method = cplus_demangle (++*mangled, work->options);
1567       if (method)
1568         {
1569           char buf[50];
1570           sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
1571           string_append (declp, buf);
1572           string_append (declp, method);
1573           free (method);
1574           n = strlen (*mangled);
1575           (*mangled) += n;
1576         }
1577       else
1578         {
1579           success = 0;
1580         }
1581     }
1582   else
1583     {
1584       success = 0;
1585     }
1586   return (success);
1587 }
1588
1589 /*
1590
1591 LOCAL FUNCTION
1592
1593         arm_special -- special handling of ARM/lucid mangled strings
1594
1595 SYNOPSIS
1596
1597         static int
1598         arm_special (struct work_stuff *work, const char **mangled,
1599                         string *declp);
1600
1601
1602 DESCRIPTION
1603
1604         Process some special ARM style mangling forms that don't fit
1605         the normal pattern.  For example:
1606
1607                 __vtbl__3foo            (foo virtual table)
1608                 __vtbl__3foo__3bar      (bar::foo virtual table)
1609
1610  */
1611
1612 static int
1613 arm_special (work, mangled, declp)
1614      struct work_stuff *work;
1615      const char **mangled;
1616      string *declp;
1617 {
1618   int n;
1619   int success = 1;
1620   const char *scan;
1621
1622   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
1623     {
1624       /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
1625          and create the decl.  Note that we consume the entire mangled
1626          input string, which means that demangle_signature has no work
1627          to do. */
1628       scan = *mangled + ARM_VTABLE_STRLEN;
1629       while (*scan != '\0')        /* first check it can be demangled */
1630         {
1631           n = consume_count (&scan);
1632           if (n==0)
1633             {
1634               return (0);           /* no good */
1635             }
1636           scan += n;
1637           if (scan[0] == '_' && scan[1] == '_')
1638             {
1639               scan += 2;
1640             }
1641         }
1642       (*mangled) += ARM_VTABLE_STRLEN;
1643       while (**mangled != '\0')
1644         {
1645           n = consume_count (mangled);
1646           string_prependn (declp, *mangled, n);
1647           (*mangled) += n;
1648           if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
1649             {
1650               string_prepend (declp, "::");
1651               (*mangled) += 2;
1652             }
1653         }
1654       string_append (declp, " virtual table");
1655     }
1656   else
1657     {
1658       success = 0;
1659     }
1660   return (success);
1661 }
1662
1663 /*
1664
1665 LOCAL FUNCTION
1666
1667         demangle_qualified -- demangle 'Q' qualified name strings
1668
1669 SYNOPSIS
1670
1671         static int
1672         demangle_qualified (struct work_stuff *, const char *mangled,
1673                             string *result, int isfuncname, int append);
1674
1675 DESCRIPTION
1676
1677         Demangle a qualified name, such as "Q25Outer5Inner" which is
1678         the mangled form of "Outer::Inner".  The demangled output is
1679         prepended or appended to the result string according to the
1680         state of the append flag.
1681
1682         If isfuncname is nonzero, then the qualified name we are building
1683         is going to be used as a member function name, so if it is a
1684         constructor or destructor function, append an appropriate
1685         constructor or destructor name.  I.E. for the above example,
1686         the result for use as a constructor is "Outer::Inner::Inner"
1687         and the result for use as a destructor is "Outer::Inner::~Inner".
1688
1689 BUGS
1690
1691         Numeric conversion is ASCII dependent (FIXME).
1692
1693  */
1694
1695 static int
1696 demangle_qualified (work, mangled, result, isfuncname, append)
1697      struct work_stuff *work;
1698      const char **mangled;
1699      string *result;
1700      int isfuncname;
1701      int append;
1702 {
1703   int qualifiers;
1704   int namelength;
1705   int success = 1;
1706   const char *p;
1707   char num[2];
1708   string temp;
1709
1710   string_init (&temp);
1711   switch ((*mangled)[1])
1712     {
1713     case '_':
1714       /* GNU mangled name with more than 9 classes.  The count is preceded
1715          by an underscore (to distinguish it from the <= 9 case) and followed
1716          by an underscore.  */
1717       p = *mangled + 2;
1718       qualifiers = atoi (p);
1719       if (!isdigit (*p) || *p == '0')
1720         success = 0;
1721
1722       /* Skip the digits.  */
1723       while (isdigit (*p))
1724         ++p;
1725
1726       if (*p != '_')
1727         success = 0;
1728
1729       *mangled = p + 1;
1730       break;
1731
1732     case '1':
1733     case '2':
1734     case '3':
1735     case '4':
1736     case '5':
1737     case '6':
1738     case '7':
1739     case '8':
1740     case '9':
1741       /* The count is in a single digit.  */
1742       num[0] = (*mangled)[1];
1743       num[1] = '\0';
1744       qualifiers = atoi (num);
1745
1746       /* If there is an underscore after the digit, skip it.  This is
1747          said to be for ARM-qualified names, but the ARM makes no
1748          mention of such an underscore.  Perhaps cfront uses one.  */
1749       if ((*mangled)[2] == '_')
1750         {
1751           (*mangled)++;
1752         }
1753       (*mangled) += 2;
1754       break;
1755
1756     case '0':
1757     default:
1758       success = 0;
1759     }
1760
1761   if (!success)
1762     return success;
1763
1764   /* Pick off the names and collect them in the temp buffer in the order
1765      in which they are found, separated by '::'. */
1766
1767   while (qualifiers-- > 0)
1768     {
1769       if (*mangled[0] == '_') 
1770         *mangled = *mangled + 1;
1771       if (*mangled[0] == 't')
1772         {
1773           success = demangle_template(work, mangled, &temp, 0);
1774           if (!success) break;
1775         }
1776       else
1777         {       
1778           namelength = consume_count (mangled);
1779           if (strlen (*mangled) < namelength)
1780             {
1781             /* Simple sanity check failed */
1782                success = 0;
1783                break;
1784             }
1785           string_appendn (&temp, *mangled, namelength);
1786           *mangled += namelength;
1787         }
1788       if (qualifiers > 0)
1789         {
1790           string_appendn (&temp, "::", 2);
1791         }
1792     }
1793
1794   /* If we are using the result as a function name, we need to append
1795      the appropriate '::' separated constructor or destructor name.
1796      We do this here because this is the most convenient place, where
1797      we already have a pointer to the name and the length of the name. */
1798
1799   if (isfuncname && (work->constructor & 1 || work->destructor & 1))
1800     {
1801       string_appendn (&temp, "::", 2);
1802       if (work -> destructor & 1)
1803         {
1804           string_append (&temp, "~");
1805         }
1806       string_appendn (&temp, (*mangled) - namelength, namelength);
1807     }
1808
1809   /* Now either prepend the temp buffer to the result, or append it, 
1810      depending upon the state of the append flag. */
1811
1812   if (append)
1813     {
1814       string_appends (result, &temp);
1815     }
1816   else
1817     {
1818       if (!STRING_EMPTY (result))
1819         {
1820           string_appendn (&temp, "::", 2);
1821         }
1822       string_prepends (result, &temp);
1823     }
1824
1825   string_delete (&temp);
1826   return (success);
1827 }
1828
1829 /*
1830
1831 LOCAL FUNCTION
1832
1833         get_count -- convert an ascii count to integer, consuming tokens
1834
1835 SYNOPSIS
1836
1837         static int
1838         get_count (const char **type, int *count)
1839
1840 DESCRIPTION
1841
1842         Return 0 if no conversion is performed, 1 if a string is converted.
1843 */
1844
1845 static int
1846 get_count (type, count)
1847      const char **type;
1848      int *count;
1849 {
1850   const char *p;
1851   int n;
1852
1853   if (!isdigit (**type))
1854     {
1855       return (0);
1856     }
1857   else
1858     {
1859       *count = **type - '0';
1860       (*type)++;
1861       if (isdigit (**type))
1862         {
1863           p = *type;
1864           n = *count;
1865           do 
1866             {
1867               n *= 10;
1868               n += *p - '0';
1869               p++;
1870             } 
1871           while (isdigit (*p));
1872           if (*p == '_')
1873             {
1874               *type = p + 1;
1875               *count = n;
1876             }
1877         }
1878     }
1879   return (1);
1880 }
1881
1882 /* result will be initialised here; it will be freed on failure */
1883
1884 static int
1885 do_type (work, mangled, result)
1886      struct work_stuff *work;
1887      const char **mangled;
1888      string *result;
1889 {
1890   int n;
1891   int done;
1892   int success;
1893   string decl;
1894   const char *remembered_type;
1895   int constp;
1896   int volatilep;
1897
1898   string_init (&decl);
1899   string_init (result);
1900
1901   done = 0;
1902   success = 1;
1903   while (success && !done)
1904     {
1905       int member;
1906       switch (**mangled)
1907         {
1908
1909         /* A pointer type */
1910         case 'P':
1911         case 'p':
1912           (*mangled)++;
1913           string_prepend (&decl, "*");
1914           break;
1915
1916         /* A reference type */
1917         case 'R':
1918           (*mangled)++;
1919           string_prepend (&decl, "&");
1920           break;
1921
1922         /* An array */
1923         case 'A':
1924           {
1925             const char *p = ++(*mangled);
1926
1927             string_prepend (&decl, "(");
1928             string_append (&decl, ")[");
1929             /* Copy anything up until the next underscore (the size of the
1930                array).  */
1931             while (**mangled && **mangled != '_')
1932               ++(*mangled);
1933             if (**mangled == '_')
1934               {
1935                 string_appendn (&decl, p, *mangled - p);
1936                 string_append (&decl, "]");             
1937                 *mangled += 1;
1938               }
1939             else
1940               success = 0;
1941             break;
1942           }
1943
1944         /* A back reference to a previously seen type */
1945         case 'T':
1946           (*mangled)++;
1947           if (!get_count (mangled, &n) || n >= work -> ntypes)
1948             {
1949               success = 0;
1950             }
1951           else
1952             {
1953               remembered_type = work -> typevec[n];
1954               mangled = &remembered_type;
1955             }
1956           break;
1957
1958         /* A function */
1959         case 'F':
1960           (*mangled)++;
1961           if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
1962             {
1963               string_prepend (&decl, "(");
1964               string_append (&decl, ")");
1965             }
1966           /* After picking off the function args, we expect to either find the
1967              function return type (preceded by an '_') or the end of the
1968              string. */
1969           if (!demangle_args (work, mangled, &decl)
1970               || (**mangled != '_' && **mangled != '\0'))
1971             {
1972               success = 0;
1973             }
1974           if (success && (**mangled == '_'))
1975             {
1976               (*mangled)++;
1977             }
1978           break;
1979
1980         case 'M':
1981         case 'O':
1982           {
1983             constp = 0;
1984             volatilep = 0;
1985
1986             member = **mangled == 'M';
1987             (*mangled)++;
1988             if (!isdigit (**mangled))
1989               {
1990                 success = 0;
1991                 break;
1992               }
1993             n = consume_count (mangled);
1994             if (strlen (*mangled) < n)
1995               {
1996                 success = 0;
1997                 break;
1998               }
1999             string_append (&decl, ")");
2000             string_prepend (&decl, "::");
2001             string_prependn (&decl, *mangled, n);
2002             string_prepend (&decl, "(");
2003             *mangled += n;
2004             if (member)
2005               {
2006                 if (**mangled == 'C')
2007                   {
2008                     (*mangled)++;
2009                     constp = 1;
2010                   }
2011                 if (**mangled == 'V')
2012                   {
2013                     (*mangled)++;
2014                     volatilep = 1;
2015                   }
2016                 if (*(*mangled)++ != 'F')
2017                   {
2018                     success = 0;
2019                     break;
2020                   }
2021               }
2022             if ((member && !demangle_args (work, mangled, &decl))
2023                 || **mangled != '_')
2024               {
2025                 success = 0;
2026                 break;
2027               }
2028             (*mangled)++;
2029             if (! PRINT_ANSI_QUALIFIERS)
2030               {
2031                 break;
2032               }
2033             if (constp)
2034               {
2035                 APPEND_BLANK (&decl);
2036                 string_append (&decl, "const");
2037               }
2038             if (volatilep)
2039               {
2040                 APPEND_BLANK (&decl);
2041                 string_append (&decl, "volatile");
2042               }
2043             break;
2044           }
2045         case 'G':
2046             (*mangled)++;
2047             break;
2048
2049         case 'C':
2050           (*mangled)++;
2051 /*
2052           if ((*mangled)[1] == 'P')
2053             {
2054 */
2055               if (PRINT_ANSI_QUALIFIERS)
2056                 {
2057                   if (!STRING_EMPTY (&decl))
2058                     {
2059                       string_prepend (&decl, " ");
2060                     }
2061                   string_prepend (&decl, "const");
2062                 }
2063               break;
2064 /*
2065             }
2066 */
2067
2068           /* fall through */
2069         default:
2070           done = 1;
2071           break;
2072         }
2073     }
2074
2075   switch (**mangled)
2076     {
2077       /* A qualified name, such as "Outer::Inner". */
2078       case 'Q':
2079         success = demangle_qualified (work, mangled, result, 0, 1);
2080         break;
2081
2082       default:
2083         success = demangle_fund_type (work, mangled, result);
2084         break;
2085     }
2086
2087   if (success)
2088     {
2089       if (!STRING_EMPTY (&decl))
2090         {
2091           string_append (result, " ");
2092           string_appends (result, &decl);
2093         }
2094     }
2095   else
2096     {
2097       string_delete (result);
2098     }
2099   string_delete (&decl);
2100   return (success);
2101 }
2102
2103 /* Given a pointer to a type string that represents a fundamental type
2104    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2105    string in which the demangled output is being built in RESULT, and
2106    the WORK structure, decode the types and add them to the result.
2107
2108    For example:
2109
2110         "Ci"    =>      "const int"
2111         "Sl"    =>      "signed long"
2112         "CUs"   =>      "const unsigned short"
2113
2114    */
2115
2116 static int
2117 demangle_fund_type (work, mangled, result)
2118      struct work_stuff *work;
2119      const char **mangled;
2120      string *result;
2121 {
2122   int done = 0;
2123   int success = 1;
2124
2125   /* First pick off any type qualifiers.  There can be more than one. */
2126
2127   while (!done)
2128     {
2129       switch (**mangled)
2130         {
2131           case 'C':
2132             (*mangled)++;
2133             if (PRINT_ANSI_QUALIFIERS)
2134               {
2135                 APPEND_BLANK (result);
2136                 string_append (result, "const");
2137               }
2138             break;
2139           case 'U':
2140             (*mangled)++;
2141             APPEND_BLANK (result);
2142             string_append (result, "unsigned");
2143             break;
2144           case 'S': /* signed char only */
2145             (*mangled)++;
2146             APPEND_BLANK (result);
2147             string_append (result, "signed");
2148             break;
2149           case 'V':
2150             (*mangled)++;
2151             if (PRINT_ANSI_QUALIFIERS)
2152               {
2153                 APPEND_BLANK (result);
2154                 string_append (result, "volatile");
2155               }
2156             break;
2157           default:
2158             done = 1;
2159             break;
2160         }
2161     }
2162
2163   /* Now pick off the fundamental type.  There can be only one. */
2164
2165   switch (**mangled)
2166     {
2167       case '\0':
2168       case '_':
2169         break;
2170       case 'v':
2171         (*mangled)++;
2172         APPEND_BLANK (result);
2173         string_append (result, "void");
2174         break;
2175       case 'x':
2176         (*mangled)++;
2177         APPEND_BLANK (result);
2178         string_append (result, "long long");
2179         break;
2180       case 'l':
2181         (*mangled)++;
2182         APPEND_BLANK (result);
2183         string_append (result, "long");
2184         break;
2185       case 'i':
2186         (*mangled)++;
2187         APPEND_BLANK (result);
2188         string_append (result, "int");
2189         break;
2190       case 's':
2191         (*mangled)++;
2192         APPEND_BLANK (result);
2193         string_append (result, "short");
2194         break;
2195       case 'b':
2196         (*mangled)++;
2197         APPEND_BLANK (result);
2198         string_append (result, "bool");
2199         break;
2200       case 'c':
2201         (*mangled)++;
2202         APPEND_BLANK (result);
2203         string_append (result, "char");
2204         break;
2205       case 'w':
2206         (*mangled)++;
2207         APPEND_BLANK (result);
2208         string_append (result, "wchar_t");
2209         break;
2210       case 'r':
2211         (*mangled)++;
2212         APPEND_BLANK (result);
2213         string_append (result, "long double");
2214         break;
2215       case 'd':
2216         (*mangled)++;
2217         APPEND_BLANK (result);
2218         string_append (result, "double");
2219         break;
2220       case 'f':
2221         (*mangled)++;
2222         APPEND_BLANK (result);
2223         string_append (result, "float");
2224         break;
2225       case 'G':
2226         (*mangled)++;
2227         if (!isdigit (**mangled))
2228           {
2229             success = 0;
2230             break;
2231           }
2232         /* fall through */
2233       /* An explicit type, such as "6mytype" or "7integer" */
2234       case '0':
2235       case '1':
2236       case '2':
2237       case '3':
2238       case '4':
2239       case '5':
2240       case '6':
2241       case '7':
2242       case '8':
2243       case '9':
2244         APPEND_BLANK (result);
2245         if (!demangle_class_name (work, mangled, result)) {
2246           --result->p;
2247           success = 0;
2248         }
2249         break;
2250       case 't':
2251         success = demangle_template(work,mangled, result, 0);
2252         break;
2253       default:
2254         success = 0;
2255         break;
2256       }
2257
2258   return (success);
2259 }
2260
2261 /* `result' will be initialized in do_type; it will be freed on failure */
2262
2263 static int
2264 do_arg (work, mangled, result)
2265      struct work_stuff *work;
2266      const char **mangled;
2267      string *result;
2268 {
2269   const char *start = *mangled;
2270
2271   if (!do_type (work, mangled, result))
2272     {
2273       return (0);
2274     }
2275   else
2276     {
2277       remember_type (work, start, *mangled - start);
2278       return (1);
2279     }
2280 }
2281
2282 static void
2283 remember_type (work, start, len)
2284      struct work_stuff *work;
2285      const char *start;
2286      int len;
2287 {
2288   char *tem;
2289
2290   if (work -> ntypes >= work -> typevec_size)
2291     {
2292       if (work -> typevec_size == 0)
2293         {
2294           work -> typevec_size = 3;
2295           work -> typevec =
2296             (char **) xmalloc (sizeof (char *) * work -> typevec_size);
2297         }
2298       else
2299         {
2300           work -> typevec_size *= 2;
2301           work -> typevec =
2302             (char **) xrealloc ((char *)work -> typevec,
2303                                 sizeof (char *) * work -> typevec_size);
2304         }
2305     }
2306   tem = xmalloc (len + 1);
2307   memcpy (tem, start, len);
2308   tem[len] = '\0';
2309   work -> typevec[work -> ntypes++] = tem;
2310 }
2311
2312 /* Forget the remembered types, but not the type vector itself. */
2313
2314 static void
2315 forget_types (work)
2316      struct work_stuff *work;
2317 {
2318   int i;
2319
2320   while (work -> ntypes > 0)
2321     {
2322       i = --(work -> ntypes);
2323       if (work -> typevec[i] != NULL)
2324         {
2325           free (work -> typevec[i]);
2326           work -> typevec[i] = NULL;
2327         }
2328     }
2329 }
2330
2331 /* Process the argument list part of the signature, after any class spec
2332    has been consumed, as well as the first 'F' character (if any).  For
2333    example:
2334
2335    "__als__3fooRT0"             =>      process "RT0"
2336    "complexfunc5__FPFPc_PFl_i"  =>      process "PFPc_PFl_i"
2337
2338    DECLP must be already initialised, usually non-empty.  It won't be freed
2339    on failure.
2340
2341    Note that g++ differs significantly from ARM and lucid style mangling
2342    with regards to references to previously seen types.  For example, given
2343    the source fragment:
2344
2345      class foo {
2346        public:
2347        foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
2348      };
2349
2350      foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2351      void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2352
2353    g++ produces the names:
2354
2355      __3fooiRT0iT2iT2
2356      foo__FiR3fooiT1iT1
2357
2358    while lcc (and presumably other ARM style compilers as well) produces:
2359
2360      foo__FiR3fooT1T2T1T2
2361      __ct__3fooFiR3fooT1T2T1T2
2362
2363    Note that g++ bases it's type numbers starting at zero and counts all
2364    previously seen types, while lucid/ARM bases it's type numbers starting
2365    at one and only considers types after it has seen the 'F' character
2366    indicating the start of the function args.  For lucid/ARM style, we
2367    account for this difference by discarding any previously seen types when
2368    we see the 'F' character, and subtracting one from the type number
2369    reference.
2370
2371  */
2372
2373 static int
2374 demangle_args (work, mangled, declp)
2375      struct work_stuff *work;
2376      const char **mangled;
2377      string *declp;
2378 {
2379   string arg;
2380   int need_comma = 0;
2381   int r;
2382   int t;
2383   const char *tem;
2384   char temptype;
2385
2386   if (PRINT_ARG_TYPES)
2387     {
2388       string_append (declp, "(");
2389       if (**mangled == '\0')
2390         {
2391           string_append (declp, "void");
2392         }
2393     }
2394
2395   while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
2396     {
2397       if ((**mangled == 'N') || (**mangled == 'T'))
2398         {
2399           temptype = *(*mangled)++;
2400           
2401           if (temptype == 'N')
2402             {
2403               if (!get_count (mangled, &r))
2404                 {
2405                   return (0);
2406                 }
2407             }
2408           else
2409             {
2410               r = 1;
2411             }
2412           if (ARM_DEMANGLING && work -> ntypes >= 10)
2413             {
2414               /* If we have 10 or more types we might have more than a 1 digit
2415                  index so we'll have to consume the whole count here. This
2416                  will lose if the next thing is a type name preceded by a
2417                  count but it's impossible to demangle that case properly
2418                  anyway. Eg if we already have 12 types is T12Pc "(..., type1,
2419                  Pc, ...)"  or "(..., type12, char *, ...)" */
2420               if ((t = consume_count(mangled)) == 0)
2421                 {
2422                   return (0);
2423                 }
2424             }
2425           else
2426             {
2427               if (!get_count (mangled, &t))
2428                 {
2429                   return (0);
2430                 }
2431             }
2432           if (LUCID_DEMANGLING || ARM_DEMANGLING)
2433             {
2434               t--;
2435             }
2436           /* Validate the type index.  Protect against illegal indices from
2437              malformed type strings. */
2438           if ((t < 0) || (t >= work -> ntypes))
2439             {
2440               return (0);
2441             }
2442           while (--r >= 0)
2443             {
2444               tem = work -> typevec[t];
2445               if (need_comma && PRINT_ARG_TYPES)
2446                 {
2447                   string_append (declp, ", ");
2448                 }
2449               if (!do_arg (work, &tem, &arg))
2450                 {
2451                   return (0);
2452                 }
2453               if (PRINT_ARG_TYPES)
2454                 {
2455                   string_appends (declp, &arg);
2456                 }
2457               string_delete (&arg);
2458               need_comma = 1;
2459             }
2460         }
2461       else
2462         {
2463           if (need_comma & PRINT_ARG_TYPES)
2464             {
2465               string_append (declp, ", ");
2466             }
2467           if (!do_arg (work, mangled, &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
2480   if (**mangled == 'e')
2481     {
2482       (*mangled)++;
2483       if (PRINT_ARG_TYPES)
2484         {
2485           if (need_comma)
2486             {
2487               string_append (declp, ",");
2488             }
2489           string_append (declp, "...");
2490         }
2491     }
2492
2493   if (PRINT_ARG_TYPES)
2494     {
2495       string_append (declp, ")");
2496     }
2497   return (1);
2498 }
2499
2500 static void
2501 demangle_function_name (work, mangled, declp, scan)
2502      struct work_stuff *work;
2503      const char **mangled;
2504      string *declp;
2505      const char *scan;
2506 {
2507   int i;
2508   int len;
2509   string type;
2510   const char *tem;
2511
2512   string_appendn (declp, (*mangled), scan - (*mangled));
2513   string_need (declp, 1);
2514   *(declp -> p) = '\0';
2515
2516   /* Consume the function name, including the "__" separating the name
2517      from the signature.  We are guaranteed that SCAN points to the
2518      separator. */
2519
2520   (*mangled) = scan + 2;
2521
2522   if (LUCID_DEMANGLING || ARM_DEMANGLING)
2523     {
2524
2525       /* See if we have an ARM style constructor or destructor operator.
2526          If so, then just record it, clear the decl, and return.
2527          We can't build the actual constructor/destructor decl until later,
2528          when we recover the class name from the signature. */
2529
2530       if (strcmp (declp -> b, "__ct") == 0)
2531         {
2532           work -> constructor += 1;
2533           string_clear (declp);
2534           return;
2535         }
2536       else if (strcmp (declp -> b, "__dt") == 0)
2537         {
2538           work -> destructor += 1;
2539           string_clear (declp);
2540           return;
2541         }
2542     }
2543
2544   if (declp->p - declp->b >= 3 
2545       && declp->b[0] == 'o'
2546       && declp->b[1] == 'p'
2547       && strchr (cplus_markers, declp->b[2]) != NULL)
2548     {
2549       /* see if it's an assignment expression */
2550       if (declp->p - declp->b >= 10 /* op$assign_ */
2551           && memcmp (declp->b + 3, "assign_", 7) == 0)
2552         {
2553           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2554             {
2555               len = declp->p - declp->b - 10;
2556               if (strlen (optable[i].in) == len
2557                   && memcmp (optable[i].in, declp->b + 10, len) == 0)
2558                 {
2559                   string_clear (declp);
2560                   string_append (declp, "operator");
2561                   string_append (declp, optable[i].out);
2562                   string_append (declp, "=");
2563                   break;
2564                 }
2565             }
2566         }
2567       else
2568         {
2569           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2570             {
2571               int len = declp->p - declp->b - 3;
2572               if (strlen (optable[i].in) == len 
2573                   && memcmp (optable[i].in, declp->b + 3, len) == 0)
2574                 {
2575                   string_clear (declp);
2576                   string_append (declp, "operator");
2577                   string_append (declp, optable[i].out);
2578                   break;
2579                 }
2580             }
2581         }
2582     }
2583   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
2584            && strchr (cplus_markers, declp->b[4]) != NULL)
2585     {
2586       /* type conversion operator */
2587       tem = declp->b + 5;
2588       if (do_type (work, &tem, &type))
2589         {
2590           string_clear (declp);
2591           string_append (declp, "operator ");
2592           string_appends (declp, &type);
2593           string_delete (&type);
2594         }
2595     }
2596   else if (declp->b[0] == '_' && declp->b[1] == '_'
2597           && declp->b[2] == 'o' && declp->b[3] == 'p')
2598     {
2599       /* ANSI.  */
2600       /* type conversion operator.  */
2601       tem = declp->b + 4;
2602       if (do_type (work, &tem, &type))
2603         {
2604           string_clear (declp);
2605           string_append (declp, "operator ");
2606           string_appends (declp, &type);
2607           string_delete (&type);
2608         }
2609     }
2610   else if (declp->b[0] == '_' && declp->b[1] == '_'
2611            && declp->b[2] >= 'a' && declp->b[2] <= 'z'
2612            && declp->b[3] >= 'a' && declp->b[3] <= 'z')
2613     {
2614       if (declp->b[4] == '\0')
2615         {
2616           /* Operator.  */
2617           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2618             {
2619               if (strlen (optable[i].in) == 2
2620                   && memcmp (optable[i].in, declp->b + 2, 2) == 0)
2621                 {
2622                   string_clear (declp);
2623                   string_append (declp, "operator");
2624                   string_append (declp, optable[i].out);
2625                   break;
2626                 }
2627             }
2628         }
2629       else
2630         {
2631           if (declp->b[2] == 'a' && declp->b[5] == '\0')
2632             {
2633               /* Assignment. */
2634               for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2635                 {
2636                   if (strlen (optable[i].in) == 3
2637                       && memcmp (optable[i].in, declp->b + 2, 3) == 0)
2638                     {
2639                       string_clear (declp);
2640                       string_append (declp, "operator");
2641                       string_append (declp, optable[i].out);
2642                       break;
2643                     }                 
2644                 }
2645             }
2646         }
2647     }
2648 }
2649
2650 /* a mini string-handling package */
2651
2652 static void
2653 string_need (s, n)
2654      string *s;
2655      int n;
2656 {
2657   int tem;
2658
2659   if (s->b == NULL)
2660     {
2661       if (n < 32)
2662         {
2663           n = 32;
2664         }
2665       s->p = s->b = xmalloc (n);
2666       s->e = s->b + n;
2667     }
2668   else if (s->e - s->p < n)
2669     {
2670       tem = s->p - s->b;
2671       n += tem;
2672       n *= 2;
2673       s->b = xrealloc (s->b, n);
2674       s->p = s->b + tem;
2675       s->e = s->b + n;
2676     }
2677 }
2678
2679 static void
2680 string_delete (s)
2681      string *s;
2682 {
2683   if (s->b != NULL)
2684     {
2685       free (s->b);
2686       s->b = s->e = s->p = NULL;
2687     }
2688 }
2689
2690 static void
2691 string_init (s)
2692      string *s;
2693 {
2694   s->b = s->p = s->e = NULL;
2695 }
2696
2697 static void 
2698 string_clear (s)
2699      string *s;
2700 {
2701   s->p = s->b;
2702 }
2703
2704 #if 0
2705
2706 static int
2707 string_empty (s)
2708      string *s;
2709 {
2710   return (s->b == s->p);
2711 }
2712
2713 #endif
2714
2715 static void
2716 string_append (p, s)
2717      string *p;
2718      const char *s;
2719 {
2720   int n;
2721   if (s == NULL || *s == '\0')
2722     return;
2723   n = strlen (s);
2724   string_need (p, n);
2725   memcpy (p->p, s, n);
2726   p->p += n;
2727 }
2728
2729 static void
2730 string_appends (p, s)
2731      string *p, *s;
2732 {
2733   int n;
2734
2735   if (s->b != s->p)
2736     {
2737       n = s->p - s->b;
2738       string_need (p, n);
2739       memcpy (p->p, s->b, n);
2740       p->p += n;
2741     }
2742 }
2743
2744 static void
2745 string_appendn (p, s, n)
2746      string *p;
2747      const char *s;
2748      int n;
2749 {
2750   if (n != 0)
2751     {
2752       string_need (p, n);
2753       memcpy (p->p, s, n);
2754       p->p += n;
2755     }
2756 }
2757
2758 static void
2759 string_prepend (p, s)
2760      string *p;
2761      const char *s;
2762 {
2763   if (s != NULL && *s != '\0')
2764     {
2765       string_prependn (p, s, strlen (s));
2766     }
2767 }
2768
2769 static void
2770 string_prepends (p, s)
2771      string *p, *s;
2772 {
2773   if (s->b != s->p)
2774     {
2775       string_prependn (p, s->b, s->p - s->b);
2776     }
2777 }
2778
2779 static void
2780 string_prependn (p, s, n)
2781      string *p;
2782      const char *s;
2783      int n;
2784 {
2785   char *q;
2786
2787   if (n != 0)
2788     {
2789       string_need (p, n);
2790       for (q = p->p - 1; q >= p->b; q--)
2791         {
2792           q[n] = q[0];
2793         }
2794       memcpy (p->b, s, n);
2795       p->p += n;
2796     }
2797 }
2798
2799 /* To generate a standalone demangler program for testing purposes,
2800    just compile and link this file with -DMAIN and libiberty.a.  When
2801    run, it demangles each command line arg, or each stdin string, and
2802    prints the result on stdout. */
2803
2804 #ifdef MAIN
2805
2806 static void
2807 demangle_it (mangled_name)
2808   char *mangled_name;
2809 {
2810   char *result;
2811
2812   result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI);
2813   if (result == NULL)
2814     {
2815       printf ("%s\n", mangled_name);
2816     }
2817   else
2818     {
2819       printf ("%s\n", result);
2820       free (result);
2821     }
2822 }
2823
2824 #include "getopt.h"
2825
2826 static char *program_name;
2827 static char *program_version = VERSION;
2828
2829 static void
2830 usage (stream, status)
2831      FILE *stream;
2832      int status;
2833 {    
2834   fprintf (stream, "\
2835 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
2836        [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
2837        [--help] [--version] [arg...]\n",
2838            program_name);
2839   exit (status);
2840 }
2841
2842 #define MBUF_SIZE 512
2843 char mbuffer[MBUF_SIZE];
2844
2845 /* Defined in the automatically-generated underscore.c. */
2846 extern int prepends_underscore;
2847
2848 int strip_underscore = 0;
2849
2850 static struct option long_options[] = {
2851   {"strip-underscores", no_argument, 0, '_'},
2852   {"format", required_argument, 0, 's'},
2853   {"help", no_argument, 0, 'h'},
2854   {"no-strip-underscores", no_argument, 0, 'n'},
2855   {"version", no_argument, 0, 'v'},
2856   {0, no_argument, 0, 0}
2857 };
2858
2859 int
2860 main (argc, argv)
2861      int argc;
2862      char **argv;
2863 {
2864   char *result;
2865   int c;
2866
2867   program_name = argv[0];
2868
2869   strip_underscore = prepends_underscore;
2870
2871   while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF)
2872     {
2873       switch (c)
2874         {
2875           case '?':
2876             usage (stderr, 1);
2877             break;
2878           case 'h':
2879             usage (stdout, 0);
2880           case 'n':
2881             strip_underscore = 0;
2882             break;
2883           case 'v':
2884             printf ("GNU %s version %s\n", program_name, program_version);
2885             exit (0);
2886           case '_':
2887             strip_underscore = 1;
2888             break;
2889           case 's':
2890             if (strcmp (optarg, "gnu") == 0)
2891               {
2892                 current_demangling_style = gnu_demangling;
2893               }
2894             else if (strcmp (optarg, "lucid") == 0)
2895               {
2896                 current_demangling_style = lucid_demangling;
2897               }
2898             else if (strcmp (optarg, "arm") == 0)
2899               {
2900                 current_demangling_style = arm_demangling;
2901               }
2902             else
2903               {
2904                 fprintf (stderr, "%s: unknown demangling style `%s'\n",
2905                          program_name, optarg);
2906                 exit (1);
2907               }
2908             break;
2909         }
2910     }
2911
2912   if (optind < argc)
2913     {
2914       for ( ; optind < argc; optind++)
2915         {
2916           demangle_it (argv[optind]);
2917         }
2918     }
2919   else
2920     {
2921       for (;;)
2922         {
2923           int i = 0;
2924           c = getchar ();
2925           /* Try to read a label. */
2926           while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
2927             {
2928               if (i >= MBUF_SIZE-1)
2929                 break;
2930               mbuffer[i++] = c;
2931               c = getchar ();
2932             }
2933           if (i > 0)
2934             {
2935               int skip_first = 0;
2936
2937               if (mbuffer[0] == '.')
2938                 ++skip_first;
2939               if (strip_underscore && mbuffer[skip_first] == '_')
2940                 ++skip_first;
2941
2942               if (skip_first > i)
2943                 skip_first = i;
2944
2945               mbuffer[i] = 0;
2946               
2947               result = cplus_demangle (mbuffer + skip_first,
2948                                        DMGL_PARAMS | DMGL_ANSI);
2949               if (result)
2950                 {
2951                   if (mbuffer[0] == '.')
2952                     putc ('.', stdout);
2953                   fputs (result, stdout);
2954                   free (result);
2955                 }
2956               else
2957                 fputs (mbuffer, stdout);
2958
2959               fflush (stdout);
2960             }
2961           if (c == EOF)
2962             break;
2963           putchar (c);
2964         }
2965     }
2966
2967   exit (0);
2968 }
2969
2970 static void
2971 fatal (str)
2972      char *str;
2973 {
2974   fprintf (stderr, "%s: %s\n", program_name, str);
2975   exit (1);
2976 }
2977
2978 char * malloc ();
2979 char * realloc ();
2980
2981 char *
2982 xmalloc (size)
2983      unsigned size;
2984 {
2985   register char *value = (char *) malloc (size);
2986   if (value == 0)
2987     fatal ("virtual memory exhausted");
2988   return value;
2989 }
2990
2991 char *
2992 xrealloc (ptr, size)
2993      char *ptr;
2994      unsigned size;
2995 {
2996   register char *value = (char *) realloc (ptr, size);
2997   if (value == 0)
2998     fatal ("virtual memory exhausted");
2999   return value;
3000 }
3001 #endif  /* main */