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

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