OSDN Git Service

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