OSDN Git Service

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