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           if (!success)
01756             {
01757                  break;
01758             }
01759         }
01760          else
01761         {
01762           string  param;
01763           string* s;
01764 
01765           /* otherwise, value parameter */
01766 
01767           /* temp is initialized in do_type */
01768           success = do_type (work, mangled, &temp);
01769           string_delete(&temp);
01770           if (!success)
01771             break;
01772 
01773           if (!is_type)
01774             {
01775                  s = &param;
01776                  string_init (s);
01777             }
01778           else
01779             s = tname;
01780 
01781           success = demangle_template_value_parm (work, mangled, s,
01782                                                   (type_kind_t) success);
01783 
01784           if (!success)
01785             {
01786                  if (!is_type)
01787                 string_delete (s);
01788                  success = 0;
01789                  break;
01790             }
01791 
01792           if (!is_type)
01793             {
01794                  int len = s->p - s->b;
01795                  work->tmpl_argvec[i] = xmalloc (len + 1);
01796                  memcpy (work->tmpl_argvec[i], s->b, len);
01797                  work->tmpl_argvec[i][len] = '\0';
01798 
01799                  string_appends (tname, s);
01800                  string_delete (s);
01801             }
01802         }
01803          need_comma = 1;
01804     }
01805   if (is_java_array)
01806     {
01807          string_append (tname, "[]");
01808     }
01809   else
01810     {
01811          if (tname->p[-1] == '>')
01812         string_append (tname, " ");
01813          string_append (tname, ">");
01814     }
01815 
01816   if (is_type && remember)
01817     remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
01818 
01819   /*
01820     if (work -> static_type)
01821     {
01822     string_append (declp, *mangled + 1);
01823     *mangled += strlen (*mangled);
01824     success = 1;
01825     }
01826     else
01827     {
01828     success = demangle_args (work, mangled, declp);
01829     }
01830     }
01831     */
01832   return (success);
01833 }
01834 
01835 static int
01836 arm_pt (work, mangled, n, anchor, args)
01837         struct work_stuff *work;
01838         const char *mangled;
01839         int n;
01840         const char **anchor, **args;
01841 {
01842   /* Check if ARM template with "__pt__" in it ("parameterized type") */
01843   /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
01844   if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = mystrstr (mangled, "__pt__")))
01845     {
01846          int len;
01847          *args = *anchor + 6;
01848          len = consume_count (args);
01849          if (len == -1)
01850         return 0;
01851          if (*args + len == mangled + n && **args == '_')
01852         {
01853           ++*args;
01854           return 1;
01855         }
01856     }
01857   if (AUTO_DEMANGLING || EDG_DEMANGLING)
01858     {
01859          if ((*anchor = mystrstr (mangled, "__tm__"))
01860                 || (*anchor = mystrstr (mangled, "__ps__"))
01861                 || (*anchor = mystrstr (mangled, "__pt__")))
01862            {
01863                 int len;
01864                 *args = *anchor + 6;
01865                 len = consume_count (args);
01866           if (len == -1)
01867             return 0;
01868                 if (*args + len == mangled + n && **args == '_')
01869                   {
01870                     ++*args;
01871                     return 1;
01872                   }
01873            }
01874          else if ((*anchor = mystrstr (mangled, "__S")))
01875            {
01876           int len;
01877           *args = *anchor + 3;
01878           len = consume_count (args);
01879           if (len == -1)
01880             return 0;
01881           if (*args + len == mangled + n && **args == '_')
01882                   {
01883                     ++*args;
01884                  return 1;
01885                   }
01886            }
01887     }
01888 
01889   return 0;
01890 }
01891 
01892 static void
01893 demangle_arm_hp_template (work, mangled, n, declp)
01894         struct work_stuff *work;
01895         const char **mangled;
01896         int n;
01897         string *declp;
01898 {
01899   const char *p;
01900   const char *args;
01901   const char *e = *mangled + n;
01902   string arg;
01903 
01904   /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
01905         template args */
01906   if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
01907     {
01908          char *start_spec_args = NULL;
01909 
01910          /* First check for and omit template specialization pseudo-arguments,
01911             such as in "Spec<#1,#1.*>" */
01912          start_spec_args = strchr (*mangled, '<');
01913          if (start_spec_args && (start_spec_args - *mangled < n))
01914            string_appendn (declp, *mangled, start_spec_args - *mangled);
01915          else
01916            string_appendn (declp, *mangled, n);
01917          (*mangled) += n + 1;
01918          string_init (&arg);
01919          if (work->temp_start == -1) /* non-recursive call */
01920            work->temp_start = declp->p - declp->b;
01921          string_append (declp, "<");
01922          while (1)
01923            {
01924                 string_clear (&arg);
01925                 switch (**mangled)
01926                   {
01927                     case 'T':
01928                          /* 'T' signals a type parameter */
01929                          (*mangled)++;
01930                          if (!do_type (work, mangled, &arg))
01931                            goto hpacc_template_args_done;
01932                          break;
01933 
01934                     case 'U':
01935                     case 'S':
01936                          /* 'U' or 'S' signals an integral value */
01937                          if (!do_hpacc_template_const_value (work, mangled, &arg))
01938                            goto hpacc_template_args_done;
01939                          break;
01940 
01941                     case 'A':
01942                          /* 'A' signals a named constant expression (literal) */
01943                          if (!do_hpacc_template_literal (work, mangled, &arg))
01944                            goto hpacc_template_args_done;
01945                          break;
01946 
01947                     default:
01948                          /* Today, 1997-09-03, we have only the above types
01949                             of template parameters */
01950                          /* FIXME: maybe this should fail and return null */
01951                          goto hpacc_template_args_done;
01952                   }
01953                 string_appends (declp, &arg);
01954             /* Check if we're at the end of template args.
01955                    0 if at end of static member of template class,
01956                    _ if done with template args for a function */
01957                 if ((**mangled == '\000') || (**mangled == '_'))
01958                   break;
01959                 else
01960                   string_append (declp, ",");
01961            }
01962     hpacc_template_args_done:
01963          string_append (declp, ">");
01964          string_delete (&arg);
01965          if (**mangled == '_')
01966            (*mangled)++;
01967          return;
01968     }
01969   /* ARM template? (Also handles HP cfront extensions) */
01970   else if (arm_pt (work, *mangled, n, &p, &args))
01971     {
01972          string type_str;
01973 
01974          string_init (&arg);
01975          string_appendn (declp, *mangled, p - *mangled);
01976          if (work->temp_start == -1)  /* non-recursive call */
01977         work->temp_start = declp->p - declp->b;
01978          string_append (declp, "<");
01979          /* should do error checking here */
01980          while (args < e) {
01981         string_clear (&arg);
01982 
01983         /* Check for type or literal here */
01984         switch (*args)
01985           {
01986             /* HP cfront extensions to ARM for template args */
01987             /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */
01988             /* FIXME: We handle only numeric literals for HP cfront */
01989                 case 'X':
01990                   /* A typed constant value follows */
01991                   args++;
01992                   if (!do_type (work, &args, &type_str))
01993                  goto cfront_template_args_done;
01994                   string_append (&arg, "(");
01995                   string_appends (&arg, &type_str);
01996                   string_append (&arg, ")");
01997                   if (*args != 'L')
01998                     goto cfront_template_args_done;
01999                   args++;
02000                   /* Now snarf a literal value following 'L' */
02001                   if (!snarf_numeric_literal (&args, &arg))
02002                  goto cfront_template_args_done;
02003                   break;
02004 
02005                 case 'L':
02006                   /* Snarf a literal following 'L' */
02007                   args++;
02008                   if (!snarf_numeric_literal (&args, &arg))
02009                  goto cfront_template_args_done;
02010                   break;
02011                 default:
02012                   /* Not handling other HP cfront stuff */
02013                   if (!do_type (work, &args, &arg))
02014                     goto cfront_template_args_done;
02015           }
02016         string_appends (declp, &arg);
02017         string_append (declp, ",");
02018          }
02019     cfront_template_args_done:
02020          string_delete (&arg);
02021          if (args >= e)
02022         --declp->p; /* remove extra comma */
02023          string_append (declp, ">");
02024     }
02025   else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
02026            && (*mangled)[9] == 'N'
02027            && (*mangled)[8] == (*mangled)[10]
02028            && strchr (cplus_markers, (*mangled)[8]))
02029     {
02030          /* A member of the anonymous namespace.  */
02031          string_append (declp, "{anonymous}");
02032     }
02033   else
02034     {
02035          if (work->temp_start == -1) /* non-recursive call only */
02036         work->temp_start = 0;     /* disable in recursive calls */
02037          string_appendn (declp, *mangled, n);
02038     }
02039   *mangled += n;
02040 }
02041 
02042 /* Extract a class name, possibly a template with arguments, from the
02043    mangled string; qualifiers, local class indicators, etc. have
02044    already been dealt with */
02045 
02046 static int
02047 demangle_class_name (work, mangled, declp)
02048         struct work_stuff *work;
02049         const char **mangled;
02050         string *declp;
02051 {
02052   int n;
02053   int success = 0;
02054 
02055   n = consume_count (mangled);
02056   if (n == -1)
02057     return 0;
02058   if ((int) strlen (*mangled) >= n)
02059     {
02060          demangle_arm_hp_template (work, mangled, n, declp);
02061          success = 1;
02062     }
02063 
02064   return (success);
02065 }
02066 
02067 /*
02068 
02069 LOCAL FUNCTION
02070 
02071         demangle_class -- demangle a mangled class sequence
02072 
02073 SYNOPSIS
02074 
02075         static int
02076         demangle_class (struct work_stuff *work, const char **mangled,
02077                         strint *declp)
02078 
02079 DESCRIPTION
02080 
02081         DECLP points to the buffer into which demangling is being done.
02082 
02083         *MANGLED points to the current token to be demangled.  On input,
02084         it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
02085         On exit, it points to the next token after the mangled class on
02086         success, or the first unconsumed token on failure.
02087 
02088         If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
02089         we are demangling a constructor or destructor.  In this case
02090         we prepend "class::class" or "class::~class" to DECLP.
02091 
02092         Otherwise, we prepend "class::" to the current DECLP.
02093 
02094         Reset the constructor/destructor flags once they have been
02095         "consumed".  This allows demangle_class to be called later during
02096         the same demangling, to do normal class demangling.
02097 
02098         Returns 1 if demangling is successful, 0 otherwise.
02099 
02100 */
02101 
02102 static int
02103 demangle_class (work, mangled, declp)
02104         struct work_stuff *work;
02105         const char **mangled;
02106         string *declp;
02107 {
02108   int success = 0;
02109   int btype;
02110   string class_name;
02111   char *save_class_name_end = 0;
02112 
02113   string_init (&class_name);
02114   btype = register_Btype (work);
02115   if (demangle_class_name (work, mangled, &class_name))
02116     {
02117          save_class_name_end = class_name.p;
02118          if ((work->constructor & 1) || (work->destructor & 1))
02119         {
02120                 /* adjust so we don't include template args */
02121                 if (work->temp_start && (work->temp_start != -1))
02122                   {
02123                     class_name.p = class_name.b + work->temp_start;
02124                   }
02125           string_prepends (declp, &class_name);
02126           if (work -> destructor & 1)
02127             {
02128                  string_prepend (declp, "~");
02129                     work -> destructor -= 1;
02130             }
02131           else
02132             {
02133                  work -> constructor -= 1;
02134             }
02135         }
02136          class_name.p = save_class_name_end;
02137          remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
02138          remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
02139          string_prepend (declp, SCOPE_STRING (work));
02140          string_prepends (declp, &class_name);
02141          success = 1;
02142     }
02143   string_delete (&class_name);
02144   return (success);
02145 }
02146 
02147 /*
02148 
02149 LOCAL FUNCTION
02150 
02151         demangle_prefix -- consume the mangled name prefix and find signature
02152 
02153 SYNOPSIS
02154 
02155         static int
02156         demangle_prefix (struct work_stuff *work, const char **mangled,
02157                          string *declp);
02158 
02159 DESCRIPTION
02160 
02161         Consume and demangle the prefix of the mangled name.
02162 
02163         DECLP points to the string buffer into which demangled output is
02164         placed.  On entry, the buffer is empty.  On exit it contains
02165         the root function name, the demangled operator name, or in some
02166         special cases either nothing or the completely demangled result.
02167 
02168         MANGLED points to the current pointer into the mangled name.  As each
02169         token of the mangled name is consumed, it is updated.  Upon entry
02170         the current mangled name pointer points to the first character of
02171         the mangled name.  Upon exit, it should point to the first character
02172         of the signature if demangling was successful, or to the first
02173         unconsumed character if demangling of the prefix was unsuccessful.
02174 
02175         Returns 1 on success, 0 otherwise.
02176  */
02177 
02178 static int
02179 demangle_prefix (work, mangled, declp)
02180         struct work_stuff *work;
02181         const char **mangled;
02182         string *declp;
02183 {
02184   int success = 1;
02185   const char *scan;
02186   int i;
02187 
02188   if (strlen(*mangled) > 6
02189          && (strncmp(*mangled, "_imp__", 6) == 0
02190                 || strncmp(*mangled, "__imp_", 6) == 0))
02191     {
02192          /* it's a symbol imported from a PE dynamic library. Check for both
02193             new style prefix _imp__ and legacy __imp_ used by older versions
02194          of dlltool. */
02195          (*mangled) += 6;
02196          work->dllimported = 1;
02197     }
02198   else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
02199     {
02200          char *marker = strchr (cplus_markers, (*mangled)[8]);
02201          if (marker != NULL && *marker == (*mangled)[10])
02202         {
02203           if ((*mangled)[9] == 'D')
02204             {
02205                  /* it's a GNU global destructor to be executed at program exit */
02206                  (*mangled) += 11;
02207                  work->destructor = 2;
02208                  if (gnu_special (work, mangled, declp))
02209                 return success;
02210             }
02211           else if ((*mangled)[9] == 'I')
02212             {
02213                  /* it's a GNU global constructor to be executed at program init */
02214                  (*mangled) += 11;
02215                  work->constructor = 2;
02216                  if (gnu_special (work, mangled, declp))
02217                 return success;
02218             }
02219         }
02220     }
02221   else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0)
02222     {
02223          /* it's a ARM global destructor to be executed at program exit */
02224          (*mangled) += 7;
02225          work->destructor = 2;
02226     }
02227   else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0)
02228     {
02229          /* it's a ARM global constructor to be executed at program initial */
02230          (*mangled) += 7;
02231          work->constructor = 2;
02232     }
02233 
02234   /*  This block of code is a reduction in strength time optimization
02235          of:
02236          scan = mystrstr (*mangled, "__"); */
02237 
02238   {
02239     scan = *mangled;
02240 
02241     do {
02242          scan = strchr (scan, '_');
02243     } while (scan != NULL && *++scan != '_');
02244 
02245     if (scan != NULL) --scan;
02246   }
02247 
02248   if (scan != NULL)
02249     {
02250          /* We found a sequence of two or more '_', ensure that we start at
02251          the last pair in the sequence.  */
02252          i = strspn (scan, "_");
02253          if (i > 2)
02254         {
02255           scan += (i - 2);
02256         }
02257     }
02258 
02259   if (scan == NULL)
02260     {
02261          success = 0;
02262     }
02263   else if (work -> static_type)
02264     {
02265          if (!isdigit ((unsigned char)scan[0]) && (scan[0] != 't'))
02266         {
02267           success = 0;
02268         }
02269     }
02270   else if ((scan == *mangled)
02271            && (isdigit ((unsigned char)scan[2]) || (scan[2] == 'Q')
02272                   || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
02273     {
02274          /* The ARM says nothing about the mangling of local variables.
02275          But cfront mangles local variables by prepending __<nesting_level>
02276          to them. As an extension to ARM demangling we handle this case.  */
02277          if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
02278           && isdigit ((unsigned char)scan[2]))
02279         {
02280           *mangled = scan + 2;
02281           consume_count (mangled);
02282           string_append (declp, *mangled);
02283           *mangled += strlen (*mangled);
02284           success = 1;
02285         }
02286          else
02287         {
02288           /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
02289                 names like __Q2_3foo3bar for nested type names.  So don't accept
02290                 this style of constructor for cfront demangling.  A GNU
02291                 style member-template constructor starts with 'H'. */
02292           if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING))
02293             work -> constructor += 1;
02294           *mangled = scan + 2;
02295         }
02296     }
02297   else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
02298     {
02299          /* Cfront-style parameterized type.  Handled later as a signature. */
02300          success = 1;
02301 
02302          /* ARM template? */
02303          demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
02304     }
02305   else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm')
02306                                                 || (scan[2] == 'p' && scan[3] == 's')
02307                                                 || (scan[2] == 'p' && scan[3] == 't')))
02308     {
02309          /* EDG-style parameterized type.  Handled later as a signature. */
02310          success = 1;
02311 
02312          /* EDG template? */
02313          demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
02314     }
02315   else if ((scan == *mangled) && !isdigit ((unsigned char)scan[2])
02316            && (scan[2] != 't'))
02317     {
02318          /* Mangled name starts with "__".  Skip over any leading '_' characters,
02319          then find the next "__" that separates the prefix from the signature.
02320          */
02321          if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
02322           || (arm_special (mangled, declp) == 0))
02323         {
02324           while (*scan == '_')
02325             {
02326                  scan++;
02327             }
02328           if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
02329             {
02330                  /* No separator (I.E. "__not_mangled"), or empty signature
02331                  (I.E. "__not_mangled_either__") */
02332                  success = 0;
02333             }
02334           else
02335             {
02336                  const char *tmp;
02337 
02338                     /* Look for the LAST occurrence of __, allowing names to
02339                           have the '__' sequence embedded in them. */
02340                  if (!(ARM_DEMANGLING || HP_DEMANGLING))
02341                 {
02342                   while ((tmp = mystrstr (scan + 2, "__")) != NULL)
02343                     scan = tmp;
02344                 }
02345                  if (*(scan + 2) == '\0')
02346                 success = 0;
02347                     else
02348                          demangle_function_name (work, mangled, declp, scan);
02349             }
02350         }
02351     }
02352   else if (*(scan + 2) != '\0')
02353     {
02354          /* Mangled name does not start with "__" but does have one somewhere
02355          in there with non empty stuff after it.  Looks like a global
02356          function name.  */
02357          demangle_function_name (work, mangled, declp, scan);
02358     }
02359   else
02360     {
02361          /* Doesn't look like a mangled name */
02362          success = 0;
02363     }
02364 
02365   if (!success && (work->constructor == 2 || work->destructor == 2))
02366     {
02367          string_append (declp, *mangled);
02368          *mangled += strlen (*mangled);
02369          success = 1;
02370     }
02371   return (success);
02372 }
02373 
02374 /*
02375 
02376 LOCAL FUNCTION
02377 
02378         gnu_special -- special handling of gnu mangled strings
02379 
02380 SYNOPSIS
02381 
02382         static int
02383         gnu_special (struct work_stuff *work, const char **mangled,
02384                         string *declp);
02385 
02386 
02387 DESCRIPTION
02388 
02389         Process some special GNU style mangling forms that don't fit
02390         the normal pattern.  For example:
02391 
02392                 _$_3foo         (destructor for class foo)
02393                 _vt$foo         (foo virtual table)
02394                 _vt$foo$bar     (foo::bar virtual table)
02395                 __vt_foo        (foo virtual table, new style with thunks)
02396                 _3foo$varname   (static data member)
02397                 _Q22rs2tu$vw    (static data member)
02398                 __t6vector1Zii  (constructor with template)
02399                 __thunk_4__$_7ostream (virtual function thunk)
02400  */
02401 
02402 static int
02403 gnu_special (work, mangled, declp)
02404         struct work_stuff *work;
02405         const char **mangled;
02406         string *declp;
02407 {
02408   int n;
02409   int success = 1;
02410   const char *p;
02411 
02412   if ((*mangled)[0] == '_'
02413          && strchr (cplus_markers, (*mangled)[1]) != NULL
02414          && (*mangled)[2] == '_')
02415     {
02416          /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
02417          (*mangled) += 3;
02418          work -> destructor += 1;
02419     }
02420   else if ((*mangled)[0] == '_'
02421            && (((*mangled)[1] == '_'
02422                 && (*mangled)[2] == 'v'
02423                 && (*mangled)[3] == 't'
02424                 && (*mangled)[4] == '_')
02425                   || ((*mangled)[1] == 'v'
02426                    && (*mangled)[2] == 't'
02427                    && strchr (cplus_markers, (*mangled)[3]) != NULL)))
02428     {
02429          /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
02430             and create the decl.  Note that we consume the entire mangled
02431          input string, which means that demangle_signature has no work
02432          to do.  */
02433          if ((*mangled)[2] == 'v')
02434         (*mangled) += 5; /* New style, with thunks: "__vt_" */
02435          else
02436         (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
02437          while (**mangled != '\0')
02438         {
02439           switch (**mangled)
02440             {
02441             case 'Q':
02442             case 'K':
02443                  success = demangle_qualified (work, mangled, declp, 0, 1);
02444                  break;
02445             case 't':
02446                  success = demangle_template (work, mangled, declp, 0, 1,
02447                                            1);
02448                  break;
02449             default:
02450                  if (isdigit((unsigned char)*mangled[0]))
02451                 {
02452                   n = consume_count(mangled);
02453                   /* We may be seeing a too-large size, or else a
02454                         ".<digits>" indicating a static local symbol.  In
02455                         any case, declare victory and move on; *don't* try
02456                         to use n to allocate.  */
02457                   if (n > (int) strlen (*mangled))
02458                     {
02459                          success = 1;
02460                          break;
02461                     }
02462                 }
02463                  else
02464                 {
02465                   n = strcspn (*mangled, cplus_markers);
02466                 }
02467                  string_appendn (declp, *mangled, n);
02468                  (*mangled) += n;
02469             }
02470 
02471           p = strpbrk (*mangled, cplus_markers);
02472           if (success && ((p == NULL) || (p == *mangled)))
02473             {
02474                  if (p != NULL)
02475                 {
02476                   string_append (declp, SCOPE_STRING (work));
02477                   (*mangled)++;
02478                 }
02479             }
02480           else
02481             {
02482                  success = 0;
02483                  break;
02484             }
02485         }
02486          if (success)
02487         string_append (declp, " virtual table");
02488     }
02489   else if ((*mangled)[0] == '_'
02490            && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
02491            && (p = strpbrk (*mangled, cplus_markers)) != NULL)
02492     {
02493          /* static data member, "_3foo$varname" for example */
02494          (*mangled)++;
02495          switch (**mangled)
02496         {
02497         case 'Q':
02498         case 'K':
02499           success = demangle_qualified (work, mangled, declp, 0, 1);
02500           break;
02501         case 't':
02502           success = demangle_template (work, mangled, declp, 0, 1, 1);
02503           break;
02504         default:
02505           n = consume_count (mangled);
02506           if (n < 0 || n > (long) strlen (*mangled))
02507             {
02508                  success = 0;
02509                  break;
02510             }
02511           string_appendn (declp, *mangled, n);
02512           (*mangled) += n;
02513         }
02514          if (success && (p == *mangled))
02515         {
02516           /* Consumed everything up to the cplus_marker, append the
02517                 variable name.  */
02518           (*mangled)++;
02519           string_append (declp, SCOPE_STRING (work));
02520           n = strlen (*mangled);
02521           string_appendn (declp, *mangled, n);
02522           (*mangled) += n;
02523         }
02524          else
02525         {
02526           success = 0;
02527         }
02528     }
02529   else if (strncmp (*mangled, "__thunk_", 8) == 0)
02530     {
02531          int delta;
02532 
02533          (*mangled) += 8;
02534          delta = consume_count (mangled);
02535          if (delta == -1)
02536         success = 0;
02537          else
02538         {
02539           char *method = internal_cplus_demangle (work, ++*mangled);
02540 
02541           if (method)
02542             {
02543                  char buf[50];
02544                  sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
02545                  string_append (declp, buf);
02546                  string_append (declp, method);
02547                  free (method);
02548                  n = strlen (*mangled);
02549                  (*mangled) += n;
02550             }
02551           else
02552             {
02553                  success = 0;
02554             }
02555         }
02556     }
02557   else if (strncmp (*mangled, "__t", 3) == 0
02558            && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
02559     {
02560          p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
02561          (*mangled) += 4;
02562          switch (**mangled)
02563         {
02564         case 'Q':
02565         case 'K':
02566           success = demangle_qualified (work, mangled, declp, 0, 1);
02567           break;
02568         case 't':
02569           success = demangle_template (work, mangled, declp, 0, 1, 1);
02570           break;
02571         default:
02572           success = demangle_fund_type (work, mangled, declp);
02573           break;
02574         }
02575          if (success && **mangled != '\0')
02576         success = 0;
02577          if (success)
02578         string_append (declp, p);
02579     }
02580   else
02581     {
02582          success = 0;
02583     }
02584   return (success);
02585 }
02586 
02587 static void
02588 recursively_demangle(work, mangled, result, namelength)
02589         struct work_stuff *work;
02590         const char **mangled;
02591         string *result;
02592         int namelength;
02593 {
02594   char * recurse = (char *)NULL;
02595   char * recurse_dem = (char *)NULL;
02596 
02597   recurse = (char *) xmalloc (namelength + 1);
02598   memcpy (recurse, *mangled, namelength);
02599   recurse[namelength] = '\000';
02600 
02601   recurse_dem = cplus_demangle (recurse, work->options);
02602 
02603   if (recurse_dem)
02604     {
02605          string_append (result, recurse_dem);
02606          free (recurse_dem);
02607     }
02608   else
02609     {
02610          string_appendn (result, *mangled, namelength);
02611     }
02612   free (recurse);
02613   *mangled += namelength;
02614 }
02615 
02616 /*
02617 
02618 LOCAL FUNCTION
02619 
02620         arm_special -- special handling of ARM/lucid mangled strings
02621 
02622 SYNOPSIS
02623 
02624         static int
02625         arm_special (const char **mangled,
02626                         string *declp);
02627 
02628 
02629 DESCRIPTION
02630 
02631         Process some special ARM style mangling forms that don't fit
02632         the normal pattern.  For example:
02633 
02634                 __vtbl__3foo            (foo virtual table)
02635                 __vtbl__3foo__3bar      (bar::foo virtual table)
02636 
02637  */
02638 
02639 static int
02640 arm_special (mangled, declp)
02641         const char **mangled;
02642         string *declp;
02643 {
02644   int n;
02645   int success = 1;
02646   const char *scan;
02647 
02648   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
02649     {
02650          /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
02651             and create the decl.  Note that we consume the entire mangled
02652          input string, which means that demangle_signature has no work
02653          to do.  */
02654          scan = *mangled + ARM_VTABLE_STRLEN;
02655          while (*scan != '\0')        /* first check it can be demangled */
02656            {
02657                 n = consume_count (&scan);
02658                 if (n == -1)
02659             {
02660                  return (0);           /* no good */
02661             }
02662                 scan += n;
02663                 if (scan[0] == '_' && scan[1] == '_')
02664             {
02665                  scan += 2;
02666             }
02667            }
02668          (*mangled) += ARM_VTABLE_STRLEN;
02669          while (**mangled != '\0')
02670         {
02671           n = consume_count (mangled);
02672                 if (n == -1
02673                  || n > (long) strlen (*mangled))
02674             return 0;
02675           string_prependn (declp, *mangled, n);
02676           (*mangled) += n;
02677           if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
02678             {
02679                  string_prepend (declp, "::");
02680                  (*mangled) += 2;
02681             }
02682         }
02683          string_append (declp, " virtual table");
02684     }
02685   else
02686     {
02687          success = 0;
02688     }
02689   return (success);
02690 }
02691 
02692 /*
02693 
02694 LOCAL FUNCTION
02695 
02696         demangle_qualified -- demangle 'Q' qualified name strings
02697 
02698 SYNOPSIS
02699 
02700         static int
02701         demangle_qualified (struct work_stuff *, const char *mangled,
02702                             string *result, int isfuncname, int append);
02703 
02704 DESCRIPTION
02705 
02706         Demangle a qualified name, such as "Q25Outer5Inner" which is
02707         the mangled form of "Outer::Inner".  The demangled output is
02708         prepended or appended to the result string according to the
02709         state of the append flag.
02710 
02711         If isfuncname is nonzero, then the qualified name we are building
02712         is going to be used as a member function name, so if it is a
02713         constructor or destructor function, append an appropriate
02714         constructor or destructor name.  I.E. for the above example,
02715         the result for use as a constructor is "Outer::Inner::Inner"
02716         and the result for use as a destructor is "Outer::Inner::~Inner".
02717 
02718 BUGS
02719 
02720         Numeric conversion is ASCII dependent (FIXME).
02721 
02722  */
02723 
02724 static int
02725 demangle_qualified (work, mangled, result, isfuncname, append)
02726         struct work_stuff *work;
02727         const char **mangled;
02728         string *result;
02729         int isfuncname;
02730         int append;
02731 {
02732   int qualifiers = 0;
02733   int success = 1;
02734   char num[2];
02735   string temp;
02736   string last_name;
02737   int bindex = register_Btype (work);
02738 
02739   /* We only make use of ISFUNCNAME if the entity is a constructor or
02740         destructor.  */
02741   isfuncname = (isfuncname
02742                 && ((work->constructor & 1) || (work->destructor & 1)));
02743 
02744   string_init (&temp);
02745   string_init (&last_name);
02746 
02747   if ((*mangled)[0] == 'K')
02748     {
02749     /* Squangling qualified name reuse */
02750          int idx;
02751          (*mangled)++;
02752          idx = consume_count_with_underscores (mangled);
02753          if (idx == -1 || idx >= work -> numk)
02754            success = 0;
02755          else
02756            string_append (&temp, work -> ktypevec[idx]);
02757     }
02758   else
02759     switch ((*mangled)[1])
02760     {
02761     case '_':
02762          /* GNU mangled name with more than 9 classes.  The count is preceded
02763          by an underscore (to distinguish it from the <= 9 case) and followed
02764          by an underscore.  */
02765          (*mangled)++;
02766          qualifiers = consume_count_with_underscores (mangled);
02767          if (qualifiers == -1)
02768         success = 0;
02769          break;
02770 
02771     case '1':
02772     case '2':
02773     case '3':
02774     case '4':
02775     case '5':
02776     case '6':
02777     case '7':
02778     case '8':
02779     case '9':
02780          /* The count is in a single digit.  */
02781          num[0] = (*mangled)[1];
02782          num[1] = '\0';
02783          qualifiers = atoi (num);
02784 
02785          /* If there is an underscore after the digit, skip it.  This is
02786          said to be for ARM-qualified names, but the ARM makes no
02787          mention of such an underscore.  Perhaps cfront uses one.  */
02788          if ((*mangled)[2] == '_')
02789         {
02790           (*mangled)++;
02791         }
02792          (*mangled) += 2;
02793          break;
02794 
02795     case '0':
02796     default:
02797          success = 0;
02798     }
02799 
02800   if (!success)
02801     return success;
02802 
02803   /* Pick off the names and collect them in the temp buffer in the order
02804         in which they are found, separated by '::'.  */
02805 
02806   while (qualifiers-- > 0)
02807     {
02808          int remember_K = 1;
02809          string_clear (&last_name);
02810 
02811          if (*mangled[0] == '_')
02812         (*mangled)++;
02813 
02814          if (*mangled[0] == 't')
02815         {
02816           /* Here we always append to TEMP since we will want to use
02817                 the template name without the template parameters as a
02818                 constructor or destructor name.  The appropriate
02819                 (parameter-less) value is returned by demangle_template
02820                 in LAST_NAME.  We do not remember the template type here,
02821                 in order to match the G++ mangling algorithm.  */
02822           success = demangle_template(work, mangled, &temp,
02823                                          &last_name, 1, 0);
02824           if (!success)
02825             break;
02826         }
02827          else if (*mangled[0] == 'K')
02828         {
02829                 int idx;
02830                 (*mangled)++;
02831                 idx = consume_count_with_underscores (mangled);
02832                 if (idx == -1 || idx >= work->numk)
02833                   success = 0;
02834                 else
02835                   string_append (&temp, work->ktypevec[idx]);
02836                 remember_K = 0;
02837 
02838           if (!success) break;
02839         }
02840          else
02841         {
02842           if (EDG_DEMANGLING)
02843                   {
02844                  int namelength;
02845                  /* Now recursively demangle the qualifier
02846                   * This is necessary to deal with templates in
02847                   * mangling styles like EDG */
02848                  namelength = consume_count (mangled);
02849                  if (namelength == -1)
02850                 {
02851                   success = 0;
02852                   break;
02853                 }
02854                  recursively_demangle(work, mangled, &temp, namelength);
02855                   }
02856                 else
02857                   {
02858                     success = do_type (work, mangled, &last_name);
02859                     if (!success)
02860                          break;
02861                     string_appends (&temp, &last_name);
02862                   }
02863         }
02864 
02865          if (remember_K)
02866         remember_Ktype (work, temp.b, LEN_STRING (&temp));
02867 
02868          if (qualifiers > 0)
02869         string_append (&temp, SCOPE_STRING (work));
02870     }
02871 
02872   remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
02873 
02874   /* If we are using the result as a function name, we need to append
02875         the appropriate '::' separated constructor or destructor name.
02876         We do this here because this is the most convenient place, where
02877         we already have a pointer to the name and the length of the name.  */
02878 
02879   if (isfuncname)
02880     {
02881          string_append (&temp, SCOPE_STRING (work));
02882          if (work -> destructor & 1)
02883         string_append (&temp, "~");
02884          string_appends (&temp, &last_name);
02885     }
02886 
02887   /* Now either prepend the temp buffer to the result, or append it,
02888         depending upon the state of the append flag.  */
02889 
02890   if (append)
02891     string_appends (result, &temp);
02892   else
02893     {
02894          if (!STRING_EMPTY (result))
02895         string_append (&temp, SCOPE_STRING (work));
02896          string_prepends (result, &temp);
02897     }
02898 
02899   string_delete (&last_name);
02900   string_delete (&temp);
02901   return (success);
02902 }
02903 
02904 /*
02905 
02906 LOCAL FUNCTION
02907 
02908         get_count -- convert an ascii count to integer, consuming tokens
02909 
02910 SYNOPSIS
02911 
02912         static int
02913         get_count (const char **type, int *count)
02914 
02915 DESCRIPTION
02916 
02917         Assume that *type points at a count in a mangled name; set
02918         *count to its value, and set *type to the next character after
02919         the count.  There are some weird rules in effect here.
02920 
02921         If *type does not point at a string of digits, return zero.
02922 
02923         If *type points at a string of digits followed by an
02924         underscore, set *count to their value as an integer, advance
02925         *type to point *after the underscore, and return 1.
02926 
02927         If *type points at a string of digits not followed by an
02928         underscore, consume only the first digit.  Set *count to its
02929         value as an integer, leave *type pointing after that digit,
02930         and return 1.
02931 
02932            The excuse for this odd behavior: in the ARM and HP demangling
02933            styles, a type can be followed by a repeat count of the form
02934            `Nxy', where:
02935 
02936            `x' is a single digit specifying how many additional copies
02937                   of the type to append to the argument list, and
02938 
02939            `y' is one or more digits, specifying the zero-based index of
02940                   the first repeated argument in the list.  Yes, as you're
02941                   unmangling the name you can figure this out yourself, but
02942                   it's there anyway.
02943 
02944            So, for example, in `bar__3fooFPiN51', the first argument is a
02945            pointer to an integer (`Pi'), and then the next five arguments
02946            are the same (`N5'), and the first repeat is the function's
02947            second argument (`1').
02948 */
02949 
02950 static int
02951 get_count (type, count)
02952         const char **type;
02953         int *count;
02954 {
02955   const char *p;
02956   int n;
02957 
02958   if (!isdigit ((unsigned char)**type))
02959     return (0);
02960   else
02961     {
02962          *count = **type - '0';
02963          (*type)++;
02964          if (isdigit ((unsigned char)**type))
02965         {
02966           p = *type;
02967           n = *count;
02968           do
02969             {
02970                  n *= 10;
02971                  n += *p - '0';
02972                  p++;
02973             }
02974           while (isdigit ((unsigned char)*p));
02975           if (*p == '_')
02976             {
02977                  *type = p + 1;
02978                  *count = n;
02979             }
02980         }
02981     }
02982   return (1);
02983 }
02984 
02985 /* RESULT will be initialised here; it will be freed on failure.  The
02986    value returned is really a type_kind_t.  */
02987 
02988 static int
02989 do_type (work, mangled, result)
02990         struct work_stuff *work;
02991         const char **mangled;
02992         string *result;
02993 {
02994   int n;
02995   int done;
02996   int success;
02997   string decl;
02998   const char *remembered_type;
02999   int type_quals;
03000   string btype;
03001   type_kind_t tk = tk_none;
03002 
03003   string_init (&btype);
03004   string_init (&decl);
03005   string_init (result);
03006 
03007   done = 0;
03008   success = 1;
03009   while (success && !done)
03010     {
03011          int member;
03012          switch (**mangled)
03013         {
03014 
03015           /* A pointer type */
03016         case 'P':
03017         case 'p':
03018           (*mangled)++;
03019           if (! (work -> options & DMGL_JAVA))
03020             string_prepend (&decl, "*");
03021           if (tk == tk_none)
03022             tk = tk_pointer;
03023           break;
03024 
03025           /* A reference type */
03026         case 'R':
03027           (*mangled)++;
03028           string_prepend (&decl, "&");
03029           if (tk == tk_none)
03030             tk = tk_reference;
03031           break;
03032 
03033           /* An array */
03034         case 'A':
03035           {
03036             ++(*mangled);
03037             if (!STRING_EMPTY (&decl)
03038                 && (decl.b[0] == '*' || decl.b[0] == '&'))
03039                  {
03040                 string_prepend (&decl, "(");
03041                 string_append (&decl, ")");
03042                  }
03043             string_append (&decl, "[");
03044             if (**mangled != '_')
03045                  success = demangle_template_value_parm (work, mangled, &decl,
03046                                                          tk_integral);
03047             if (**mangled == '_')
03048                  ++(*mangled);
03049             string_append (&decl, "]");
03050             break;
03051           }
03052 
03053         /* A back reference to a previously seen type */
03054         case 'T':
03055           (*mangled)++;
03056           if (!get_count (mangled, &n) || n >= work -> ntypes)
03057             {
03058                  success = 0;
03059             }
03060           else
03061             {
03062                  remembered_type = work -> typevec[n];
03063                  mangled = &remembered_type;
03064             }
03065           break;
03066 
03067           /* A function */
03068         case 'F':
03069           (*mangled)++;
03070             if (!STRING_EMPTY (&decl)
03071                 && (decl.b[0] == '*' || decl.b[0] == '&'))
03072             {
03073                  string_prepend (&decl, "(");
03074                  string_append (&decl, ")");
03075             }
03076           /* After picking off the function args, we expect to either find the
03077                 function return type (preceded by an '_') or the end of the
03078                 string.  */
03079           if (!demangle_nested_args (work, mangled, &decl)
03080                  || (**mangled != '_' && **mangled != '\0'))
03081             {
03082                  success = 0;
03083                  break;
03084             }
03085           if (success && (**mangled == '_'))
03086             (*mangled)++;
03087           break;
03088 
03089         case 'M':
03090         case 'O':
03091           {
03092             type_quals = TYPE_UNQUALIFIED;
03093 
03094             member = **mangled == 'M';
03095             (*mangled)++;
03096 
03097             string_append (&decl, ")");
03098 
03099             /* We don't need to prepend `::' for a qualified name;
03100                   demangle_qualified will do that for us.  */
03101             if (**mangled != 'Q')
03102                  string_prepend (&decl, SCOPE_STRING (work));
03103 
03104             if (isdigit ((unsigned char)**mangled))
03105                  {
03106                 n = consume_count (mangled);
03107                 if (n == -1
03108                     || (int) strlen (*mangled) < n)
03109                   {
03110                     success = 0;
03111                     break;
03112                   }
03113                 string_prependn (&decl, *mangled, n);
03114                 *mangled += n;
03115                  }
03116             else if (**mangled == 'X' || **mangled == 'Y')
03117                  {
03118                 string temp;
03119                 do_type (work, mangled, &temp);
03120                 string_prepends (&decl, &temp);
03121                  }
03122             else if (**mangled == 't')
03123                  {
03124                 string temp;
03125                 string_init (&temp);
03126                 success = demangle_template (work, mangled, &temp,
03127                                                 NULL, 1, 1);
03128                 if (success)
03129                   {
03130                     string_prependn (&decl, temp.b, temp.p - temp.b);
03131                     string_clear (&temp);
03132                   }
03133                 else
03134                   break;
03135                  }
03136             else if (**mangled == 'Q')
03137                  {
03138                 success = demangle_qualified (work, mangled, &decl,
03139                                                  /*isfuncnam=*/0, 
03140                                                  /*append=*/0);
03141                 if (!success)
03142                   break;
03143                  }
03144             else
03145                  {
03146                 success = 0;
03147                 break;
03148                  }
03149 
03150             string_prepend (&decl, "(");
03151             if (member)
03152                  {
03153                 switch (**mangled)
03154                   {
03155                   case 'C':
03156                   case 'V':
03157                   case 'u':
03158                     type_quals |= code_for_qualifier (**mangled);
03159                     (*mangled)++;
03160                     break;
03161 
03162                   default:
03163                     break;
03164                   }
03165 
03166                 if (*(*mangled)++ != 'F')
03167                   {
03168                     success = 0;
03169                     break;
03170                   }
03171                  }
03172             if ((member && !demangle_nested_args (work, mangled, &decl))
03173                 || **mangled != '_')
03174                  {
03175                 success = 0;
03176                 break;
03177                  }
03178             (*mangled)++;
03179             if (! PRINT_ANSI_QUALIFIERS)
03180                  {
03181                 break;
03182                  }
03183             if (type_quals != TYPE_UNQUALIFIED)
03184                  {
03185                 APPEND_BLANK (&decl);
03186                 string_append (&decl, qualifier_string (type_quals));
03187                  }
03188             break;
03189           }
03190            case 'G':
03191           (*mangled)++;
03192           break;
03193 
03194         case 'C':
03195         case 'V':
03196         case 'u':
03197           if (PRINT_ANSI_QUALIFIERS)
03198             {
03199                  if (!STRING_EMPTY (&decl))
03200                 string_prepend (&decl, " ");
03201 
03202                  string_prepend (&decl, demangle_qualifier (**mangled));
03203             }
03204           (*mangled)++;
03205           break;
03206           /*
03207             }
03208             */
03209 
03210           /* fall through */
03211         default:
03212           done = 1;
03213           break;
03214         }
03215     }
03216 
03217   if (success) switch (**mangled)
03218     {
03219          /* A qualified name, such as "Outer::Inner".  */
03220     case 'Q':
03221     case 'K':
03222          {
03223            success = demangle_qualified (work, mangled, result, 0, 1);
03224            break;
03225          }
03226 
03227     /* A back reference to a previously seen squangled type */
03228     case 'B':
03229          (*mangled)++;
03230          if (!get_count (mangled, &n) || n >= work -> numb)
03231         success = 0;
03232          else
03233         string_append (result, work->btypevec[n]);
03234          break;
03235 
03236     case 'X':
03237     case 'Y':
03238          /* A template parm.  We substitute the corresponding argument. */
03239          {
03240         int idx;
03241 
03242         (*mangled)++;
03243         idx = consume_count_with_underscores (mangled);
03244 
03245         if (idx == -1
03246             || (work->tmpl_argvec && idx >= work->ntmpl_args)
03247             || consume_count_with_underscores (mangled) == -1)
03248           {
03249             success = 0;
03250             break;
03251           }
03252 
03253         if (work->tmpl_argvec)
03254           string_append (result, work->tmpl_argvec[idx]);
03255         else
03256           string_append_template_idx (result, idx);
03257 
03258         success = 1;
03259          }
03260     break;
03261 
03262     default:
03263          success = demangle_fund_type (work, mangled, result);
03264          if (tk == tk_none)
03265         tk = (type_kind_t) success;
03266          break;
03267     }
03268 
03269   if (success)
03270     {
03271          if (!STRING_EMPTY (&decl))
03272         {
03273           string_append (result, " ");
03274           string_appends (result, &decl);
03275         }
03276     }
03277   else
03278     string_delete (result);
03279   string_delete (&decl);
03280 
03281   if (success)
03282     /* Assume an integral type, if we're not sure.  */
03283     return (int) ((tk == tk_none) ? tk_integral : tk);
03284   else
03285     return 0;
03286 }
03287 
03288 /* Given a pointer to a type string that represents a fundamental type
03289    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
03290    string in which the demangled output is being built in RESULT, and
03291    the WORK structure, decode the types and add them to the result.
03292 
03293    For example:
03294 
03295         "Ci"    =>      "const int"
03296         "Sl"    =>      "signed long"
03297         "CUs"   =>      "const unsigned short"
03298 
03299    The value returned is really a type_kind_t.  */
03300 
03301 static int
03302 demangle_fund_type (work, mangled, result)
03303         struct work_stuff *work;
03304         const char **mangled;
03305         string *result;
03306 {
03307   int done = 0;
03308   int success = 1;
03309   char buf[10];
03310   int dec = 0;
03311   string btype;
03312   type_kind_t tk = tk_integral;
03313 
03314   string_init (&btype);
03315 
03316   /* First pick off any type qualifiers.  There can be more than one.  */
03317 
03318   while (!done)
03319     {
03320          switch (**mangled)
03321         {
03322         case 'C':
03323         case 'V':
03324         case 'u':
03325           if (PRINT_ANSI_QUALIFIERS)
03326             {
03327                     if (!STRING_EMPTY (result))
03328                          string_prepend (result, " ");
03329                  string_prepend (result, demangle_qualifier (**mangled));
03330             }
03331           (*mangled)++;
03332           break;
03333         case 'U':
03334           (*mangled)++;
03335           APPEND_BLANK (result);
03336           string_append (result, "unsigned");
03337           break;
03338         case 'S': /* signed char only */
03339           (*mangled)++;
03340           APPEND_BLANK (result);
03341           string_append (result, "signed");
03342           break;
03343         case 'J':
03344           (*mangled)++;
03345           APPEND_BLANK (result);
03346           string_append (result, "__complex");
03347           break;
03348         default:
03349           done = 1;
03350           break;
03351         }
03352     }
03353 
03354   /* Now pick off the fundamental type.  There can be only one.  */
03355 
03356   switch (**mangled)
03357     {
03358     case '\0':
03359     case '_':
03360          break;
03361     case 'v':
03362          (*mangled)++;
03363          APPEND_BLANK (result);
03364          string_append (result, "void");
03365          break;
03366     case 'x':
03367          (*mangled)++;
03368          APPEND_BLANK (result);
03369          string_append (result, "long long");
03370          break;
03371     case 'l':
03372          (*mangled)++;
03373          APPEND_BLANK (result);
03374          string_append (result, "long");
03375          break;
03376     case 'i':
03377          (*mangled)++;
03378          APPEND_BLANK (result);
03379          string_append (result, "int");
03380          break;
03381     case 's':
03382          (*mangled)++;
03383          APPEND_BLANK (result);
03384          string_append (result, "short");
03385          break;
03386     case 'b':
03387          (*mangled)++;
03388          APPEND_BLANK (result);
03389          string_append (result, "bool");
03390          tk = tk_bool;
03391          break;
03392     case 'c':
03393          (*mangled)++;
03394          APPEND_BLANK (result);
03395          string_append (result, "char");
03396          tk = tk_char;
03397          break;
03398     case 'w':
03399          (*mangled)++;
03400          APPEND_BLANK (result);
03401          string_append (result, "wchar_t");
03402          tk = tk_char;
03403          break;
03404     case 'r':
03405          (*mangled)++;
03406          APPEND_BLANK (result);
03407          string_append (result, "long double");
03408          tk = tk_real;
03409          break;
03410     case 'd':
03411          (*mangled)++;
03412          APPEND_BLANK (result);
03413          string_append (result, "double");
03414          tk = tk_real;
03415          break;
03416     case 'f':
03417          (*mangled)++;
03418          APPEND_BLANK (result);
03419          string_append (result, "float");
03420          tk = tk_real;
03421          break;
03422     case 'G':
03423          (*mangled)++;
03424          if (!isdigit ((unsigned char)**mangled))
03425         {
03426           success = 0;
03427           break;
03428         }
03429     case 'I':
03430          (*mangled)++;
03431          if (**mangled == '_')
03432         {
03433           int i;
03434           (*mangled)++;
03435           for (i = 0;
03436                   i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
03437                   (*mangled)++, i++)
03438             buf[i] = **mangled;
03439           if (**mangled != '_')
03440             {
03441                  success = 0;
03442                  break;
03443             }
03444           buf[i] = '\0';
03445           (*mangled)++;
03446         }
03447          else
03448         {
03449           strncpy (buf, *mangled, 2);
03450           buf[2] = '\0';
03451           *mangled += min (strlen (*mangled), 2);
03452         }
03453          sscanf (buf, "%x", &dec);
03454          sprintf (buf, "int%i_t", dec);
03455          APPEND_BLANK (result);
03456          string_append (result, buf);
03457          break;
03458 
03459          /* fall through */
03460          /* An explicit type, such as "6mytype" or "7integer" */
03461     case '0':
03462     case '1':
03463     case '2':
03464     case '3':
03465     case '4':
03466     case '5':
03467     case '6':
03468     case '7':
03469     case '8':
03470     case '9':
03471          {
03472            int bindex = register_Btype (work);
03473            string btype;
03474            string_init (&btype);
03475            if (demangle_class_name (work, mangled, &btype)) {
03476                 remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
03477                 APPEND_BLANK (result);
03478                 string_appends (result, &btype);
03479            }
03480            else
03481                 success = 0;
03482            string_delete (&btype);
03483            break;
03484          }
03485     case 't':
03486          {
03487            success = demangle_template (work, mangled, &btype, 0, 1, 1);
03488            string_appends (result, &btype);
03489            break;
03490          }
03491     default:
03492          success = 0;
03493          break;
03494     }
03495 
03496   return success ? ((int) tk) : 0;
03497 }
03498 
03499 
03500 /* Handle a template's value parameter for HP aCC (extension from ARM)
03501    **mangled points to 'S' or 'U' */
03502 
03503 static int
03504 do_hpacc_template_const_value (work, mangled, result)
03505         struct work_stuff *work;
03506         const char **mangled;
03507         string *result;
03508 {
03509   int unsigned_const;
03510 
03511   if (**mangled != 'U' && **mangled != 'S')
03512     return 0;
03513 
03514   unsigned_const = (**mangled == 'U');
03515 
03516   (*mangled)++;
03517 
03518   switch (**mangled)
03519     {
03520          case 'N':
03521            string_append (result, "-");
03522            /* fall through */
03523          case 'P':
03524            (*mangled)++;
03525            break;
03526          case 'M':
03527            /* special case for -2^31 */
03528            string_append (result, "-2147483648");
03529            (*mangled)++;
03530            return 1;
03531          default:
03532            return 0;
03533     }
03534 
03535   /* We have to be looking at an integer now */
03536   if (!(isdigit ((unsigned char)**mangled)))
03537     return 0;
03538 
03539   /* We only deal with integral values for template
03540         parameters -- so it's OK to look only for digits */
03541   while (isdigit ((unsigned char)**mangled))
03542     {
03543          char_str[0] = **mangled;
03544          string_append (result, char_str);
03545          (*mangled)++;
03546     }
03547 
03548   if (unsigned_const)
03549     string_append (result, "U");
03550 
03551   /* FIXME? Some day we may have 64-bit (or larger :-) ) constants
03552         with L or LL suffixes. pai/1997-09-03 */
03553 
03554   return 1; /* success */
03555 }
03556 
03557 /* Handle a template's literal parameter for HP aCC (extension from ARM)
03558    **mangled is pointing to the 'A' */
03559 
03560 static int
03561 do_hpacc_template_literal (work, mangled, result)
03562         struct work_stuff *work;
03563         const char **mangled;
03564         string *result;
03565 {
03566   int literal_len = 0;
03567   char * recurse;
03568   char * recurse_dem;
03569 
03570   if (**mangled != 'A')
03571     return 0;
03572 
03573   (*mangled)++;
03574 
03575   literal_len = consume_count (mangled);
03576 
03577   if (literal_len <= 0)
03578     return 0;
03579 
03580   /* Literal parameters are names of arrays, functions, etc.  and the
03581         canonical representation uses the address operator */
03582   string_append (result, "&");
03583 
03584   /* Now recursively demangle the literal name */
03585   recurse = (char *) xmalloc (literal_len + 1);
03586   memcpy (recurse, *mangled, literal_len);
03587   recurse[literal_len] = '\000';
03588 
03589   recurse_dem = cplus_demangle (recurse, work->options);
03590 
03591   if (recurse_dem)
03592     {
03593          string_append (result, recurse_dem);
03594          free (recurse_dem);
03595     }
03596   else
03597     {
03598          string_appendn (result, *mangled, literal_len);
03599     }
03600   (*mangled) += literal_len;
03601   free (recurse);
03602 
03603   return 1;
03604 }
03605 
03606 static int
03607 snarf_numeric_literal (args, arg)
03608         const char ** args;
03609         string * arg;
03610 {
03611   if (**args == '-')
03612     {
03613          char_str[0] = '-';
03614          string_append (arg, char_str);
03615          (*args)++;
03616     }
03617   else if (**args == '+')
03618     (*args)++;
03619 
03620   if (!isdigit ((unsigned char)**args))
03621     return 0;
03622 
03623   while (isdigit ((unsigned char)**args))
03624     {
03625          char_str[0] = **args;
03626          string_append (arg, char_str);
03627          (*args)++;
03628     }
03629 
03630   return 1;
03631 }
03632 
03633 /* Demangle the next argument, given by MANGLED into RESULT, which
03634    *should be an uninitialized* string.  It will be initialized here,
03635    and free'd should anything go wrong.  */
03636 
03637 static int
03638 do_arg (work, mangled, result)
03639         struct work_stuff *work;
03640         const char **mangled;
03641         string *result;
03642 {
03643   /* Remember where we started so that we can record the type, for
03644         non-squangling type remembering.  */
03645   const char *start = *mangled;
03646 
03647   string_init (result);
03648 
03649   if (work->nrepeats > 0)
03650     {
03651          --work->nrepeats;
03652 
03653          if (work->previous_argument == 0)
03654         return 0;
03655 
03656          /* We want to reissue the previous type in this argument list.  */
03657          string_appends (result, work->previous_argument);
03658          return 1;
03659     }
03660 
03661   if (**mangled == 'n')
03662     {
03663          /* A squangling-style repeat.  */
03664          (*mangled)++;
03665          work->nrepeats = consume_count(mangled);
03666 
03667          if (work->nrepeats <= 0)
03668         /* This was not a repeat count after all.  */
03669         return 0;
03670 
03671          if (work->nrepeats > 9)
03672         {
03673           if (**mangled != '_')
03674             /* The repeat count should be followed by an '_' in this
03675                   case.  */
03676             return 0;
03677           else
03678             (*mangled)++;
03679         }
03680 
03681          /* Now, the repeat is all set up.  */
03682          return do_arg (work, mangled, result);
03683     }
03684 
03685   /* Save the result in WORK->previous_argument so that we can find it
03686         if it's repeated.  Note that saving START is not good enough: we
03687         do not want to add additional types to the back-referenceable
03688         type vector when processing a repeated type.  */
03689   if (work->previous_argument)
03690     string_clear (work->previous_argument);
03691   else
03692     {
03693          work->previous_argument = (string*) xmalloc (sizeof (string));
03694          string_init (work->previous_argument);
03695     }
03696 
03697   if (!do_type (work, mangled, work->previous_argument))
03698     return 0;
03699 
03700   string_appends (result, work->previous_argument);
03701 
03702   remember_type (work, start, *mangled - start);
03703   return 1;
03704 }
03705 
03706 static void
03707 remember_type (work, start, len)
03708         struct work_stuff *work;
03709         const char *start;
03710         int len;
03711 {
03712   char *tem;
03713 
03714   if (work->forgetting_types)
03715     return;
03716 
03717   if (work -> ntypes >= work -> typevec_size)
03718     {
03719          if (work -> typevec_size == 0)
03720         {
03721           work -> typevec_size = 3;
03722           work -> typevec
03723             = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
03724         }
03725          else
03726         {
03727           work -> typevec_size *= 2;
03728           work -> typevec
03729             = (char **) xrealloc ((char *)work -> typevec,
03730                                   sizeof (char *) * work -> typevec_size);
03731         }
03732     }
03733   tem = xmalloc (len + 1);
03734   memcpy (tem, start, len);
03735   tem[len] = '\0';
03736   work -> typevec[work -> ntypes++] = tem;
03737 }
03738 
03739 
03740 /* Remember a K type class qualifier. */
03741 static void
03742 remember_Ktype (work, start, len)
03743         struct work_stuff *work;
03744         const char *start;
03745         int len;
03746 {
03747   char *tem;
03748 
03749   if (work -> numk >= work -> ksize)
03750     {
03751          if (work -> ksize == 0)
03752         {
03753           work -> ksize = 5;
03754           work -> ktypevec
03755             = (char **) xmalloc (sizeof (char *) * work -> ksize);
03756         }
03757          else
03758         {
03759           work -> ksize *= 2;
03760           work -> ktypevec
03761             = (char **) xrealloc ((char *)work -> ktypevec,
03762                                   sizeof (char *) * work -> ksize);
03763         }
03764     }
03765   tem = xmalloc (len + 1);
03766   memcpy (tem, start, len);
03767   tem[len] = '\0';
03768   work -> ktypevec[work -> numk++] = tem;
03769 }
03770 
03771 /* Register a B code, and get an index for it. B codes are registered
03772    as they are seen, rather than as they are completed, so map<temp<char> >
03773    registers map<temp<char> > as B0, and temp<char> as B1 */
03774 
03775 static int
03776 register_Btype (work)
03777         struct work_stuff *work;
03778 {
03779   int ret;
03780 
03781   if (work -> numb >= work -> bsize)
03782     {
03783          if (work -> bsize == 0)
03784         {
03785           work -> bsize = 5;
03786           work -> btypevec
03787             = (char **) xmalloc (sizeof (char *) * work -> bsize);
03788         }
03789          else
03790         {
03791           work -> bsize *= 2;
03792           work -> btypevec
03793             = (char **) xrealloc ((char *)work -> btypevec,
03794                                   sizeof (char *) * work -> bsize);
03795         }
03796     }
03797   ret = work -> numb++;
03798   work -> btypevec[ret] = NULL;
03799   return(ret);
03800 }
03801 
03802 /* Store a value into a previously registered B code type. */
03803 
03804 static void
03805 remember_Btype (work, start, len, index)
03806         struct work_stuff *work;
03807         const char *start;
03808         int len, index;
03809 {
03810   char *tem;
03811 
03812   tem = xmalloc (len + 1);
03813   memcpy (tem, start, len);
03814   tem[len] = '\0';
03815   work -> btypevec[index] = tem;
03816 }
03817 
03818 /* Lose all the info related to B and K type codes. */
03819 static void
03820 forget_B_and_K_types (work)
03821         struct work_stuff *work;
03822 {
03823   int i;
03824 
03825   while (work -> numk > 0)
03826     {
03827          i = --(work -> numk);
03828          if (work -> ktypevec[i] != NULL)
03829         {
03830           free (work -> ktypevec[i]);
03831           work -> ktypevec[i] = NULL;
03832         }
03833     }
03834 
03835   while (work -> numb > 0)
03836     {
03837          i = --(work -> numb);
03838          if (work -> btypevec[i] != NULL)
03839         {
03840           free (work -> btypevec[i]);
03841           work -> btypevec[i] = NULL;
03842         }
03843     }
03844 }
03845 /* Forget the remembered types, but not the type vector itself.  */
03846 
03847 static void
03848 forget_types (work)
03849         struct work_stuff *work;
03850 {
03851   int i;
03852 
03853   while (work -> ntypes > 0)
03854     {
03855          i = --(work -> ntypes);
03856          if (work -> typevec[i] != NULL)
03857         {
03858           free (work -> typevec[i]);
03859           work -> typevec[i] = NULL;
03860         }
03861     }
03862 }
03863 
03864 /* Process the argument list part of the signature, after any class spec
03865    has been consumed, as well as the first 'F' character (if any).  For
03866    example:
03867 
03868    "__als__3fooRT0"             =>      process "RT0"
03869    "complexfunc5__FPFPc_PFl_i"  =>      process "PFPc_PFl_i"
03870 
03871    DECLP must be already initialised, usually non-empty.  It won't be freed
03872    on failure.
03873 
03874    Note that g++ differs significantly from ARM and lucid style mangling
03875    with regards to references to previously seen types.  For example, given
03876    the source fragment:
03877 
03878         class foo {
03879           public:
03880           foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
03881         };
03882 
03883         foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
03884         void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
03885 
03886    g++ produces the names:
03887 
03888         __3fooiRT0iT2iT2
03889         foo__FiR3fooiT1iT1
03890 
03891    while lcc (and presumably other ARM style compilers as well) produces:
03892 
03893         foo__FiR3fooT1T2T1T2
03894         __ct__3fooFiR3fooT1T2T1T2
03895 
03896    Note that g++ bases its type numbers starting at zero and counts all
03897    previously seen types, while lucid/ARM bases its type numbers starting
03898    at one and only considers types after it has seen the 'F' character
03899    indicating the start of the function args.  For lucid/ARM style, we
03900    account for this difference by discarding any previously seen types when
03901    we see the 'F' character, and subtracting one from the type number
03902    reference.
03903 
03904  */
03905 
03906 static int
03907 demangle_args (work, mangled, declp)
03908         struct work_stuff *work;
03909         const char **mangled;
03910         string *declp;
03911 {
03912   string arg;
03913   int need_comma = 0;
03914   int r;
03915   int t;
03916   const char *tem;
03917   char temptype;
03918 
03919   if (PRINT_ARG_TYPES)
03920     {
03921          string_append (declp, "(");
03922          if (**mangled == '\0')
03923         {
03924           string_append (declp, "void");
03925         }
03926     }
03927 
03928   while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
03929          || work->nrepeats > 0)
03930     {
03931          if ((**mangled == 'N') || (**mangled == 'T'))
03932         {
03933           temptype = *(*mangled)++;
03934 
03935           if (temptype == 'N')
03936             {
03937                  if (!get_count (mangled, &r))
03938                 {
03939                   return (0);
03940                 }
03941             }
03942           else
03943             {
03944                  r = 1;
03945             }
03946                 if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10)
03947                   {
03948                     /* If we have 10 or more types we might have more than a 1 digit
03949                           index so we'll have to consume the whole count here. This
03950                           will lose if the next thing is a type name preceded by a
03951                           count but it's impossible to demangle that case properly
03952                           anyway. Eg if we already have 12 types is T12Pc "(..., type1,
03953                           Pc, ...)"  or "(..., type12, char *, ...)" */
03954                     if ((t = consume_count(mangled)) <= 0)
03955                          {
03956                            return (0);
03957                          }
03958                   }
03959                 else
03960             {
03961                  if (!get_count (mangled, &t))
03962                 {
03963                         return (0);
03964                 }
03965             }
03966           if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
03967             {
03968                  t--;
03969             }
03970           /* Validate the type index.  Protect against illegal indices from
03971                 malformed type strings.  */
03972           if ((t < 0) || (t >= work -> ntypes))
03973             {
03974                  return (0);
03975             }
03976           while (work->nrepeats > 0 || --r >= 0)
03977             {
03978                  tem = work -> typevec[t];
03979                  if (need_comma && PRINT_ARG_TYPES)
03980                 {
03981                   string_append (declp, ", ");
03982                 }
03983                  if (!do_arg (work, &tem, &arg))
03984                 {
03985                   return (0);
03986                 }
03987                  if (PRINT_ARG_TYPES)
03988                 {
03989                   string_appends (declp, &arg);
03990                 }
03991                  string_delete (&arg);
03992                  need_comma = 1;
03993             }
03994         }
03995          else
03996         {
03997           if (need_comma && PRINT_ARG_TYPES)
03998             string_append (declp, ", ");
03999           if (!do_arg (work, mangled, &arg))
04000             return (0);
04001           if (PRINT_ARG_TYPES)
04002             string_appends (declp, &arg);
04003           string_delete (&arg);
04004           need_comma = 1;
04005         }
04006     }
04007 
04008   if (**mangled == 'e')
04009     {
04010          (*mangled)++;
04011          if (PRINT_ARG_TYPES)
04012         {
04013           if (need_comma)
04014             {
04015                  string_append (declp, ",");
04016             }
04017           string_append (declp, "...");
04018         }
04019     }
04020 
04021   if (PRINT_ARG_TYPES)
04022     {
04023          string_append (declp, ")");
04024     }
04025   return (1);
04026 }
04027 
04028 /* Like demangle_args, but for demangling the argument lists of function
04029    and method pointers or references, not top-level declarations.  */
04030 
04031 static int
04032 demangle_nested_args (work, mangled, declp)
04033         struct work_stuff *work;
04034         const char **mangled;
04035         string *declp;
04036 {
04037   string* saved_previous_argument;
04038   int result;
04039   int saved_nrepeats;
04040 
04041   /* The G++ name-mangling algorithm does not remember types on nested
04042         argument lists, unless -fsquangling is used, and in that case the
04043         type vector updated by remember_type is not used.  So, we turn
04044         off remembering of types here.  */
04045   ++work->forgetting_types;
04046 
04047   /* For the repeat codes used with -fsquangling, we must keep track of
04048         the last argument.  */
04049   saved_previous_argument = work->previous_argument;
04050   saved_nrepeats = work->nrepeats;
04051   work->previous_argument = 0;
04052   work->nrepeats = 0;
04053 
04054   /* Actually demangle the arguments.  */
04055   result = demangle_args (work, mangled, declp);
04056 
04057   /* Restore the previous_argument field.  */
04058   if (work->previous_argument)
04059     string_delete (work->previous_argument);
04060   work->previous_argument = saved_previous_argument;
04061   --work->forgetting_types;
04062   work->nrepeats = saved_nrepeats;
04063 
04064   return result;
04065 }
04066 
04067 static void
04068 demangle_function_name (work, mangled, declp, scan)
04069         struct work_stuff *work;
04070         const char **mangled;
04071         string *declp;
04072         const char *scan;
04073 {
04074   size_t i;
04075   string type;
04076   const char *tem;
04077 
04078   string_appendn (declp, (*mangled), scan - (*mangled));
04079   string_need (declp, 1);
04080   *(declp -> p) = '\0';
04081 
04082   /* Consume the function name, including the "__" separating the name
04083         from the signature.  We are guaranteed that SCAN points to the
04084         separator.  */
04085 
04086   (*mangled) = scan + 2;
04087   /* We may be looking at an instantiation of a template function:
04088         foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a
04089         following _F marks the start of the function arguments.  Handle
04090         the template arguments first. */
04091 
04092   if (HP_DEMANGLING && (**mangled == 'X'))
04093     {
04094          demangle_arm_hp_template (work, mangled, 0, declp);
04095          /* This leaves MANGLED pointing to the 'F' marking func args */
04096     }
04097 
04098   if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
04099     {
04100 
04101          /* See if we have an ARM style constructor or destructor operator.
04102          If so, then just record it, clear the decl, and return.
04103          We can't build the actual constructor/destructor decl until later,
04104          when we recover the class name from the signature.  */
04105 
04106          if (strcmp (declp -> b, "__ct") == 0)
04107         {
04108           work -> constructor += 1;
04109           string_clear (declp);
04110           return;
04111         }
04112          else if (strcmp (declp -> b, "__dt") == 0)
04113         {
04114           work -> destructor += 1;
04115           string_clear (declp);
04116           return;
04117         }
04118     }
04119 
04120   if (declp->p - declp->b >= 3
04121          && declp->b[0] == 'o'
04122          && declp->b[1] == 'p'
04123          && strchr (cplus_markers, declp->b[2]) != NULL)
04124     {
04125          /* see if it's an assignment expression */
04126          if (declp->p - declp->b >= 10 /* op$assign_ */
04127           && memcmp (declp->b + 3, "assign_", 7) == 0)
04128         {
04129           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
04130             {
04131                  int len = declp->p - declp->b - 10;
04132                  if ((int) strlen (optable[i].in) == len
04133                   && memcmp (optable[i].in, declp->b + 10, len) == 0)
04134                 {
04135                   string_clear (declp);
04136                   string_append (declp, "operator");
04137                   string_append (declp, optable[i].out);
04138                   string_append (declp, "=");
04139                   break;
04140                 }
04141             }
04142         }
04143          else
04144         {
04145           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
04146             {
04147                  int len = declp->p - declp->b - 3;
04148                  if ((int) strlen (optable[i].in) == len
04149                   && memcmp (optable[i].in, declp->b + 3, len) == 0)
04150                 {
04151                   string_clear (declp);
04152                   string_append (declp, "operator");
04153                   string_append (declp, optable[i].out);
04154                   break;
04155                 }
04156             }
04157         }
04158     }
04159   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
04160            && strchr (cplus_markers, declp->b[4]) != NULL)
04161     {
04162          /* type conversion operator */
04163          tem = declp->b + 5;
04164          if (do_type (work, &tem, &type))
04165         {
04166           string_clear (declp);
04167           string_append (declp, "operator ");
04168           string_appends (declp, &type);
04169           string_delete (&type);
04170         }
04171     }
04172   else if (declp->b[0] == '_' && declp->b[1] == '_'
04173            && declp->b[2] == 'o' && declp->b[3] == 'p')
04174     {
04175          /* ANSI.  */
04176          /* type conversion operator.  */
04177          tem = declp->b + 4;
04178          if (do_type (work, &tem, &type))
04179         {
04180           string_clear (declp);
04181           string_append (declp, "operator ");
04182           string_appends (declp, &type);
04183           string_delete (&type);
04184         }
04185     }
04186   else if (declp->b[0] == '_' && declp->b[1] == '_'
04187            && declp->b[2] >= 'a' && declp->b[2] <= 'z'
04188            && declp->b[3] >= 'a' && declp->b[3] <= 'z')
04189     {
04190          if (declp->b[4] == '\0')
04191         {
04192           /* Operator.  */
04193           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
04194             {
04195                  if (strlen (optable[i].in) == 2
04196                   && memcmp (optable[i].in, declp->b + 2, 2) == 0)
04197                 {
04198                   string_clear (declp);
04199                   string_append (declp, "operator");
04200                   string_append (declp, optable[i].out);
04201                   break;
04202                 }
04203             }
04204         }
04205          else
04206         {
04207           if (declp->b[2] == 'a' && declp->b[5] == '\0')
04208             {
04209                  /* Assignment.  */
04210                  for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
04211                 {
04212                   if (strlen (optable[i].in) == 3
04213                          && memcmp (optable[i].in, declp->b + 2, 3) == 0)
04214                     {
04215                          string_clear (declp);
04216                          string_append (declp, "operator");
04217                          string_append (declp, optable[i].out);
04218                          break;
04219                     }
04220                 }
04221             }
04222         }
04223     }
04224 }
04225 
04226 /* a mini string-handling package */
04227 
04228 static void
04229 string_need (s, n)
04230         string *s;
04231         int n;
04232 {
04233   int tem;
04234 
04235   if (s->b == NULL)
04236     {
04237          if (n < 32)
04238         {
04239           n = 32;
04240         }
04241          s->p = s->b = xmalloc (n);
04242          s->e = s->b + n;
04243     }
04244   else if (s->e - s->p < n)
04245     {
04246          tem = s->p - s->b;
04247          n += tem;
04248          n *= 2;
04249          s->b = xrealloc (s->b, n);
04250          s->p = s->b + tem;
04251          s->e = s->b + n;
04252     }
04253 }
04254 
04255 static void
04256 string_delete (s)
04257         string *s;
04258 {
04259   if (s->b != NULL)
04260     {
04261          free (s->b);
04262          s->b = s->e = s->p = NULL;
04263     }
04264 }
04265 
04266 static void
04267 string_init (s)
04268         string *s;
04269 {
04270   s->b = s->p = s->e = NULL;
04271 }
04272 
04273 static void
04274 string_clear (s)
04275         string *s;
04276 {
04277   s->p = s->b;
04278 }
04279 
04280 #if 0
04281 
04282 static int
04283 string_empty (s)
04284         string *s;
04285 {
04286   return (s->b == s->p);
04287 }
04288 
04289 #endif
04290 
04291 static void
04292 string_append (p, s)
04293         string *p;
04294         const char *s;
04295 {
04296   int n;
04297   if (s == NULL || *s == '\0')
04298     return;
04299   n = strlen (s);
04300   string_need (p, n);
04301   memcpy (p->p, s, n);
04302   p->p += n;
04303 }
04304 
04305 static void
04306 string_appends (p, s)
04307         string *p, *s;
04308 {
04309   int n;
04310 
04311   if (s->b != s->p)
04312     {
04313          n = s->p - s->b;
04314          string_need (p, n);
04315          memcpy (p->p, s->b, n);
04316          p->p += n;
04317     }
04318 }
04319 
04320 static void
04321 string_appendn (p, s, n)
04322         string *p;
04323         const char *s;
04324         int n;
04325 {
04326   if (n != 0)
04327     {
04328          string_need (p, n);
04329          memcpy (p->p, s, n);
04330          p->p += n;
04331     }
04332 }
04333 
04334 static void
04335 string_prepend (p, s)
04336         string *p;
04337         const char *s;
04338 {
04339   if (s != NULL && *s != '\0')
04340     {
04341          string_prependn (p, s, strlen (s));
04342     }
04343 }
04344 
04345 static void
04346 string_prepends (p, s)
04347         string *p, *s;
04348 {
04349   if (s->b != s->p)
04350     {
04351          string_prependn (p, s->b, s->p - s->b);
04352     }
04353 }
04354 
04355 static void
04356 string_prependn (p, s, n)
04357         string *p;
04358         const char *s;
04359         int n;
04360 {
04361   char *q;
04362 
04363   if (n != 0)
04364     {
04365          string_need (p, n);
04366          for (q = p->p - 1; q >= p->b; q--)
04367         {
04368           q[n] = q[0];
04369         }
04370          memcpy (p->b, s, n);
04371          p->p += n;
04372     }
04373 }
04374 
04375 static void
04376 string_append_template_idx (s, idx)
04377         string *s;
04378         int idx;
04379 {
04380   char buf[INTBUF_SIZE + 1 /* 'T' */];
04381   sprintf(buf, "T%d", idx);
04382   string_append (s, buf);
04383 }
04384 
04385 

Generated on Fri May 7 21:15:29 2004 by doxygen 1.3.5