Demangle.c

Go to the documentation of this file.
00001 /* @(#)root/clib:$Id: Demangle.c 23679 2008-05-07 14:10:06Z rdm $ */
00002 /* Author: */
00003 
00004 /* Demangler for GNU C++
00005    Copyright 1989, 1991 Free Software Foundation, Inc.
00006    Written by James Clark (jjc@jclark.uucp)
00007    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
00008 
00009 This file is part of the libiberty library.
00010 Libiberty is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU Library General Public
00012 License as published by the Free Software Foundation; either
00013 version 2 of the License, or (at your option) any later version.
00014 
00015 Libiberty is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 Library General Public License for more details.
00019 
00020 You should have received a copy of the GNU Library General Public
00021 License along with libiberty; see the file COPYING.LIB.  If
00022 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
00023 Cambridge, MA 02139, USA.  */
00024 
00025 /* This file exports two functions; cplus_mangle_opname and cplus_demangle. */
00026 
00027 
00028 #include "Demangle.h"
00029 #undef CURRENT_DEMANGLING_STYLE
00030 #define CURRENT_DEMANGLING_STYLE work->options
00031 #include <ctype.h>
00032 #include <string.h>
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 
00036 /* In order to allow a single demangler executable to demangle strings
00037    using various common values of CPLUS_MARKER, as well as any specific
00038    one set at compile time, we maintain a string containing all the
00039    commonly used ones, and check to see if the marker we are looking for
00040    is in that string.  CPLUS_MARKER is usually '$' on systems where the
00041    assembler can deal with that.  Where the assembler can't, it's usually
00042    '.' (but on many systems '.' is used for other things).  We put the
00043    current defined CPLUS_MARKER first (which defaults to '$'), followed
00044    by the next most common value, followed by an explicit '$' in case
00045    the value of CPLUS_MARKER is not '$'.
00046 
00047    We could avoid this if we could just get g++ to tell us what the actual
00048    cplus marker character is as part of the debug information, perhaps by
00049    ensuring that it is the character that terminates the gcc<n>_compiled
00050    marker symbol (FIXME). */
00051 
00052 #if !defined (CPLUS_MARKER)
00053 #define CPLUS_MARKER '$'
00054 #endif
00055 
00056 enum demangling_styles current_demangling_style = gnu_demangling;
00057 
00058 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
00059 
00060 void
00061 set_cplus_marker_for_demangling (ch)
00062      int ch;
00063 {
00064     cplus_markers[0] = ch;
00065 }
00066 
00067 /* Stuff that is shared between sub-routines.
00068  * Using a shared structure allows cplus_demangle to be reentrant. */
00069 
00070 struct work_stuff
00071 {
00072   int options;
00073   char **typevec;
00074   int ntypes;
00075   int typevec_size;
00076   int constructor;
00077   int destructor;
00078   int static_type;      /* A static member function */
00079   int const_type;       /* A const member function */
00080 };
00081 
00082 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
00083 #define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
00084 
00085 static const struct optable
00086 {
00087   const char *in;
00088   const char *out;
00089   int flags;
00090 } optable[] = {
00091   {"nw",          " new",       DMGL_ANSI},     /* new (1.92,    ansi) */
00092   {"dl",          " delete",    DMGL_ANSI},     /* new (1.92,    ansi) */
00093   {"new",         " new",       0},             /* old (1.91,    and 1.x) */
00094   {"delete",      " delete",    0},             /* old (1.91,    and 1.x) */
00095   {"vn",          " new []",    DMGL_ANSI},     /* GNU, pending ansi */
00096   {"vd",          " delete []", DMGL_ANSI},     /* GNU, pending ansi */
00097   {"as",          "=",          DMGL_ANSI},     /* ansi */
00098   {"ne",          "!=",         DMGL_ANSI},     /* old, ansi */
00099   {"eq",          "==",         DMGL_ANSI},     /* old, ansi */
00100   {"ge",          ">=",         DMGL_ANSI},     /* old, ansi */
00101   {"gt",          ">",          DMGL_ANSI},     /* old, ansi */
00102   {"le",          "<=",         DMGL_ANSI},     /* old, ansi */
00103   {"lt",          "<",          DMGL_ANSI},     /* old, ansi */
00104   {"plus",        "+",          0},             /* old */
00105   {"pl",          "+",          DMGL_ANSI},     /* ansi */
00106   {"apl",         "+=",         DMGL_ANSI},     /* ansi */
00107   {"minus",       "-",          0},             /* old */
00108   {"mi",          "-",          DMGL_ANSI},     /* ansi */
00109   {"ami",         "-=",         DMGL_ANSI},     /* ansi */
00110   {"mult",        "*",          0},             /* old */
00111   {"ml",          "*",          DMGL_ANSI},     /* ansi */
00112   {"amu",         "*=",         DMGL_ANSI},     /* ansi (ARM/Lucid) */
00113   {"aml",         "*=",         DMGL_ANSI},     /* ansi (GNU/g++) */
00114   {"convert",     "+",          0},             /* old (unary +) */
00115   {"negate",      "-",          0},             /* old (unary -) */
00116   {"trunc_mod",   "%",          0},             /* old */
00117   {"md",          "%",          DMGL_ANSI},     /* ansi */
00118   {"amd",         "%=",         DMGL_ANSI},     /* ansi */
00119   {"trunc_div",   "/",          0},             /* old */
00120   {"dv",          "/",          DMGL_ANSI},     /* ansi */
00121   {"adv",         "/=",         DMGL_ANSI},     /* ansi */
00122   {"truth_andif", "&&",         0},             /* old */
00123   {"aa",          "&&",         DMGL_ANSI},     /* ansi */
00124   {"truth_orif",  "||",         0},             /* old */
00125   {"oo",          "||",         DMGL_ANSI},     /* ansi */
00126   {"truth_not",   "!",          0},             /* old */
00127   {"nt",          "!",          DMGL_ANSI},     /* ansi */
00128   {"postincrement","++",        0},             /* old */
00129   {"pp",          "++",         DMGL_ANSI},     /* ansi */
00130   {"postdecrement","--",        0},             /* old */
00131   {"mm",          "--",         DMGL_ANSI},     /* ansi */
00132   {"bit_ior",     "|",          0},             /* old */
00133   {"or",          "|",          DMGL_ANSI},     /* ansi */
00134   {"aor",         "|=",         DMGL_ANSI},     /* ansi */
00135   {"bit_xor",     "^",          0},             /* old */
00136   {"er",          "^",          DMGL_ANSI},     /* ansi */
00137   {"aer",         "^=",         DMGL_ANSI},     /* ansi */
00138   {"bit_and",     "&",          0},             /* old */
00139   {"ad",          "&",          DMGL_ANSI},     /* ansi */
00140   {"aad",         "&=",         DMGL_ANSI},     /* ansi */
00141   {"bit_not",     "~",          0},             /* old */
00142   {"co",          "~",          DMGL_ANSI},     /* ansi */
00143   {"call",        "()",         0},             /* old */
00144   {"cl",          "()",         DMGL_ANSI},     /* ansi */
00145   {"alshift",     "<<",         0},             /* old */
00146   {"ls",          "<<",         DMGL_ANSI},     /* ansi */
00147   {"als",         "<<=",        DMGL_ANSI},     /* ansi */
00148   {"arshift",     ">>",         0},             /* old */
00149   {"rs",          ">>",         DMGL_ANSI},     /* ansi */
00150   {"ars",         ">>=",        DMGL_ANSI},     /* ansi */
00151   {"component",   "->",         0},             /* old */
00152   {"pt",          "->",         DMGL_ANSI},     /* ansi; Lucid C++ form */
00153   {"rf",          "->",         DMGL_ANSI},     /* ansi; ARM/GNU form */
00154   {"indirect",    "*",          0},             /* old */
00155   {"method_call",  "->()",      0},             /* old */
00156   {"addr",        "&",          0},             /* old (unary &) */
00157   {"array",       "[]",         0},             /* old */
00158   {"vc",          "[]",         DMGL_ANSI},     /* ansi */
00159   {"compound",    ", ",         0},             /* old */
00160   {"cm",          ", ",         DMGL_ANSI},     /* ansi */
00161   {"cond",        "?:",         0},             /* old */
00162   {"cn",          "?:",         DMGL_ANSI},     /* psuedo-ansi */
00163   {"max",         ">?",         0},             /* old */
00164   {"mx",          ">?",         DMGL_ANSI},     /* psuedo-ansi */
00165   {"min",         "<?",         0},             /* old */
00166   {"mn",          "<?",         DMGL_ANSI},     /* psuedo-ansi */
00167   {"nop",         "",           0},             /* old (for operator=) */
00168   {"rm",          "->*",        DMGL_ANSI}      /* ansi */
00169 };
00170 
00171 
00172 typedef struct string           /* Beware: these aren't required to be */
00173 {                               /*  '\0' terminated. */
00174   char *b;                      /* pointer to start of string */
00175   char *p;                      /* pointer after last character */
00176   char *e;                      /* pointer after end of allocated space */
00177 } string;
00178 
00179 #define STRING_EMPTY(str)       ((str) -> b == (str) -> p)
00180 #define PREPEND_BLANK(str)      {if (!STRING_EMPTY(str)) \
00181                                    string_prepend(str, " ");}
00182 #define APPEND_BLANK(str)       {if (!STRING_EMPTY(str)) \
00183                                    string_append(str, " ");}
00184 
00185 #define ARM_VTABLE_STRING "__vtbl__"    /* Lucid/ARM virtual table prefix */
00186 #define ARM_VTABLE_STRLEN 8             /* strlen (ARM_VTABLE_STRING) */
00187 
00188 /* Prototypes for local functions */
00189 
00190 static char *
00191 mop_up (struct work_stuff *, string *, int);
00192 
00193 #if 0
00194 static int
00195 demangle_method_args (struct work_stuff *work, const char **, string *);
00196 #endif
00197 
00198 static int
00199 demangle_template (struct work_stuff *work, const char **, string *, string *);
00200 
00201 static int
00202 demangle_qualified (struct work_stuff *, const char **, string *, int, int);
00203 
00204 static int
00205 demangle_class (struct work_stuff *, const char **, string *);
00206 
00207 static int
00208 demangle_fund_type (struct work_stuff *, const char **, string *);
00209 
00210 static int
00211 demangle_signature (struct work_stuff *, const char **, string *);
00212 
00213 static int
00214 demangle_prefix (struct work_stuff *, const char **, string *);
00215 
00216 static int
00217 gnu_special (struct work_stuff *, const char **, string *);
00218 
00219 static int
00220 arm_special (struct work_stuff *, const char **, string *);
00221 
00222 static void
00223 string_need (string *, int);
00224 
00225 static void
00226 string_delete (string *);
00227 
00228 static void
00229 string_init (string *);
00230 
00231 static void
00232 string_clear (string *);
00233 
00234 #if 0
00235 static int
00236 string_empty (string *);
00237 #endif
00238 
00239 static void
00240 string_append (string *, const char *);
00241 
00242 static void
00243 string_appends (string *, string *);
00244 
00245 static void
00246 string_appendn (string *, const char *, int);
00247 
00248 static void
00249 string_prepend (string *, const char *);
00250 
00251 static void
00252 string_prependn (string *, const char *, int);
00253 
00254 static int
00255 get_count (const char **, int *);
00256 
00257 static int
00258 consume_count (const char **);
00259 
00260 static int
00261 demangle_args (struct work_stuff *, const char **, string *);
00262 
00263 static int
00264 do_type (struct work_stuff *, const char **, string *);
00265 
00266 static int
00267 do_arg (struct work_stuff *, const char **, string *);
00268 
00269 static void
00270 demangle_function_name (struct work_stuff *, const char **, string *,
00271                         const char *);
00272 
00273 static void
00274 remember_type (struct work_stuff *, const char *, int);
00275 
00276 static void
00277 forget_types (struct work_stuff *);
00278 
00279 static void
00280 string_prepends (string *, string *);
00281 
00282 /*  Translate count to integer, consuming tokens in the process.
00283     Conversion terminates on the first non-digit character.
00284     Trying to consume something that isn't a count results in
00285     no consumption of input and a return of 0. */
00286 
00287 static int
00288 consume_count (type)
00289     const char **type;
00290 {
00291     int count = 0;
00292 
00293     while (isdigit (**type))
00294       {
00295         count *= 10;
00296         count += **type - '0';
00297         (*type)++;
00298       }
00299     return (count);
00300 }
00301 
00302 int
00303 cplus_demangle_opname (opname, result, options)
00304      char *opname;
00305      char *result;
00306      int options;
00307 {
00308   int len, i, len1, ret;
00309   string type;
00310   struct work_stuff work[1];
00311   const char *tem;
00312 
00313   len = strlen(opname);
00314   result[0] = '\0';
00315   ret = 0;
00316   work->options = options;
00317 
00318   if (opname[0] == '_' && opname[1] == '_'
00319           && opname[2] == 'o' && opname[3] == 'p')
00320     {
00321       /* ANSI.  */
00322       /* type conversion operator.  */
00323       tem = opname + 4;
00324       if (do_type (work, &tem, &type))
00325         {
00326           strcat (result, "operator ");
00327           strncat (result, type.b, type.p - type.b);
00328           string_delete (&type);
00329           ret = 1;
00330         }
00331     }
00332   else if (opname[0] == '_' && opname[1] == '_'
00333            && opname[2] >= 'a' && opname[2] <= 'z'
00334            && opname[3] >= 'a' && opname[3] <= 'z')
00335     {
00336       if (opname[4] == '\0')
00337         {
00338           /* Operator.  */
00339           for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
00340             {
00341               if (strlen (optable[i].in) == 2
00342                   && memcmp (optable[i].in, opname + 2, 2) == 0)
00343                 {
00344                   strcat (result, "operator");
00345                   strcat (result, optable[i].out);
00346                   ret = 1;
00347                   break;
00348                 }
00349             }
00350         }
00351       else
00352         {
00353           if (opname[2] == 'a' && opname[5] == '\0')
00354             {
00355               /* Assignment. */
00356               for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
00357                 {
00358                   if (strlen (optable[i].in) == 3
00359                       && memcmp (optable[i].in, opname + 2, 3) == 0)
00360                     {
00361                       strcat (result, "operator");
00362                       strcat (result, optable[i].out);
00363                       ret = 1;
00364                       break;
00365                     }
00366                 }
00367             }
00368         }
00369     }
00370   else if (len >= 3
00371       && opname[0] == 'o'
00372       && opname[1] == 'p'
00373       && strchr (cplus_markers, opname[2]) != NULL)
00374     {
00375       /* see if it's an assignment expression */
00376       if (len >= 10 /* op$assign_ */
00377           && memcmp (opname + 3, "assign_", 7) == 0)
00378         {
00379           for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
00380             {
00381               len1 = len - 10;
00382               if ((int)strlen (optable[i].in) == len1
00383                   && memcmp (optable[i].in, opname + 10, len1) == 0)
00384                 {
00385                   strcat (result, "operator");
00386                   strcat (result, optable[i].out);
00387                   strcat (result, "=");
00388                   ret = 1;
00389                   break;
00390                 }
00391             }
00392         }
00393       else
00394         {
00395           for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
00396             {
00397               len1 = len - 3;
00398               if ((int)strlen (optable[i].in) == len1
00399                   && memcmp (optable[i].in, opname + 3, len1) == 0)
00400                 {
00401                   strcat (result, "operator");
00402                   strcat (result, optable[i].out);
00403                   ret = 1;
00404                   break;
00405                 }
00406             }
00407         }
00408     }
00409   else if (len >= 5 && memcmp (opname, "type", 4) == 0
00410            && strchr (cplus_markers, opname[4]) != NULL)
00411     {
00412       /* type conversion operator */
00413       tem = opname + 5;
00414       if (do_type (work, &tem, &type))
00415         {
00416           strcat (result, "operator ");
00417           strncat (result, type.b, type.p - type.b);
00418           string_delete (&type);
00419           ret = 1;
00420         }
00421     }
00422   return ret;
00423 
00424 }
00425 /* Takes operator name as e.g. "++" and returns mangled
00426    operator name (e.g. "postincrement_expr"), or NULL if not found.
00427 
00428    If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
00429    if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
00430 
00431 char *
00432 cplus_mangle_opname (opname, options)
00433      char *opname;
00434      int options;
00435 {
00436   int i;
00437   int len;
00438 
00439   len = strlen (opname);
00440   for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
00441     {
00442       if ((int)strlen (optable[i].out) == len
00443           && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
00444           && memcmp (optable[i].out, opname, len) == 0)
00445         return ((char *)optable[i].in);
00446     }
00447   return (0);
00448 }
00449 
00450 /* check to see whether MANGLED can match TEXT in the first TEXT_LEN
00451    characters. */
00452 
00453 int cplus_match (mangled, text, text_len)
00454      const char *mangled;
00455      char *text;
00456      int text_len;
00457 {
00458   if (strncmp (mangled, text, text_len) != 0) {
00459     return(0); /* cannot match either */
00460   } else {
00461     return(1); /* matches mangled, may match demangled */
00462   }
00463 }
00464 
00465 /* char *cplus_demangle (const char *mangled, int options)
00466 
00467    If MANGLED is a mangled function name produced by GNU C++, then
00468    a pointer to a malloced string giving a C++ representation
00469    of the name will be returned; otherwise NULL will be returned.
00470    It is the caller's responsibility to free the string which
00471    is returned.
00472 
00473    The OPTIONS arg may contain one or more of the following bits:
00474 
00475         DMGL_ANSI       ANSI qualifiers such as `const' and `void' are
00476                         included.
00477         DMGL_PARAMS     Function parameters are included.
00478 
00479    For example,
00480 
00481    cplus_demangle ("foo__1Ai", DMGL_PARAMS)             => "A::foo(int)"
00482    cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
00483    cplus_demangle ("foo__1Ai", 0)                       => "A::foo"
00484 
00485    cplus_demangle ("foo__1Afe", DMGL_PARAMS)            => "A::foo(float,...)"
00486    cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
00487    cplus_demangle ("foo__1Afe", 0)                      => "A::foo"
00488 
00489    Note that any leading underscores, or other such characters prepended by
00490    the compilation system, are presumed to have already been stripped from
00491    MANGLED.  */
00492 
00493 char *
00494 cplus_demangle (mangled, options)
00495      const char *mangled;
00496      int options;
00497 {
00498   string decl;
00499   int success = 0;
00500   struct work_stuff work[1];
00501   char *demangled = NULL;
00502 
00503   if ((mangled != NULL) && (*mangled != '\0'))
00504     {
00505       memset ((char *) work, 0, sizeof (work));
00506       work -> options = options;
00507       if ((work->options & DMGL_STYLE_MASK) == 0)
00508         work->options |= (int)current_demangling_style & DMGL_STYLE_MASK;
00509 
00510       string_init (&decl);
00511 
00512       /* First check to see if gnu style demangling is active and if the
00513          string to be demangled contains a CPLUS_MARKER.  If so, attempt to
00514          recognize one of the gnu special forms rather than looking for a
00515          standard prefix.  In particular, don't worry about whether there
00516          is a "__" string in the mangled string.  Consider "_$_5__foo" for
00517          example. */
00518 
00519       if ((AUTO_DEMANGLING || GNU_DEMANGLING))
00520         {
00521           success = gnu_special (work, &mangled, &decl);
00522         }
00523       if (!success)
00524         {
00525           success = demangle_prefix (work, &mangled, &decl);
00526         }
00527       if (success && (*mangled != '\0'))
00528         {
00529           success = demangle_signature (work, &mangled, &decl);
00530         }
00531       if (work->constructor == 2)
00532         {
00533           string_prepend(&decl, "global constructors keyed to ");
00534           work->constructor = 0;
00535         }
00536       else if (work->destructor == 2)
00537         {
00538           string_prepend(&decl, "global destructors keyed to ");
00539           work->destructor = 0;
00540         }
00541       demangled = mop_up (work, &decl, success);
00542     }
00543   return (demangled);
00544 }
00545 
00546 static char *
00547 mop_up (work, declp, success)
00548      struct work_stuff *work;
00549      string *declp;
00550      int success;
00551 {
00552   char *demangled = NULL;
00553 
00554   /* Discard the remembered types, if any. */
00555 
00556   forget_types (work);
00557   if (work -> typevec != NULL)
00558     {
00559       free ((char *) work -> typevec);
00560     }
00561 
00562   /* If demangling was successful, ensure that the demangled string is null
00563      terminated and return it.  Otherwise, free the demangling decl. */
00564 
00565   if (!success)
00566     {
00567       string_delete (declp);
00568     }
00569   else
00570     {
00571       string_appendn (declp, "", 1);
00572       demangled = declp -> b;
00573     }
00574   return (demangled);
00575 }
00576 
00577 /*
00578 
00579 LOCAL FUNCTION
00580 
00581         demangle_signature -- demangle the signature part of a mangled name
00582 
00583 SYNOPSIS
00584 
00585         static int
00586         demangle_signature (struct work_stuff *work, const char **mangled,
00587                             string *declp);
00588 
00589 DESCRIPTION
00590 
00591         Consume and demangle the signature portion of the mangled name.
00592 
00593         DECLP is the string where demangled output is being built.  At
00594         entry it contains the demangled root name from the mangled name
00595         prefix.  I.E. either a demangled operator name or the root function
00596         name.  In some special cases, it may contain nothing.
00597 
00598         *MANGLED points to the current unconsumed location in the mangled
00599         name.  As tokens are consumed and demangling is performed, the
00600         pointer is updated to continuously point at the next token to
00601         be consumed.
00602 
00603         Demangling GNU style mangled names is nasty because there is no
00604         explicit token that marks the start of the outermost function
00605         argument list.
00606 */
00607 
00608 static int
00609 demangle_signature (work, mangled, declp)
00610      struct work_stuff *work;
00611      const char **mangled;
00612      string *declp;
00613 {
00614   int success = 1;
00615   int func_done = 0;
00616   int expect_func = 0;
00617   const char *oldmangled = NULL;
00618   string trawname;
00619   string tname;
00620 
00621   while (success && (**mangled != '\0'))
00622     {
00623       switch (**mangled)
00624         {
00625           case 'Q':
00626             oldmangled = *mangled;
00627             success = demangle_qualified (work, mangled, declp, 1, 0);
00628             if (success)
00629               {
00630                 remember_type (work, oldmangled, *mangled - oldmangled);
00631               }
00632             if (AUTO_DEMANGLING || GNU_DEMANGLING)
00633               {
00634                 expect_func = 1;
00635               }
00636             oldmangled = NULL;
00637             break;
00638 
00639           case 'S':
00640             /* Static member function */
00641             if (oldmangled == NULL)
00642               {
00643                 oldmangled = *mangled;
00644               }
00645             (*mangled)++;
00646             work -> static_type = 1;
00647             break;
00648 
00649           case 'C':
00650             /* a const member function */
00651             if (oldmangled == NULL)
00652               {
00653                 oldmangled = *mangled;
00654               }
00655             (*mangled)++;
00656             work -> const_type = 1;
00657             break;
00658 
00659           case '0': case '1': case '2': case '3': case '4':
00660           case '5': case '6': case '7': case '8': case '9':
00661             if (oldmangled == NULL)
00662               {
00663                 oldmangled = *mangled;
00664               }
00665             success = demangle_class (work, mangled, declp);
00666             if (success)
00667               {
00668                 remember_type (work, oldmangled, *mangled - oldmangled);
00669               }
00670             if (AUTO_DEMANGLING || GNU_DEMANGLING)
00671               {
00672                 expect_func = 1;
00673               }
00674             oldmangled = NULL;
00675             break;
00676 
00677           case 'F':
00678             /* Function */
00679             /* ARM style demangling includes a specific 'F' character after
00680              the class name.  For GNU style, it is just implied.  So we can
00681              safely just consume any 'F' at this point and be compatible
00682              with either style. */
00683 
00684             oldmangled = NULL;
00685             func_done = 1;
00686             (*mangled)++;
00687 
00688             /* For lucid/ARM style we have to forget any types we might
00689                have remembered up to this point, since they were not argument
00690                types.  GNU style considers all types seen as available for
00691                back references.  See comment in demangle_args() */
00692 
00693             if (LUCID_DEMANGLING || ARM_DEMANGLING)
00694               {
00695                 forget_types (work);
00696               }
00697             success = demangle_args (work, mangled, declp);
00698             break;
00699 
00700           case 't':
00701             /* G++ Template */
00702             string_init(&trawname);
00703             string_init(&tname);
00704             if (oldmangled == NULL)
00705               {
00706                 oldmangled = *mangled;
00707               }
00708             success = demangle_template (work, mangled, &tname, &trawname);
00709             if (success)
00710               {
00711                 remember_type (work, oldmangled, *mangled - oldmangled);
00712               }
00713             string_append(&tname, "::");
00714             string_prepends(declp, &tname);
00715             if (work -> destructor & 1)
00716               {
00717                 string_prepend (&trawname, "~");
00718                 string_appends (declp, &trawname);
00719                 work->destructor -= 1;
00720               }
00721             if ((work->constructor & 1) || (work->destructor & 1))
00722               {
00723                 string_appends (declp, &trawname);
00724                 work->constructor -= 1;
00725               }
00726             string_delete(&trawname);
00727             string_delete(&tname);
00728             oldmangled = NULL;
00729             expect_func = 1;
00730             break;
00731 
00732           case '_':
00733             /* At the outermost level, we cannot have a return type specified,
00734                so if we run into another '_' at this point we are dealing with
00735                a mangled name that is either bogus, or has been mangled by
00736                some algorithm we don't know how to deal with.  So just
00737                reject the entire demangling. */
00738             success = 0;
00739             break;
00740 
00741           default:
00742             if (AUTO_DEMANGLING || GNU_DEMANGLING)
00743               {
00744                 /* Assume we have stumbled onto the first outermost function
00745                    argument token, and start processing args. */
00746                 func_done = 1;
00747                 success = demangle_args (work, mangled, declp);
00748               }
00749             else
00750               {
00751                 /* Non-GNU demanglers use a specific token to mark the start
00752                    of the outermost function argument tokens.  Typically 'F',
00753                    for ARM-demangling, for example.  So if we find something
00754                    we are not prepared for, it must be an error. */
00755                 success = 0;
00756               }
00757             break;
00758         }
00759 /*
00760       if (AUTO_DEMANGLING || GNU_DEMANGLING)
00761 */
00762         {
00763           if (success && expect_func)
00764             {
00765               func_done = 1;
00766               success = demangle_args (work, mangled, declp);
00767             }
00768         }
00769     }
00770   if (success && !func_done)
00771     {
00772       if (AUTO_DEMANGLING || GNU_DEMANGLING)
00773         {
00774           /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
00775              bar__3fooi is 'foo::bar(int)'.  We get here when we find the
00776              first case, and need to ensure that the '(void)' gets added to
00777              the current declp.  Note that with ARM, the first case
00778              represents the name of a static data member 'foo::bar',
00779              which is in the current declp, so we leave it alone. */
00780           success = demangle_args (work, mangled, declp);
00781         }
00782     }
00783   if (success && work -> static_type && PRINT_ARG_TYPES)
00784     {
00785       string_append (declp, " static");
00786     }
00787   if (success && work -> const_type && PRINT_ARG_TYPES)
00788     {
00789       string_append (declp, " const");
00790     }
00791   return (success);
00792 }
00793 
00794 #if 0
00795 
00796 static int
00797 demangle_method_args (work, mangled, declp)
00798      struct work_stuff *work;
00799      const char **mangled;
00800      string *declp;
00801 {
00802   int success = 0;
00803 
00804   if (work -> static_type)
00805     {
00806       string_append (declp, *mangled + 1);
00807       *mangled += strlen (*mangled);
00808       success = 1;
00809     }
00810   else
00811     {
00812       success = demangle_args (work, mangled, declp);
00813     }
00814   return (success);
00815 }
00816 
00817 #endif
00818 
00819 static int
00820 demangle_template (work, mangled, tname, trawname)
00821      struct work_stuff *work;
00822      const char **mangled;
00823      string *tname;
00824      string *trawname;
00825 {
00826   int i;
00827   int is_pointer;
00828   int is_real;
00829   int is_integral;
00830   int is_char;
00831   int r;
00832   int need_comma = 0;
00833   int success = 0;
00834   int done;
00835   const char *old_p;
00836   int symbol_len;
00837   string temp;
00838 
00839   (*mangled)++;
00840   /* get template name */
00841   if ((r = consume_count (mangled)) == 0 || (int)strlen (*mangled) < r)
00842     {
00843       return (0);
00844     }
00845   if (trawname)
00846     string_appendn (trawname, *mangled, r);
00847   string_appendn (tname, *mangled, r);
00848   *mangled += r;
00849   string_append (tname, "<");
00850   /* get size of template parameter list */
00851   if (!get_count (mangled, &r))
00852     {
00853       return (0);
00854     }
00855   for (i = 0; i < r; i++)
00856     {
00857       if (need_comma)
00858         {
00859           string_append (tname, ", ");
00860         }
00861       /* Z for type parameters */
00862       if (**mangled == 'Z')
00863         {
00864           (*mangled)++;
00865           /* temp is initialized in do_type */
00866           success = do_type (work, mangled, &temp);
00867           if (success)
00868             {
00869               string_appends (tname, &temp);
00870             }
00871           string_delete(&temp);
00872           if (!success)
00873             {
00874               break;
00875             }
00876         }
00877       else
00878         {
00879           /* otherwise, value parameter */
00880           old_p  = *mangled;
00881           is_pointer = 0;
00882           is_real = 0;
00883           is_integral = 0;
00884           is_char = 0;
00885           done = 0;
00886           /* temp is initialized in do_type */
00887           success = do_type (work, mangled, &temp);
00888 /*
00889           if (success)
00890             {
00891               string_appends (tname, &temp);
00892             }
00893 */
00894           string_delete(&temp);
00895           if (!success)
00896             {
00897               break;
00898             }
00899 /*
00900           string_append (tname, "=");
00901 */
00902           while (*old_p && !done)
00903             {
00904               switch (*old_p)
00905                 {
00906                   case 'P':
00907                   case 'p':
00908                   case 'R':
00909                     done = is_pointer = 1;
00910                     break;
00911                   case 'C':     /* const */
00912                   case 'S':     /* explicitly signed [char] */
00913                   case 'U':     /* unsigned */
00914                   case 'V':     /* volatile */
00915                   case 'F':     /* function */
00916                   case 'M':     /* member function */
00917                   case 'O':     /* ??? */
00918                     old_p++;
00919                     continue;
00920                   case 'Q':     /* qualified name */
00921                     done = is_integral = 1;
00922                     break;
00923                   case 'T':     /* remembered type */
00924                     abort ();
00925                     break;
00926                   case 'v':     /* void */
00927                     abort ();
00928                     break;
00929                   case 'x':     /* long long */
00930                   case 'l':     /* long */
00931                   case 'i':     /* int */
00932                   case 's':     /* short */
00933                   case 'w':     /* wchar_t */
00934                     done = is_integral = 1;
00935                     break;
00936                   case 'c':     /* char */
00937                     done = is_char = 1;
00938                     break;
00939                   case 'r':     /* long double */
00940                   case 'd':     /* double */
00941                   case 'f':     /* float */
00942                     done = is_real = 1;
00943                     break;
00944                   default:
00945                     /* it's probably user defined type, let's assume
00946                        it's integeral, it seems hard to figure out
00947                        what it really is */
00948                     done = is_integral = 1;
00949                 }
00950             }
00951           if (is_integral)
00952             {
00953               if (**mangled == 'm')
00954                 {
00955                   string_appendn (tname, "-", 1);
00956                   (*mangled)++;
00957                 }
00958               while (isdigit (**mangled))
00959                 {
00960                   string_appendn (tname, *mangled, 1);
00961                   (*mangled)++;
00962                 }
00963             }
00964           else if (is_char)
00965             {
00966             char tmp[2];
00967             int val;
00968               if (**mangled == 'm')
00969                 {
00970                   string_appendn (tname, "-", 1);
00971                   (*mangled)++;
00972                 }
00973               string_appendn (tname, "'", 1);
00974               val = consume_count(mangled);
00975               if (val == 0)
00976                 {
00977                   success = 0;
00978                   break;
00979                 }
00980               tmp[0] = (char)val;
00981               tmp[1] = '\0';
00982               string_appendn (tname, &tmp[0], 1);
00983               string_appendn (tname, "'", 1);
00984             }
00985           else if (is_real)
00986             {
00987               if (**mangled == 'm')
00988                 {
00989                   string_appendn (tname, "-", 1);
00990                   (*mangled)++;
00991                 }
00992               while (isdigit (**mangled))
00993                 {
00994                   string_appendn (tname, *mangled, 1);
00995                   (*mangled)++;
00996                 }
00997               if (**mangled == '.') /* fraction */
00998                 {
00999                   string_appendn (tname, ".", 1);
01000                   (*mangled)++;
01001                   while (isdigit (**mangled))
01002                     {
01003                       string_appendn (tname, *mangled, 1);
01004                       (*mangled)++;
01005                     }
01006                 }
01007               if (**mangled == 'e') /* exponent */
01008                 {
01009                   string_appendn (tname, "e", 1);
01010                   (*mangled)++;
01011                   while (isdigit (**mangled))
01012                     {
01013                       string_appendn (tname, *mangled, 1);
01014                       (*mangled)++;
01015                     }
01016                 }
01017             }
01018           else if (is_pointer)
01019             {
01020               if (!get_count (mangled, &symbol_len))
01021                 {
01022                   success = 0;
01023                   break;
01024                 }
01025               string_appendn (tname, *mangled, symbol_len);
01026               *mangled += symbol_len;
01027             }
01028         }
01029       need_comma = 1;
01030     }
01031   if (tname->p[-1] == '>')
01032     string_append (tname, " ");
01033   string_append (tname, ">");
01034 
01035 /*
01036       if (work -> static_type)
01037         {
01038           string_append (declp, *mangled + 1);
01039           *mangled += strlen (*mangled);
01040           success = 1;
01041         }
01042       else
01043         {
01044           success = demangle_args (work, mangled, declp);
01045         }
01046     }
01047 */
01048   return (success);
01049 }
01050 
01051 static int
01052 arm_pt (work, mangled, n, anchor, args)
01053      struct work_stuff *work;
01054      const char *mangled;
01055      int n;
01056      const char **anchor, **args;
01057 {
01058   /* ARM template? */
01059   if (ARM_DEMANGLING && (*anchor = strstr(mangled, "__pt__")))
01060     {
01061         int len;
01062         *args = *anchor + 6;
01063         len = consume_count (args);
01064         if (*args + len == mangled + n && **args == '_')
01065           {
01066             ++*args;
01067             return 1;
01068           }
01069     }
01070   return 0;
01071 }
01072 
01073 static void
01074 demangle_arm_pt (work, mangled, n, declp)
01075      struct work_stuff *work;
01076      const char **mangled;
01077      int n;
01078      string *declp;
01079 {
01080   const char *p;
01081   const char *args;
01082   const char *e = *mangled + n;
01083 
01084   /* ARM template? */
01085   if (arm_pt (work, *mangled, n, &p, &args))
01086   {
01087     string arg;
01088     string_init (&arg);
01089     string_appendn (declp, *mangled, p - *mangled);
01090     string_append (declp, "<");
01091     /* should do error checking here */
01092     while (args < e) {
01093       string_clear (&arg);
01094       do_type (work, &args, &arg);
01095       string_appends (declp, &arg);
01096       string_append (declp, ",");
01097     }
01098     string_delete (&arg);
01099     --declp->p;
01100     string_append (declp, ">");
01101   }
01102   else
01103   {
01104     string_appendn (declp, *mangled, n);
01105   }
01106   *mangled += n;
01107 }
01108 
01109 static int
01110 demangle_class_name (work, mangled, declp)
01111      struct work_stuff *work;
01112      const char **mangled;
01113      string *declp;
01114 {
01115   int n;
01116   int success = 0;
01117 
01118   n = consume_count (mangled);
01119   if ((int)strlen (*mangled) >= n)
01120   {
01121     demangle_arm_pt (work, mangled, n, declp);
01122     success = 1;
01123   }
01124 
01125   return (success);
01126 }
01127 
01128 /*
01129 
01130 LOCAL FUNCTION
01131 
01132         demangle_class -- demangle a mangled class sequence
01133 
01134 SYNOPSIS
01135 
01136         static int
01137         demangle_class (struct work_stuff *work, const char **mangled,
01138                         strint *declp)
01139 
01140 DESCRIPTION
01141 
01142         DECLP points to the buffer into which demangling is being done.
01143 
01144         *MANGLED points to the current token to be demangled.  On input,
01145         it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
01146         On exit, it points to the next token after the mangled class on
01147         success, or the first unconsumed token on failure.
01148 
01149         If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
01150         we are demangling a constructor or destructor.  In this case
01151         we prepend "class::class" or "class::~class" to DECLP.
01152 
01153         Otherwise, we prepend "class::" to the current DECLP.
01154 
01155         Reset the constructor/destructor flags once they have been
01156         "consumed".  This allows demangle_class to be called later during
01157         the same demangling, to do normal class demangling.
01158 
01159         Returns 1 if demangling is successful, 0 otherwise.
01160 
01161 */
01162 
01163 static int
01164 demangle_class (work, mangled, declp)
01165      struct work_stuff *work;
01166      const char **mangled;
01167      string *declp;
01168 {
01169   int success = 0;
01170   string class_name;
01171 
01172   string_init (&class_name);
01173   if (demangle_class_name (work, mangled, &class_name))
01174     {
01175       if ((work->constructor & 1) || (work->destructor & 1))
01176         {
01177           string_prepends (declp, &class_name);
01178           if (work -> destructor & 1)
01179             {
01180               string_prepend (declp, "~");
01181               work -> destructor -= 1;
01182             }
01183           else
01184             {
01185               work -> constructor -= 1;
01186             }
01187         }
01188       string_prepend (declp, "::");
01189       string_prepends (declp, &class_name);
01190       success = 1;
01191     }
01192   string_delete (&class_name);
01193   return (success);
01194 }
01195 
01196 /*
01197 
01198 LOCAL FUNCTION
01199 
01200         demangle_prefix -- consume the mangled name prefix and find signature
01201 
01202 SYNOPSIS
01203 
01204         static int
01205         demangle_prefix (struct work_stuff *work, const char **mangled,
01206                          string *declp);
01207 
01208 DESCRIPTION
01209 
01210         Consume and demangle the prefix of the mangled name.
01211 
01212         DECLP points to the string buffer into which demangled output is
01213         placed.  On entry, the buffer is empty.  On exit it contains
01214         the root function name, the demangled operator name, or in some
01215         special cases either nothing or the completely demangled result.
01216 
01217         MANGLED points to the current pointer into the mangled name.  As each
01218         token of the mangled name is consumed, it is updated.  Upon entry
01219         the current mangled name pointer points to the first character of
01220         the mangled name.  Upon exit, it should point to the first character
01221         of the signature if demangling was successful, or to the first
01222         unconsumed character if demangling of the prefix was unsuccessful.
01223 
01224         Returns 1 on success, 0 otherwise.
01225  */
01226 
01227 static int
01228 demangle_prefix (work, mangled, declp)
01229      struct work_stuff *work;
01230      const char **mangled;
01231      string *declp;
01232 {
01233   int success = 1;
01234   const char *scan;
01235   int i;
01236 
01237   if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
01238     {
01239       char *marker = strchr (cplus_markers, (*mangled)[8]);
01240       if (marker != NULL && *marker == (*mangled)[10])
01241         {
01242           if ((*mangled)[9] == 'D')
01243             {
01244               /* it's a GNU global destructor to be executed at program exit */
01245               (*mangled) += 11;
01246               work->destructor = 2;
01247             }
01248           else if ((*mangled)[9] == 'I')
01249             {
01250               /* it's a GNU global constructor to be executed at program init */
01251               (*mangled) += 11;
01252               work->constructor = 2;
01253             }
01254         }
01255     }
01256   else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
01257     {
01258       /* it's a ARM global destructor to be executed at program exit */
01259       (*mangled) += 7;
01260       work->destructor = 2;
01261     }
01262   else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
01263     {
01264       /* it's a ARM global constructor to be executed at program initial */
01265       (*mangled) += 7;
01266       work->constructor = 2;
01267     }
01268 
01269 /*  This block of code is a reduction in strength time optimization
01270     of:
01271         scan = strstr (*mangled, "__"); */
01272 
01273   {
01274     scan = *mangled;
01275 
01276     do {
01277       scan = strchr (scan, '_');
01278     } while (scan != NULL && *++scan != '_');
01279 
01280     if (scan != NULL) --scan;
01281   }
01282 
01283   if (scan != NULL)
01284     {
01285       /* We found a sequence of two or more '_', ensure that we start at
01286          the last pair in the sequence. */
01287       i = strspn (scan, "_");
01288       if (i > 2)
01289         {
01290           scan += (i - 2);
01291         }
01292     }
01293 
01294   if (scan == NULL)
01295     {
01296       success = 0;
01297     }
01298   else if (work -> static_type)
01299     {
01300       if (!isdigit (scan[0]) && (scan[0] != 't'))
01301         {
01302           success = 0;
01303         }
01304     }
01305   else if ((scan == *mangled) &&
01306            (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')))
01307     {
01308       /* The ARM says nothing about the mangling of local variables.
01309          But cfront mangles local variables by prepending __<nesting_level>
01310          to them. As an extension to ARM demangling we handle this case.  */
01311       if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
01312         {
01313           *mangled = scan + 2;
01314           consume_count (mangled);
01315           string_append (declp, *mangled);
01316           *mangled += strlen (*mangled);
01317           success = 1;
01318         }
01319       else
01320         {
01321           /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
01322              names like __Q2_3foo3bar for nested type names.  So don't accept
01323              this style of constructor for cfront demangling.  */
01324           if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
01325             work -> constructor += 1;
01326           *mangled = scan + 2;
01327         }
01328     }
01329   else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
01330     {
01331       /* Mangled name starts with "__".  Skip over any leading '_' characters,
01332          then find the next "__" that separates the prefix from the signature.
01333          */
01334       if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
01335           || (arm_special (work, mangled, declp) == 0))
01336         {
01337           while (*scan == '_')
01338             {
01339               scan++;
01340             }
01341           if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
01342             {
01343               /* No separator (I.E. "__not_mangled"), or empty signature
01344                  (I.E. "__not_mangled_either__") */
01345               success = 0;
01346             }
01347           else
01348             {
01349               demangle_function_name (work, mangled, declp, scan);
01350             }
01351         }
01352     }
01353   else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
01354     {
01355       /* Cfront-style parameterized type.  Handled later as a signature. */
01356       success = 1;
01357 
01358       /* ARM template? */
01359       demangle_arm_pt (work, mangled, (int)strlen (*mangled), declp);
01360     }
01361   else if (*(scan + 2) != '\0')
01362     {
01363       /* Mangled name does not start with "__" but does have one somewhere
01364          in there with non empty stuff after it.  Looks like a global
01365          function name. */
01366       demangle_function_name (work, mangled, declp, scan);
01367     }
01368   else
01369     {
01370       /* Doesn't look like a mangled name */
01371       success = 0;
01372     }
01373 
01374   if (!success && (work->constructor == 2 || work->destructor == 2))
01375     {
01376       string_append (declp, *mangled);
01377       *mangled += strlen (*mangled);
01378       success = 1;
01379     }
01380   return (success);
01381 }
01382 
01383 /*
01384 
01385 LOCAL FUNCTION
01386 
01387         gnu_special -- special handling of gnu mangled strings
01388 
01389 SYNOPSIS
01390 
01391         static int
01392         gnu_special (struct work_stuff *work, const char **mangled,
01393                      string *declp);
01394 
01395 
01396 DESCRIPTION
01397 
01398         Process some special GNU style mangling forms that don't fit
01399         the normal pattern.  For example:
01400 
01401                 _$_3foo         (destructor for class foo)
01402                 _vt$foo         (foo virtual table)
01403                 _vt$foo$bar     (foo::bar virtual table)
01404                 __vt_foo        (foo virtual table, new style with thunks)
01405                 _3foo$varname   (static data member)
01406                 _Q22rs2tu$vw    (static data member)
01407                 __t6vector1Zii  (constructor with template)
01408                 __thunk_4__$_7ostream (virtual function thunk)
01409  */
01410 
01411 static int
01412 gnu_special (work, mangled, declp)
01413      struct work_stuff *work;
01414      const char **mangled;
01415      string *declp;
01416 {
01417   int n;
01418   int success = 1;
01419   const char *p;
01420 
01421   if ((*mangled)[0] == '_'
01422       && strchr (cplus_markers, (*mangled)[1]) != NULL
01423       && (*mangled)[2] == '_')
01424     {
01425       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
01426       (*mangled) += 3;
01427       work -> destructor += 1;
01428     }
01429   else if ((*mangled)[0] == '_'
01430            && (((*mangled)[1] == '_'
01431                 && (*mangled)[2] == 'v'
01432                 && (*mangled)[3] == 't'
01433                 && (*mangled)[4] == '_')
01434              || ((*mangled)[1] == 'v'
01435                  && (*mangled)[2] == 't'
01436                  && strchr (cplus_markers, (*mangled)[3]) != NULL)))
01437     {
01438       /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
01439          and create the decl.  Note that we consume the entire mangled
01440          input string, which means that demangle_signature has no work
01441          to do. */
01442       if ((*mangled)[2] == 'v')
01443         (*mangled) += 5; /* New style, with thunks: "__vt_" */
01444       else
01445         (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
01446       while (**mangled != '\0')
01447         {
01448           p = strpbrk (*mangled, cplus_markers);
01449           switch (**mangled)
01450             {
01451             case 'Q':
01452               success = demangle_qualified (work, mangled, declp, 0, 1);
01453               break;
01454             case 't':
01455               success = demangle_template (work, mangled, declp, 0);
01456               break;
01457             default:
01458               if (isdigit(*mangled[0]))
01459                 {
01460                   n = consume_count(mangled);
01461                 }
01462               else
01463                 {
01464                   n = strcspn (*mangled, cplus_markers);
01465                 }
01466               string_appendn (declp, *mangled, n);
01467               (*mangled) += n;
01468             }
01469 
01470           if (success && ((p == NULL) || (p == *mangled)))
01471             {
01472               if (p != NULL)
01473                 {
01474                   string_append (declp, "::");
01475                   (*mangled)++;
01476                 }
01477             }
01478           else
01479             {
01480               success = 0;
01481               break;
01482             }
01483         }
01484       if (success)
01485         string_append (declp, " virtual table");
01486     }
01487   else if ((*mangled)[0] == '_'
01488            && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
01489            && (p = strpbrk (*mangled, cplus_markers)) != NULL)
01490     {
01491       /* static data member, "_3foo$varname" for example */
01492       (*mangled)++;
01493       switch (**mangled)
01494         {
01495           case 'Q':
01496             success = demangle_qualified (work, mangled, declp, 0, 1);
01497             break;
01498           case 't':
01499             success = demangle_template (work, mangled, declp, 0);
01500             break;
01501           default:
01502             n = consume_count (mangled);
01503             string_appendn (declp, *mangled, n);
01504             (*mangled) += n;
01505         }
01506       if (success && (p == *mangled))
01507         {
01508           /* Consumed everything up to the cplus_marker, append the
01509              variable name. */
01510           (*mangled)++;
01511           string_append (declp, "::");
01512           n = strlen (*mangled);
01513           string_appendn (declp, *mangled, n);
01514           (*mangled) += n;
01515         }
01516       else
01517         {
01518           success = 0;
01519         }
01520     }
01521   else if (strncmp (*mangled, "__thunk_", 8) == 0)
01522     {
01523       int delta = ((*mangled) += 8, consume_count (mangled));
01524       char *method = cplus_demangle (++*mangled, work->options);
01525       if (method)
01526         {
01527           char buf[50];
01528           sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
01529           string_append (declp, buf);
01530           string_append (declp, method);
01531           free (method);
01532           n = strlen (*mangled);
01533           (*mangled) += n;
01534         }
01535       else
01536         {
01537           success = 0;
01538         }
01539     }
01540   else
01541     {
01542       success = 0;
01543     }
01544   return (success);
01545 }
01546 
01547 /*
01548 
01549 LOCAL FUNCTION
01550 
01551         arm_special -- special handling of ARM/lucid mangled strings
01552 
01553 SYNOPSIS
01554 
01555         static int
01556         arm_special (struct work_stuff *work, const char **mangled,
01557                         string *declp);
01558 
01559 
01560 DESCRIPTION
01561 
01562         Process some special ARM style mangling forms that don't fit
01563         the normal pattern.  For example:
01564 
01565                 __vtbl__3foo            (foo virtual table)
01566                 __vtbl__3foo__3bar      (bar::foo virtual table)
01567 
01568  */
01569 
01570 static int
01571 arm_special (struct work_stuff *work, const char **mangled, string *declp)
01572 {
01573   int n;
01574   int success = 1;
01575   const char *scan;
01576 
01577   if (work) { }  /* not used */
01578 
01579   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
01580     {
01581       /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
01582          and create the decl.  Note that we consume the entire mangled
01583          input string, which means that demangle_signature has no work
01584          to do. */
01585       scan = *mangled + ARM_VTABLE_STRLEN;
01586       while (*scan != '\0')        /* first check it can be demangled */
01587         {
01588           n = consume_count (&scan);
01589           if (n==0)
01590             {
01591               return (0);           /* no good */
01592             }
01593           scan += n;
01594           if (scan[0] == '_' && scan[1] == '_')
01595             {
01596               scan += 2;
01597             }
01598         }
01599       (*mangled) += ARM_VTABLE_STRLEN;
01600       while (**mangled != '\0')
01601         {
01602           n = consume_count (mangled);
01603           string_prependn (declp, *mangled, n);
01604           (*mangled) += n;
01605           if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
01606             {
01607               string_prepend (declp, "::");
01608               (*mangled) += 2;
01609             }
01610         }
01611       string_append (declp, " virtual table");
01612     }
01613   else
01614     {
01615       success = 0;
01616     }
01617   return (success);
01618 }
01619 
01620 /*
01621 
01622 LOCAL FUNCTION
01623 
01624         demangle_qualified -- demangle 'Q' qualified name strings
01625 
01626 SYNOPSIS
01627 
01628         static int
01629         demangle_qualified (struct work_stuff *, const char *mangled,
01630                             string *result, int isfuncname, int append);
01631 
01632 DESCRIPTION
01633 
01634         Demangle a qualified name, such as "Q25Outer5Inner" which is
01635         the mangled form of "Outer::Inner".  The demangled output is
01636         prepended or appended to the result string according to the
01637         state of the append flag.
01638 
01639         If isfuncname is nonzero, then the qualified name we are building
01640         is going to be used as a member function name, so if it is a
01641         constructor or destructor function, append an appropriate
01642         constructor or destructor name.  I.E. for the above example,
01643         the result for use as a constructor is "Outer::Inner::Inner"
01644         and the result for use as a destructor is "Outer::Inner::~Inner".
01645 
01646 BUGS
01647 
01648         Numeric conversion is ASCII dependent (FIXME).
01649 
01650  */
01651 
01652 static int
01653 demangle_qualified (work, mangled, result, isfuncname, append)
01654      struct work_stuff *work;
01655      const char **mangled;
01656      string *result;
01657      int isfuncname;
01658      int append;
01659 {
01660   int qualifiers = 0;
01661   int namelength = 0;
01662   int success = 1;
01663   const char *p;
01664   char num[2];
01665   string temp;
01666 
01667   string_init (&temp);
01668   switch ((*mangled)[1])
01669     {
01670     case '_':
01671       /* GNU mangled name with more than 9 classes.  The count is preceded
01672          by an underscore (to distinguish it from the <= 9 case) and followed
01673          by an underscore.  */
01674       p = *mangled + 2;
01675       qualifiers = atoi (p);
01676       if (!isdigit (*p) || *p == '0')
01677         success = 0;
01678 
01679       /* Skip the digits.  */
01680       while (isdigit (*p))
01681         ++p;
01682 
01683       if (*p != '_')
01684         success = 0;
01685 
01686       *mangled = p + 1;
01687       break;
01688 
01689     case '1':
01690     case '2':
01691     case '3':
01692     case '4':
01693     case '5':
01694     case '6':
01695     case '7':
01696     case '8':
01697     case '9':
01698       /* The count is in a single digit.  */
01699       num[0] = (*mangled)[1];
01700       num[1] = '\0';
01701       qualifiers = atoi (num);
01702 
01703       /* If there is an underscore after the digit, skip it.  This is
01704          said to be for ARM-qualified names, but the ARM makes no
01705          mention of such an underscore.  Perhaps cfront uses one.  */
01706       if ((*mangled)[2] == '_')
01707         {
01708           (*mangled)++;
01709         }
01710       (*mangled) += 2;
01711       break;
01712 
01713     case '0':
01714     default:
01715       success = 0;
01716     }
01717 
01718   if (!success)
01719     return success;
01720 
01721   /* Pick off the names and collect them in the temp buffer in the order
01722      in which they are found, separated by '::'. */
01723 
01724   while (qualifiers-- > 0)
01725     {
01726       if (*mangled[0] == '_')
01727         *mangled = *mangled + 1;
01728       if (*mangled[0] == 't')
01729         {
01730           success = demangle_template(work, mangled, &temp, 0);
01731           if (!success) break;
01732         }
01733       else
01734         {
01735           namelength = consume_count (mangled);
01736           if ((int)strlen (*mangled) < namelength)
01737             {
01738             /* Simple sanity check failed */
01739                success = 0;
01740                break;
01741             }
01742           string_appendn (&temp, *mangled, namelength);
01743           *mangled += namelength;
01744         }
01745       if (qualifiers > 0)
01746         {
01747           string_appendn (&temp, "::", 2);
01748         }
01749     }
01750 
01751   /* If we are using the result as a function name, we need to append
01752      the appropriate '::' separated constructor or destructor name.
01753      We do this here because this is the most convenient place, where
01754      we already have a pointer to the name and the length of the name. */
01755 
01756   if (isfuncname && (work->constructor & 1 || work->destructor & 1))
01757     {
01758       string_appendn (&temp, "::", 2);
01759       if (work -> destructor & 1)
01760         {
01761           string_append (&temp, "~");
01762         }
01763       string_appendn (&temp, (*mangled) - namelength, namelength);
01764     }
01765 
01766   /* Now either prepend the temp buffer to the result, or append it,
01767      depending upon the state of the append flag. */
01768 
01769   if (append)
01770     {
01771       string_appends (result, &temp);
01772     }
01773   else
01774     {
01775       if (!STRING_EMPTY (result))
01776         {
01777           string_appendn (&temp, "::", 2);
01778         }
01779       string_prepends (result, &temp);
01780     }
01781 
01782   string_delete (&temp);
01783   return (success);
01784 }
01785 
01786 /*
01787 
01788 LOCAL FUNCTION
01789 
01790         get_count -- convert an ascii count to integer, consuming tokens
01791 
01792 SYNOPSIS
01793 
01794         static int
01795         get_count (const char **type, int *count)
01796 
01797 DESCRIPTION
01798 
01799         Return 0 if no conversion is performed, 1 if a string is converted.
01800 */
01801 
01802 static int
01803 get_count (type, count)
01804      const char **type;
01805      int *count;
01806 {
01807   const char *p;
01808   int n;
01809 
01810   if (!isdigit (**type))
01811     {
01812       return (0);
01813     }
01814   else
01815     {
01816       *count = **type - '0';
01817       (*type)++;
01818       if (isdigit (**type))
01819         {
01820           p = *type;
01821           n = *count;
01822           do
01823             {
01824               n *= 10;
01825               n += *p - '0';
01826               p++;
01827             }
01828           while (isdigit (*p));
01829           if (*p == '_')
01830             {
01831               *type = p + 1;
01832               *count = n;
01833             }
01834         }
01835     }
01836   return (1);
01837 }
01838 
01839 /* result will be initialised here; it will be freed on failure */
01840 
01841 static int
01842 do_type (work, mangled, result)
01843      struct work_stuff *work;
01844      const char **mangled;
01845      string *result;
01846 {
01847   int n;
01848   int done;
01849   int success;
01850   string decl;
01851   const char *remembered_type;
01852   int constp;
01853   int volatilep;
01854 
01855   string_init (&decl);
01856   string_init (result);
01857 
01858   done = 0;
01859   success = 1;
01860   while (success && !done)
01861     {
01862       int member;
01863       switch (**mangled)
01864         {
01865 
01866         /* A pointer type */
01867         case 'P':
01868         case 'p':
01869           (*mangled)++;
01870           string_prepend (&decl, "*");
01871           break;
01872 
01873         /* A reference type */
01874         case 'R':
01875           (*mangled)++;
01876           string_prepend (&decl, "&");
01877           break;
01878 
01879         /* An array */
01880         case 'A':
01881           {
01882             const char *p = ++(*mangled);
01883 
01884             string_prepend (&decl, "(");
01885             string_append (&decl, ")[");
01886             /* Copy anything up until the next underscore (the size of the
01887                array).  */
01888             while (**mangled && **mangled != '_')
01889               ++(*mangled);
01890             if (**mangled == '_')
01891               {
01892                 string_appendn (&decl, p, *mangled - p);
01893                 string_append (&decl, "]");
01894                 *mangled += 1;
01895               }
01896             else
01897               success = 0;
01898             break;
01899           }
01900 
01901         /* A back reference to a previously seen type */
01902         case 'T':
01903           (*mangled)++;
01904           if (!get_count (mangled, &n) || n >= work -> ntypes)
01905             {
01906               success = 0;
01907             }
01908           else
01909             {
01910               remembered_type = work -> typevec[n];
01911               mangled = &remembered_type;
01912             }
01913           break;
01914 
01915         /* A function */
01916         case 'F':
01917           (*mangled)++;
01918           if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
01919             {
01920               string_prepend (&decl, "(");
01921               string_append (&decl, ")");
01922             }
01923           /* After picking off the function args, we expect to either find the
01924              function return type (preceded by an '_') or the end of the
01925              string. */
01926           if (!demangle_args (work, mangled, &decl)
01927               || (**mangled != '_' && **mangled != '\0'))
01928             {
01929               success = 0;
01930             }
01931           if (success && (**mangled == '_'))
01932             {
01933               (*mangled)++;
01934             }
01935           break;
01936 
01937         case 'M':
01938         case 'O':
01939           {
01940             constp = 0;
01941             volatilep = 0;
01942 
01943             member = **mangled == 'M';
01944             (*mangled)++;
01945             if (!isdigit (**mangled))
01946               {
01947                 success = 0;
01948                 break;
01949               }
01950             n = consume_count (mangled);
01951             if ((int)strlen (*mangled) < n)
01952               {
01953                 success = 0;
01954                 break;
01955               }
01956             string_append (&decl, ")");
01957             string_prepend (&decl, "::");
01958             string_prependn (&decl, *mangled, n);
01959             string_prepend (&decl, "(");
01960             *mangled += n;
01961             if (member)
01962               {
01963                 if (**mangled == 'C')
01964                   {
01965                     (*mangled)++;
01966                     constp = 1;
01967                   }
01968                 if (**mangled == 'V')
01969                   {
01970                     (*mangled)++;
01971                     volatilep = 1;
01972                   }
01973                 if (*(*mangled)++ != 'F')
01974                   {
01975                     success = 0;
01976                     break;
01977                   }
01978               }
01979             if ((member && !demangle_args (work, mangled, &decl))
01980                 || **mangled != '_')
01981               {
01982                 success = 0;
01983                 break;
01984               }
01985             (*mangled)++;
01986             if (! PRINT_ANSI_QUALIFIERS)
01987               {
01988                 break;
01989               }
01990             if (constp)
01991               {
01992                 APPEND_BLANK (&decl);
01993                 string_append (&decl, "const");
01994               }
01995             if (volatilep)
01996               {
01997                 APPEND_BLANK (&decl);
01998                 string_append (&decl, "volatile");
01999               }
02000             break;
02001           }
02002         case 'G':
02003             (*mangled)++;
02004             break;
02005 
02006         case 'C':
02007           (*mangled)++;
02008 /*
02009           if ((*mangled)[1] == 'P')
02010             {
02011 */
02012               if (PRINT_ANSI_QUALIFIERS)
02013                 {
02014                   if (!STRING_EMPTY (&decl))
02015                     {
02016                       string_prepend (&decl, " ");
02017                     }
02018                   string_prepend (&decl, "const");
02019                 }
02020               break;
02021 /*
02022             }
02023 */
02024 
02025           /* fall through */
02026         default:
02027           done = 1;
02028           break;
02029         }
02030     }
02031 
02032   switch (**mangled)
02033     {
02034       /* A qualified name, such as "Outer::Inner". */
02035       case 'Q':
02036         success = demangle_qualified (work, mangled, result, 0, 1);
02037         break;
02038 
02039       default:
02040         success = demangle_fund_type (work, mangled, result);
02041         break;
02042     }
02043 
02044   if (success)
02045     {
02046       if (!STRING_EMPTY (&decl))
02047         {
02048           string_append (result, " ");
02049           string_appends (result, &decl);
02050         }
02051     }
02052   else
02053     {
02054       string_delete (result);
02055     }
02056   string_delete (&decl);
02057   return (success);
02058 }
02059 
02060 /* Given a pointer to a type string that represents a fundamental type
02061    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
02062    string in which the demangled output is being built in RESULT, and
02063    the WORK structure, decode the types and add them to the result.
02064 
02065    For example:
02066 
02067         "Ci"    =>      "const int"
02068         "Sl"    =>      "signed long"
02069         "CUs"   =>      "const unsigned short"
02070 
02071    */
02072 
02073 static int
02074 demangle_fund_type (work, mangled, result)
02075      struct work_stuff *work;
02076      const char **mangled;
02077      string *result;
02078 {
02079   int done = 0;
02080   int success = 1;
02081 
02082   /* First pick off any type qualifiers.  There can be more than one. */
02083 
02084   while (!done)
02085     {
02086       switch (**mangled)
02087         {
02088           case 'C':
02089             (*mangled)++;
02090             if (PRINT_ANSI_QUALIFIERS)
02091               {
02092                 APPEND_BLANK (result);
02093                 string_append (result, "const");
02094               }
02095             break;
02096           case 'U':
02097             (*mangled)++;
02098             APPEND_BLANK (result);
02099             string_append (result, "unsigned");
02100             break;
02101           case 'S': /* signed char only */
02102             (*mangled)++;
02103             APPEND_BLANK (result);
02104             string_append (result, "signed");
02105             break;
02106           case 'V':
02107             (*mangled)++;
02108             if (PRINT_ANSI_QUALIFIERS)
02109               {
02110                 APPEND_BLANK (result);
02111                 string_append (result, "volatile");
02112               }
02113             break;
02114           default:
02115             done = 1;
02116             break;
02117         }
02118     }
02119 
02120   /* Now pick off the fundamental type.  There can be only one. */
02121 
02122   switch (**mangled)
02123     {
02124       case '\0':
02125       case '_':
02126         break;
02127       case 'v':
02128         (*mangled)++;
02129         APPEND_BLANK (result);
02130         string_append (result, "void");
02131         break;
02132       case 'x':
02133         (*mangled)++;
02134         APPEND_BLANK (result);
02135         string_append (result, "long long");
02136         break;
02137       case 'l':
02138         (*mangled)++;
02139         APPEND_BLANK (result);
02140         string_append (result, "long");
02141         break;
02142       case 'i':
02143         (*mangled)++;
02144         APPEND_BLANK (result);
02145         string_append (result, "int");
02146         break;
02147       case 's':
02148         (*mangled)++;
02149         APPEND_BLANK (result);
02150         string_append (result, "short");
02151         break;
02152       case 'b':
02153         (*mangled)++;
02154         APPEND_BLANK (result);
02155         string_append (result, "bool");
02156         break;
02157       case 'c':
02158         (*mangled)++;
02159         APPEND_BLANK (result);
02160         string_append (result, "char");
02161         break;
02162       case 'w':
02163         (*mangled)++;
02164         APPEND_BLANK (result);
02165         string_append (result, "wchar_t");
02166         break;
02167       case 'r':
02168         (*mangled)++;
02169         APPEND_BLANK (result);
02170         string_append (result, "long double");
02171         break;
02172       case 'd':
02173         (*mangled)++;
02174         APPEND_BLANK (result);
02175         string_append (result, "double");
02176         break;
02177       case 'f':
02178         (*mangled)++;
02179         APPEND_BLANK (result);
02180         string_append (result, "float");
02181         break;
02182       case 'G':
02183         (*mangled)++;
02184         if (!isdigit (**mangled))
02185           {
02186             success = 0;
02187             break;
02188           }
02189         /* fall through */
02190       /* An explicit type, such as "6mytype" or "7integer" */
02191       case '0':
02192       case '1':
02193       case '2':
02194       case '3':
02195       case '4':
02196       case '5':
02197       case '6':
02198       case '7':
02199       case '8':
02200       case '9':
02201         APPEND_BLANK (result);
02202         if (!demangle_class_name (work, mangled, result)) {
02203           --result->p;
02204           success = 0;
02205         }
02206         break;
02207       case 't':
02208         success = demangle_template(work,mangled, result, 0);
02209         break;
02210       default:
02211         success = 0;
02212         break;
02213       }
02214 
02215   return (success);
02216 }
02217 
02218 /* `result' will be initialized in do_type; it will be freed on failure */
02219 
02220 static int
02221 do_arg (work, mangled, result)
02222      struct work_stuff *work;
02223      const char **mangled;
02224      string *result;
02225 {
02226   const char *start = *mangled;
02227 
02228   if (!do_type (work, mangled, result))
02229     {
02230       return (0);
02231     }
02232   else
02233     {
02234       remember_type (work, start, *mangled - start);
02235       return (1);
02236     }
02237 }
02238 
02239 static void
02240 remember_type (work, start, len)
02241      struct work_stuff *work;
02242      const char *start;
02243      int len;
02244 {
02245   char *tem;
02246 
02247   if (work -> ntypes >= work -> typevec_size)
02248     {
02249       if (work -> typevec_size == 0)
02250         {
02251           work -> typevec_size = 3;
02252           work -> typevec =
02253             (char **) malloc (sizeof (char *) * work -> typevec_size);
02254         }
02255       else
02256         {
02257           work -> typevec_size *= 2;
02258           work -> typevec =
02259             (char **) realloc ((char *)work -> typevec,
02260                                 sizeof (char *) * work -> typevec_size);
02261         }
02262     }
02263   tem = malloc (len + 1);
02264   memcpy (tem, start, len);
02265   tem[len] = '\0';
02266   work -> typevec[work -> ntypes++] = tem;
02267 }
02268 
02269 /* Forget the remembered types, but not the type vector itself. */
02270 
02271 static void
02272 forget_types (work)
02273      struct work_stuff *work;
02274 {
02275   int i;
02276 
02277   while (work -> ntypes > 0)
02278     {
02279       i = --(work -> ntypes);
02280       if (work -> typevec[i] != NULL)
02281         {
02282           free (work -> typevec[i]);
02283           work -> typevec[i] = NULL;
02284         }
02285     }
02286 }
02287 
02288 /* Process the argument list part of the signature, after any class spec
02289    has been consumed, as well as the first 'F' character (if any).  For
02290    example:
02291 
02292    "__als__3fooRT0"             =>      process "RT0"
02293    "complexfunc5__FPFPc_PFl_i"  =>      process "PFPc_PFl_i"
02294 
02295    DECLP must be already initialised, usually non-empty.  It won't be freed
02296    on failure.
02297 
02298    Note that g++ differs significantly from ARM and lucid style mangling
02299    with regards to references to previously seen types.  For example, given
02300    the source fragment:
02301 
02302      class foo {
02303        public:
02304        foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
02305      };
02306 
02307      foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
02308      void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
02309 
02310    g++ produces the names:
02311 
02312      __3fooiRT0iT2iT2
02313      foo__FiR3fooiT1iT1
02314 
02315    while lcc (and presumably other ARM style compilers as well) produces:
02316 
02317      foo__FiR3fooT1T2T1T2
02318      __ct__3fooFiR3fooT1T2T1T2
02319 
02320    Note that g++ bases it's type numbers starting at zero and counts all
02321    previously seen types, while lucid/ARM bases it's type numbers starting
02322    at one and only considers types after it has seen the 'F' character
02323    indicating the start of the function args.  For lucid/ARM style, we
02324    account for this difference by discarding any previously seen types when
02325    we see the 'F' character, and subtracting one from the type number
02326    reference.
02327 
02328  */
02329 
02330 static int
02331 demangle_args (work, mangled, declp)
02332      struct work_stuff *work;
02333      const char **mangled;
02334      string *declp;
02335 {
02336   string arg;
02337   int need_comma = 0;
02338   int r;
02339   int t;
02340   const char *tem;
02341   char temptype;
02342 
02343   if (PRINT_ARG_TYPES)
02344     {
02345       string_append (declp, "(");
02346       if (**mangled == '\0')
02347         {
02348           string_append (declp, "void");
02349         }
02350     }
02351 
02352   while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
02353     {
02354       if ((**mangled == 'N') || (**mangled == 'T'))
02355         {
02356           temptype = *(*mangled)++;
02357 
02358           if (temptype == 'N')
02359             {
02360               if (!get_count (mangled, &r))
02361                 {
02362                   return (0);
02363                 }
02364             }
02365           else
02366             {
02367               r = 1;
02368             }
02369           if (ARM_DEMANGLING && work -> ntypes >= 10)
02370             {
02371               /* If we have 10 or more types we might have more than a 1 digit
02372                  index so we'll have to consume the whole count here. This
02373                  will loose if the next thing is a type name preceeded by a
02374                  count but it's impossible to demangle that case properly
02375                  anyway. Eg if we already have 12 types is T12Pc "(..., type1,
02376                  anyway. Eg if we already have 12 types is T12Pc "(..., type1,
02377                  Pc, ...)"  or "(..., type12, char *, ...)" */
02378               if ((t = consume_count(mangled)) == 0)
02379                 {
02380                   return (0);
02381                 }
02382             }
02383           else
02384             {
02385               if (!get_count (mangled, &t))
02386                 {
02387                   return (0);
02388                 }
02389             }
02390           if (LUCID_DEMANGLING || ARM_DEMANGLING)
02391             {
02392               t--;
02393             }
02394           /* Validate the type index.  Protect against illegal indices from
02395              malformed type strings. */
02396           if ((t < 0) || (t >= work -> ntypes))
02397             {
02398               return (0);
02399             }
02400           while (--r >= 0)
02401             {
02402               tem = work -> typevec[t];
02403               if (need_comma && PRINT_ARG_TYPES)
02404                 {
02405                   string_append (declp, ", ");
02406                 }
02407               if (!do_arg (work, &tem, &arg))
02408                 {
02409                   return (0);
02410                 }
02411               if (PRINT_ARG_TYPES)
02412                 {
02413                   string_appends (declp, &arg);
02414                 }
02415               string_delete (&arg);
02416               need_comma = 1;
02417             }
02418         }
02419       else
02420         {
02421           if (need_comma & PRINT_ARG_TYPES)
02422             {
02423               string_append (declp, ", ");
02424             }
02425           if (!do_arg (work, mangled, &arg))
02426             {
02427               return (0);
02428             }
02429           if (PRINT_ARG_TYPES)
02430             {
02431               string_appends (declp, &arg);
02432             }
02433           string_delete (&arg);
02434           need_comma = 1;
02435         }
02436     }
02437 
02438   if (**mangled == 'e')
02439     {
02440       (*mangled)++;
02441       if (PRINT_ARG_TYPES)
02442         {
02443           if (need_comma)
02444             {
02445               string_append (declp, ",");
02446             }
02447           string_append (declp, "...");
02448         }
02449     }
02450 
02451   if (PRINT_ARG_TYPES)
02452     {
02453       string_append (declp, ")");
02454     }
02455   return (1);
02456 }
02457 
02458 static void
02459 demangle_function_name (work, mangled, declp, scan)
02460      struct work_stuff *work;
02461      const char **mangled;
02462      string *declp;
02463      const char *scan;
02464 {
02465   int i;
02466   int len;
02467   string type;
02468   const char *tem;
02469 
02470   string_appendn (declp, (*mangled), scan - (*mangled));
02471   string_need (declp, 1);
02472   *(declp -> p) = '\0';
02473 
02474   /* Consume the function name, including the "__" separating the name
02475      from the signature.  We are guaranteed that SCAN points to the
02476      separator. */
02477 
02478   (*mangled) = scan + 2;
02479 
02480   if (LUCID_DEMANGLING || ARM_DEMANGLING)
02481     {
02482 
02483       /* See if we have an ARM style constructor or destructor operator.
02484          If so, then just record it, clear the decl, and return.
02485          We can't build the actual constructor/destructor decl until later,
02486          when we recover the class name from the signature. */
02487 
02488       if (strcmp (declp -> b, "__ct") == 0)
02489         {
02490           work -> constructor += 1;
02491           string_clear (declp);
02492           return;
02493         }
02494       else if (strcmp (declp -> b, "__dt") == 0)
02495         {
02496           work -> destructor += 1;
02497           string_clear (declp);
02498           return;
02499         }
02500     }
02501 
02502   if (declp->p - declp->b >= 3
02503       && declp->b[0] == 'o'
02504       && declp->b[1] == 'p'
02505       && strchr (cplus_markers, declp->b[2]) != NULL)
02506     {
02507       /* see if it's an assignment expression */
02508       if (declp->p - declp->b >= 10 /* op$assign_ */
02509           && memcmp (declp->b + 3, "assign_", 7) == 0)
02510         {
02511           for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
02512             {
02513               len = declp->p - declp->b - 10;
02514               if ((int)strlen (optable[i].in) == len
02515                   && memcmp (optable[i].in, declp->b + 10, len) == 0)
02516                 {
02517                   string_clear (declp);
02518                   string_append (declp, "operator");
02519                   string_append (declp, optable[i].out);
02520                   string_append (declp, "=");
02521                   break;
02522                 }
02523             }
02524         }
02525       else
02526         {
02527           for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
02528             {
02529               len = declp->p - declp->b - 3;
02530               if ((int)strlen(optable[i].in) == len
02531                   && memcmp (optable[i].in, declp->b + 3, len) == 0)
02532                 {
02533                   string_clear (declp);
02534                   string_append (declp, "operator");
02535                   string_append (declp, optable[i].out);
02536                   break;
02537                 }
02538             }
02539         }
02540     }
02541   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
02542            && strchr (cplus_markers, declp->b[4]) != NULL)
02543     {
02544       /* type conversion operator */
02545       tem = declp->b + 5;
02546       if (do_type (work, &tem, &type))
02547         {
02548           string_clear (declp);
02549           string_append (declp, "operator ");
02550           string_appends (declp, &type);
02551           string_delete (&type);
02552         }
02553     }
02554   else if (declp->b[0] == '_' && declp->b[1] == '_'
02555           && declp->b[2] == 'o' && declp->b[3] == 'p')
02556     {
02557       /* ANSI.  */
02558       /* type conversion operator.  */
02559       tem = declp->b + 4;
02560       if (do_type (work, &tem, &type))
02561         {
02562           string_clear (declp);
02563           string_append (declp, "operator ");
02564           string_appends (declp, &type);
02565           string_delete (&type);
02566         }
02567     }
02568   else if (declp->b[0] == '_' && declp->b[1] == '_'
02569            && declp->b[2] >= 'a' && declp->b[2] <= 'z'
02570            && declp->b[3] >= 'a' && declp->b[3] <= 'z')
02571     {
02572       if (declp->b[4] == '\0')
02573         {
02574           /* Operator.  */
02575           for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
02576             {
02577               if ((int)strlen (optable[i].in) == 2
02578                   && memcmp (optable[i].in, declp->b + 2, 2) == 0)
02579                 {
02580                   string_clear (declp);
02581                   string_append (declp, "operator");
02582                   string_append (declp, optable[i].out);
02583                   break;
02584                 }
02585             }
02586         }
02587       else
02588         {
02589           if (declp->b[2] == 'a' && declp->b[5] == '\0')
02590             {
02591               /* Assignment. */
02592               for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
02593                 {
02594                   if ((int)strlen (optable[i].in) == 3
02595                       && memcmp (optable[i].in, declp->b + 2, 3) == 0)
02596                     {
02597                       string_clear (declp);
02598                       string_append (declp, "operator");
02599                       string_append (declp, optable[i].out);
02600                       break;
02601                     }
02602                 }
02603             }
02604         }
02605     }
02606 }
02607 
02608 /* a mini string-handling package */
02609 
02610 static void
02611 string_need (s, n)
02612      string *s;
02613      int n;
02614 {
02615   int tem;
02616 
02617   if (s->b == NULL)
02618     {
02619       if (n < 32)
02620         {
02621           n = 32;
02622         }
02623       s->p = s->b = malloc (n);
02624       s->e = s->b + n;
02625     }
02626   else if (s->e - s->p < n)
02627     {
02628       tem = s->p - s->b;
02629       n += tem;
02630       n *= 2;
02631       s->b = realloc (s->b, n);
02632       s->p = s->b + tem;
02633       s->e = s->b + n;
02634     }
02635 }
02636 
02637 static void
02638 string_delete (s)
02639      string *s;
02640 {
02641   if (s->b != NULL)
02642     {
02643       free (s->b);
02644       s->b = s->e = s->p = NULL;
02645     }
02646 }
02647 
02648 static void
02649 string_init (s)
02650      string *s;
02651 {
02652   s->b = s->p = s->e = NULL;
02653 }
02654 
02655 static void
02656 string_clear (s)
02657      string *s;
02658 {
02659   s->p = s->b;
02660 }
02661 
02662 #if 0
02663 
02664 static int
02665 string_empty (s)
02666      string *s;
02667 {
02668   return (s->b == s->p);
02669 }
02670 
02671 #endif
02672 
02673 static void
02674 string_append (p, s)
02675      string *p;
02676      const char *s;
02677 {
02678   int n;
02679   if (s == NULL || *s == '\0')
02680     return;
02681   n = strlen (s);
02682   string_need (p, n);
02683   memcpy (p->p, s, n);
02684   p->p += n;
02685 }
02686 
02687 static void
02688 string_appends (p, s)
02689      string *p, *s;
02690 {
02691   int n;
02692 
02693   if (s->b != s->p)
02694     {
02695       n = s->p - s->b;
02696       string_need (p, n);
02697       memcpy (p->p, s->b, n);
02698       p->p += n;
02699     }
02700 }
02701 
02702 static void
02703 string_appendn (p, s, n)
02704      string *p;
02705      const char *s;
02706      int n;
02707 {
02708   if (n != 0)
02709     {
02710       string_need (p, n);
02711       memcpy (p->p, s, n);
02712       p->p += n;
02713     }
02714 }
02715 
02716 static void
02717 string_prepend (p, s)
02718      string *p;
02719      const char *s;
02720 {
02721   if (s != NULL && *s != '\0')
02722     {
02723       string_prependn (p, s, strlen (s));
02724     }
02725 }
02726 
02727 static void
02728 string_prepends (p, s)
02729      string *p, *s;
02730 {
02731   if (s->b != s->p)
02732     {
02733       string_prependn (p, s->b, s->p - s->b);
02734     }
02735 }
02736 
02737 static void
02738 string_prependn (p, s, n)
02739      string *p;
02740      const char *s;
02741      int n;
02742 {
02743   char *q;
02744 
02745   if (n != 0)
02746     {
02747       string_need (p, n);
02748       for (q = p->p - 1; q >= p->b; q--)
02749         {
02750           q[n] = q[0];
02751         }
02752       memcpy (p->b, s, n);
02753       p->p += n;
02754     }
02755 }
02756 
02757 /* To generate a standalone demangler program for testing purposes,
02758    just compile and link this file with -DMAIN and libiberty.a.  When
02759    run, it demangles each command line arg, or each stdin string, and
02760    prints the result on stdout. */
02761 
02762 #ifdef MAIN
02763 
02764 static void
02765 demangle_it (mangled_name)
02766   char *mangled_name;
02767 {
02768   char *result;
02769 
02770   result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI);
02771   if (result == NULL)
02772     {
02773       printf ("%s\n", mangled_name);
02774     }
02775   else
02776     {
02777       printf ("%s\n", result);
02778       free (result);
02779     }
02780 }
02781 
02782 #include "getopt.h"
02783 
02784 static char *program_name;
02785 extern char *program_version;
02786 
02787 static void
02788 usage (stream, status)
02789      FILE *stream;
02790      int status;
02791 {
02792   fprintf (stream, "\
02793 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
02794        [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
02795        [--help] [--version] [arg...]\n",
02796            program_name);
02797   exit (status);
02798 }
02799 
02800 #define MBUF_SIZE 512
02801 char mbuffer[MBUF_SIZE];
02802 
02803 /* Defined in the automatically-generated ../binutils/underscore.c. */
02804 extern int prepends_underscore;
02805 
02806 int strip_underscore = 0;
02807 
02808 static struct option long_options[] = {
02809   {"strip-underscores", no_argument, 0, '_'},
02810   {"format", required_argument, 0, 's'},
02811   {"help", no_argument, 0, 'h'},
02812   {"no-strip-underscores", no_argument, 0, 'n'},
02813   {"version", no_argument, 0, 'v'},
02814   {0, no_argument, 0, 0}
02815 };
02816 
02817 int
02818 main (argc, argv)
02819      int argc;
02820      char **argv;
02821 {
02822   char *result;
02823   int c;
02824 
02825   program_name = argv[0];
02826   malloc_set_program_name (program_name);
02827 
02828   strip_underscore = prepends_underscore;
02829 
02830   while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF)
02831     {
02832       switch (c)
02833         {
02834           case '?':
02835             usage (stderr, 1);
02836             break;
02837           case 'h':
02838             usage (stdout, 0);
02839           case 'n':
02840             strip_underscore = 0;
02841             break;
02842           case 'v':
02843             printf ("GNU %s version %s\n", program_name, program_version);
02844             exit (0);
02845           case '_':
02846             strip_underscore = 1;
02847             break;
02848           case 's':
02849             if (strcmp (optarg, "gnu") == 0)
02850               {
02851                 current_demangling_style = gnu_demangling;
02852               }
02853             else if (strcmp (optarg, "lucid") == 0)
02854               {
02855                 current_demangling_style = lucid_demangling;
02856               }
02857             else if (strcmp (optarg, "arm") == 0)
02858               {
02859                 current_demangling_style = arm_demangling;
02860               }
02861             else
02862               {
02863                 fprintf (stderr, "%s: unknown demangling style `%s'\n",
02864                          program_name, optarg);
02865                 exit (1);
02866               }
02867             break;
02868         }
02869     }
02870 
02871   if (optind < argc)
02872     {
02873       for ( ; optind < argc; optind++)
02874         {
02875           demangle_it (argv[optind]);
02876         }
02877     }
02878   else
02879     {
02880       for (;;)
02881         {
02882           int i = 0;
02883           c = getchar ();
02884           /* Try to read a label. */
02885           while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
02886             {
02887               if (i >= MBUF_SIZE-1)
02888                 break;
02889               mbuffer[i++] = c;
02890               c = getchar ();
02891             }
02892           if (i > 0)
02893             {
02894               int skip_first = strip_underscore && i > 1 && mbuffer[0] == '_';
02895               mbuffer[i] = 0;
02896 
02897               result = cplus_demangle (mbuffer+skip_first,
02898                                        DMGL_PARAMS | DMGL_ANSI);
02899               if (result)
02900                 {
02901                   fputs (result, stdout);
02902                   free (result);
02903                 }
02904               else
02905                 fputs (mbuffer + skip_first, stdout);
02906 
02907               fflush (stdout);
02908             }
02909           if (c == EOF)
02910             break;
02911           putchar (c);
02912         }
02913     }
02914 
02915   exit (0);
02916 }
02917 
02918 #endif  /* main */

Generated on Tue Jul 5 14:11:25 2011 for ROOT_528-00b_version by  doxygen 1.5.1