source: trunk/third/gcc/cplus-dem.c @ 11288

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