Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

cplus-dem.c

Go to the documentation of this file.
00001 /* Demangler for GNU C++
00002    Copyright 1989, 91, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
00003    Written by James Clark (jjc@jclark.uucp)
00004    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
00005    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
00006 
00007 This file is part of the libiberty library.
00008 Libiberty is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU Library General Public
00010 License as published by the Free Software Foundation; either
00011 version 2 of the License, or (at your option) any later version.
00012 
00013 Libiberty is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 Library General Public License for more details.
00017 
00018 You should have received a copy of the GNU Library General Public
00019 License along with libiberty; see the file COPYING.LIB.  If
00020 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00021 Boston, MA 02111-1307, USA.  */
00022 
00023 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
00024 
00025    This file imports xmalloc and xrealloc, which are like malloc and
00026    realloc except that they generate a fatal error if there is no
00027    available memory.  */
00028 
00029 /* This file lives in both GCC and libiberty.  When making changes, please
00030    try not to break either.  */
00031 
00032 #ifdef HAVE_CONFIG_H
00033 #include "config.h"
00034 #endif
00035 
00036 #include <ctype.h>
00037 #include <sys/types.h>
00038 #include <string.h>
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 
00042 #include "demangle.h"
00043 #undef CURRENT_DEMANGLING_STYLE
00044 #define CURRENT_DEMANGLING_STYLE work->options
00045 
00046 
00047 #define xmalloc malloc
00048 #define xrealloc realloc
00049 
00050 #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
00051 
00052 /* A value at least one greater than the maximum number of characters
00053    that will be output when using the `%d' format with `printf'.  */
00054 #define INTBUF_SIZE 32
00055 
00056 extern void fancy_abort (void);
00057 
00058 static const char *mystrstr (const char *, const char *);
00059 
00060 static const char *
00061 mystrstr (s1, s2)
00062         const char *s1, *s2;
00063 {
00064   register const char *p = s1;
00065   register int len = strlen (s2);
00066 
00067   for (; (p = strchr (p, *s2)) != 0; p++)
00068     {
00069          if (strncmp (p, s2, len) == 0)
00070         {
00071           return (p);
00072         }
00073     }
00074   return (0);
00075 }
00076 
00077 /* In order to allow a single demangler executable to demangle strings
00078    using various common values of CPLUS_MARKER, as well as any specific
00079    one set at compile time, we maintain a string containing all the
00080    commonly used ones, and check to see if the marker we are looking for
00081    is in that string.  CPLUS_MARKER is usually '$' on systems where the
00082    assembler can deal with that.  Where the assembler can't, it's usually
00083    '.' (but on many systems '.' is used for other things).  We put the
00084    current defined CPLUS_MARKER first (which defaults to '$'), followed
00085    by the next most common value, followed by an explicit '$' in case
00086    the value of CPLUS_MARKER is not '$'.
00087 
00088    We could avoid this if we could just get g++ to tell us what the actual
00089    cplus marker character is as part of the debug information, perhaps by
00090    ensuring that it is the character that terminates the gcc<n>_compiled
00091    marker symbol (FIXME).  */
00092 
00093 #if !defined (CPLUS_MARKER)
00094 #define CPLUS_MARKER '$'
00095 #endif
00096 
00097 enum demangling_styles current_demangling_style = gnu_demangling;
00098 
00099 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
00100 
00101 static char char_str[2] = { '\000', '\000' };
00102 
00103 void
00104 set_cplus_marker_for_demangling (ch)
00105         int ch;
00106 {
00107   cplus_markers[0] = ch;
00108 }
00109 
00110 typedef struct string           /* Beware: these aren't required to be */
00111 {                               /*  '\0' terminated.  */
00112   char *b;                      /* pointer to start of string */
00113   char *p;                      /* pointer after last character */
00114   char *e;                      /* pointer after end of allocated space */
00115 } string;
00116 
00117 /* Stuff that is shared between sub-routines.
00118    Using a shared structure allows cplus_demangle to be reentrant.  */
00119 
00120 struct work_stuff
00121 {
00122   int options;
00123   char **typevec;
00124   char **ktypevec;
00125   char **btypevec;
00126   int numk;
00127   int numb;
00128   int ksize;
00129   int bsize;
00130   int ntypes;
00131   int typevec_size;
00132   int constructor;
00133   int destructor;
00134   int static_type;      /* A static member function */
00135   int temp_start;       /* index in demangled to start of template args */
00136   int type_quals;       /* The type qualifiers.  */
00137   int dllimported;      /* Symbol imported from a PE DLL */
00138   char **tmpl_argvec;   /* Template function arguments. */
00139   int ntmpl_args;       /* The number of template function arguments. */
00140   int forgetting_types; /* Nonzero if we are not remembering the types
00141                            we see.  */
00142   string* previous_argument; /* The last function argument demangled.  */
00143   int nrepeats;         /* The number of times to repeat the previous
00144                            argument.  */
00145 };
00146 
00147 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
00148 #define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
00149 
00150 static const struct optable
00151 {
00152   const char *in;
00153   const char *out;
00154   int flags;
00155 } optable[] = {
00156   {"nw",          " new",       DMGL_ANSI},     /* new (1.92,    ansi) */
00157   {"dl",          " delete",    DMGL_ANSI},     /* new (1.92,    ansi) */
00158   {"new",         " new",       0},             /* old (1.91,    and 1.x) */
00159   {"delete",      " delete",    0},             /* old (1.91,    and 1.x) */
00160   {"vn",          " new []",    DMGL_ANSI},     /* GNU, pending ansi */
00161   {"vd",          " delete []", DMGL_ANSI},     /* GNU, pending ansi */
00162   {"as",          "=",          DMGL_ANSI},     /* ansi */
00163   {"ne",          "!=",         DMGL_ANSI},     /* old, ansi */
00164   {"eq",          "==",         DMGL_ANSI},     /* old, ansi */
00165   {"ge",          ">=",         DMGL_ANSI},     /* old, ansi */
00166   {"gt",          ">",          DMGL_ANSI},     /* old, ansi */
00167   {"le",          "<=",         DMGL_ANSI},     /* old, ansi */
00168   {"lt",          "<",          DMGL_ANSI},     /* old, ansi */
00169   {"plus",        "+",          0},             /* old */
00170   {"pl",          "+",          DMGL_ANSI},     /* ansi */
00171   {"apl",         "+=",         DMGL_ANSI},     /* ansi */
00172   {"minus",       "-",          0},             /* old */
00173   {"mi",          "-",          DMGL_ANSI},     /* ansi */
00174   {"ami",         "-=",         DMGL_ANSI},     /* ansi */
00175   {"mult",        "*",          0},             /* old */
00176   {"ml",          "*",          DMGL_ANSI},     /* ansi */
00177   {"amu",         "*=",         DMGL_ANSI},     /* ansi (ARM/Lucid) */
00178   {"aml",         "*=",         DMGL_ANSI},     /* ansi (GNU/g++) */
00179   {"convert",     "+",          0},             /* old (unary +) */
00180   {"negate",      "-",          0},             /* old (unary -) */
00181   {"trunc_mod",   "%",          0},             /* old */
00182   {"md",          "%",          DMGL_ANSI},     /* ansi */
00183   {"amd",         "%=",         DMGL_ANSI},     /* ansi */
00184   {"trunc_div",   "/",          0},             /* old */
00185   {"dv",          "/",          DMGL_ANSI},     /* ansi */
00186   {"adv",         "/=",         DMGL_ANSI},     /* ansi */
00187   {"truth_andif", "&&",         0},             /* old */
00188   {"aa",          "&&",         DMGL_ANSI},     /* ansi */
00189   {"truth_orif",  "||",         0},             /* old */
00190   {"oo",          "||",         DMGL_ANSI},     /* ansi */
00191   {"truth_not",   "!",          0},             /* old */
00192   {"nt",          "!",          DMGL_ANSI},     /* ansi */
00193   {"postincrement","++",        0},             /* old */
00194   {"pp",          "++",         DMGL_ANSI},     /* ansi */
00195   {"postdecrement","--",        0},             /* old */
00196   {"mm",          "--",         DMGL_ANSI},     /* ansi */
00197   {"bit_ior",     "|",          0},             /* old */
00198   {"or",          "|",          DMGL_ANSI},     /* ansi */
00199   {"aor",         "|=",         DMGL_ANSI},     /* ansi */
00200   {"bit_xor",     "^",          0},             /* old */
00201   {"er",          "^",          DMGL_ANSI},     /* ansi */
00202   {"aer",         "^=",         DMGL_ANSI},     /* ansi */
00203   {"bit_and",     "&",          0},             /* old */
00204   {"ad",          "&",          DMGL_ANSI},     /* ansi */
00205   {"aad",         "&=",         DMGL_ANSI},     /* ansi */
00206   {"bit_not",     "~",          0},             /* old */
00207   {"co",          "~",          DMGL_ANSI},     /* ansi */
00208   {"call",        "()",         0},             /* old */
00209   {"cl",          "()",         DMGL_ANSI},     /* ansi */
00210   {"alshift",     "<<",         0},             /* old */
00211   {"ls",          "<<",         DMGL_ANSI},     /* ansi */
00212   {"als",         "<<=",        DMGL_ANSI},     /* ansi */
00213   {"arshift",     ">>",         0},             /* old */
00214   {"rs",          ">>",         DMGL_ANSI},     /* ansi */
00215   {"ars",         ">>=",        DMGL_ANSI},     /* ansi */
00216   {"component",   "->",         0},             /* old */
00217   {"pt",          "->",         DMGL_ANSI},     /* ansi; Lucid C++ form */
00218   {"rf",          "->",         DMGL_ANSI},     /* ansi; ARM/GNU form */
00219   {"indirect",    "*",          0},             /* old */
00220   {"method_call",  "->()",      0},             /* old */
00221   {"addr",        "&",          0},             /* old (unary &) */
00222   {"array",       "[]",         0},             /* old */
00223   {"vc",          "[]",         DMGL_ANSI},     /* ansi */
00224   {"compound",    ", ",         0},             /* old */
00225   {"cm",          ", ",         DMGL_ANSI},     /* ansi */
00226   {"cond",        "?:",         0},             /* old */
00227   {"cn",          "?:",         DMGL_ANSI},     /* pseudo-ansi */
00228   {"max",         ">?",         0},             /* old */
00229   {"mx",          ">?",         DMGL_ANSI},     /* pseudo-ansi */
00230   {"min",         "<?",         0},             /* old */
00231   {"mn",          "<?",         DMGL_ANSI},     /* pseudo-ansi */
00232   {"nop",         "",           0},             /* old (for operator=) */
00233   {"rm",          "->*",        DMGL_ANSI},     /* ansi */
00234   {"sz",          "sizeof ",    DMGL_ANSI}      /* pseudo-ansi */
00235 };
00236 
00237 /* These values are used to indicate the various type varieties.
00238    They are all non-zero so that they can be used as `success'
00239    values.  */
00240 typedef enum type_kind_t
00241 {
00242   tk_none,
00243   tk_pointer,
00244   tk_reference,
00245   tk_integral,
00246   tk_bool,
00247   tk_char,
00248   tk_real
00249 } type_kind_t;
00250 
00251 #define STRING_EMPTY(str)       ((str) -> b == (str) -> p)
00252 #define PREPEND_BLANK(str)      {if (!STRING_EMPTY(str)) \
00253     string_prepend(str, " ");}
00254 #define APPEND_BLANK(str)       {if (!STRING_EMPTY(str)) \
00255     string_append(str, " ");}
00256 #define LEN_STRING(str)         ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
00257 
00258 /* The scope separator appropriate for the language being demangled.  */
00259 
00260 #define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
00261 
00262 #define ARM_VTABLE_STRING "__vtbl__"    /* Lucid/ARM virtual table prefix */
00263 #define ARM_VTABLE_STRLEN 8             /* strlen (ARM_VTABLE_STRING) */
00264 
00265 /* Prototypes for local functions */
00266 
00267 static char *
00268 mop_up (struct work_stuff *, string *, int);
00269 
00270 static void
00271 squangle_mop_up (struct work_stuff *);
00272 
00273 #if 0
00274 static int
00275 demangle_method_args (struct work_stuff *, const char **, string *);
00276 #endif
00277 
00278 static char *
00279 internal_cplus_demangle (struct work_stuff *, const char *);
00280 
00281 static int
00282 demangle_template_template_parm (struct work_stuff *work,
00283                                          const char **, string *);
00284 
00285 static int
00286 demangle_template (struct work_stuff *work, const char **, string *,
00287                            string *, int, int);
00288 
00289 static int
00290 arm_pt (struct work_stuff *, const char *, int, const char **,
00291                 const char **);
00292 
00293 static int
00294 demangle_class_name (struct work_stuff *, const char **, string *);
00295 
00296 static int
00297 demangle_qualified (struct work_stuff *, const char **, string *,
00298                             int, int);
00299 
00300 static int
00301 demangle_class (struct work_stuff *, const char **, string *);
00302 
00303 static int
00304 demangle_fund_type (struct work_stuff *, const char **, string *);
00305 
00306 static int
00307 demangle_signature (struct work_stuff *, const char **, string *);
00308 
00309 static int
00310 demangle_prefix (struct work_stuff *, const char **, string *);
00311 
00312 static int
00313 gnu_special (struct work_stuff *, const char **, string *);
00314 
00315 static int
00316 arm_special (const char **, string *);
00317 
00318 static void
00319 string_need (string *, int);
00320 
00321 static void
00322 string_delete (string *);
00323 
00324 static void
00325 string_init (string *);
00326 
00327 static void
00328 string_clear (string *);
00329 
00330 #if 0
00331 static int
00332 string_empty (string *);
00333 #endif
00334 
00335 static void
00336 string_append (string *, const char *);
00337 
00338 static void
00339 string_appends (string *, string *);
00340 
00341 static void
00342 string_appendn (string *, const char *, int);
00343 
00344 static void
00345 string_prepend (string *, const char *);
00346 
00347 static void
00348 string_prependn (string *, const char *, int);
00349 
00350 static void
00351 string_append_template_idx (string *, int);
00352 
00353 static int
00354 get_count (const char **, int *);
00355 
00356 static int
00357 consume_count (const char **);
00358 
00359 static int
00360 consume_count_with_underscores (const char**);
00361 
00362 static int
00363 demangle_args (struct work_stuff *, const char **, string *);
00364 
00365 static int
00366 demangle_nested_args (struct work_stuff*, const char**, string*);
00367 
00368 static int
00369 do_type (struct work_stuff *, const char **, string *);
00370 
00371 static int
00372 do_arg (struct work_stuff *, const char **, string *);
00373 
00374 static void
00375 demangle_function_name (struct work_stuff *, const char **, string *,
00376                                 const char *);
00377 
00378 static void
00379 remember_type (struct work_stuff *, const char *, int);
00380 
00381 static void
00382 remember_Btype (struct work_stuff *, const char *, int, int);
00383 
00384 static int
00385 register_Btype (struct work_stuff *);
00386 
00387 static void
00388 remember_Ktype (struct work_stuff *, const char *, int);
00389 
00390 static void
00391 forget_types (struct work_stuff *);
00392 
00393 static void
00394 forget_B_and_K_types (struct work_stuff *);
00395 
00396 static void
00397 string_prepends (string *, string *);
00398 
00399 static int
00400 demangle_template_value_parm (struct work_stuff*, const char**,
00401                                          string*, type_kind_t);
00402 
00403 static int
00404 do_hpacc_template_const_value (struct work_stuff *, const char **, string *);
00405 
00406 static int
00407 do_hpacc_template_literal (struct work_stuff *, const char **, string *);
00408 
00409 static int
00410 snarf_numeric_literal (const char **, string *);
00411 
00412 /* There is a TYPE_QUAL value for each type qualifier.  They can be
00413    combined by bitwise-or to form the complete set of qualifiers for a
00414    type.  */
00415 
00416 #define TYPE_UNQUALIFIED   0x0
00417 #define TYPE_QUAL_CONST    0x1
00418 #define TYPE_QUAL_VOLATILE 0x2
00419 #define TYPE_QUAL_RESTRICT 0x4
00420 
00421 static int
00422 code_for_qualifier (int);
00423 
00424 static const char*
00425 qualifier_string (int);
00426 
00427 static const char*
00428 demangle_qualifier (int);
00429 
00430 static int
00431 demangle_expression (struct work_stuff *, const char **, string *, 
00432                                 type_kind_t);
00433 
00434 static int
00435 demangle_integral_value (struct work_stuff *, const char **,
00436                                  string *);
00437 
00438 static int
00439 demangle_real_value (struct work_stuff *, const char **, string *);
00440 
00441 static void
00442 demangle_arm_hp_template (struct work_stuff *, const char **, int,
00443                                   string *);
00444 
00445 static void
00446 recursively_demangle (struct work_stuff *, const char **, string *,
00447                                  int);
00448 
00449 /* Translate count to integer, consuming tokens in the process.
00450    Conversion terminates on the first non-digit character.
00451 
00452    Trying to consume something that isn't a count results in no
00453    consumption of input and a return of -1.
00454 
00455    Overflow consumes the rest of the digits, and returns -1.  */
00456 
00457 static int
00458 consume_count (type)
00459         const char **type;
00460 {
00461   int count = 0;
00462 
00463   if (! isdigit ((unsigned char)**type))
00464     return -1;
00465 
00466   while (isdigit ((unsigned char)**type))
00467     {
00468          count *= 10;
00469 
00470          /* Check for overflow.
00471          We assume that count is represented using two's-complement;
00472          no power of two is divisible by ten, so if an overflow occurs
00473          when multiplying by ten, the result will not be a multiple of
00474          ten.  */
00475          if ((count % 10) != 0)
00476         {
00477           while (isdigit ((unsigned char) **type))
00478             (*type)++;
00479           return -1;
00480         }
00481 
00482          count += **type - '0';
00483          (*type)++;
00484     }
00485 
00486   return (count);
00487 }
00488 
00489 
00490 /* Like consume_count, but for counts that are preceded and followed
00491    by '_' if they are greater than 10.  Also, -1 is returned for
00492    failure, since 0 can be a valid value.  */
00493 
00494 static int
00495 consume_count_with_underscores (mangled)
00496         const char **mangled;
00497 {
00498   int idx;
00499 
00500   if (**mangled == '_')
00501     {
00502          (*mangled)++;
00503          if (!isdigit ((unsigned char)**mangled))
00504         return -1;
00505 
00506          idx = consume_count (mangled);
00507          if (**mangled != '_')
00508         /* The trailing underscore was missing. */
00509         return -1;
00510 
00511          (*mangled)++;
00512     }
00513   else
00514     {
00515          if (**mangled < '0' || **mangled > '9')
00516         return -1;
00517 
00518          idx = **mangled - '0';
00519          (*mangled)++;
00520     }
00521 
00522   return idx;
00523 }
00524 
00525 /* C is the code for a type-qualifier.  Return the TYPE_QUAL
00526    corresponding to this qualifier.  */
00527 
00528 static int
00529 code_for_qualifier (c)
00530   int c;
00531 {
00532   switch (c)
00533     {
00534     case 'C':
00535          return TYPE_QUAL_CONST;
00536 
00537     case 'V':
00538          return TYPE_QUAL_VOLATILE;
00539 
00540     case 'u':
00541          return TYPE_QUAL_RESTRICT;
00542 
00543     default:
00544          break;
00545     }
00546 
00547   /* C was an invalid qualifier.  */
00548   abort ();
00549 }
00550 
00551 /* Return the string corresponding to the qualifiers given by
00552    TYPE_QUALS.  */
00553 
00554 static const char*
00555 qualifier_string (type_quals)
00556         int type_quals;
00557 {
00558   switch (type_quals)
00559     {
00560     case TYPE_UNQUALIFIED:
00561          return "";
00562 
00563     case TYPE_QUAL_CONST:
00564          return "const";
00565 
00566     case TYPE_QUAL_VOLATILE:
00567          return "volatile";
00568 
00569     case TYPE_QUAL_RESTRICT:
00570          return "__restrict";
00571 
00572     case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
00573          return "const volatile";
00574 
00575     case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
00576          return "const __restrict";
00577 
00578     case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
00579          return "volatile __restrict";
00580 
00581     case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
00582          return "const volatile __restrict";
00583 
00584     default:
00585          break;
00586     }
00587 
00588   /* TYPE_QUALS was an invalid qualifier set.  */
00589   abort ();
00590 }
00591 
00592 /* C is the code for a type-qualifier.  Return the string
00593    corresponding to this qualifier.  This function should only be
00594    called with a valid qualifier code.  */
00595 
00596 static const char*
00597 demangle_qualifier (c)
00598   int c;
00599 {
00600   return qualifier_string (code_for_qualifier (c));
00601 }
00602 
00603 int
00604 cplus_demangle_opname (opname, result, options)
00605         const char *opname;
00606         char *result;
00607         int options;
00608 {
00609   int len, len1, ret;
00610   string type;
00611   struct work_stuff work[1];
00612   const char *tem;
00613 
00614   len = strlen(opname);
00615   result[0] = '\0';
00616   ret = 0;
00617   memset ((char *) work, 0, sizeof (work));
00618   work->options = options;
00619 
00620   if (opname[0] == '_' && opname[1] == '_'
00621          && opname[2] == 'o' && opname[3] == 'p')
00622     {
00623          /* ANSI.  */
00624          /* type conversion operator.  */
00625          tem = opname + 4;
00626          if (do_type (work, &tem, &type))
00627         {
00628           strcat (result, "operator ");
00629           strncat (result, type.b, type.p - type.b);
00630           string_delete (&type);
00631           ret = 1;
00632         }
00633     }
00634   else if (opname[0] == '_' && opname[1] == '_'
00635            && opname[2] >= 'a' && opname[2] <= 'z'
00636            && opname[3] >= 'a' && opname[3] <= 'z')
00637     {
00638          if (opname[4] == '\0')
00639         {
00640           /* Operator.  */
00641           size_t i;
00642           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
00643             {
00644                  if (strlen (optable[i].in) == 2
00645                   && memcmp (optable[i].in, opname + 2, 2) == 0)
00646                 {
00647                   strcat (result, "operator");
00648                   strcat (result, optable[i].out);
00649                   ret = 1;
00650                   break;
00651                 }
00652             }
00653         }
00654          else
00655         {
00656           if (opname[2] == 'a' && opname[5] == '\0')
00657             {
00658                  /* Assignment.  */
00659                  size_t i;
00660                  for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
00661                 {
00662                   if (strlen (optable[i].in) == 3
00663                          && memcmp (optable[i].in, opname + 2, 3) == 0)
00664                     {
00665                          strcat (result, "operator");
00666                          strcat (result, optable[i].out);
00667                          ret = 1;
00668                          break;
00669                     }
00670                 }
00671             }
00672         }
00673     }
00674   else if (len >= 3
00675            && opname[0] == 'o'
00676            && opname[1] == 'p'
00677            && strchr (cplus_markers, opname[2]) != NULL)
00678     {
00679          /* see if it's an assignment expression */
00680          if (len >= 10 /* op$assign_ */
00681           && memcmp (opname + 3, "assign_", 7) == 0)
00682         {
00683           size_t i;
00684           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
00685             {
00686                  len1 = len - 10;
00687                  if ((int) strlen (optable[i].in) == len1
00688                   && memcmp (optable[i].in, opname + 10, len1) == 0)
00689                 {
00690                   strcat (result, "operator");
00691                   strcat (result, optable[i].out);
00692                   strcat (result, "=");
00693                   ret = 1;
00694                   break;
00695                 }
00696             }
00697         }
00698          else
00699         {
00700           size_t i;
00701           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
00702             {
00703                  len1 = len - 3;
00704                  if ((int) strlen (optable[i].in) == len1
00705                   && memcmp (optable[i].in, opname + 3, len1) == 0)
00706                 {
00707                   strcat (result, "operator");
00708                   strcat (result, optable[i].out);
00709                   ret = 1;
00710                   break;
00711                 }
00712             }
00713         }
00714     }
00715   else if (len >= 5 && memcmp (opname, "type", 4) == 0
00716            && strchr (cplus_markers, opname[4]) != NULL)
00717     {
00718          /* type conversion operator */
00719          tem = opname + 5;
00720          if (do_type (work, &tem, &type))
00721         {
00722           strcat (result, "operator ");
00723           strncat (result, type.b, type.p - type.b);
00724           string_delete (&type);
00725           ret = 1;
00726         }
00727     }
00728   squangle_mop_up (work);
00729   return ret;
00730 
00731 }
00732 /* Takes operator name as e.g. "++" and returns mangled
00733    operator name (e.g. "postincrement_expr"), or NULL if not found.
00734 
00735    If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
00736    if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
00737 
00738 const char *
00739 cplus_mangle_opname (opname, options)
00740         const char *opname;
00741         int options;
00742 {
00743   size_t i;
00744   int len;
00745 
00746   len = strlen (opname);
00747   for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
00748     {
00749          if ((int) strlen (optable[i].out) == len
00750           && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
00751           && memcmp (optable[i].out, opname, len) == 0)
00752         return optable[i].in;
00753     }
00754   return (0);
00755 }
00756 
00757 /* char *cplus_demangle (const char *mangled, int options)
00758 
00759    If MANGLED is a mangled function name produced by GNU C++, then
00760    a pointer to a malloced string giving a C++ representation
00761    of the name will be returned; otherwise NULL will be returned.
00762    It is the caller's responsibility to free the string which
00763    is returned.
00764 
00765    The OPTIONS arg may contain one or more of the following bits:
00766 
00767         DMGL_ANSI       ANSI qualifiers such as `const' and `void' are
00768                         included.
00769         DMGL_PARAMS     Function parameters are included.
00770 
00771    For example,
00772 
00773    cplus_demangle ("foo__1Ai", DMGL_PARAMS)             => "A::foo(int)"
00774    cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
00775    cplus_demangle ("foo__1Ai", 0)                       => "A::foo"
00776 
00777    cplus_demangle ("foo__1Afe", DMGL_PARAMS)            => "A::foo(float,...)"
00778    cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
00779    cplus_demangle ("foo__1Afe", 0)                      => "A::foo"
00780 
00781    Note that any leading underscores, or other such characters prepended by
00782    the compilation system, are presumed to have already been stripped from
00783    MANGLED.  */
00784 
00785 char *
00786 cplus_demangle (mangled, options)
00787         const char *mangled;
00788         int options;
00789 {
00790   char *ret;
00791   struct work_stuff work[1];
00792   memset ((char *) work, 0, sizeof (work));
00793   work -> options = options;
00794   if ((work -> options & DMGL_STYLE_MASK) == 0)
00795     work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK;
00796 
00797   ret = internal_cplus_demangle (work, mangled);
00798   squangle_mop_up (work);
00799   return (ret);
00800 }
00801 
00802 
00803 /* This function performs most of what cplus_demangle use to do, but
00804    to be able to demangle a name with a B, K or n code, we need to
00805    have a longer term memory of what types have been seen. The original
00806    now intializes and cleans up the squangle code info, while internal
00807    calls go directly to this routine to avoid resetting that info. */
00808 
00809 static char *
00810 internal_cplus_demangle (work, mangled)
00811         struct work_stuff *work;
00812         const char *mangled;
00813 {
00814 
00815   string decl;
00816   int success = 0;
00817   char *demangled = NULL;
00818   int s1,s2,s3,s4;
00819   s1 = work->constructor;
00820   s2 = work->destructor;
00821   s3 = work->static_type;
00822   s4 = work->type_quals;
00823   work->constructor = work->destructor = 0;
00824   work->type_quals = TYPE_UNQUALIFIED;
00825   work->dllimported = 0;
00826 
00827   if ((mangled != NULL) && (*mangled != '\0'))
00828     {
00829          string_init (&decl);
00830 
00831          /* First check to see if gnu style demangling is active and if the
00832          string to be demangled contains a CPLUS_MARKER.  If so, attempt to
00833          recognize one of the gnu special forms rather than looking for a
00834          standard prefix.  In particular, don't worry about whether there
00835          is a "__" string in the mangled string.  Consider "_$_5__foo" for
00836          example.  */
00837 
00838          if ((AUTO_DEMANGLING || GNU_DEMANGLING))
00839         {
00840           success = gnu_special (work, &mangled, &decl);
00841         }
00842          if (!success)
00843         {
00844           success = demangle_prefix (work, &mangled, &decl);
00845         }
00846          if (success && (*mangled != '\0'))
00847         {
00848           success = demangle_signature (work, &mangled, &decl);
00849         }
00850          if (work->constructor == 2)
00851            {
00852                 string_prepend (&decl, "global constructors keyed to ");
00853                 work->constructor = 0;
00854            }
00855          else if (work->destructor == 2)
00856            {
00857                 string_prepend (&decl, "global destructors keyed to ");
00858                 work->destructor = 0;
00859            }
00860          else if (work->dllimported == 1)
00861            {
00862                 string_prepend (&decl, "import stub for ");
00863                 work->dllimported = 0;
00864            }
00865          demangled = mop_up (work, &decl, success);
00866     }
00867   work->constructor = s1;
00868   work->destructor = s2;
00869   work->static_type = s3;
00870   work->type_quals = s4;
00871   return (demangled);
00872 }
00873 
00874 
00875 /* Clear out and squangling related storage */
00876 static void
00877 squangle_mop_up (work)
00878         struct work_stuff *work;
00879 {
00880   /* clean up the B and K type mangling types. */
00881   forget_B_and_K_types (work);
00882   if (work -> btypevec != NULL)
00883     {
00884          free ((char *) work -> btypevec);
00885     }
00886   if (work -> ktypevec != NULL)
00887     {
00888          free ((char *) work -> ktypevec);
00889     }
00890 }
00891 
00892 /* Clear out any mangled storage */
00893 
00894 static char *
00895 mop_up (work, declp, success)
00896         struct work_stuff *work;
00897         string *declp;
00898         int success;
00899 {
00900   char *demangled = NULL;
00901 
00902   /* Discard the remembered types, if any.  */
00903 
00904   forget_types (work);
00905   if (work -> typevec != NULL)
00906     {
00907          free ((char *) work -> typevec);
00908          work -> typevec = NULL;
00909          work -> typevec_size = 0;
00910     }
00911   if (work->tmpl_argvec)
00912     {
00913          int i;
00914 
00915          for (i = 0; i < work->ntmpl_args; i++)
00916         if (work->tmpl_argvec[i])
00917           free ((char*) work->tmpl_argvec[i]);
00918 
00919          free ((char*) work->tmpl_argvec);
00920          work->tmpl_argvec = NULL;
00921     }
00922   if (work->previous_argument)
00923     {
00924          string_delete (work->previous_argument);
00925          free ((char*) work->previous_argument);
00926          work->previous_argument = NULL;
00927     }
00928 
00929   /* If demangling was successful, ensure that the demangled string is null
00930         terminated and return it.  Otherwise, free the demangling decl.  */
00931 
00932   if (!success)
00933     {
00934          string_delete (declp);
00935     }
00936   else
00937     {
00938          string_appendn (declp, "", 1);
00939          demangled = declp -> b;
00940     }
00941   return (demangled);
00942 }
00943 
00944 /*
00945 
00946 LOCAL FUNCTION
00947 
00948         demangle_signature -- demangle the signature part of a mangled name
00949 
00950 SYNOPSIS
00951 
00952         static int
00953         demangle_signature (struct work_stuff *work, const char **mangled,
00954                             string *declp);
00955 
00956 DESCRIPTION
00957 
00958         Consume and demangle the signature portion of the mangled name.
00959 
00960         DECLP is the string where demangled output is being built.  At
00961         entry it contains the demangled root name from the mangled name
00962         prefix.  I.E. either a demangled operator name or the root function
00963         name.  In some special cases, it may contain nothing.
00964 
00965         *MANGLED points to the current unconsumed location in the mangled
00966         name.  As tokens are consumed and demangling is performed, the
00967         pointer is updated to continuously point at the next token to
00968         be consumed.
00969 
00970         Demangling GNU style mangled names is nasty because there is no
00971         explicit token that marks the start of the outermost function
00972         argument list.  */
00973 
00974 static int
00975 demangle_signature (work, mangled, declp)
00976         struct work_stuff *work;
00977         const char **mangled;
00978         string *declp;
00979 {
00980   int success = 1;
00981   int func_done = 0;
00982   int expect_func = 0;
00983   int expect_return_type = 0;
00984   const char *oldmangled = NULL;
00985   string trawname;
00986   string tname;
00987 
00988   while (success && (**mangled != '\0'))
00989     {
00990          switch (**mangled)
00991         {
00992         case 'Q':
00993           oldmangled = *mangled;
00994           success = demangle_qualified (work, mangled, declp, 1, 0);
00995           if (success)
00996             remember_type (work, oldmangled, *mangled - oldmangled);
00997           if (AUTO_DEMANGLING || GNU_DEMANGLING)
00998             expect_func = 1;
00999           oldmangled = NULL;
01000           break;
01001 
01002            case 'K':
01003           oldmangled = *mangled;
01004           success = demangle_qualified (work, mangled, declp, 1, 0);
01005           if (AUTO_DEMANGLING || GNU_DEMANGLING)
01006             {
01007                  expect_func = 1;
01008             }
01009           oldmangled = NULL;
01010           break;
01011 
01012         case 'S':
01013           /* Static member function */
01014           if (oldmangled == NULL)
01015             {
01016                  oldmangled = *mangled;
01017             }
01018           (*mangled)++;
01019           work -> static_type = 1;
01020           break;
01021 
01022         case 'C':
01023         case 'V':
01024         case 'u':
01025           work->type_quals |= code_for_qualifier (**mangled);
01026 
01027           /* a qualified member function */
01028           if (oldmangled == NULL)
01029             oldmangled = *mangled;
01030           (*mangled)++;
01031           break;
01032 
01033         case 'L':
01034           /* Local class name follows after "Lnnn_" */
01035           if (HP_DEMANGLING)
01036             {
01037                  while (**mangled && (**mangled != '_'))
01038                 (*mangled)++;
01039                  if (!**mangled)
01040                 success = 0;
01041                  else
01042                 (*mangled)++;
01043             }
01044           else
01045             success = 0;
01046           break;
01047 
01048         case '0': case '1': case '2': case '3': case '4':
01049         case '5': case '6': case '7': case '8': case '9':
01050           if (oldmangled == NULL)
01051             {
01052                  oldmangled = *mangled;
01053             }
01054                 work->temp_start = -1; /* uppermost call to demangle_class */
01055           success = demangle_class (work, mangled, declp);
01056           if (success)
01057             {
01058                  remember_type (work, oldmangled, *mangled - oldmangled);
01059             }
01060           if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
01061             {
01062                     /* EDG and others will have the "F", so we let the loop cycle
01063                           if we are looking at one. */
01064                     if (**mangled != 'F')
01065                           expect_func = 1;
01066             }
01067           oldmangled = NULL;
01068           break;
01069 
01070         case 'B':
01071           {
01072             string s;
01073             success = do_type (work, mangled, &s);
01074             if (success)
01075                  {
01076                 string_append (&s, SCOPE_STRING (work));
01077                 string_prepends (declp, &s);
01078                  }
01079             oldmangled = NULL;
01080             expect_func = 1;
01081           }
01082           break;
01083 
01084         case 'F':
01085           /* Function */
01086           /* ARM/HP style demangling includes a specific 'F' character after
01087                 the class name.  For GNU style, it is just implied.  So we can
01088                 safely just consume any 'F' at this point and be compatible
01089                 with either style.  */
01090 
01091           oldmangled = NULL;
01092           func_done = 1;
01093           (*mangled)++;
01094 
01095           /* For lucid/ARM/HP style we have to forget any types we might
01096                 have remembered up to this point, since they were not argument
01097                 types.  GNU style considers all types seen as available for
01098                 back references.  See comment in demangle_args() */
01099 
01100           if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
01101             {
01102                  forget_types (work);
01103             }
01104           success = demangle_args (work, mangled, declp);
01105           /* After picking off the function args, we expect to either
01106                 find the function return type (preceded by an '_') or the
01107                 end of the string. */
01108           if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
01109             {
01110                  ++(*mangled);
01111                     /* At this level, we do not care about the return type. */
01112                     success = do_type (work, mangled, &tname);
01113                     string_delete (&tname);
01114                   }
01115 
01116           break;
01117 
01118         case 't':
01119           /* G++ Template */
01120           string_init(&trawname);
01121           string_init(&tname);
01122           if (oldmangled == NULL)
01123             {
01124                  oldmangled = *mangled;
01125             }
01126           success = demangle_template (work, mangled, &tname,
01127                                           &trawname, 1, 1);
01128           if (success)
01129             {
01130                  remember_type (work, oldmangled, *mangled - oldmangled);
01131             }
01132           string_append (&tname, SCOPE_STRING (work));
01133 
01134           string_prepends(declp, &tname);
01135           if (work -> destructor & 1)
01136             {
01137                  string_prepend (&trawname, "~");
01138                  string_appends (declp, &trawname);
01139                  work->destructor -= 1;
01140             }
01141           if ((work->constructor & 1) || (work->destructor & 1))
01142             {
01143                  string_appends (declp, &trawname);
01144                  work->constructor -= 1;
01145             }
01146           string_delete(&trawname);
01147           string_delete(&tname);
01148           oldmangled = NULL;
01149           expect_func = 1;
01150           break;
01151 
01152         case '_':
01153           if (GNU_DEMANGLING && expect_return_type)
01154             {
01155                  /* Read the return type. */
01156                  string return_type;
01157                  string_init (&return_type);
01158 
01159                  (*mangled)++;
01160                  success = do_type (work, mangled, &return_type);
01161                  APPEND_BLANK (&return_type);
01162 
01163                  string_prepends (declp, &return_type);
01164                  string_delete (&return_type);
01165                  break;
01166             }
01167           else
01168             /* At the outermost level, we cannot have a return type specified,
01169                   so if we run into another '_' at this point we are dealing with
01170                   a mangled name that is either bogus, or has been mangled by
01171                   some algorithm we don't know how to deal with.  So just
01172                   reject the entire demangling.  */
01173                   /* However, "_nnn" is an expected suffix for alternate entry point
01174                         numbered nnn for a function, with HP aCC, so skip over that
01175                         without reporting failure. pai/1997-09-04 */
01176                   if (HP_DEMANGLING)
01177                     {
01178                          (*mangled)++;
01179                          while (**mangled && isdigit ((unsigned char)**mangled))
01180                            (*mangled)++;
01181                     }
01182                   else
01183                  success = 0;
01184           break;
01185 
01186         case 'H':
01187           if (GNU_DEMANGLING)
01188             {
01189                  /* A G++ template function.  Read the template arguments. */
01190                  success = demangle_template (work, mangled, declp, 0, 0,
01191                                            0);
01192                  if (!(work->constructor & 1))
01193                 expect_return_type = 1;
01194                  (*mangled)++;
01195                  break;
01196             }
01197           else
01198             /* fall through */
01199             {;}
01200 
01201         default:
01202           if (AUTO_DEMANGLING || GNU_DEMANGLING)
01203             {
01204                  /* Assume we have stumbled onto the first outermost function
01205                  argument token, and start processing args.  */
01206                  func_done = 1;
01207                  success = demangle_args (work, mangled, declp);
01208             }
01209           else
01210             {
01211                  /* Non-GNU demanglers use a specific token to mark the start
01212                  of the outermost function argument tokens.  Typically 'F',
01213                  for ARM/HP-demangling, for example.  So if we find something
01214                  we are not prepared for, it must be an error.  */
01215                  success = 0;
01216             }
01217           break;
01218         }
01219          /*
01220         if (AUTO_DEMANGLING || GNU_DEMANGLING)
01221         */
01222          {
01223         if (success && expect_func)
01224           {
01225             func_done = 1;
01226                     if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
01227                          {
01228                            forget_types (work);
01229                          }
01230             success = demangle_args (work, mangled, declp);
01231             /* Since template include the mangling of their return types,
01232                   we must set expect_func to 0 so that we don't try do
01233                   demangle more arguments the next time we get here.  */
01234             expect_func = 0;
01235           }
01236          }
01237     }
01238   if (success && !func_done)
01239     {
01240          if (AUTO_DEMANGLING || GNU_DEMANGLING)
01241         {
01242           /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
01243                 bar__3fooi is 'foo::bar(int)'.  We get here when we find the
01244                 first case, and need to ensure that the '(void)' gets added to
01245                 the current declp.  Note that with ARM/HP, the first case
01246                 represents the name of a static data member 'foo::bar',
01247                 which is in the current declp, so we leave it alone.  */
01248           success = demangle_args (work, mangled, declp);
01249         }
01250     }
01251   if (success && PRINT_ARG_TYPES)
01252     {
01253          if (work->static_type)
01254         string_append (declp, " static");
01255          if (work->type_quals != TYPE_UNQUALIFIED)
01256         {
01257           APPEND_BLANK (declp);
01258           string_append (declp, qualifier_string (work->type_quals));
01259         }
01260     }
01261 
01262   return (success);
01263 }
01264 
01265 #if 0
01266 
01267 static int
01268 demangle_method_args (work, mangled, declp)
01269         struct work_stuff *work;
01270         const char **mangled;
01271         string *declp;
01272 {
01273   int success = 0;
01274 
01275   if (work -> static_type)
01276     {
01277          string_append (declp, *mangled + 1);
01278          *mangled += strlen (*mangled);
01279          success = 1;
01280     }
01281   else
01282     {
01283          success = demangle_args (work, mangled, declp);
01284     }
01285   return (success);
01286 }
01287 
01288 #endif
01289 
01290 static int
01291 demangle_template_template_parm (work, mangled, tname)
01292         struct work_stuff *work;
01293         const char **mangled;
01294         string *tname;
01295 {
01296   int i;
01297   int r;
01298   int need_comma = 0;
01299   int success = 1;
01300   string temp;
01301 
01302   string_append (tname, "template <");
01303   /* get size of template parameter list */
01304   if (get_count (mangled, &r))
01305     {
01306          for (i = 0; i < r; i++)
01307         {
01308           if (need_comma)
01309             {
01310                  string_append (tname, ", ");
01311             }
01312 
01313             /* Z for type parameters */
01314             if (**mangled == 'Z')
01315                  {
01316                 (*mangled)++;
01317                 string_append (tname, "class");
01318                  }
01319                  /* z for template parameters */
01320             else if (**mangled == 'z')
01321                  {
01322                 (*mangled)++;
01323                 success =
01324                   demangle_template_template_parm (work, mangled, tname);
01325                 if (!success)
01326                   {
01327                     break;
01328                   }
01329                  }
01330             else
01331                  {
01332                 /* temp is initialized in do_type */
01333                 success = do_type (work, mangled, &temp);
01334                 if (success)
01335                   {
01336                     string_appends (tname, &temp);
01337                   }
01338                 string_delete(&temp);
01339                 if (!success)
01340                   {
01341                     break;
01342                   }
01343                  }
01344           need_comma = 1;
01345         }
01346 
01347     }
01348   if (tname->p[-1] == '>')
01349     string_append (tname, " ");
01350   string_append (tname, "> class");
01351   return (success);
01352 }
01353 
01354 static int
01355 demangle_expression (work, mangled, s, tk)
01356         struct work_stuff *work;
01357         const char** mangled;
01358         string* s;
01359         type_kind_t tk;
01360 {
01361   int need_operator = 0;
01362   int success;
01363 
01364   success = 1;
01365   string_appendn (s, "(", 1);
01366   (*mangled)++;
01367   while (success && **mangled != 'W' && **mangled != '\0')
01368     {
01369          if (need_operator)
01370         {
01371           size_t i;
01372           size_t len;
01373 
01374           success = 0;
01375 
01376           len = strlen (*mangled);
01377 
01378           for (i = 0;
01379                   i < sizeof (optable) / sizeof (optable [0]);
01380                   ++i)
01381             {
01382                  size_t l = strlen (optable[i].in);
01383 
01384                  if (l <= len
01385                   && memcmp (optable[i].in, *mangled, l) == 0)
01386                 {
01387                   string_appendn (s, " ", 1);
01388                   string_append (s, optable[i].out);
01389                   string_appendn (s, " ", 1);
01390                   success = 1;
01391                   (*mangled) += l;
01392                   break;
01393                 }
01394             }
01395 
01396           if (!success)
01397             break;
01398         }
01399          else
01400         need_operator = 1;
01401 
01402          success = demangle_template_value_parm (work, mangled, s, tk);
01403     }
01404 
01405   if (**mangled != 'W')
01406     success = 0;
01407   else
01408     {
01409          string_appendn (s, ")", 1);
01410          (*mangled)++;
01411     }
01412 
01413   return success;
01414 }
01415 
01416 static int
01417 demangle_integral_value (work, mangled, s)
01418         struct work_stuff *work;
01419         const char** mangled;
01420         string* s;
01421 {
01422   int success;
01423 
01424   if (**mangled == 'E')
01425     success = demangle_expression (work, mangled, s, tk_integral);
01426   else if (**mangled == 'Q' || **mangled == 'K')
01427     success = demangle_qualified (work, mangled, s, 0, 1);
01428   else
01429     {
01430          int value;
01431 
01432          success = 0;
01433 
01434          /* Negative numbers are indicated with a leading `m'.  */
01435          if (**mangled == 'm')
01436         {
01437           string_appendn (s, "-", 1);
01438           (*mangled)++;
01439         }
01440 
01441          /* Read the rest of the number.  */
01442          value = consume_count_with_underscores (mangled);
01443          if (value != -1)
01444         {
01445           char buf[INTBUF_SIZE];
01446           sprintf (buf, "%d", value);
01447           string_append (s, buf);
01448 
01449           /* If the next character is an underscore, skip it.  */
01450           if (**mangled == '_')
01451             (*mangled)++;
01452 
01453           /* All is well.  */
01454           success = 1;
01455         }
01456     }
01457 
01458   return success;
01459 }
01460 
01461 /* Demangle the real value in MANGLED.  */
01462 
01463 static int
01464 demangle_real_value (work, mangled, s)
01465         struct work_stuff *work;
01466         const char **mangled;
01467         string* s;
01468 {
01469   if (**mangled == 'E')
01470     return demangle_expression (work, mangled, s, tk_real);
01471 
01472   if (**mangled == 'm')
01473     {
01474          string_appendn (s, "-", 1);
01475          (*mangled)++;
01476     }
01477   while (isdigit ((unsigned char)**mangled))
01478     {
01479          string_appendn (s, *mangled, 1);
01480          (*mangled)++;
01481     }
01482   if (**mangled == '.') /* fraction */
01483     {
01484          string_appendn (s, ".", 1);
01485          (*mangled)++;
01486          while (isdigit ((unsigned char)**mangled))
01487         {
01488           string_appendn (s, *mangled, 1);
01489           (*mangled)++;
01490         }
01491     }
01492   if (**mangled == 'e') /* exponent */
01493     {
01494          string_appendn (s, "e", 1);
01495          (*mangled)++;
01496          while (isdigit ((unsigned char)**mangled))
01497         {
01498           string_appendn (s, *mangled, 1);
01499           (*mangled)++;
01500         }
01501     }
01502 
01503   return 1;
01504 }
01505 
01506 static int
01507 demangle_template_value_parm (work, mangled, s, tk)
01508         struct work_stuff *work;
01509         const char **mangled;
01510         string* s;
01511         type_kind_t tk;
01512 {
01513   int success = 1;
01514 
01515   if (**mangled == 'Y')
01516     {
01517          /* The next argument is a template parameter. */
01518          int idx;
01519 
01520          (*mangled)++;
01521          idx = consume_count_with_underscores (mangled);
01522          if (idx == -1
01523           || (work->tmpl_argvec && idx >= work->ntmpl_args)
01524           || consume_count_with_underscores (mangled) == -1)
01525         return -1;
01526          if (work->tmpl_argvec)
01527         string_append (s, work->tmpl_argvec[idx]);
01528          else
01529         string_append_template_idx (s, idx);
01530     }
01531   else if (tk == tk_integral)
01532     success = demangle_integral_value (work, mangled, s);
01533   else if (tk == tk_char)
01534     {
01535          char tmp[2];
01536          int val;
01537          if (**mangled == 'm')
01538         {
01539           string_appendn (s, "-", 1);
01540           (*mangled)++;
01541         }
01542          string_appendn (s, "'", 1);
01543          val = consume_count(mangled);
01544          if (val <= 0)
01545         success = 0;
01546          else
01547         {
01548           tmp[0] = (char)val;
01549           tmp[1] = '\0';
01550           string_appendn (s, &tmp[0], 1);
01551           string_appendn (s, "'", 1);
01552         }
01553     }
01554   else if (tk == tk_bool)
01555     {
01556          int val = consume_count (mangled);
01557          if (val == 0)
01558         string_appendn (s, "false", 5);
01559          else if (val == 1)
01560         string_appendn (s, "true", 4);
01561          else
01562         success = 0;
01563     }
01564   else if (tk == tk_real)
01565     success = demangle_real_value (work, mangled, s);
01566   else if (tk == tk_pointer || tk == tk_reference)
01567     {
01568          if (**mangled == 'Q')
01569         success = demangle_qualified (work, mangled, s,
01570                                          /*isfuncname=*/0, 
01571                                          /*append=*/1);
01572          else
01573         {
01574           int symbol_len  = consume_count (mangled);
01575           if (symbol_len == -1)
01576             return -1;
01577           if (symbol_len == 0)
01578             string_appendn (s, "0", 1);
01579           else
01580             {
01581                  char *p = xmalloc (symbol_len + 1), *q;
01582                  strncpy (p, *mangled, symbol_len);
01583                  p [symbol_len] = '\0';
01584                  /* We use cplus_demangle here, rather than
01585                  internal_cplus_demangle, because the name of the entity
01586                  mangled here does not make use of any of the squangling
01587                  or type-code information we have built up thus far; it is
01588                  mangled independently.  */
01589                  q = cplus_demangle (p, work->options);
01590                  if (tk == tk_pointer)
01591                 string_appendn (s, "&", 1);
01592                  /* FIXME: Pointer-to-member constants should get a
01593                  qualifying class name here.  */
01594                  if (q)
01595                 {
01596                   string_append (s, q);
01597                   free (q);
01598                 }
01599                  else
01600                 string_append (s, p);
01601                  free (p);
01602             }
01603           *mangled += symbol_len;
01604         }
01605     }
01606 
01607   return success;
01608 }
01609 
01610 /* Demangle the template name in MANGLED.  The full name of the
01611    template (e.g., S<int>) is placed in TNAME.  The name without the
01612    template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
01613    non-NULL.  If IS_TYPE is nonzero, this template is a type template,
01614    not a function template.  If both IS_TYPE and REMEMBER are nonzero,
01615    the tmeplate is remembered in the list of back-referenceable
01616    types.  */
01617 
01618 static int
01619 demangle_template (work, mangled, tname, trawname, is_type, remember)
01620         struct work_stuff *work;
01621         const char **mangled;
01622         string *tname;
01623         string *trawname;
01624         int is_type;
01625         int remember;
01626 {
01627   int i;
01628   int r;
01629   int need_comma = 0;
01630   int success = 0;
01631   const char *start;
01632   int is_java_array = 0;
01633   string temp;
01634   int bindex = 0;
01635 
01636   (*mangled)++;
01637   if (is_type)
01638     {
01639          if (remember)
01640         bindex = register_Btype (work);
01641          start = *mangled;
01642          /* get template name */
01643          if (**mangled == 'z')
01644         {
01645           int idx;
01646           (*mangled)++;
01647           (*mangled)++;
01648 
01649           idx = consume_count_with_underscores (mangled);
01650           if (idx == -1
01651                  || (work->tmpl_argvec && idx >= work->ntmpl_args)
01652                  || consume_count_with_underscores (mangled) == -1)
01653             return (0);
01654 
01655           if (work->tmpl_argvec)
01656             {
01657                  string_append (tname, work->tmpl_argvec[idx]);
01658                  if (trawname)
01659                 string_append (trawname, work->tmpl_argvec[idx]);
01660             }
01661           else
01662             {
01663                  string_append_template_idx (tname, idx);
01664                  if (trawname)
01665                 string_append_template_idx (trawname, idx);
01666             }
01667         }
01668          else
01669         {
01670           if ((r = consume_count (mangled)) <= 0
01671                  || (int) strlen (*mangled) < r)
01672             {
01673                  return (0);
01674             }
01675           is_java_array = (work -> options & DMGL_JAVA)
01676             && strncmp (*mangled, "JArray1Z", 8) == 0;
01677           if (! is_java_array)
01678             {
01679                  string_appendn (tname, *mangled, r);
01680             }
01681           if (trawname)
01682             string_appendn (trawname, *mangled, r);
01683           *mangled += r;
01684         }
01685     }
01686   if (!is_java_array)
01687     string_append (tname, "<");
01688   /* get size of template parameter list */
01689   if (!get_count (mangled, &r))
01690     {
01691          return (0);
01692     }
01693   if (!is_type)
01694     {
01695          /* Create an array for saving the template argument values. */
01696          work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
01697          work->ntmpl_args = r;
01698          for (i = 0; i < r; i++)
01699         work->tmpl_argvec[i] = 0;
01700     }
01701   for (i = 0; i < r; i++)
01702     {
01703          if (need_comma)
01704         {
01705           string_append (tname, ", ");
01706         }
01707          /* Z for type parameters */
01708          if (**mangled == 'Z')
01709         {
01710           (*mangled)++;
01711           /* temp is initialized in do_type */
01712           success = do_type (work, mangled, &temp);
01713           if (success)
01714             {
01715                  string_appends (tname, &temp);
01716 
01717                  if (!is_type)
01718                 {
01719                   /* Save the template argument. */
01720                   int len = temp.p - temp.b;
01721                   work->tmpl_argvec[i] = xmalloc (len + 1);
01722                   memcpy (work->tmpl_argvec[i], temp.b, len);
01723                   work->tmpl_argvec[i][len] = '\0';
01724                 }
01725             }
01726           string_delete(&temp);
01727           if (!success)
01728             {
01729                  break;
01730             }
01731         }
01732          /* z for template parameters */
01733          else if (**mangled == 'z')
01734         {
01735           int r2;
01736           (*mangled)++;
01737           success = demangle_template_template_parm (work, mangled, tname);
01738 
01739           if (success
01740                  && (r2 = consume_count (mangled)) > 0
01741                  && (int) strlen (*mangled) >= r2)
01742             {
01743                  string_append (tname, " ");
01744                  string_appendn (tname, *mangled, r2);
01745                  if (!is_type)
01746                 {
01747                   /* Save the template argument. */
01748                   int len = r2;
01749                   work->tmpl_argvec[i] = xmalloc (len + 1);
01750                   memcpy (work->tmpl_argvec[i], *mangled, len);
01751                   work->tmpl_argvec[i][len] = '\0';
01752                 }
01753                  *mangled += r2;
01754             }
01755