OSDN Git Service

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