Back to index

cell-binutils  2.17cvs20070401
cplus-dem.c
Go to the documentation of this file.
00001 /* Demangler for GNU C++
00002    Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
00003    2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
00004    Written by James Clark (jjc@jclark.uucp)
00005    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
00006    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
00007 
00008 This file is part of the libiberty library.
00009 Libiberty is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU Library General Public
00011 License as published by the Free Software Foundation; either
00012 version 2 of the License, or (at your option) any later version.
00013 
00014 In addition to the permissions in the GNU Library General Public
00015 License, the Free Software Foundation gives you unlimited permission
00016 to link the compiled version of this file into combinations with other
00017 programs, and to distribute those combinations without any restriction
00018 coming from the use of this file.  (The Library Public License
00019 restrictions do apply in other respects; for example, they cover
00020 modification of the file, and distribution when not linked into a
00021 combined executable.)
00022 
00023 Libiberty is distributed in the hope that it will be useful,
00024 but WITHOUT ANY WARRANTY; without even the implied warranty of
00025 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 Library General Public License for more details.
00027 
00028 You should have received a copy of the GNU Library General Public
00029 License along with libiberty; see the file COPYING.LIB.  If
00030 not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00031 Boston, MA 02110-1301, USA.  */
00032 
00033 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
00034 
00035    This file imports xmalloc and xrealloc, which are like malloc and
00036    realloc except that they generate a fatal error if there is no
00037    available memory.  */
00038 
00039 /* This file lives in both GCC and libiberty.  When making changes, please
00040    try not to break either.  */
00041 
00042 #ifdef HAVE_CONFIG_H
00043 #include "config.h"
00044 #endif
00045 
00046 #include "safe-ctype.h"
00047 
00048 #include <sys/types.h>
00049 #include <string.h>
00050 #include <stdio.h>
00051 
00052 #ifdef HAVE_STDLIB_H
00053 #include <stdlib.h>
00054 #else
00055 char * malloc ();
00056 char * realloc ();
00057 #endif
00058 
00059 #include <demangle.h>
00060 #undef CURRENT_DEMANGLING_STYLE
00061 #define CURRENT_DEMANGLING_STYLE work->options
00062 
00063 #include "libiberty.h"
00064 
00065 static char *ada_demangle (const char *, int);
00066 
00067 #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
00068 
00069 /* A value at least one greater than the maximum number of characters
00070    that will be output when using the `%d' format with `printf'.  */
00071 #define INTBUF_SIZE 32
00072 
00073 extern void fancy_abort (void) ATTRIBUTE_NORETURN;
00074 
00075 /* In order to allow a single demangler executable to demangle strings
00076    using various common values of CPLUS_MARKER, as well as any specific
00077    one set at compile time, we maintain a string containing all the
00078    commonly used ones, and check to see if the marker we are looking for
00079    is in that string.  CPLUS_MARKER is usually '$' on systems where the
00080    assembler can deal with that.  Where the assembler can't, it's usually
00081    '.' (but on many systems '.' is used for other things).  We put the
00082    current defined CPLUS_MARKER first (which defaults to '$'), followed
00083    by the next most common value, followed by an explicit '$' in case
00084    the value of CPLUS_MARKER is not '$'.
00085 
00086    We could avoid this if we could just get g++ to tell us what the actual
00087    cplus marker character is as part of the debug information, perhaps by
00088    ensuring that it is the character that terminates the gcc<n>_compiled
00089    marker symbol (FIXME).  */
00090 
00091 #if !defined (CPLUS_MARKER)
00092 #define CPLUS_MARKER '$'
00093 #endif
00094 
00095 enum demangling_styles current_demangling_style = auto_demangling;
00096 
00097 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
00098 
00099 static char char_str[2] = { '\000', '\000' };
00100 
00101 void
00102 set_cplus_marker_for_demangling (int ch)
00103 {
00104   cplus_markers[0] = ch;
00105 }
00106 
00107 typedef struct string              /* Beware: these aren't required to be */
00108 {                           /*  '\0' terminated.  */
00109   char *b;                  /* pointer to start of string */
00110   char *p;                  /* pointer after last character */
00111   char *e;                  /* pointer after end of allocated space */
00112 } string;
00113 
00114 /* Stuff that is shared between sub-routines.
00115    Using a shared structure allows cplus_demangle to be reentrant.  */
00116 
00117 struct work_stuff
00118 {
00119   int options;
00120   char **typevec;
00121   char **ktypevec;
00122   char **btypevec;
00123   int numk;
00124   int numb;
00125   int ksize;
00126   int bsize;
00127   int ntypes;
00128   int typevec_size;
00129   int constructor;
00130   int destructor;
00131   int static_type;   /* A static member function */
00132   int temp_start;       /* index in demangled to start of template args */
00133   int type_quals;       /* The type qualifiers.  */
00134   int dllimported;   /* Symbol imported from a PE DLL */
00135   char **tmpl_argvec;   /* Template function arguments. */
00136   int ntmpl_args;       /* The number of template function arguments. */
00137   int forgetting_types; /* Nonzero if we are not remembering the types
00138                         we see.  */
00139   string* previous_argument; /* The last function argument demangled.  */
00140   int nrepeats;         /* The number of times to repeat the previous
00141                         argument.  */
00142 };
00143 
00144 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
00145 #define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
00146 
00147 static const struct optable
00148 {
00149   const char *const in;
00150   const char *const out;
00151   const int flags;
00152 } optable[] = {
00153   {"nw",        " new",     DMGL_ANSI},   /* new (1.92,  ansi) */
00154   {"dl",        " delete",  DMGL_ANSI},   /* new (1.92,  ansi) */
00155   {"new",       " new",     0},           /* old (1.91,  and 1.x) */
00156   {"delete",    " delete",  0},           /* old (1.91,  and 1.x) */
00157   {"vn",        " new []",  DMGL_ANSI},   /* GNU, pending ansi */
00158   {"vd",        " delete []",      DMGL_ANSI},   /* GNU, pending ansi */
00159   {"as",        "=",        DMGL_ANSI},   /* ansi */
00160   {"ne",        "!=",              DMGL_ANSI},   /* old, ansi */
00161   {"eq",        "==",              DMGL_ANSI},   /* old,       ansi */
00162   {"ge",        ">=",              DMGL_ANSI},   /* old,       ansi */
00163   {"gt",        ">",        DMGL_ANSI},   /* old,       ansi */
00164   {"le",        "<=",              DMGL_ANSI},   /* old,       ansi */
00165   {"lt",        "<",        DMGL_ANSI},   /* old,       ansi */
00166   {"plus",      "+",        0},           /* old */
00167   {"pl",        "+",        DMGL_ANSI},   /* ansi */
00168   {"apl",       "+=",              DMGL_ANSI},   /* ansi */
00169   {"minus",     "-",        0},           /* old */
00170   {"mi",        "-",        DMGL_ANSI},   /* ansi */
00171   {"ami",       "-=",              DMGL_ANSI},   /* ansi */
00172   {"mult",      "*",        0},           /* old */
00173   {"ml",        "*",        DMGL_ANSI},   /* ansi */
00174   {"amu",       "*=",              DMGL_ANSI},   /* ansi (ARM/Lucid) */
00175   {"aml",       "*=",              DMGL_ANSI},   /* ansi (GNU/g++) */
00176   {"convert",   "+",        0},           /* old (unary +) */
00177   {"negate",    "-",        0},           /* old (unary -) */
00178   {"trunc_mod",        "%",        0},           /* old */
00179   {"md",        "%",        DMGL_ANSI},   /* ansi */
00180   {"amd",       "%=",              DMGL_ANSI},   /* ansi */
00181   {"trunc_div",        "/",        0},           /* old */
00182   {"dv",        "/",        DMGL_ANSI},   /* ansi */
00183   {"adv",       "/=",              DMGL_ANSI},   /* ansi */
00184   {"truth_andif", "&&",            0},           /* old */
00185   {"aa",        "&&",              DMGL_ANSI},   /* ansi */
00186   {"truth_orif",  "||",            0},           /* old */
00187   {"oo",        "||",              DMGL_ANSI},   /* ansi */
00188   {"truth_not",        "!",        0},           /* old */
00189   {"nt",        "!",        DMGL_ANSI},   /* ansi */
00190   {"postincrement","++",    0},           /* old */
00191   {"pp",        "++",              DMGL_ANSI},   /* ansi */
00192   {"postdecrement","--",    0},           /* old */
00193   {"mm",        "--",              DMGL_ANSI},   /* ansi */
00194   {"bit_ior",   "|",        0},           /* old */
00195   {"or",        "|",        DMGL_ANSI},   /* ansi */
00196   {"aor",       "|=",              DMGL_ANSI},   /* ansi */
00197   {"bit_xor",   "^",        0},           /* old */
00198   {"er",        "^",        DMGL_ANSI},   /* ansi */
00199   {"aer",       "^=",              DMGL_ANSI},   /* ansi */
00200   {"bit_and",   "&",        0},           /* old */
00201   {"ad",        "&",        DMGL_ANSI},   /* ansi */
00202   {"aad",       "&=",              DMGL_ANSI},   /* ansi */
00203   {"bit_not",   "~",        0},           /* old */
00204   {"co",        "~",        DMGL_ANSI},   /* ansi */
00205   {"call",      "()",              0},           /* old */
00206   {"cl",        "()",              DMGL_ANSI},   /* ansi */
00207   {"alshift",   "<<",              0},           /* old */
00208   {"ls",        "<<",              DMGL_ANSI},   /* ansi */
00209   {"als",       "<<=",      DMGL_ANSI},   /* ansi */
00210   {"arshift",   ">>",              0},           /* old */
00211   {"rs",        ">>",              DMGL_ANSI},   /* ansi */
00212   {"ars",       ">>=",      DMGL_ANSI},   /* ansi */
00213   {"component",        "->",              0},           /* old */
00214   {"pt",        "->",              DMGL_ANSI},   /* ansi; Lucid C++ form */
00215   {"rf",        "->",              DMGL_ANSI},   /* ansi; ARM/GNU form */
00216   {"indirect",         "*",        0},           /* old */
00217   {"method_call",  "->()",  0},           /* old */
00218   {"addr",      "&",        0},           /* old (unary &) */
00219   {"array",     "[]",              0},           /* old */
00220   {"vc",        "[]",              DMGL_ANSI},   /* ansi */
00221   {"compound",         ", ",              0},           /* old */
00222   {"cm",        ", ",              DMGL_ANSI},   /* ansi */
00223   {"cond",      "?:",              0},           /* old */
00224   {"cn",        "?:",              DMGL_ANSI},   /* pseudo-ansi */
00225   {"max",       ">?",              0},           /* old */
00226   {"mx",        ">?",              DMGL_ANSI},   /* pseudo-ansi */
00227   {"min",       "<?",              0},           /* old */
00228   {"mn",        "<?",              DMGL_ANSI},   /* pseudo-ansi */
00229   {"nop",       "",         0},           /* old (for operator=) */
00230   {"rm",        "->*",      DMGL_ANSI},   /* ansi */
00231   {"sz",          "sizeof ",    DMGL_ANSI}      /* pseudo-ansi */
00232 };
00233 
00234 /* These values are used to indicate the various type varieties.
00235    They are all non-zero so that they can be used as `success'
00236    values.  */
00237 typedef enum type_kind_t
00238 {
00239   tk_none,
00240   tk_pointer,
00241   tk_reference,
00242   tk_integral,
00243   tk_bool,
00244   tk_char,
00245   tk_real
00246 } type_kind_t;
00247 
00248 const struct demangler_engine libiberty_demanglers[] =
00249 {
00250   {
00251     NO_DEMANGLING_STYLE_STRING,
00252     no_demangling,
00253     "Demangling disabled"
00254   }
00255   ,
00256   {
00257     AUTO_DEMANGLING_STYLE_STRING,
00258       auto_demangling,
00259       "Automatic selection based on executable"
00260   }
00261   ,
00262   {
00263     GNU_DEMANGLING_STYLE_STRING,
00264       gnu_demangling,
00265       "GNU (g++) style demangling"
00266   }
00267   ,
00268   {
00269     LUCID_DEMANGLING_STYLE_STRING,
00270       lucid_demangling,
00271       "Lucid (lcc) style demangling"
00272   }
00273   ,
00274   {
00275     ARM_DEMANGLING_STYLE_STRING,
00276       arm_demangling,
00277       "ARM style demangling"
00278   }
00279   ,
00280   {
00281     HP_DEMANGLING_STYLE_STRING,
00282       hp_demangling,
00283       "HP (aCC) style demangling"
00284   }
00285   ,
00286   {
00287     EDG_DEMANGLING_STYLE_STRING,
00288       edg_demangling,
00289       "EDG style demangling"
00290   }
00291   ,
00292   {
00293     GNU_V3_DEMANGLING_STYLE_STRING,
00294     gnu_v3_demangling,
00295     "GNU (g++) V3 ABI-style demangling"
00296   }
00297   ,
00298   {
00299     JAVA_DEMANGLING_STYLE_STRING,
00300     java_demangling,
00301     "Java style demangling"
00302   }
00303   ,
00304   {
00305     GNAT_DEMANGLING_STYLE_STRING,
00306     gnat_demangling,
00307     "GNAT style demangling"
00308   }
00309   ,
00310   {
00311     NULL, unknown_demangling, NULL
00312   }
00313 };
00314 
00315 #define STRING_EMPTY(str)   ((str) -> b == (str) -> p)
00316 #define APPEND_BLANK(str)   {if (!STRING_EMPTY(str)) \
00317     string_append(str, " ");}
00318 #define LEN_STRING(str)         ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
00319 
00320 /* The scope separator appropriate for the language being demangled.  */
00321 
00322 #define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
00323 
00324 #define ARM_VTABLE_STRING "__vtbl__"      /* Lucid/ARM virtual table prefix */
00325 #define ARM_VTABLE_STRLEN 8        /* strlen (ARM_VTABLE_STRING) */
00326 
00327 /* Prototypes for local functions */
00328 
00329 static void delete_work_stuff (struct work_stuff *);
00330 
00331 static void delete_non_B_K_work_stuff (struct work_stuff *);
00332 
00333 static char *mop_up (struct work_stuff *, string *, int);
00334 
00335 static void squangle_mop_up (struct work_stuff *);
00336 
00337 static void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *);
00338 
00339 #if 0
00340 static int
00341 demangle_method_args (struct work_stuff *, const char **, string *);
00342 #endif
00343 
00344 static char *
00345 internal_cplus_demangle (struct work_stuff *, const char *);
00346 
00347 static int
00348 demangle_template_template_parm (struct work_stuff *work,
00349                                  const char **, string *);
00350 
00351 static int
00352 demangle_template (struct work_stuff *work, const char **, string *,
00353                    string *, int, int);
00354 
00355 static int
00356 arm_pt (struct work_stuff *, const char *, int, const char **,
00357         const char **);
00358 
00359 static int
00360 demangle_class_name (struct work_stuff *, const char **, string *);
00361 
00362 static int
00363 demangle_qualified (struct work_stuff *, const char **, string *,
00364                     int, int);
00365 
00366 static int demangle_class (struct work_stuff *, const char **, string *);
00367 
00368 static int demangle_fund_type (struct work_stuff *, const char **, string *);
00369 
00370 static int demangle_signature (struct work_stuff *, const char **, string *);
00371 
00372 static int demangle_prefix (struct work_stuff *, const char **, string *);
00373 
00374 static int gnu_special (struct work_stuff *, const char **, string *);
00375 
00376 static int arm_special (const char **, string *);
00377 
00378 static void string_need (string *, int);
00379 
00380 static void string_delete (string *);
00381 
00382 static void
00383 string_init (string *);
00384 
00385 static void string_clear (string *);
00386 
00387 #if 0
00388 static int string_empty (string *);
00389 #endif
00390 
00391 static void string_append (string *, const char *);
00392 
00393 static void string_appends (string *, string *);
00394 
00395 static void string_appendn (string *, const char *, int);
00396 
00397 static void string_prepend (string *, const char *);
00398 
00399 static void string_prependn (string *, const char *, int);
00400 
00401 static void string_append_template_idx (string *, int);
00402 
00403 static int get_count (const char **, int *);
00404 
00405 static int consume_count (const char **);
00406 
00407 static int consume_count_with_underscores (const char**);
00408 
00409 static int demangle_args (struct work_stuff *, const char **, string *);
00410 
00411 static int demangle_nested_args (struct work_stuff*, const char**, string*);
00412 
00413 static int do_type (struct work_stuff *, const char **, string *);
00414 
00415 static int do_arg (struct work_stuff *, const char **, string *);
00416 
00417 static void
00418 demangle_function_name (struct work_stuff *, const char **, string *,
00419                         const char *);
00420 
00421 static int
00422 iterate_demangle_function (struct work_stuff *,
00423                            const char **, string *, const char *);
00424 
00425 static void remember_type (struct work_stuff *, const char *, int);
00426 
00427 static void remember_Btype (struct work_stuff *, const char *, int, int);
00428 
00429 static int register_Btype (struct work_stuff *);
00430 
00431 static void remember_Ktype (struct work_stuff *, const char *, int);
00432 
00433 static void forget_types (struct work_stuff *);
00434 
00435 static void forget_B_and_K_types (struct work_stuff *);
00436 
00437 static void string_prepends (string *, string *);
00438 
00439 static int
00440 demangle_template_value_parm (struct work_stuff*, const char**,
00441                               string*, type_kind_t);
00442 
00443 static int
00444 do_hpacc_template_const_value (struct work_stuff *, const char **, string *);
00445 
00446 static int
00447 do_hpacc_template_literal (struct work_stuff *, const char **, string *);
00448 
00449 static int snarf_numeric_literal (const char **, string *);
00450 
00451 /* There is a TYPE_QUAL value for each type qualifier.  They can be
00452    combined by bitwise-or to form the complete set of qualifiers for a
00453    type.  */
00454 
00455 #define TYPE_UNQUALIFIED   0x0
00456 #define TYPE_QUAL_CONST    0x1
00457 #define TYPE_QUAL_VOLATILE 0x2
00458 #define TYPE_QUAL_RESTRICT 0x4
00459 
00460 static int code_for_qualifier (int);
00461 
00462 static const char* qualifier_string (int);
00463 
00464 static const char* demangle_qualifier (int);
00465 
00466 static int demangle_expression (struct work_stuff *, const char **, string *, 
00467                                 type_kind_t);
00468 
00469 static int
00470 demangle_integral_value (struct work_stuff *, const char **, string *);
00471 
00472 static int
00473 demangle_real_value (struct work_stuff *, const char **, string *);
00474 
00475 static void
00476 demangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
00477 
00478 static void
00479 recursively_demangle (struct work_stuff *, const char **, string *, int);
00480 
00481 static void grow_vect (char **, size_t *, size_t, int);
00482 
00483 /* Translate count to integer, consuming tokens in the process.
00484    Conversion terminates on the first non-digit character.
00485 
00486    Trying to consume something that isn't a count results in no
00487    consumption of input and a return of -1.
00488 
00489    Overflow consumes the rest of the digits, and returns -1.  */
00490 
00491 static int
00492 consume_count (const char **type)
00493 {
00494   int count = 0;
00495 
00496   if (! ISDIGIT ((unsigned char)**type))
00497     return -1;
00498 
00499   while (ISDIGIT ((unsigned char)**type))
00500     {
00501       count *= 10;
00502 
00503       /* Check for overflow.
00504         We assume that count is represented using two's-complement;
00505         no power of two is divisible by ten, so if an overflow occurs
00506         when multiplying by ten, the result will not be a multiple of
00507         ten.  */
00508       if ((count % 10) != 0)
00509        {
00510          while (ISDIGIT ((unsigned char) **type))
00511            (*type)++;
00512          return -1;
00513        }
00514 
00515       count += **type - '0';
00516       (*type)++;
00517     }
00518 
00519   if (count < 0)
00520     count = -1;
00521 
00522   return (count);
00523 }
00524 
00525 
00526 /* Like consume_count, but for counts that are preceded and followed
00527    by '_' if they are greater than 10.  Also, -1 is returned for
00528    failure, since 0 can be a valid value.  */
00529 
00530 static int
00531 consume_count_with_underscores (const char **mangled)
00532 {
00533   int idx;
00534 
00535   if (**mangled == '_')
00536     {
00537       (*mangled)++;
00538       if (!ISDIGIT ((unsigned char)**mangled))
00539        return -1;
00540 
00541       idx = consume_count (mangled);
00542       if (**mangled != '_')
00543        /* The trailing underscore was missing. */
00544        return -1;
00545 
00546       (*mangled)++;
00547     }
00548   else
00549     {
00550       if (**mangled < '0' || **mangled > '9')
00551        return -1;
00552 
00553       idx = **mangled - '0';
00554       (*mangled)++;
00555     }
00556 
00557   return idx;
00558 }
00559 
00560 /* C is the code for a type-qualifier.  Return the TYPE_QUAL
00561    corresponding to this qualifier.  */
00562 
00563 static int
00564 code_for_qualifier (int c)
00565 {
00566   switch (c)
00567     {
00568     case 'C':
00569       return TYPE_QUAL_CONST;
00570 
00571     case 'V':
00572       return TYPE_QUAL_VOLATILE;
00573 
00574     case 'u':
00575       return TYPE_QUAL_RESTRICT;
00576 
00577     default:
00578       break;
00579     }
00580 
00581   /* C was an invalid qualifier.  */
00582   abort ();
00583 }
00584 
00585 /* Return the string corresponding to the qualifiers given by
00586    TYPE_QUALS.  */
00587 
00588 static const char*
00589 qualifier_string (int type_quals)
00590 {
00591   switch (type_quals)
00592     {
00593     case TYPE_UNQUALIFIED:
00594       return "";
00595 
00596     case TYPE_QUAL_CONST:
00597       return "const";
00598 
00599     case TYPE_QUAL_VOLATILE:
00600       return "volatile";
00601 
00602     case TYPE_QUAL_RESTRICT:
00603       return "__restrict";
00604 
00605     case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
00606       return "const volatile";
00607 
00608     case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
00609       return "const __restrict";
00610 
00611     case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
00612       return "volatile __restrict";
00613 
00614     case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
00615       return "const volatile __restrict";
00616 
00617     default:
00618       break;
00619     }
00620 
00621   /* TYPE_QUALS was an invalid qualifier set.  */
00622   abort ();
00623 }
00624 
00625 /* C is the code for a type-qualifier.  Return the string
00626    corresponding to this qualifier.  This function should only be
00627    called with a valid qualifier code.  */
00628 
00629 static const char*
00630 demangle_qualifier (int c)
00631 {
00632   return qualifier_string (code_for_qualifier (c));
00633 }
00634 
00635 int
00636 cplus_demangle_opname (const char *opname, char *result, int options)
00637 {
00638   int len, len1, ret;
00639   string type;
00640   struct work_stuff work[1];
00641   const char *tem;
00642 
00643   len = strlen(opname);
00644   result[0] = '\0';
00645   ret = 0;
00646   memset ((char *) work, 0, sizeof (work));
00647   work->options = options;
00648 
00649   if (opname[0] == '_' && opname[1] == '_'
00650       && opname[2] == 'o' && opname[3] == 'p')
00651     {
00652       /* ANSI.  */
00653       /* type conversion operator.  */
00654       tem = opname + 4;
00655       if (do_type (work, &tem, &type))
00656        {
00657          strcat (result, "operator ");
00658          strncat (result, type.b, type.p - type.b);
00659          string_delete (&type);
00660          ret = 1;
00661        }
00662     }
00663   else if (opname[0] == '_' && opname[1] == '_'
00664           && ISLOWER((unsigned char)opname[2])
00665           && ISLOWER((unsigned char)opname[3]))
00666     {
00667       if (opname[4] == '\0')
00668        {
00669          /* Operator.  */
00670          size_t i;
00671          for (i = 0; i < ARRAY_SIZE (optable); i++)
00672            {
00673              if (strlen (optable[i].in) == 2
00674                 && memcmp (optable[i].in, opname + 2, 2) == 0)
00675               {
00676                 strcat (result, "operator");
00677                 strcat (result, optable[i].out);
00678                 ret = 1;
00679                 break;
00680               }
00681            }
00682        }
00683       else
00684        {
00685          if (opname[2] == 'a' && opname[5] == '\0')
00686            {
00687              /* Assignment.  */
00688              size_t i;
00689              for (i = 0; i < ARRAY_SIZE (optable); i++)
00690               {
00691                 if (strlen (optable[i].in) == 3
00692                     && memcmp (optable[i].in, opname + 2, 3) == 0)
00693                   {
00694                     strcat (result, "operator");
00695                     strcat (result, optable[i].out);
00696                     ret = 1;
00697                     break;
00698                   }
00699               }
00700            }
00701        }
00702     }
00703   else if (len >= 3
00704           && opname[0] == 'o'
00705           && opname[1] == 'p'
00706           && strchr (cplus_markers, opname[2]) != NULL)
00707     {
00708       /* see if it's an assignment expression */
00709       if (len >= 10 /* op$assign_ */
00710          && memcmp (opname + 3, "assign_", 7) == 0)
00711        {
00712          size_t i;
00713          for (i = 0; i < ARRAY_SIZE (optable); i++)
00714            {
00715              len1 = len - 10;
00716              if ((int) strlen (optable[i].in) == len1
00717                 && memcmp (optable[i].in, opname + 10, len1) == 0)
00718               {
00719                 strcat (result, "operator");
00720                 strcat (result, optable[i].out);
00721                 strcat (result, "=");
00722                 ret = 1;
00723                 break;
00724               }
00725            }
00726        }
00727       else
00728        {
00729          size_t i;
00730          for (i = 0; i < ARRAY_SIZE (optable); i++)
00731            {
00732              len1 = len - 3;
00733              if ((int) strlen (optable[i].in) == len1
00734                 && memcmp (optable[i].in, opname + 3, len1) == 0)
00735               {
00736                 strcat (result, "operator");
00737                 strcat (result, optable[i].out);
00738                 ret = 1;
00739                 break;
00740               }
00741            }
00742        }
00743     }
00744   else if (len >= 5 && memcmp (opname, "type", 4) == 0
00745           && strchr (cplus_markers, opname[4]) != NULL)
00746     {
00747       /* type conversion operator */
00748       tem = opname + 5;
00749       if (do_type (work, &tem, &type))
00750        {
00751          strcat (result, "operator ");
00752          strncat (result, type.b, type.p - type.b);
00753          string_delete (&type);
00754          ret = 1;
00755        }
00756     }
00757   squangle_mop_up (work);
00758   return ret;
00759 
00760 }
00761 
00762 /* Takes operator name as e.g. "++" and returns mangled
00763    operator name (e.g. "postincrement_expr"), or NULL if not found.
00764 
00765    If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
00766    if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
00767 
00768 const char *
00769 cplus_mangle_opname (const char *opname, int options)
00770 {
00771   size_t i;
00772   int len;
00773 
00774   len = strlen (opname);
00775   for (i = 0; i < ARRAY_SIZE (optable); i++)
00776     {
00777       if ((int) strlen (optable[i].out) == len
00778          && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
00779          && memcmp (optable[i].out, opname, len) == 0)
00780        return optable[i].in;
00781     }
00782   return (0);
00783 }
00784 
00785 /* Add a routine to set the demangling style to be sure it is valid and
00786    allow for any demangler initialization that maybe necessary. */
00787 
00788 enum demangling_styles
00789 cplus_demangle_set_style (enum demangling_styles style)
00790 {
00791   const struct demangler_engine *demangler = libiberty_demanglers; 
00792 
00793   for (; demangler->demangling_style != unknown_demangling; ++demangler)
00794     if (style == demangler->demangling_style)
00795       {
00796        current_demangling_style = style;
00797        return current_demangling_style;
00798       }
00799 
00800   return unknown_demangling;
00801 }
00802 
00803 /* Do string name to style translation */
00804 
00805 enum demangling_styles
00806 cplus_demangle_name_to_style (const char *name)
00807 {
00808   const struct demangler_engine *demangler = libiberty_demanglers; 
00809 
00810   for (; demangler->demangling_style != unknown_demangling; ++demangler)
00811     if (strcmp (name, demangler->demangling_style_name) == 0)
00812       return demangler->demangling_style;
00813 
00814   return unknown_demangling;
00815 }
00816 
00817 /* char *cplus_demangle (const char *mangled, int options)
00818 
00819    If MANGLED is a mangled function name produced by GNU C++, then
00820    a pointer to a @code{malloc}ed string giving a C++ representation
00821    of the name will be returned; otherwise NULL will be returned.
00822    It is the caller's responsibility to free the string which
00823    is returned.
00824 
00825    The OPTIONS arg may contain one or more of the following bits:
00826 
00827        DMGL_ANSI     ANSI qualifiers such as `const' and `void' are
00828                      included.
00829        DMGL_PARAMS   Function parameters are included.
00830 
00831    For example,
00832 
00833    cplus_demangle ("foo__1Ai", DMGL_PARAMS)             => "A::foo(int)"
00834    cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
00835    cplus_demangle ("foo__1Ai", 0)                => "A::foo"
00836 
00837    cplus_demangle ("foo__1Afe", DMGL_PARAMS)            => "A::foo(float,...)"
00838    cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
00839    cplus_demangle ("foo__1Afe", 0)               => "A::foo"
00840 
00841    Note that any leading underscores, or other such characters prepended by
00842    the compilation system, are presumed to have already been stripped from
00843    MANGLED.  */
00844 
00845 char *
00846 cplus_demangle (const char *mangled, int options)
00847 {
00848   char *ret;
00849   struct work_stuff work[1];
00850 
00851   if (current_demangling_style == no_demangling)
00852     return xstrdup (mangled);
00853 
00854   memset ((char *) work, 0, sizeof (work));
00855   work->options = options;
00856   if ((work->options & DMGL_STYLE_MASK) == 0)
00857     work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
00858 
00859   /* The V3 ABI demangling is implemented elsewhere.  */
00860   if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
00861     {
00862       ret = cplus_demangle_v3 (mangled, work->options);
00863       if (ret || GNU_V3_DEMANGLING)
00864        return ret;
00865     }
00866 
00867   if (JAVA_DEMANGLING)
00868     {
00869       ret = java_demangle_v3 (mangled);
00870       if (ret)
00871         return ret;
00872     }
00873 
00874   if (GNAT_DEMANGLING)
00875     return ada_demangle(mangled,options);
00876 
00877   ret = internal_cplus_demangle (work, mangled);
00878   squangle_mop_up (work);
00879   return (ret);
00880 }
00881 
00882 
00883 /* Assuming *OLD_VECT points to an array of *SIZE objects of size
00884    ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
00885    updating *OLD_VECT and *SIZE as necessary.  */
00886 
00887 static void
00888 grow_vect (char **old_vect, size_t *size, size_t min_size, int element_size)
00889 {
00890   if (*size < min_size)
00891     {
00892       *size *= 2;
00893       if (*size < min_size)
00894        *size = min_size;
00895       *old_vect = XRESIZEVAR (char, *old_vect, *size * element_size);
00896     }
00897 }
00898 
00899 /* Demangle ada names:
00900    1. Discard final __{DIGIT}+ or ${DIGIT}+
00901    2. Convert other instances of embedded "__" to `.'.
00902    3. Discard leading _ada_.
00903    4. Remove everything after first ___ if it is followed by 'X'.
00904    5. Put symbols that should be suppressed in <...> brackets.
00905    The resulting string is valid until the next call of ada_demangle.  */
00906 
00907 static char *
00908 ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
00909 {
00910   int i, j;
00911   int len0;
00912   const char* p;
00913   char *demangled = NULL;
00914   int changed;
00915   size_t demangled_size = 0;
00916   
00917   changed = 0;
00918 
00919   if (strncmp (mangled, "_ada_", 5) == 0)
00920     {
00921       mangled += 5;
00922       changed = 1;
00923     }
00924   
00925   if (mangled[0] == '_' || mangled[0] == '<')
00926     goto Suppress;
00927   
00928   p = strstr (mangled, "___");
00929   if (p == NULL)
00930     len0 = strlen (mangled);
00931   else
00932     {
00933       if (p[3] == 'X')
00934        {
00935          len0 = p - mangled;
00936          changed = 1;
00937        }
00938       else
00939        goto Suppress;
00940     }
00941   
00942   /* Make demangled big enough for possible expansion by operator name.  */
00943   grow_vect (&demangled,
00944             &demangled_size,  2 * len0 + 1,
00945             sizeof (char));
00946   
00947   if (ISDIGIT ((unsigned char) mangled[len0 - 1])) {
00948     for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1)
00949       ;
00950     if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_')
00951       {
00952        len0 = i - 1;
00953        changed = 1;
00954       }
00955     else if (mangled[i] == '$')
00956       {
00957        len0 = i;
00958        changed = 1;
00959       }
00960   }
00961   
00962   for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
00963        i += 1, j += 1)
00964     demangled[j] = mangled[i];
00965   
00966   while (i < len0)
00967     {
00968       if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_')
00969        {
00970          demangled[j] = '.';
00971          changed = 1;
00972          i += 2; j += 1;
00973        }
00974       else
00975        {
00976          demangled[j] = mangled[i];
00977          i += 1;  j += 1;
00978        }
00979     }
00980   demangled[j] = '\000';
00981   
00982   for (i = 0; demangled[i] != '\0'; i += 1)
00983     if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ')
00984       goto Suppress;
00985 
00986   if (! changed)
00987     return NULL;
00988   else
00989     return demangled;
00990   
00991  Suppress:
00992   grow_vect (&demangled,
00993             &demangled_size,  strlen (mangled) + 3,
00994             sizeof (char));
00995 
00996   if (mangled[0] == '<')
00997      strcpy (demangled, mangled);
00998   else
00999     sprintf (demangled, "<%s>", mangled);
01000 
01001   return demangled;
01002 }
01003 
01004 /* This function performs most of what cplus_demangle use to do, but
01005    to be able to demangle a name with a B, K or n code, we need to
01006    have a longer term memory of what types have been seen. The original
01007    now initializes and cleans up the squangle code info, while internal
01008    calls go directly to this routine to avoid resetting that info. */
01009 
01010 static char *
01011 internal_cplus_demangle (struct work_stuff *work, const char *mangled)
01012 {
01013 
01014   string decl;
01015   int success = 0;
01016   char *demangled = NULL;
01017   int s1, s2, s3, s4;
01018   s1 = work->constructor;
01019   s2 = work->destructor;
01020   s3 = work->static_type;
01021   s4 = work->type_quals;
01022   work->constructor = work->destructor = 0;
01023   work->type_quals = TYPE_UNQUALIFIED;
01024   work->dllimported = 0;
01025 
01026   if ((mangled != NULL) && (*mangled != '\0'))
01027     {
01028       string_init (&decl);
01029 
01030       /* First check to see if gnu style demangling is active and if the
01031         string to be demangled contains a CPLUS_MARKER.  If so, attempt to
01032         recognize one of the gnu special forms rather than looking for a
01033         standard prefix.  In particular, don't worry about whether there
01034         is a "__" string in the mangled string.  Consider "_$_5__foo" for
01035         example.  */
01036 
01037       if ((AUTO_DEMANGLING || GNU_DEMANGLING))
01038        {
01039          success = gnu_special (work, &mangled, &decl);
01040        }
01041       if (!success)
01042        {
01043          success = demangle_prefix (work, &mangled, &decl);
01044        }
01045       if (success && (*mangled != '\0'))
01046        {
01047          success = demangle_signature (work, &mangled, &decl);
01048        }
01049       if (work->constructor == 2)
01050         {
01051           string_prepend (&decl, "global constructors keyed to ");
01052           work->constructor = 0;
01053         }
01054       else if (work->destructor == 2)
01055         {
01056           string_prepend (&decl, "global destructors keyed to ");
01057           work->destructor = 0;
01058         }
01059       else if (work->dllimported == 1)
01060         {
01061           string_prepend (&decl, "import stub for ");
01062           work->dllimported = 0;
01063         }
01064       demangled = mop_up (work, &decl, success);
01065     }
01066   work->constructor = s1;
01067   work->destructor = s2;
01068   work->static_type = s3;
01069   work->type_quals = s4;
01070   return demangled;
01071 }
01072 
01073 
01074 /* Clear out and squangling related storage */
01075 static void
01076 squangle_mop_up (struct work_stuff *work)
01077 {
01078   /* clean up the B and K type mangling types. */
01079   forget_B_and_K_types (work);
01080   if (work -> btypevec != NULL)
01081     {
01082       free ((char *) work -> btypevec);
01083     }
01084   if (work -> ktypevec != NULL)
01085     {
01086       free ((char *) work -> ktypevec);
01087     }
01088 }
01089 
01090 
01091 /* Copy the work state and storage.  */
01092 
01093 static void
01094 work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
01095 {
01096   int i;
01097 
01098   delete_work_stuff (to);
01099 
01100   /* Shallow-copy scalars.  */
01101   memcpy (to, from, sizeof (*to));
01102 
01103   /* Deep-copy dynamic storage.  */
01104   if (from->typevec_size)
01105     to->typevec = XNEWVEC (char *, from->typevec_size);
01106 
01107   for (i = 0; i < from->ntypes; i++)
01108     {
01109       int len = strlen (from->typevec[i]) + 1;
01110 
01111       to->typevec[i] = XNEWVEC (char, len);
01112       memcpy (to->typevec[i], from->typevec[i], len);
01113     }
01114 
01115   if (from->ksize)
01116     to->ktypevec = XNEWVEC (char *, from->ksize);
01117 
01118   for (i = 0; i < from->numk; i++)
01119     {
01120       int len = strlen (from->ktypevec[i]) + 1;
01121 
01122       to->ktypevec[i] = XNEWVEC (char, len);
01123       memcpy (to->ktypevec[i], from->ktypevec[i], len);
01124     }
01125 
01126   if (from->bsize)
01127     to->btypevec = XNEWVEC (char *, from->bsize);
01128 
01129   for (i = 0; i < from->numb; i++)
01130     {
01131       int len = strlen (from->btypevec[i]) + 1;
01132 
01133       to->btypevec[i] = XNEWVEC (char , len);
01134       memcpy (to->btypevec[i], from->btypevec[i], len);
01135     }
01136 
01137   if (from->ntmpl_args)
01138     to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
01139 
01140   for (i = 0; i < from->ntmpl_args; i++)
01141     {
01142       int len = strlen (from->tmpl_argvec[i]) + 1;
01143 
01144       to->tmpl_argvec[i] = XNEWVEC (char, len);
01145       memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
01146     }
01147 
01148   if (from->previous_argument)
01149     {
01150       to->previous_argument = XNEW (string);
01151       string_init (to->previous_argument);
01152       string_appends (to->previous_argument, from->previous_argument);
01153     }
01154 }
01155 
01156 
01157 /* Delete dynamic stuff in work_stuff that is not to be re-used.  */
01158 
01159 static void
01160 delete_non_B_K_work_stuff (struct work_stuff *work)
01161 {
01162   /* Discard the remembered types, if any.  */
01163 
01164   forget_types (work);
01165   if (work -> typevec != NULL)
01166     {
01167       free ((char *) work -> typevec);
01168       work -> typevec = NULL;
01169       work -> typevec_size = 0;
01170     }
01171   if (work->tmpl_argvec)
01172     {
01173       int i;
01174 
01175       for (i = 0; i < work->ntmpl_args; i++)
01176        if (work->tmpl_argvec[i])
01177          free ((char*) work->tmpl_argvec[i]);
01178 
01179       free ((char*) work->tmpl_argvec);
01180       work->tmpl_argvec = NULL;
01181     }
01182   if (work->previous_argument)
01183     {
01184       string_delete (work->previous_argument);
01185       free ((char*) work->previous_argument);
01186       work->previous_argument = NULL;
01187     }
01188 }
01189 
01190 
01191 /* Delete all dynamic storage in work_stuff.  */
01192 static void
01193 delete_work_stuff (struct work_stuff *work)
01194 {
01195   delete_non_B_K_work_stuff (work);
01196   squangle_mop_up (work);
01197 }
01198 
01199 
01200 /* Clear out any mangled storage */
01201 
01202 static char *
01203 mop_up (struct work_stuff *work, string *declp, int success)
01204 {
01205   char *demangled = NULL;
01206 
01207   delete_non_B_K_work_stuff (work);
01208 
01209   /* If demangling was successful, ensure that the demangled string is null
01210      terminated and return it.  Otherwise, free the demangling decl.  */
01211 
01212   if (!success)
01213     {
01214       string_delete (declp);
01215     }
01216   else
01217     {
01218       string_appendn (declp, "", 1);
01219       demangled = declp->b;
01220     }
01221   return (demangled);
01222 }
01223 
01224 /*
01225 
01226 LOCAL FUNCTION
01227 
01228        demangle_signature -- demangle the signature part of a mangled name
01229 
01230 SYNOPSIS
01231 
01232        static int
01233        demangle_signature (struct work_stuff *work, const char **mangled,
01234                          string *declp);
01235 
01236 DESCRIPTION
01237 
01238        Consume and demangle the signature portion of the mangled name.
01239 
01240        DECLP is the string where demangled output is being built.  At
01241        entry it contains the demangled root name from the mangled name
01242        prefix.  I.E. either a demangled operator name or the root function
01243        name.  In some special cases, it may contain nothing.
01244 
01245        *MANGLED points to the current unconsumed location in the mangled
01246        name.  As tokens are consumed and demangling is performed, the
01247        pointer is updated to continuously point at the next token to
01248        be consumed.
01249 
01250        Demangling GNU style mangled names is nasty because there is no
01251        explicit token that marks the start of the outermost function
01252        argument list.  */
01253 
01254 static int
01255 demangle_signature (struct work_stuff *work,
01256                     const char **mangled, string *declp)
01257 {
01258   int success = 1;
01259   int func_done = 0;
01260   int expect_func = 0;
01261   int expect_return_type = 0;
01262   const char *oldmangled = NULL;
01263   string trawname;
01264   string tname;
01265 
01266   while (success && (**mangled != '\0'))
01267     {
01268       switch (**mangled)
01269        {
01270        case 'Q':
01271          oldmangled = *mangled;
01272          success = demangle_qualified (work, mangled, declp, 1, 0);
01273          if (success)
01274            remember_type (work, oldmangled, *mangled - oldmangled);
01275          if (AUTO_DEMANGLING || GNU_DEMANGLING)
01276            expect_func = 1;
01277          oldmangled = NULL;
01278          break;
01279 
01280         case 'K':
01281          oldmangled = *mangled;
01282          success = demangle_qualified (work, mangled, declp, 1, 0);
01283          if (AUTO_DEMANGLING || GNU_DEMANGLING)
01284            {
01285              expect_func = 1;
01286            }
01287          oldmangled = NULL;
01288          break;
01289 
01290        case 'S':
01291          /* Static member function */
01292          if (oldmangled == NULL)
01293            {
01294              oldmangled = *mangled;
01295            }
01296          (*mangled)++;
01297          work -> static_type = 1;
01298          break;
01299 
01300        case 'C':
01301        case 'V':
01302        case 'u':
01303          work->type_quals |= code_for_qualifier (**mangled);
01304 
01305          /* a qualified member function */
01306          if (oldmangled == NULL)
01307            oldmangled = *mangled;
01308          (*mangled)++;
01309          break;
01310 
01311        case 'L':
01312          /* Local class name follows after "Lnnn_" */
01313          if (HP_DEMANGLING)
01314            {
01315              while (**mangled && (**mangled != '_'))
01316               (*mangled)++;
01317              if (!**mangled)
01318               success = 0;
01319              else
01320               (*mangled)++;
01321            }
01322          else
01323            success = 0;
01324          break;
01325 
01326        case '0': case '1': case '2': case '3': case '4':
01327        case '5': case '6': case '7': case '8': case '9':
01328          if (oldmangled == NULL)
01329            {
01330              oldmangled = *mangled;
01331            }
01332           work->temp_start = -1; /* uppermost call to demangle_class */
01333          success = demangle_class (work, mangled, declp);
01334          if (success)
01335            {
01336              remember_type (work, oldmangled, *mangled - oldmangled);
01337            }
01338          if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
01339            {
01340               /* EDG and others will have the "F", so we let the loop cycle
01341                  if we are looking at one. */
01342               if (**mangled != 'F')
01343                  expect_func = 1;
01344            }
01345          oldmangled = NULL;
01346          break;
01347 
01348        case 'B':
01349          {
01350            string s;
01351            success = do_type (work, mangled, &s);
01352            if (success)
01353              {
01354               string_append (&s, SCOPE_STRING (work));
01355               string_prepends (declp, &s);
01356               string_delete (&s);
01357              }
01358            oldmangled = NULL;
01359            expect_func = 1;
01360          }
01361          break;
01362 
01363        case 'F':
01364          /* Function */
01365          /* ARM/HP style demangling includes a specific 'F' character after
01366             the class name.  For GNU style, it is just implied.  So we can
01367             safely just consume any 'F' at this point and be compatible
01368             with either style.  */
01369 
01370          oldmangled = NULL;
01371          func_done = 1;
01372          (*mangled)++;
01373 
01374          /* For lucid/ARM/HP style we have to forget any types we might
01375             have remembered up to this point, since they were not argument
01376             types.  GNU style considers all types seen as available for
01377             back references.  See comment in demangle_args() */
01378 
01379          if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
01380            {
01381              forget_types (work);
01382            }
01383          success = demangle_args (work, mangled, declp);
01384          /* After picking off the function args, we expect to either
01385             find the function return type (preceded by an '_') or the
01386             end of the string. */
01387          if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
01388            {
01389              ++(*mangled);
01390               /* At this level, we do not care about the return type. */
01391               success = do_type (work, mangled, &tname);
01392               string_delete (&tname);
01393             }
01394 
01395          break;
01396 
01397        case 't':
01398          /* G++ Template */
01399          string_init(&trawname);
01400          string_init(&tname);
01401          if (oldmangled == NULL)
01402            {
01403              oldmangled = *mangled;
01404            }
01405          success = demangle_template (work, mangled, &tname,
01406                                    &trawname, 1, 1);
01407          if (success)
01408            {
01409              remember_type (work, oldmangled, *mangled - oldmangled);
01410            }
01411          string_append (&tname, SCOPE_STRING (work));
01412 
01413          string_prepends(declp, &tname);
01414          if (work -> destructor & 1)
01415            {
01416              string_prepend (&trawname, "~");
01417              string_appends (declp, &trawname);
01418              work->destructor -= 1;
01419            }
01420          if ((work->constructor & 1) || (work->destructor & 1))
01421            {
01422              string_appends (declp, &trawname);
01423              work->constructor -= 1;
01424            }
01425          string_delete(&trawname);
01426          string_delete(&tname);
01427          oldmangled = NULL;
01428          expect_func = 1;
01429          break;
01430 
01431        case '_':
01432          if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
01433            {
01434              /* Read the return type. */
01435              string return_type;
01436 
01437              (*mangled)++;
01438              success = do_type (work, mangled, &return_type);
01439              APPEND_BLANK (&return_type);
01440 
01441              string_prepends (declp, &return_type);
01442              string_delete (&return_type);
01443              break;
01444            }
01445          else
01446            /* At the outermost level, we cannot have a return type specified,
01447               so if we run into another '_' at this point we are dealing with
01448               a mangled name that is either bogus, or has been mangled by
01449               some algorithm we don't know how to deal with.  So just
01450               reject the entire demangling.  */
01451             /* However, "_nnn" is an expected suffix for alternate entry point
01452                numbered nnn for a function, with HP aCC, so skip over that
01453                without reporting failure. pai/1997-09-04 */
01454             if (HP_DEMANGLING)
01455               {
01456                 (*mangled)++;
01457                 while (**mangled && ISDIGIT ((unsigned char)**mangled))
01458                   (*mangled)++;
01459               }
01460             else
01461              success = 0;
01462          break;
01463 
01464        case 'H':
01465          if (AUTO_DEMANGLING || GNU_DEMANGLING)
01466            {
01467              /* A G++ template function.  Read the template arguments. */
01468              success = demangle_template (work, mangled, declp, 0, 0,
01469                                       0);
01470              if (!(work->constructor & 1))
01471               expect_return_type = 1;
01472              (*mangled)++;
01473              break;
01474            }
01475          else
01476            /* fall through */
01477            {;}
01478 
01479        default:
01480          if (AUTO_DEMANGLING || GNU_DEMANGLING)
01481            {
01482              /* Assume we have stumbled onto the first outermost function
01483                argument token, and start processing args.  */
01484              func_done = 1;
01485              success = demangle_args (work, mangled, declp);
01486            }
01487          else
01488            {
01489              /* Non-GNU demanglers use a specific token to mark the start
01490                of the outermost function argument tokens.  Typically 'F',
01491                for ARM/HP-demangling, for example.  So if we find something
01492                we are not prepared for, it must be an error.  */
01493              success = 0;
01494            }
01495          break;
01496        }
01497       /*
01498        if (AUTO_DEMANGLING || GNU_DEMANGLING)
01499        */
01500       {
01501        if (success && expect_func)
01502          {
01503            func_done = 1;
01504               if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
01505                 {
01506                   forget_types (work);
01507                 }
01508            success = demangle_args (work, mangled, declp);
01509            /* Since template include the mangling of their return types,
01510               we must set expect_func to 0 so that we don't try do
01511               demangle more arguments the next time we get here.  */
01512            expect_func = 0;
01513          }
01514       }
01515     }
01516   if (success && !func_done)
01517     {
01518       if (AUTO_DEMANGLING || GNU_DEMANGLING)
01519        {
01520          /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
01521             bar__3fooi is 'foo::bar(int)'.  We get here when we find the
01522             first case, and need to ensure that the '(void)' gets added to
01523             the current declp.  Note that with ARM/HP, the first case
01524             represents the name of a static data member 'foo::bar',
01525             which is in the current declp, so we leave it alone.  */
01526          success = demangle_args (work, mangled, declp);
01527        }
01528     }
01529   if (success && PRINT_ARG_TYPES)
01530     {
01531       if (work->static_type)
01532        string_append (declp, " static");
01533       if (work->type_quals != TYPE_UNQUALIFIED)
01534        {
01535          APPEND_BLANK (declp);
01536          string_append (declp, qualifier_string (work->type_quals));
01537        }
01538     }
01539 
01540   return (success);
01541 }
01542 
01543 #if 0
01544 
01545 static int
01546 demangle_method_args (struct work_stuff *work, const char **mangled,
01547                       string *declp)
01548 {
01549   int success = 0;
01550 
01551   if (work -> static_type)
01552     {
01553       string_append (declp, *mangled + 1);
01554       *mangled += strlen (*mangled);
01555       success = 1;
01556     }
01557   else
01558     {
01559       success = demangle_args (work, mangled, declp);
01560     }
01561   return (success);
01562 }
01563 
01564 #endif
01565 
01566 static int
01567 demangle_template_template_parm (struct work_stuff *work,
01568                                  const char **mangled, string *tname)
01569 {
01570   int i;
01571   int r;
01572   int need_comma = 0;
01573   int success = 1;
01574   string temp;
01575 
01576   string_append (tname, "template <");
01577   /* get size of template parameter list */
01578   if (get_count (mangled, &r))
01579     {
01580       for (i = 0; i < r; i++)
01581        {
01582          if (need_comma)
01583            {
01584              string_append (tname, ", ");
01585            }
01586 
01587            /* Z for type parameters */
01588            if (**mangled == 'Z')
01589              {
01590               (*mangled)++;
01591               string_append (tname, "class");
01592              }
01593              /* z for template parameters */
01594            else if (**mangled == 'z')
01595              {
01596               (*mangled)++;
01597               success =
01598                 demangle_template_template_parm (work, mangled, tname);
01599               if (!success)
01600                 {
01601                   break;
01602                 }
01603              }
01604            else
01605              {
01606               /* temp is initialized in do_type */
01607               success = do_type (work, mangled, &temp);
01608               if (success)
01609                 {
01610                   string_appends (tname, &temp);
01611                 }
01612               string_delete(&temp);
01613               if (!success)
01614                 {
01615                   break;
01616                 }
01617              }
01618          need_comma = 1;
01619        }
01620 
01621     }
01622   if (tname->p[-1] == '>')
01623     string_append (tname, " ");
01624   string_append (tname, "> class");
01625   return (success);
01626 }
01627 
01628 static int
01629 demangle_expression (struct work_stuff *work, const char **mangled,
01630                      string *s, type_kind_t tk)
01631 {
01632   int need_operator = 0;
01633   int success;
01634 
01635   success = 1;
01636   string_appendn (s, "(", 1);
01637   (*mangled)++;
01638   while (success && **mangled != 'W' && **mangled != '\0')
01639     {
01640       if (need_operator)
01641        {
01642          size_t i;
01643          size_t len;
01644 
01645          success = 0;
01646 
01647          len = strlen (*mangled);
01648 
01649          for (i = 0; i < ARRAY_SIZE (optable); ++i)
01650            {
01651              size_t l = strlen (optable[i].in);
01652 
01653              if (l <= len
01654                 && memcmp (optable[i].in, *mangled, l) == 0)
01655               {
01656                 string_appendn (s, " ", 1);
01657                 string_append (s, optable[i].out);
01658                 string_appendn (s, " ", 1);
01659                 success = 1;
01660                 (*mangled) += l;
01661                 break;
01662               }
01663            }
01664 
01665          if (!success)
01666            break;
01667        }
01668       else
01669        need_operator = 1;
01670 
01671       success = demangle_template_value_parm (work, mangled, s, tk);
01672     }
01673 
01674   if (**mangled != 'W')
01675     success = 0;
01676   else
01677     {
01678       string_appendn (s, ")", 1);
01679       (*mangled)++;
01680     }
01681 
01682   return success;
01683 }
01684 
01685 static int
01686 demangle_integral_value (struct work_stuff *work,
01687                          const char **mangled, string *s)
01688 {
01689   int success;
01690 
01691   if (**mangled == 'E')
01692     success = demangle_expression (work, mangled, s, tk_integral);
01693   else if (**mangled == 'Q' || **mangled == 'K')
01694     success = demangle_qualified (work, mangled, s, 0, 1);
01695   else
01696     {
01697       int value;
01698 
01699       /* By default, we let the number decide whether we shall consume an
01700         underscore.  */
01701       int multidigit_without_leading_underscore = 0;
01702       int leave_following_underscore = 0;
01703 
01704       success = 0;
01705 
01706       if (**mangled == '_')
01707         {
01708          if (mangled[0][1] == 'm')
01709            {
01710              /* Since consume_count_with_underscores does not handle the
01711                `m'-prefix we must do it here, using consume_count and
01712                adjusting underscores: we have to consume the underscore
01713                matching the prepended one.  */
01714              multidigit_without_leading_underscore = 1;
01715              string_appendn (s, "-", 1);
01716              (*mangled) += 2;
01717            }
01718          else
01719            {
01720              /* Do not consume a following underscore;
01721                 consume_count_with_underscores will consume what
01722                 should be consumed.  */
01723              leave_following_underscore = 1;
01724            }
01725        }
01726       else
01727        {
01728          /* Negative numbers are indicated with a leading `m'.  */
01729          if (**mangled == 'm')
01730          {
01731            string_appendn (s, "-", 1);
01732            (*mangled)++;
01733          }
01734          /* Since consume_count_with_underscores does not handle
01735             multi-digit numbers that do not start with an underscore,
01736             and this number can be an integer template parameter,
01737             we have to call consume_count. */
01738          multidigit_without_leading_underscore = 1;
01739          /* These multi-digit numbers never end on an underscore,
01740             so if there is one then don't eat it. */
01741          leave_following_underscore = 1;
01742        }
01743 
01744       /* We must call consume_count if we expect to remove a trailing
01745         underscore, since consume_count_with_underscores expects
01746         the leading underscore (that we consumed) if it is to handle
01747         multi-digit numbers.  */
01748       if (multidigit_without_leading_underscore)
01749        value = consume_count (mangled);
01750       else
01751        value = consume_count_with_underscores (mangled);
01752 
01753       if (value != -1)
01754        {
01755          char buf[INTBUF_SIZE];
01756          sprintf (buf, "%d", value);
01757          string_append (s, buf);
01758 
01759          /* Numbers not otherwise delimited, might have an underscore
01760             appended as a delimeter, which we should skip.
01761 
01762             ??? This used to always remove a following underscore, which
01763             is wrong.  If other (arbitrary) cases are followed by an
01764             underscore, we need to do something more radical.  */
01765 
01766          if ((value > 9 || multidigit_without_leading_underscore)
01767              && ! leave_following_underscore
01768              && **mangled == '_')
01769            (*mangled)++;
01770 
01771          /* All is well.  */
01772          success = 1;
01773        }
01774       }
01775 
01776   return success;
01777 }
01778 
01779 /* Demangle the real value in MANGLED.  */
01780 
01781 static int
01782 demangle_real_value (struct work_stuff *work,
01783                      const char **mangled, string *s)
01784 {
01785   if (**mangled == 'E')
01786     return demangle_expression (work, mangled, s, tk_real);
01787 
01788   if (**mangled == 'm')
01789     {
01790       string_appendn (s, "-", 1);
01791       (*mangled)++;
01792     }
01793   while (ISDIGIT ((unsigned char)**mangled))
01794     {
01795       string_appendn (s, *mangled, 1);
01796       (*mangled)++;
01797     }
01798   if (**mangled == '.') /* fraction */
01799     {
01800       string_appendn (s, ".", 1);
01801       (*mangled)++;
01802       while (ISDIGIT ((unsigned char)**mangled))
01803        {
01804          string_appendn (s, *mangled, 1);
01805          (*mangled)++;
01806        }
01807     }
01808   if (**mangled == 'e') /* exponent */
01809     {
01810       string_appendn (s, "e", 1);
01811       (*mangled)++;
01812       while (ISDIGIT ((unsigned char)**mangled))
01813        {
01814          string_appendn (s, *mangled, 1);
01815          (*mangled)++;
01816        }
01817     }
01818 
01819   return 1;
01820 }
01821 
01822 static int
01823 demangle_template_value_parm (struct work_stuff *work, const char **mangled,
01824                               string *s, type_kind_t tk)
01825 {
01826   int success = 1;
01827 
01828   if (**mangled == 'Y')
01829     {
01830       /* The next argument is a template parameter. */
01831       int idx;
01832 
01833       (*mangled)++;
01834       idx = consume_count_with_underscores (mangled);
01835       if (idx == -1
01836          || (work->tmpl_argvec && idx >= work->ntmpl_args)
01837          || consume_count_with_underscores (mangled) == -1)
01838        return -1;
01839       if (work->tmpl_argvec)
01840        string_append (s, work->tmpl_argvec[idx]);
01841       else
01842        string_append_template_idx (s, idx);
01843     }
01844   else if (tk == tk_integral)
01845     success = demangle_integral_value (work, mangled, s);
01846   else if (tk == tk_char)
01847     {
01848       char tmp[2];
01849       int val;
01850       if (**mangled == 'm')
01851        {
01852          string_appendn (s, "-", 1);
01853          (*mangled)++;
01854        }
01855       string_appendn (s, "'", 1);
01856       val = consume_count(mangled);
01857       if (val <= 0)
01858        success = 0;
01859       else
01860        {
01861          tmp[0] = (char)val;
01862          tmp[1] = '\0';
01863          string_appendn (s, &tmp[0], 1);
01864          string_appendn (s, "'", 1);
01865        }
01866     }
01867   else if (tk == tk_bool)
01868     {
01869       int val = consume_count (mangled);
01870       if (val == 0)
01871        string_appendn (s, "false", 5);
01872       else if (val == 1)
01873        string_appendn (s, "true", 4);
01874       else
01875        success = 0;
01876     }
01877   else if (tk == tk_real)
01878     success = demangle_real_value (work, mangled, s);
01879   else if (tk == tk_pointer || tk == tk_reference)
01880     {
01881       if (**mangled == 'Q')
01882        success = demangle_qualified (work, mangled, s,
01883                                   /*isfuncname=*/0, 
01884                                   /*append=*/1);
01885       else
01886        {
01887          int symbol_len  = consume_count (mangled);
01888          if (symbol_len == -1)
01889            return -1;
01890          if (symbol_len == 0)
01891            string_appendn (s, "0", 1);
01892          else
01893            {
01894              char *p = XNEWVEC (char, symbol_len + 1), *q;
01895              strncpy (p, *mangled, symbol_len);
01896              p [symbol_len] = '\0';
01897              /* We use cplus_demangle here, rather than
01898                internal_cplus_demangle, because the name of the entity
01899                mangled here does not make use of any of the squangling
01900                or type-code information we have built up thus far; it is
01901                mangled independently.  */
01902              q = cplus_demangle (p, work->options);
01903              if (tk == tk_pointer)
01904               string_appendn (s, "&", 1);
01905              /* FIXME: Pointer-to-member constants should get a
01906                qualifying class name here.  */
01907              if (q)
01908               {
01909                 string_append (s, q);
01910                 free (q);
01911               }
01912              else
01913               string_append (s, p);
01914              free (p);
01915            }
01916          *mangled += symbol_len;
01917        }
01918     }
01919 
01920   return success;
01921 }
01922 
01923 /* Demangle the template name in MANGLED.  The full name of the
01924    template (e.g., S<int>) is placed in TNAME.  The name without the
01925    template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
01926    non-NULL.  If IS_TYPE is nonzero, this template is a type template,
01927    not a function template.  If both IS_TYPE and REMEMBER are nonzero,
01928    the template is remembered in the list of back-referenceable
01929    types.  */
01930 
01931 static int
01932 demangle_template (struct work_stuff *work, const char **mangled,
01933                    string *tname, string *trawname,
01934                    int is_type, int remember)
01935 {
01936   int i;
01937   int r;
01938   int need_comma = 0;
01939   int success = 0;
01940   int is_java_array = 0;
01941   string temp;
01942 
01943   (*mangled)++;
01944   if (is_type)
01945     {
01946       /* get template name */
01947       if (**mangled == 'z')
01948        {
01949          int idx;
01950          (*mangled)++;
01951          (*mangled)++;
01952 
01953          idx = consume_count_with_underscores (mangled);
01954          if (idx == -1
01955              || (work->tmpl_argvec && idx >= work->ntmpl_args)
01956              || consume_count_with_underscores (mangled) == -1)
01957            return (0);
01958 
01959          if (work->tmpl_argvec)
01960            {
01961              string_append (tname, work->tmpl_argvec[idx]);
01962              if (trawname)
01963               string_append (trawname, work->tmpl_argvec[idx]);
01964            }
01965          else
01966            {
01967              string_append_template_idx (tname, idx);
01968              if (trawname)
01969               string_append_template_idx (trawname, idx);
01970            }
01971        }
01972       else
01973        {
01974          if ((r = consume_count (mangled)) <= 0
01975              || (int) strlen (*mangled) < r)
01976            {
01977              return (0);
01978            }
01979          is_java_array = (work -> options & DMGL_JAVA)
01980            && strncmp (*mangled, "JArray1Z", 8) == 0;
01981          if (! is_java_array)
01982            {
01983              string_appendn (tname, *mangled, r);
01984            }
01985          if (trawname)
01986            string_appendn (trawname, *mangled, r);
01987          *mangled += r;
01988        }
01989     }
01990   if (!is_java_array)
01991     string_append (tname, "<");
01992   /* get size of template parameter list */
01993   if (!get_count (mangled, &r))
01994     {
01995       return (0);
01996     }
01997   if (!is_type)
01998     {
01999       /* Create an array for saving the template argument values. */
02000       work->tmpl_argvec = XNEWVEC (char *, r);
02001       work->ntmpl_args = r;
02002       for (i = 0; i < r; i++)
02003        work->tmpl_argvec[i] = 0;
02004     }
02005   for (i = 0; i < r; i++)
02006     {
02007       if (need_comma)
02008        {
02009          string_append (tname, ", ");
02010        }
02011       /* Z for type parameters */
02012       if (**mangled == 'Z')
02013        {
02014          (*mangled)++;
02015          /* temp is initialized in do_type */
02016          success = do_type (work, mangled, &temp);
02017          if (success)
02018            {
02019              string_appends (tname, &temp);
02020 
02021              if (!is_type)
02022               {
02023                 /* Save the template argument. */
02024                 int len = temp.p - temp.b;
02025                 work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
02026                 memcpy (work->tmpl_argvec[i], temp.b, len);
02027                 work->tmpl_argvec[i][len] = '\0';
02028               }
02029            }
02030          string_delete(&temp);
02031          if (!success)
02032            {
02033              break;
02034            }
02035        }
02036       /* z for template parameters */
02037       else if (**mangled == 'z')
02038        {
02039          int r2;
02040          (*mangled)++;
02041          success = demangle_template_template_parm (work, mangled, tname);
02042 
02043          if (success
02044              && (r2 = consume_count (mangled)) > 0
02045              && (int) strlen (*mangled) >= r2)
02046            {
02047              string_append (tname, " ");
02048              string_appendn (tname, *mangled, r2);
02049              if (!is_type)
02050               {
02051                 /* Save the template argument. */
02052                 int len = r2;
02053                 work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
02054                 memcpy (work->tmpl_argvec[i], *mangled, len);
02055                 work->tmpl_argvec[i][len] = '\0';
02056               }
02057              *mangled += r2;
02058            }
02059          if (!success)
02060            {
02061              break;
02062            }
02063        }
02064       else
02065        {
02066          string  param;
02067          string* s;
02068 
02069          /* otherwise, value parameter */
02070 
02071          /* temp is initialized in do_type */
02072          success = do_type (work, mangled, &temp);
02073          string_delete(&temp);
02074          if (!success)
02075            break;
02076 
02077          if (!is_type)
02078            {
02079              s = &param;
02080              string_init (s);
02081            }
02082          else
02083            s = tname;
02084 
02085          success = demangle_template_value_parm (work, mangled, s,
02086                                             (type_kind_t) success);
02087 
02088          if (!success)
02089            {
02090              if (!is_type)
02091               string_delete (s);
02092              success = 0;
02093              break;
02094            }
02095 
02096          if (!is_type)
02097            {
02098              int len = s->p - s->b;
02099              work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
02100              memcpy (work->tmpl_argvec[i], s->b, len);
02101              work->tmpl_argvec[i][len] = '\0';
02102 
02103              string_appends (tname, s);
02104              string_delete (s);
02105            }
02106        }
02107       need_comma = 1;
02108     }
02109   if (is_java_array)
02110     {
02111       string_append (tname, "[]");
02112     }
02113   else
02114     {
02115       if (tname->p[-1] == '>')
02116        string_append (tname, " ");
02117       string_append (tname, ">");
02118     }
02119 
02120   if (is_type && remember)
02121     {
02122       const int bindex = register_Btype (work);
02123       remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
02124     }
02125 
02126   /*
02127     if (work -> static_type)
02128     {
02129     string_append (declp, *mangled + 1);
02130     *mangled += strlen (*mangled);
02131     success = 1;
02132     }
02133     else
02134     {
02135     success = demangle_args (work, mangled, declp);
02136     }
02137     }
02138     */
02139   return (success);
02140 }
02141 
02142 static int
02143 arm_pt (struct work_stuff *work, const char *mangled,
02144         int n, const char **anchor, const char **args)
02145 {
02146   /* Check if ARM template with "__pt__" in it ("parameterized type") */
02147   /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
02148   if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__")))
02149     {
02150       int len;
02151       *args = *anchor + 6;
02152       len = consume_count (args);
02153       if (len == -1)
02154        return 0;
02155       if (*args + len == mangled + n && **args == '_')
02156        {
02157          ++*args;
02158          return 1;
02159        }
02160     }
02161   if (AUTO_DEMANGLING || EDG_DEMANGLING)
02162     {
02163       if ((*anchor = strstr (mangled, "__tm__"))
02164           || (*anchor = strstr (mangled, "__ps__"))
02165           || (*anchor = strstr (mangled, "__pt__")))
02166         {
02167           int len;
02168           *args = *anchor + 6;
02169           len = consume_count (args);
02170          if (len == -1)
02171            return 0;
02172           if (*args + len == mangled + n && **args == '_')
02173             {
02174               ++*args;
02175               return 1;
02176             }
02177         }
02178       else if ((*anchor = strstr (mangled, "__S")))
02179         {
02180          int len;
02181          *args = *anchor + 3;
02182          len = consume_count (args);
02183          if (len == -1)
02184            return 0;
02185          if (*args + len == mangled + n && **args == '_')
02186             {
02187               ++*args;
02188              return 1;
02189             }
02190         }
02191     }
02192 
02193   return 0;
02194 }
02195 
02196 static void
02197 demangle_arm_hp_template (struct work_stuff *work, const char **mangled,
02198                           int n, string *declp)
02199 {
02200   const char *p;
02201   const char *args;
02202   const char *e = *mangled + n;
02203   string arg;
02204 
02205   /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
02206      template args */
02207   if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
02208     {
02209       char *start_spec_args = NULL;
02210       int hold_options;
02211 
02212       /* First check for and omit template specialization pseudo-arguments,
02213          such as in "Spec<#1,#1.*>" */
02214       start_spec_args = strchr (*mangled, '<');
02215       if (start_spec_args && (start_spec_args - *mangled < n))
02216         string_appendn (declp, *mangled, start_spec_args - *mangled);
02217       else
02218         string_appendn (declp, *mangled, n);
02219       (*mangled) += n + 1;
02220       string_init (&arg);
02221       if (work->temp_start == -1) /* non-recursive call */
02222         work->temp_start = declp->p - declp->b;
02223 
02224       /* We want to unconditionally demangle parameter types in
02225         template parameters.  */
02226       hold_options = work->options;
02227       work->options |= DMGL_PARAMS;
02228 
02229       string_append (declp, "<");
02230       while (1)
02231         {
02232           string_delete (&arg);
02233           switch (**mangled)
02234             {
02235               case 'T':
02236                 /* 'T' signals a type parameter */
02237                 (*mangled)++;
02238                 if (!do_type (work, mangled, &arg))
02239                   goto hpacc_template_args_done;
02240                 break;
02241 
02242               case 'U':
02243               case 'S':
02244                 /* 'U' or 'S' signals an integral value */
02245                 if (!do_hpacc_template_const_value (work, mangled, &arg))
02246                   goto hpacc_template_args_done;
02247                 break;
02248 
02249               case 'A':
02250                 /* 'A' signals a named constant expression (literal) */
02251                 if (!do_hpacc_template_literal (work, mangled, &arg))
02252                   goto hpacc_template_args_done;
02253                 break;
02254 
02255               default:
02256                 /* Today, 1997-09-03, we have only the above types
02257                    of template parameters */
02258                 /* FIXME: maybe this should fail and return null */
02259                 goto hpacc_template_args_done;
02260             }
02261           string_appends (declp, &arg);
02262          /* Check if we're at the end of template args.
02263              0 if at end of static member of template class,
02264              _ if done with template args for a function */
02265           if ((**mangled == '\000') || (**mangled == '_'))
02266             break;
02267           else
02268             string_append (declp, ",");
02269         }
02270     hpacc_template_args_done:
02271       string_append (declp, ">");
02272       string_delete (&arg);
02273       if (**mangled == '_')
02274         (*mangled)++;
02275       work->options = hold_options;
02276       return;
02277     }
02278   /* ARM template? (Also handles HP cfront extensions) */
02279   else if (arm_pt (work, *mangled, n, &p, &args))
02280     {
02281       int hold_options;
02282       string type_str;
02283 
02284       string_init (&arg);
02285       string_appendn (declp, *mangled, p - *mangled);
02286       if (work->temp_start == -1)  /* non-recursive call */
02287        work->temp_start = declp->p - declp->b;
02288 
02289       /* We want to unconditionally demangle parameter types in
02290         template parameters.  */
02291       hold_options = work->options;
02292       work->options |= DMGL_PARAMS;
02293 
02294       string_append (declp, "<");
02295       /* should do error checking here */
02296       while (args < e) {
02297        string_delete (&arg);
02298 
02299        /* Check for type or literal here */
02300        switch (*args)
02301          {
02302            /* HP cfront extensions to ARM for template args */
02303            /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */
02304            /* FIXME: We handle only numeric literals for HP cfront */
02305           case 'X':
02306             /* A typed constant value follows */
02307             args++;
02308             if (!do_type (work, &args, &type_str))
02309              goto cfront_template_args_done;
02310             string_append (&arg, "(");
02311             string_appends (&arg, &type_str);
02312             string_delete (&type_str);
02313             string_append (&arg, ")");
02314             if (*args != 'L')
02315               goto cfront_template_args_done;
02316             args++;
02317             /* Now snarf a literal value following 'L' */
02318             if (!snarf_numeric_literal (&args, &arg))
02319              goto cfront_template_args_done;
02320             break;
02321 
02322           case 'L':
02323             /* Snarf a literal following 'L' */
02324             args++;
02325             if (!snarf_numeric_literal (&args, &arg))
02326              goto cfront_template_args_done;
02327             break;
02328           default:
02329             /* Not handling other HP cfront stuff */
02330             {
02331               const char* old_args = args;
02332               if (!do_type (work, &args, &arg))
02333                 goto cfront_template_args_done;
02334 
02335               /* Fail if we didn't make any progress: prevent infinite loop. */
02336               if (args == old_args)
02337               {
02338                 work->options = hold_options;
02339                 return;
02340               }
02341             }
02342          }
02343        string_appends (declp, &arg);
02344        string_append (declp, ",");
02345       }
02346     cfront_template_args_done:
02347       string_delete (&arg);
02348       if (args >= e)
02349        --declp->p; /* remove extra comma */
02350       string_append (declp, ">");
02351       work->options = hold_options;
02352     }
02353   else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
02354           && (*mangled)[9] == 'N'
02355           && (*mangled)[8] == (*mangled)[10]
02356           && strchr (cplus_markers, (*mangled)[8]))
02357     {
02358       /* A member of the anonymous namespace.  */
02359       string_append (declp, "{anonymous}");
02360     }
02361   else
02362     {
02363       if (work->temp_start == -1) /* non-recursive call only */
02364        work->temp_start = 0;     /* disable in recursive calls */
02365       string_appendn (declp, *mangled, n);
02366     }
02367   *mangled += n;
02368 }
02369 
02370 /* Extract a class name, possibly a template with arguments, from the
02371    mangled string; qualifiers, local class indicators, etc. have
02372    already been dealt with */
02373 
02374 static int
02375 demangle_class_name (struct work_stuff *work, const char **mangled,
02376                      string *declp)
02377 {
02378   int n;
02379   int success = 0;
02380 
02381   n = consume_count (mangled);
02382   if (n == -1)
02383     return 0;
02384   if ((int) strlen (*mangled) >= n)
02385     {
02386       demangle_arm_hp_template (work, mangled, n, declp);
02387       success = 1;
02388     }
02389 
02390   return (success);
02391 }
02392 
02393 /*
02394 
02395 LOCAL FUNCTION
02396 
02397        demangle_class -- demangle a mangled class sequence
02398 
02399 SYNOPSIS
02400 
02401        static int
02402        demangle_class (struct work_stuff *work, const char **mangled,
02403                      strint *declp)
02404 
02405 DESCRIPTION
02406 
02407        DECLP points to the buffer into which demangling is being done.
02408 
02409        *MANGLED points to the current token to be demangled.  On input,
02410        it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
02411        On exit, it points to the next token after the mangled class on
02412        success, or the first unconsumed token on failure.
02413 
02414        If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
02415        we are demangling a constructor or destructor.  In this case
02416        we prepend "class::class" or "class::~class" to DECLP.
02417 
02418        Otherwise, we prepend "class::" to the current DECLP.
02419 
02420        Reset the constructor/destructor flags once they have been
02421        "consumed".  This allows demangle_class to be called later during
02422        the same demangling, to do normal class demangling.
02423 
02424        Returns 1 if demangling is successful, 0 otherwise.
02425 
02426 */
02427 
02428 static int
02429 demangle_class (struct work_stuff *work, const char **mangled, string *declp)
02430 {
02431   int success = 0;
02432   int btype;
02433   string class_name;
02434   char *save_class_name_end = 0;
02435 
02436   string_init (&class_name);
02437   btype = register_Btype (work);
02438   if (demangle_class_name (work, mangled, &class_name))
02439     {
02440       save_class_name_end = class_name.p;
02441       if ((work->constructor & 1) || (work->destructor & 1))
02442        {
02443           /* adjust so we don't include template args */
02444           if (work->temp_start && (work->temp_start != -1))
02445             {
02446               class_name.p = class_name.b + work->temp_start;
02447             }
02448          string_prepends (declp, &class_name);
02449          if (work -> destructor & 1)
02450            {
02451              string_prepend (declp, "~");
02452               work -> destructor -= 1;
02453            }
02454          else
02455            {
02456              work -> constructor -= 1;
02457            }
02458        }
02459       class_name.p = save_class_name_end;
02460       remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
02461       remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
02462       string_prepend (declp, SCOPE_STRING (work));
02463       string_prepends (declp, &class_name);
02464       success = 1;
02465     }
02466   string_delete (&class_name);
02467   return (success);
02468 }
02469 
02470 
02471 /* Called when there's a "__" in the mangled name, with `scan' pointing to
02472    the rightmost guess.
02473 
02474    Find the correct "__"-sequence where the function name ends and the
02475    signature starts, which is ambiguous with GNU mangling.
02476    Call demangle_signature here, so we can make sure we found the right
02477    one; *mangled will be consumed so caller will not make further calls to
02478    demangle_signature.  */
02479 
02480 static int
02481 iterate_demangle_function (struct work_stuff *work, const char **mangled,
02482                            string *declp, const char *scan)
02483 {
02484   const char *mangle_init = *mangled;
02485   int success = 0;
02486   string decl_init;
02487   struct work_stuff work_init;
02488 
02489   if (*(scan + 2) == '\0')
02490     return 0;
02491 
02492   /* Do not iterate for some demangling modes, or if there's only one
02493      "__"-sequence.  This is the normal case.  */
02494   if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
02495       || strstr (scan + 2, "__") == NULL)
02496     {
02497       demangle_function_name (work, mangled, declp, scan);
02498       return 1;
02499     }
02500 
02501   /* Save state so we can restart if the guess at the correct "__" was
02502      wrong.  */
02503   string_init (&decl_init);
02504   string_appends (&decl_init, declp);
02505   memset (&work_init, 0, sizeof work_init);
02506   work_stuff_copy_to_from (&work_init, work);
02507 
02508   /* Iterate over occurrences of __, allowing names and types to have a
02509      "__" sequence in them.  We must start with the first (not the last)
02510      occurrence, since "__" most often occur between independent mangled
02511      parts, hence starting at the last occurence inside a signature
02512      might get us a "successful" demangling of the signature.  */
02513 
02514   while (scan[2])
02515     {
02516       demangle_function_name (work, mangled, declp, scan);
02517       success = demangle_signature (work, mangled, declp);
02518       if (success)
02519        break;
02520 
02521       /* Reset demangle state for the next round.  */
02522       *mangled = mangle_init;
02523       string_clear (declp);
02524       string_appends (declp, &decl_init);
02525       work_stuff_copy_to_from (work, &work_init);
02526 
02527       /* Leave this underscore-sequence.  */
02528       scan += 2;
02529 
02530       /* Scan for the next "__" sequence.  */
02531       while (*scan && (scan[0] != '_' || scan[1] != '_'))
02532        scan++;
02533 
02534       /* Move to last "__" in this sequence.  */
02535       while (*scan && *scan == '_')
02536        scan++;
02537       scan -= 2;
02538     }
02539 
02540   /* Delete saved state.  */
02541   delete_work_stuff (&work_init);
02542   string_delete (&decl_init);
02543 
02544   return success;
02545 }
02546 
02547 /*
02548 
02549 LOCAL FUNCTION
02550 
02551        demangle_prefix -- consume the mangled name prefix and find signature
02552 
02553 SYNOPSIS
02554 
02555        static int
02556        demangle_prefix (struct work_stuff *work, const char **mangled,
02557                       string *declp);
02558 
02559 DESCRIPTION
02560 
02561        Consume and demangle the prefix of the mangled name.
02562        While processing the function name root, arrange to call
02563        demangle_signature if the root is ambiguous.
02564 
02565        DECLP points to the string buffer into which demangled output is
02566        placed.  On entry, the buffer is empty.  On exit it contains
02567        the root function name, the demangled operator name, or in some
02568        special cases either nothing or the completely demangled result.
02569 
02570        MANGLED points to the current pointer into the mangled name.  As each
02571        token of the mangled name is consumed, it is updated.  Upon entry
02572        the current mangled name pointer points to the first character of
02573        the mangled name.  Upon exit, it should point to the first character
02574        of the signature if demangling was successful, or to the first
02575        unconsumed character if demangling of the prefix was unsuccessful.
02576 
02577        Returns 1 on success, 0 otherwise.
02578  */
02579 
02580 static int
02581 demangle_prefix (struct work_stuff *work, const char **mangled,
02582                  string *declp)
02583 {
02584   int success = 1;
02585   const char *scan;
02586   int i;
02587 
02588   if (strlen(*mangled) > 6
02589       && (strncmp(*mangled, "_imp__", 6) == 0
02590           || strncmp(*mangled, "__imp_", 6) == 0))
02591     {
02592       /* it's a symbol imported from a PE dynamic library. Check for both
02593          new style prefix _imp__ and legacy __imp_ used by older versions
02594         of dlltool. */
02595       (*mangled) += 6;
02596       work->dllimported = 1;
02597     }
02598   else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
02599     {
02600       char *marker = strchr (cplus_markers, (*mangled)[8]);
02601       if (marker != NULL && *marker == (*mangled)[10])
02602        {
02603          if ((*mangled)[9] == 'D')
02604            {
02605              /* it's a GNU global destructor to be executed at program exit */
02606              (*mangled) += 11;
02607              work->destructor = 2;
02608              if (gnu_special (work, mangled, declp))
02609               return success;
02610            }
02611          else if ((*mangled)[9] == 'I')
02612            {
02613              /* it's a GNU global constructor to be executed at program init */
02614              (*mangled) += 11;
02615              work->constructor = 2;
02616              if (gnu_special (work, mangled, declp))
02617               return success;
02618            }
02619        }
02620     }
02621   else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0)
02622     {
02623       /* it's a ARM global destructor to be executed at program exit */
02624       (*mangled) += 7;
02625       work->destructor = 2;
02626     }
02627   else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0)
02628     {
02629       /* it's a ARM global constructor to be executed at program initial */
02630       (*mangled) += 7;
02631       work->constructor = 2;
02632     }
02633 
02634   /*  This block of code is a reduction in strength time optimization
02635       of:
02636       scan = strstr (*mangled, "__"); */
02637 
02638   {
02639     scan = *mangled;
02640 
02641     do {
02642       scan = strchr (scan, '_');
02643     } while (scan != NULL && *++scan != '_');
02644 
02645     if (scan != NULL) --scan;
02646   }
02647 
02648   if (scan != NULL)
02649     {
02650       /* We found a sequence of two or more '_', ensure that we start at
02651         the last pair in the sequence.  */
02652       i = strspn (scan, "_");
02653       if (i > 2)
02654        {
02655          scan += (i - 2);
02656        }
02657     }
02658 
02659   if (scan == NULL)
02660     {
02661       success = 0;
02662     }
02663   else if (work -> static_type)
02664     {
02665       if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't'))
02666        {
02667          success = 0;
02668        }
02669     }
02670   else if ((scan == *mangled)
02671           && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q')
02672               || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
02673     {
02674       /* The ARM says nothing about the mangling of local variables.
02675         But cfront mangles local variables by prepending __<nesting_level>
02676         to them. As an extension to ARM demangling we handle this case.  */
02677       if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
02678          && ISDIGIT ((unsigned char)scan[2]))
02679        {
02680          *mangled = scan + 2;
02681          consume_count (mangled);
02682          string_append (declp, *mangled);
02683          *mangled += strlen (*mangled);
02684          success = 1;
02685        }
02686       else
02687        {
02688          /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
02689             names like __Q2_3foo3bar for nested type names.  So don't accept
02690             this style of constructor for cfront demangling.  A GNU
02691             style member-template constructor starts with 'H'. */
02692          if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING))
02693            work -> constructor += 1;
02694          *mangled = scan + 2;
02695        }
02696     }
02697   else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
02698     {
02699       /* Cfront-style parameterized type.  Handled later as a signature. */
02700       success = 1;
02701 
02702       /* ARM template? */
02703       demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
02704     }
02705   else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm')
02706                               || (scan[2] == 'p' && scan[3] == 's')
02707                               || (scan[2] == 'p' && scan[3] == 't')))
02708     {
02709       /* EDG-style parameterized type.  Handled later as a signature. */
02710       success = 1;
02711 
02712       /* EDG template? */
02713       demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
02714     }
02715   else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2])
02716           && (scan[2] != 't'))
02717     {
02718       /* Mangled name starts with "__".  Skip over any leading '_' characters,
02719         then find the next "__" that separates the prefix from the signature.
02720         */
02721       if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
02722          || (arm_special (mangled, declp) == 0))
02723        {
02724          while (*scan == '_')
02725            {
02726              scan++;
02727            }
02728          if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
02729            {
02730              /* No separator (I.E. "__not_mangled"), or empty signature
02731                (I.E. "__not_mangled_either__") */
02732              success = 0;
02733            }
02734          else
02735            return iterate_demangle_function (work, mangled, declp, scan);
02736        }
02737     }
02738   else if (*(scan + 2) != '\0')
02739     {
02740       /* Mangled name does not start with "__" but does have one somewhere
02741         in there with non empty stuff after it.  Looks like a global
02742         function name.  Iterate over all "__":s until the right
02743         one is found.  */
02744       return iterate_demangle_function (work, mangled, declp, scan);
02745     }
02746   else
02747     {
02748       /* Doesn't look like a mangled name */
02749       success = 0;
02750     }
02751 
02752   if (!success && (work->constructor == 2 || work->destructor == 2))
02753     {
02754       string_append (declp, *mangled);
02755       *mangled += strlen (*mangled);
02756       success = 1;
02757     }
02758   return (success);
02759 }
02760 
02761 /*
02762 
02763 LOCAL FUNCTION
02764 
02765        gnu_special -- special handling of gnu mangled strings
02766 
02767 SYNOPSIS
02768 
02769        static int
02770        gnu_special (struct work_stuff *work, const char **mangled,
02771                    string *declp);
02772 
02773 
02774 DESCRIPTION
02775 
02776        Process some special GNU style mangling forms that don't fit
02777        the normal pattern.  For example:
02778 
02779               _$_3foo              (destructor for class foo)
02780               _vt$foo              (foo virtual table)
02781               _vt$foo$bar   (foo::bar virtual table)
02782               __vt_foo      (foo virtual table, new style with thunks)
02783               _3foo$varname (static data member)
02784               _Q22rs2tu$vw  (static data member)
02785               __t6vector1Zii       (constructor with template)
02786               __thunk_4__$_7ostream (virtual function thunk)
02787  */
02788 
02789 static int
02790 gnu_special (struct work_stuff *work, const char **mangled, string *declp)
02791 {
02792   int n;
02793   int success = 1;
02794   const char *p;
02795 
02796   if ((*mangled)[0] == '_'
02797       && strchr (cplus_markers, (*mangled)[1]) != NULL
02798       && (*mangled)[2] == '_')
02799     {
02800       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
02801       (*mangled) += 3;
02802       work -> destructor += 1;
02803     }
02804   else if ((*mangled)[0] == '_'
02805           && (((*mangled)[1] == '_'
02806               && (*mangled)[2] == 'v'
02807               && (*mangled)[3] == 't'
02808               && (*mangled)[4] == '_')
02809               || ((*mangled)[1] == 'v'
02810                  && (*mangled)[2] == 't'
02811                  && strchr (cplus_markers, (*mangled)[3]) != NULL)))
02812     {
02813       /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
02814          and create the decl.  Note that we consume the entire mangled
02815         input string, which means that demangle_signature has no work
02816         to do.  */
02817       if ((*mangled)[2] == 'v')
02818        (*mangled) += 5; /* New style, with thunks: "__vt_" */
02819       else
02820        (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
02821       while (**mangled != '\0')
02822        {
02823          switch (**mangled)
02824            {
02825            case 'Q':
02826            case 'K':
02827              success = demangle_qualified (work, mangled, declp, 0, 1);
02828              break;
02829            case 't':
02830              success = demangle_template (work, mangled, declp, 0, 1,
02831                                       1);
02832              break;
02833            default:
02834              if (ISDIGIT((unsigned char)*mangled[0]))
02835               {
02836                 n = consume_count(mangled);
02837                 /* We may be seeing a too-large size, or else a
02838                    ".<digits>" indicating a static local symbol.  In
02839                    any case, declare victory and move on; *don't* try
02840                    to use n to allocate.  */
02841                 if (n > (int) strlen (*mangled))
02842                   {
02843                     success = 1;
02844                     break;
02845                   }
02846               }
02847              else
02848               {
02849                 n = strcspn (*mangled, cplus_markers);
02850               }
02851              string_appendn (declp, *mangled, n);
02852              (*mangled) += n;
02853            }
02854 
02855          p = strpbrk (*mangled, cplus_markers);
02856          if (success && ((p == NULL) || (p == *mangled)))
02857            {
02858              if (p != NULL)
02859               {
02860                 string_append (declp, SCOPE_STRING (work));
02861                 (*mangled)++;
02862               }
02863            }
02864          else
02865            {
02866              success = 0;
02867              break;
02868            }
02869        }
02870       if (success)
02871        string_append (declp, " virtual table");
02872     }
02873   else if ((*mangled)[0] == '_'
02874           && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
02875           && (p = strpbrk (*mangled, cplus_markers)) != NULL)
02876     {
02877       /* static data member, "_3foo$varname" for example */
02878       (*mangled)++;
02879       switch (**mangled)
02880        {
02881        case 'Q':
02882        case 'K':
02883          success = demangle_qualified (work, mangled, declp, 0, 1);
02884          break;
02885        case 't':
02886          success = demangle_template (work, mangled, declp, 0, 1, 1);
02887          break;
02888        default:
02889          n = consume_count (mangled);
02890          if (n < 0 || n > (long) strlen (*mangled))
02891            {
02892              success = 0;
02893              break;
02894            }
02895 
02896          if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
02897              && (*mangled)[9] == 'N'
02898              && (*mangled)[8] == (*mangled)[10]
02899              && strchr (cplus_markers, (*mangled)[8]))
02900            {
02901              /* A member of the anonymous namespace.  There's information
02902                about what identifier or filename it was keyed to, but
02903                it's just there to make the mangled name unique; we just
02904                step over it.  */
02905              string_append (declp, "{anonymous}");
02906              (*mangled) += n;
02907 
02908              /* Now p points to the marker before the N, so we need to
02909                update it to the first marker after what we consumed.  */
02910              p = strpbrk (*mangled, cplus_markers);
02911              break;
02912            }
02913 
02914          string_appendn (declp, *mangled, n);
02915          (*mangled) += n;
02916        }
02917       if (success && (p == *mangled))
02918        {
02919          /* Consumed everything up to the cplus_marker, append the
02920             variable name.  */
02921          (*mangled)++;
02922          string_append (declp, SCOPE_STRING (work));
02923          n = strlen (*mangled);
02924          string_appendn (declp, *mangled, n);
02925          (*mangled) += n;
02926        }
02927       else
02928        {
02929          success = 0;
02930        }
02931     }
02932   else if (strncmp (*mangled, "__thunk_", 8) == 0)
02933     {
02934       int delta;
02935 
02936       (*mangled) += 8;
02937       delta = consume_count (mangled);
02938       if (delta == -1)
02939        success = 0;
02940       else
02941        {
02942          char *method = internal_cplus_demangle (work, ++*mangled);
02943 
02944          if (method)
02945            {
02946              char buf[50];
02947              sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
02948              string_append (declp, buf);
02949              string_append (declp, method);
02950              free (method);
02951              n = strlen (*mangled);
02952              (*mangled) += n;
02953            }
02954          else
02955            {
02956              success = 0;
02957            }
02958        }
02959     }
02960   else if (strncmp (*mangled, "__t", 3) == 0
02961           && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
02962     {
02963       p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
02964       (*mangled) += 4;
02965       switch (**mangled)
02966        {
02967        case 'Q':
02968        case 'K':
02969          success = demangle_qualified (work, mangled, declp, 0, 1);
02970          break;
02971        case 't':
02972          success = demangle_template (work, mangled, declp, 0, 1, 1);
02973          break;
02974        default:
02975          success = do_type (work, mangled, declp);
02976          break;
02977        }
02978       if (success && **mangled != '\0')
02979        success = 0;
02980       if (success)
02981        string_append (declp, p);
02982     }
02983   else
02984     {
02985       success = 0;
02986     }
02987   return (success);
02988 }
02989 
02990 static void
02991 recursively_demangle(struct work_stuff *work, const char **mangled,
02992                      string *result, int namelength)
02993 {
02994   char * recurse = (char *)NULL;
02995   char * recurse_dem = (char *)NULL;
02996 
02997   recurse = XNEWVEC (char, namelength + 1);
02998   memcpy (recurse, *mangled, namelength);
02999   recurse[namelength] = '\000';
03000 
03001   recurse_dem = cplus_demangle (recurse, work->options);
03002 
03003   if (recurse_dem)
03004     {
03005       string_append (result, recurse_dem);
03006       free (recurse_dem);
03007     }
03008   else
03009     {
03010       string_appendn (result, *mangled, namelength);
03011     }
03012   free (recurse);
03013   *mangled += namelength;
03014 }
03015 
03016 /*
03017 
03018 LOCAL FUNCTION
03019 
03020        arm_special -- special handling of ARM/lucid mangled strings
03021 
03022 SYNOPSIS
03023 
03024        static int
03025        arm_special (const char **mangled,
03026                    string *declp);
03027 
03028 
03029 DESCRIPTION
03030 
03031        Process some special ARM style mangling forms that don't fit
03032        the normal pattern.  For example:
03033 
03034               __vtbl__3foo         (foo virtual table)
03035               __vtbl__3foo__3bar   (bar::foo virtual table)
03036 
03037  */
03038 
03039 static int
03040 arm_special (const char **mangled, string *declp)
03041 {
03042   int n;
03043   int success = 1;
03044   const char *scan;
03045 
03046   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
03047     {
03048       /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
03049          and create the decl.  Note that we consume the entire mangled
03050         input string, which means that demangle_signature has no work
03051         to do.  */
03052       scan = *mangled + ARM_VTABLE_STRLEN;
03053       while (*scan != '\0')        /* first check it can be demangled */
03054         {
03055           n = consume_count (&scan);
03056           if (n == -1)
03057            {
03058              return (0);           /* no good */
03059            }
03060           scan += n;
03061           if (scan[0] == '_' && scan[1] == '_')
03062            {
03063              scan += 2;
03064            }
03065         }
03066       (*mangled) += ARM_VTABLE_STRLEN;
03067       while (**mangled != '\0')
03068        {
03069          n = consume_count (mangled);
03070           if (n == -1
03071              || n > (long) strlen (*mangled))
03072            return 0;
03073          string_prependn (declp, *mangled, n);
03074          (*mangled) += n;
03075          if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
03076            {
03077              string_prepend (declp, "::");
03078              (*mangled) += 2;
03079            }
03080        }
03081       string_append (declp, " virtual table");
03082     }
03083   else
03084     {
03085       success = 0;
03086     }
03087   return (success);
03088 }
03089 
03090 /*
03091 
03092 LOCAL FUNCTION
03093 
03094        demangle_qualified -- demangle 'Q' qualified name strings
03095 
03096 SYNOPSIS
03097 
03098        static int
03099        demangle_qualified (struct work_stuff *, const char *mangled,
03100                          string *result, int isfuncname, int append);
03101 
03102 DESCRIPTION
03103 
03104        Demangle a qualified name, such as "Q25Outer5Inner" which is
03105        the mangled form of "Outer::Inner".  The demangled output is
03106        prepended or appended to the result string according to the
03107        state of the append flag.
03108 
03109        If isfuncname is nonzero, then the qualified name we are building
03110        is going to be used as a member function name, so if it is a
03111        constructor or destructor function, append an appropriate
03112        constructor or destructor name.  I.E. for the above example,
03113        the result for use as a constructor is "Outer::Inner::Inner"
03114        and the result for use as a destructor is "Outer::Inner::~Inner".
03115 
03116 BUGS
03117 
03118        Numeric conversion is ASCII dependent (FIXME).
03119 
03120  */
03121 
03122 static int
03123 demangle_qualified (struct work_stuff *work, const char **mangled,
03124                     string *result, int isfuncname, int append)
03125 {
03126   int qualifiers = 0;
03127   int success = 1;
03128   char num[2];
03129   string temp;
03130   string last_name;
03131   int bindex = register_Btype (work);
03132 
03133   /* We only make use of ISFUNCNAME if the entity is a constructor or
03134      destructor.  */
03135   isfuncname = (isfuncname
03136               && ((work->constructor & 1) || (work->destructor & 1)));
03137 
03138   string_init (&temp);
03139   string_init (&last_name);
03140 
03141   if ((*mangled)[0] == 'K')
03142     {
03143     /* Squangling qualified name reuse */
03144       int idx;
03145       (*mangled)++;
03146       idx = consume_count_with_underscores (mangled);
03147       if (idx == -1 || idx >= work -> numk)
03148         success = 0;
03149       else
03150         string_append (&temp, work -> ktypevec[idx]);
03151     }
03152   else
03153     switch ((*mangled)[1])
03154     {
03155     case '_':
03156       /* GNU mangled name with more than 9 classes.  The count is preceded
03157         by an underscore (to distinguish it from the <= 9 case) and followed
03158         by an underscore.  */
03159       (*mangled)++;
03160       qualifiers = consume_count_with_underscores (mangled);
03161       if (qualifiers == -1)
03162        success = 0;
03163       break;
03164 
03165     case '1':
03166     case '2':
03167     case '3':
03168     case '4':
03169     case '5':
03170     case '6':
03171     case '7':
03172     case '8':
03173     case '9':
03174       /* The count is in a single digit.  */
03175       num[0] = (*mangled)[1];
03176       num[1] = '\0';
03177       qualifiers = atoi (num);
03178 
03179       /* If there is an underscore after the digit, skip it.  This is
03180         said to be for ARM-qualified names, but the ARM makes no
03181         mention of such an underscore.  Perhaps cfront uses one.  */
03182       if ((*mangled)[2] == '_')
03183        {
03184          (*mangled)++;
03185        }
03186       (*mangled) += 2;
03187       break;
03188 
03189     case '0':
03190     default:
03191       success = 0;
03192     }
03193 
03194   if (!success)
03195     return success;
03196 
03197   /* Pick off the names and collect them in the temp buffer in the order
03198      in which they are found, separated by '::'.  */
03199 
03200   while (qualifiers-- > 0)
03201     {
03202       int remember_K = 1;
03203       string_clear (&last_name);
03204 
03205       if (*mangled[0] == '_')
03206        (*mangled)++;
03207 
03208       if (*mangled[0] == 't')
03209        {
03210          /* Here we always append to TEMP since we will want to use
03211             the template name without the template parameters as a
03212             constructor or destructor name.  The appropriate
03213             (parameter-less) value is returned by demangle_template
03214             in LAST_NAME.  We do not remember the template type here,
03215             in order to match the G++ mangling algorithm.  */
03216          success = demangle_template(work, mangled, &temp,
03217                                   &last_name, 1, 0);
03218          if (!success)
03219            break;
03220        }
03221       else if (*mangled[0] == 'K')
03222        {
03223           int idx;
03224           (*mangled)++;
03225           idx = consume_count_with_underscores (mangled);
03226           if (idx == -1 || idx >= work->numk)
03227             success = 0;
03228           else
03229             string_append (&temp, work->ktypevec[idx]);
03230           remember_K = 0;
03231 
03232          if (!success) break;
03233        }
03234       else
03235        {
03236          if (EDG_DEMANGLING)
03237             {
03238              int namelength;
03239              /* Now recursively demangle the qualifier
03240               * This is necessary to deal with templates in
03241               * mangling styles like EDG */
03242              namelength = consume_count (mangled);
03243              if (namelength == -1)
03244               {
03245                 success = 0;
03246                 break;
03247               }
03248              recursively_demangle(work, mangled, &temp, namelength);
03249             }
03250           else
03251             {
03252               string_delete (&last_name);
03253               success = do_type (work, mangled, &last_name);
03254               if (!success)
03255                 break;
03256               string_appends (&temp, &last_name);
03257             }
03258        }
03259 
03260       if (remember_K)
03261        remember_Ktype (work, temp.b, LEN_STRING (&temp));
03262 
03263       if (qualifiers > 0)
03264        string_append (&temp, SCOPE_STRING (work));
03265     }
03266 
03267   remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
03268 
03269   /* If we are using the result as a function name, we need to append
03270      the appropriate '::' separated constructor or destructor name.
03271      We do this here because this is the most convenient place, where
03272      we already have a pointer to the name and the length of the name.  */
03273 
03274   if (isfuncname)
03275     {
03276       string_append (&temp, SCOPE_STRING (work));
03277       if (work -> destructor & 1)
03278        string_append (&temp, "~");
03279       string_appends (&temp, &last_name);
03280     }
03281 
03282   /* Now either prepend the temp buffer to the result, or append it,
03283      depending upon the state of the append flag.  */
03284 
03285   if (append)
03286     string_appends (result, &temp);
03287   else
03288     {
03289       if (!STRING_EMPTY (result))
03290        string_append (&temp, SCOPE_STRING (work));
03291       string_prepends (result, &temp);
03292     }
03293 
03294   string_delete (&last_name);
03295   string_delete (&temp);
03296   return (success);
03297 }
03298 
03299 /*
03300 
03301 LOCAL FUNCTION
03302 
03303        get_count -- convert an ascii count to integer, consuming tokens
03304 
03305 SYNOPSIS
03306 
03307        static int
03308        get_count (const char **type, int *count)
03309 
03310 DESCRIPTION
03311 
03312        Assume that *type points at a count in a mangled name; set
03313        *count to its value, and set *type to the next character after
03314        the count.  There are some weird rules in effect here.
03315 
03316        If *type does not point at a string of digits, return zero.
03317 
03318        If *type points at a string of digits followed by an
03319        underscore, set *count to their value as an integer, advance
03320        *type to point *after the underscore, and return 1.
03321 
03322        If *type points at a string of digits not followed by an
03323        underscore, consume only the first digit.  Set *count to its
03324        value as an integer, leave *type pointing after that digit,
03325        and return 1.
03326 
03327         The excuse for this odd behavior: in the ARM and HP demangling
03328         styles, a type can be followed by a repeat count of the form
03329         `Nxy', where:
03330 
03331         `x' is a single digit specifying how many additional copies
03332             of the type to append to the argument list, and
03333 
03334         `y' is one or more digits, specifying the zero-based index of
03335             the first repeated argument in the list.  Yes, as you're
03336             unmangling the name you can figure this out yourself, but
03337             it's there anyway.
03338 
03339         So, for example, in `bar__3fooFPiN51', the first argument is a
03340         pointer to an integer (`Pi'), and then the next five arguments
03341         are the same (`N5'), and the first repeat is the function's
03342         second argument (`1').
03343 */
03344 
03345 static int
03346 get_count (const char **type, int *count)
03347 {
03348   const char *p;
03349   int n;
03350 
03351   if (!ISDIGIT ((unsigned char)**type))
03352     return (0);
03353   else
03354     {
03355       *count = **type - '0';
03356       (*type)++;
03357       if (ISDIGIT ((unsigned char)**type))
03358        {
03359          p = *type;
03360          n = *count;
03361          do
03362            {
03363              n *= 10;
03364              n += *p - '0';
03365              p++;
03366            }
03367          while (ISDIGIT ((unsigned char)*p));
03368          if (*p == '_')
03369            {
03370              *type = p + 1;
03371              *count = n;
03372            }
03373        }
03374     }
03375   return (1);
03376 }
03377 
03378 /* RESULT will be initialised here; it will be freed on failure.  The
03379    value returned is really a type_kind_t.  */
03380 
03381 static int
03382 do_type (struct work_stuff *work, const char **mangled, string *result)
03383 {
03384   int n;
03385   int done;
03386   int success;
03387   string decl;
03388   const char *remembered_type;
03389   int type_quals;
03390   type_kind_t tk = tk_none;
03391 
03392   string_init (&decl);
03393   string_init (result);
03394 
03395   done = 0;
03396   success = 1;
03397   while (success && !done)
03398     {
03399       int member;
03400       switch (**mangled)
03401        {
03402 
03403          /* A pointer type */
03404        case 'P':
03405        case 'p':
03406          (*mangled)++;
03407          if (! (work -> options & DMGL_JAVA))
03408            string_prepend (&decl, "*");
03409          if (tk == tk_none)
03410            tk = tk_pointer;
03411          break;
03412 
03413          /* A reference type */
03414        case 'R':
03415          (*mangled)++;
03416          string_prepend (&decl, "&");
03417          if (tk == tk_none)
03418            tk = tk_reference;
03419          break;
03420 
03421          /* An array */
03422        case 'A':
03423          {
03424            ++(*mangled);
03425            if (!STRING_EMPTY (&decl)
03426               && (decl.b[0] == '*' || decl.b[0] == '&'))
03427              {
03428               string_prepend (&decl, "(");
03429               string_append (&decl, ")");
03430              }
03431            string_append (&decl, "[");
03432            if (**mangled != '_')
03433              success = demangle_template_value_parm (work, mangled, &decl,
03434                                                 tk_integral);
03435            if (**mangled == '_')
03436              ++(*mangled);
03437            string_append (&decl, "]");
03438            break;
03439          }
03440 
03441        /* A back reference to a previously seen type */
03442        case 'T':
03443          (*mangled)++;
03444          if (!get_count (mangled, &n) || n >= work -> ntypes)
03445            {
03446              success = 0;
03447            }
03448          else
03449            {
03450              remembered_type = work -> typevec[n];
03451              mangled = &remembered_type;
03452            }
03453          break;
03454 
03455          /* A function */
03456        case 'F':
03457          (*mangled)++;
03458            if (!STRING_EMPTY (&decl)
03459               && (decl.b[0] == '*' || decl.b[0] == '&'))
03460            {
03461              string_prepend (&decl, "(");
03462              string_append (&decl, ")");
03463            }
03464          /* After picking off the function args, we expect to either find the
03465             function return type (preceded by an '_') or the end of the
03466             string.  */
03467          if (!demangle_nested_args (work, mangled, &decl)
03468              || (**mangled != '_' && **mangled != '\0'))
03469            {
03470              success = 0;
03471              break;
03472            }
03473          if (success && (**mangled == '_'))
03474            (*mangled)++;
03475          break;
03476 
03477        case 'M':
03478        case 'O':
03479          {
03480            type_quals = TYPE_UNQUALIFIED;
03481 
03482            member = **mangled == 'M';
03483            (*mangled)++;
03484 
03485            string_append (&decl, ")");
03486 
03487            /* We don't need to prepend `::' for a qualified name;
03488               demangle_qualified will do that for us.  */
03489            if (**mangled != 'Q')
03490              string_prepend (&decl, SCOPE_STRING (work));
03491 
03492            if (ISDIGIT ((unsigned char)**mangled))
03493              {
03494               n = consume_count (mangled);
03495               if (n == -1
03496                   || (int) strlen (*mangled) < n)
03497                 {
03498                   success = 0;
03499                   break;
03500                 }
03501               string_prependn (&decl, *mangled, n);
03502               *mangled += n;
03503              }
03504            else if (**mangled == 'X' || **mangled == 'Y')
03505              {
03506               string temp;
03507               do_type (work, mangled, &temp);
03508               string_prepends (&decl, &temp);
03509               string_delete (&temp);
03510              }
03511            else if (**mangled == 't')
03512              {
03513               string temp;
03514               string_init (&temp);
03515               success = demangle_template (work, mangled, &temp,
03516                                         NULL, 1, 1);
03517               if (success)
03518                 {
03519                   string_prependn (&decl, temp.b, temp.p - temp.b);
03520                   string_delete (&temp);
03521                 }
03522               else
03523                 break;
03524              }
03525            else if (**mangled == 'Q')
03526              {
03527               success = demangle_qualified (work, mangled, &decl,
03528                                          /*isfuncnam=*/0, 
03529                                          /*append=*/0);
03530               if (!success)
03531                 break;
03532              }
03533            else
03534              {
03535               success = 0;
03536               break;
03537              }
03538 
03539            string_prepend (&decl, "(");
03540            if (member)
03541              {
03542               switch (**mangled)
03543                 {
03544                 case 'C':
03545                 case 'V':
03546                 case 'u':
03547                   type_quals |= code_for_qualifier (**mangled);
03548                   (*mangled)++;
03549                   break;
03550 
03551                 default:
03552                   break;
03553                 }
03554 
03555               if (*(*mangled)++ != 'F')
03556                 {
03557                   success = 0;
03558                   break;
03559                 }
03560              }
03561            if ((member && !demangle_nested_args (work, mangled, &decl))
03562               || **mangled != '_')
03563              {
03564               success = 0;
03565               break;
03566              }
03567            (*mangled)++;
03568            if (! PRINT_ANSI_QUALIFIERS)
03569              {
03570               break;
03571              }
03572            if (type_quals != TYPE_UNQUALIFIED)
03573              {
03574               APPEND_BLANK (&decl);
03575               string_append (&decl, qualifier_string (type_quals));
03576              }
03577            break;
03578          }
03579         case 'G':
03580          (*mangled)++;
03581          break;
03582 
03583        case 'C':
03584        case 'V':
03585        case 'u':
03586          if (PRINT_ANSI_QUALIFIERS)
03587            {
03588              if (!STRING_EMPTY (&decl))
03589               string_prepend (&decl, " ");
03590 
03591              string_prepend (&decl, demangle_qualifier (**mangled));
03592            }
03593          (*mangled)++;
03594          break;
03595          /*
03596            }
03597            */
03598 
03599          /* fall through */
03600        default:
03601          done = 1;
03602          break;
03603        }
03604     }
03605 
03606   if (success) switch (**mangled)
03607     {
03608       /* A qualified name, such as "Outer::Inner".  */
03609     case 'Q':
03610     case 'K':
03611       {
03612         success = demangle_qualified (work, mangled, result, 0, 1);
03613         break;
03614       }
03615 
03616     /* A back reference to a previously seen squangled type */
03617     case 'B':
03618       (*mangled)++;
03619       if (!get_count (mangled, &n) || n >= work -> numb)
03620        success = 0;
03621       else
03622        string_append (result, work->btypevec[n]);
03623       break;
03624 
03625     case 'X':
03626     case 'Y':
03627       /* A template parm.  We substitute the corresponding argument. */
03628       {
03629        int idx;
03630 
03631        (*mangled)++;
03632        idx = consume_count_with_underscores (mangled);
03633 
03634        if (idx == -1
03635            || (work->tmpl_argvec && idx >= work->ntmpl_args)
03636            || consume_count_with_underscores (mangled) == -1)
03637          {
03638            success = 0;
03639            break;
03640          }
03641 
03642        if (work->tmpl_argvec)
03643          string_append (result, work->tmpl_argvec[idx]);
03644        else
03645          string_append_template_idx (result, idx);
03646 
03647        success = 1;
03648       }
03649     break;
03650 
03651     default:
03652       success = demangle_fund_type (work, mangled, result);
03653       if (tk == tk_none)
03654        tk = (type_kind_t) success;
03655       break;
03656     }
03657 
03658   if (success)
03659     {
03660       if (!STRING_EMPTY (&decl))
03661        {
03662          string_append (result, " ");
03663          string_appends (result, &decl);
03664        }
03665     }
03666   else
03667     string_delete (result);
03668   string_delete (&decl);
03669 
03670   if (success)
03671     /* Assume an integral type, if we're not sure.  */
03672     return (int) ((tk == tk_none) ? tk_integral : tk);
03673   else
03674     return 0;
03675 }
03676 
03677 /* Given a pointer to a type string that represents a fundamental type
03678    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
03679    string in which the demangled output is being built in RESULT, and
03680    the WORK structure, decode the types and add them to the result.
03681 
03682    For example:
03683 
03684        "Ci"   =>     "const int"
03685        "Sl"   =>     "signed long"
03686        "CUs"  =>     "const unsigned short"
03687 
03688    The value returned is really a type_kind_t.  */
03689 
03690 static int
03691 demangle_fund_type (struct work_stuff *work,
03692                     const char **mangled, string *result)
03693 {
03694   int done = 0;
03695   int success = 1;
03696   char buf[INTBUF_SIZE + 5 /* 'int%u_t' */];
03697   unsigned int dec = 0;
03698   type_kind_t tk = tk_integral;
03699 
03700   /* First pick off any type qualifiers.  There can be more than one.  */
03701 
03702   while (!done)
03703     {
03704       switch (**mangled)
03705        {
03706        case 'C':
03707        case 'V':
03708        case 'u':
03709          if (PRINT_ANSI_QUALIFIERS)
03710            {
03711               if (!STRING_EMPTY (result))
03712                 string_prepend (result, " ");
03713              string_prepend (result, demangle_qualifier (**mangled));
03714            }
03715          (*mangled)++;
03716          break;
03717        case 'U':
03718          (*mangled)++;
03719          APPEND_BLANK (result);
03720          string_append (result, "unsigned");
03721          break;
03722        case 'S': /* signed char only */
03723          (*mangled)++;
03724          APPEND_BLANK (result);
03725          string_append (result, "signed");
03726          break;
03727        case 'J':
03728          (*mangled)++;
03729          APPEND_BLANK (result);
03730          string_append (result, "__complex");
03731          break;
03732        default:
03733          done = 1;
03734          break;
03735        }
03736     }
03737 
03738   /* Now pick off the fundamental type.  There can be only one.  */
03739 
03740   switch (**mangled)
03741     {
03742     case '\0':
03743     case '_':
03744       break;
03745     case 'v':
03746       (*mangled)++;
03747       APPEND_BLANK (result);
03748       string_append (result, "void");
03749       break;
03750     case 'x':
03751       (*mangled)++;
03752       APPEND_BLANK (result);
03753       string_append (result, "long long");
03754       break;
03755     case 'l':
03756       (*mangled)++;
03757       APPEND_BLANK (result);
03758       string_append (result, "long");
03759       break;
03760     case 'i':
03761       (*mangled)++;
03762       APPEND_BLANK (result);
03763       string_append (result, "int");
03764       break;
03765     case 's':
03766       (*mangled)++;
03767       APPEND_BLANK (result);
03768       string_append (result, "short");
03769       break;
03770     case 'b':
03771       (*mangled)++;
03772       APPEND_BLANK (result);
03773       string_append (result, "bool");
03774       tk = tk_bool;
03775       break;
03776     case 'c':
03777       (*mangled)++;
03778       APPEND_BLANK (result);
03779       string_append (result, "char");
03780       tk = tk_char;
03781       break;
03782     case 'w':
03783       (*mangled)++;
03784       APPEND_BLANK (result);
03785       string_append (result, "wchar_t");
03786       tk = tk_char;
03787       break;
03788     case 'r':
03789       (*mangled)++;
03790       APPEND_BLANK (result);
03791       string_append (result, "long double");
03792       tk = tk_real;
03793       break;
03794     case 'd':
03795       (*mangled)++;
03796       APPEND_BLANK (result);
03797       string_append (result, "double");
03798       tk = tk_real;
03799       break;
03800     case 'f':
03801       (*mangled)++;
03802       APPEND_BLANK (result);
03803       string_append (result, "float");
03804       tk = tk_real;
03805       break;
03806     case 'G':
03807       (*mangled)++;
03808       if (!ISDIGIT ((unsigned char)**mangled))
03809        {
03810          success = 0;
03811          break;
03812        }
03813     case 'I':
03814       (*mangled)++;
03815       if (**mangled == '_')
03816        {
03817          int i;
03818          (*mangled)++;
03819          for (i = 0;
03820               i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
03821               (*mangled)++, i++)
03822            buf[i] = **mangled;
03823          if (**mangled != '_')
03824            {
03825              success = 0;
03826              break;
03827            }
03828          buf[i] = '\0';
03829          (*mangled)++;
03830        }
03831       else
03832        {
03833          strncpy (buf, *mangled, 2);
03834          buf[2] = '\0';
03835          *mangled += min (strlen (*mangled), 2);
03836        }
03837       sscanf (buf, "%x", &dec);
03838       sprintf (buf, "int%u_t", dec);
03839       APPEND_BLANK (result);
03840       string_append (result, buf);
03841       break;
03842 
03843       /* fall through */
03844       /* An explicit type, such as "6mytype" or "7integer" */
03845     case '0':
03846     case '1':
03847     case '2':
03848     case '3':
03849     case '4':
03850     case '5':
03851     case '6':
03852     case '7':
03853     case '8':
03854     case '9':
03855       {
03856         int bindex = register_Btype (work);
03857         string btype;
03858         string_init (&btype);
03859         if (demangle_class_name (work, mangled, &btype)) {
03860           remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
03861           APPEND_BLANK (result);
03862           string_appends (result, &btype);
03863         }
03864         else
03865           success = 0;
03866         string_delete (&btype);
03867         break;
03868       }
03869     case 't':
03870       {
03871         string btype;
03872         string_init (&btype);
03873         success = demangle_template (work, mangled, &btype, 0, 1, 1);
03874         string_appends (result, &btype);
03875         string_delete (&btype);
03876         break;
03877       }
03878     default:
03879       success = 0;
03880       break;
03881     }
03882 
03883   return success ? ((int) tk) : 0;
03884 }
03885 
03886 
03887 /* Handle a template's value parameter for HP aCC (extension from ARM)
03888    **mangled points to 'S' or 'U' */
03889 
03890 static int
03891 do_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED,
03892                                const char **mangled, string *result)
03893 {
03894   int unsigned_const;
03895 
03896   if (**mangled != 'U' && **mangled != 'S')
03897     return 0;
03898 
03899   unsigned_const = (**mangled == 'U');
03900 
03901   (*mangled)++;
03902 
03903   switch (**mangled)
03904     {
03905       case 'N':
03906         string_append (result, "-");
03907         /* fall through */
03908       case 'P':
03909         (*mangled)++;
03910         break;
03911       case 'M':
03912         /* special case for -2^31 */
03913         string_append (result, "-2147483648");
03914         (*mangled)++;
03915         return 1;
03916       default:
03917         return 0;
03918     }
03919 
03920   /* We have to be looking at an integer now */
03921   if (!(ISDIGIT ((unsigned char)**mangled)))
03922     return 0;
03923 
03924   /* We only deal with integral values for template
03925      parameters -- so it's OK to look only for digits */
03926   while (ISDIGIT ((unsigned char)**mangled))
03927     {
03928       char_str[0] = **mangled;
03929       string_append (result, char_str);
03930       (*mangled)++;
03931     }
03932 
03933   if (unsigned_const)
03934     string_append (result, "U");
03935 
03936   /* FIXME? Some day we may have 64-bit (or larger :-) ) constants
03937      with L or LL suffixes. pai/1997-09-03 */
03938 
03939   return 1; /* success */
03940 }
03941 
03942 /* Handle a template's literal parameter for HP aCC (extension from ARM)
03943    **mangled is pointing to the 'A' */
03944 
03945 static int
03946 do_hpacc_template_literal (struct work_stuff *work, const char **mangled,
03947                            string *result)
03948 {
03949   int literal_len = 0;
03950   char * recurse;
03951   char * recurse_dem;
03952 
03953   if (**mangled != 'A')
03954     return 0;
03955 
03956   (*mangled)++;
03957 
03958   literal_len = consume_count (mangled);
03959 
03960   if (literal_len <= 0)
03961     return 0;
03962 
03963   /* Literal parameters are names of arrays, functions, etc.  and the
03964      canonical representation uses the address operator */
03965   string_append (result, "&");
03966 
03967   /* Now recursively demangle the literal name */
03968   recurse = XNEWVEC (char, literal_len + 1);
03969   memcpy (recurse, *mangled, literal_len);
03970   recurse[literal_len] = '\000';
03971 
03972   recurse_dem = cplus_demangle (recurse, work->options);
03973 
03974   if (recurse_dem)
03975     {
03976       string_append (result, recurse_dem);
03977       free (recurse_dem);
03978     }
03979   else
03980     {
03981       string_appendn (result, *mangled, literal_len);
03982     }
03983   (*mangled) += literal_len;
03984   free (recurse);
03985 
03986   return 1;
03987 }
03988 
03989 static int
03990 snarf_numeric_literal (const char **args, string *arg)
03991 {
03992   if (**args == '-')
03993     {
03994       char_str[0] = '-';
03995       string_append (arg, char_str);
03996       (*args)++;
03997     }
03998   else if (**args == '+')
03999     (*args)++;
04000 
04001   if (!ISDIGIT ((unsigned char)**args))
04002     return 0;
04003 
04004   while (ISDIGIT ((unsigned char)**args))
04005     {
04006       char_str[0] = **args;
04007       string_append (arg, char_str);
04008       (*args)++;
04009     }
04010 
04011   return 1;
04012 }
04013 
04014 /* Demangle the next argument, given by MANGLED into RESULT, which
04015    *should be an uninitialized* string.  It will be initialized here,
04016    and free'd should anything go wrong.  */
04017 
04018 static int
04019 do_arg (struct work_stuff *work, const char **mangled, string *result)
04020 {
04021   /* Remember where we started so that we can record the type, for
04022      non-squangling type remembering.  */
04023   const char *start = *mangled;
04024 
04025   string_init (result);
04026 
04027   if (work->nrepeats > 0)
04028     {
04029       --work->nrepeats;
04030 
04031       if (work->previous_argument == 0)
04032        return 0;
04033 
04034       /* We want to reissue the previous type in this argument list.  */
04035       string_appends (result, work->previous_argument);
04036       return 1;
04037     }
04038 
04039   if (**mangled == 'n')
04040     {
04041       /* A squangling-style repeat.  */
04042       (*mangled)++;
04043       work->nrepeats = consume_count(mangled);
04044 
04045       if (work->nrepeats <= 0)
04046        /* This was not a repeat count after all.  */
04047        return 0;
04048 
04049       if (work->nrepeats > 9)
04050        {
04051          if (**mangled != '_')
04052            /* The repeat count should be followed by an '_' in this
04053               case.  */
04054            return 0;
04055          else
04056            (*mangled)++;
04057        }
04058 
04059       /* Now, the repeat is all set up.  */
04060       return do_arg (work, mangled, result);
04061     }
04062 
04063   /* Save the result in WORK->previous_argument so that we can find it
04064      if it's repeated.  Note that saving START is not good enough: we
04065      do not want to add additional types to the back-referenceable
04066      type vector when processing a repeated type.  */
04067   if (work->previous_argument)
04068     string_delete (work->previous_argument);
04069   else
04070     work->previous_argument = XNEW (string);
04071 
04072   if (!do_type (work, mangled, work->previous_argument))
04073     return 0;
04074 
04075   string_appends (result, work->previous_argument);
04076 
04077   remember_type (work, start, *mangled - start);
04078   return 1;
04079 }
04080 
04081 static void
04082 remember_type (struct work_stuff *work, const char *start, int len)
04083 {
04084   char *tem;
04085 
04086   if (work->forgetting_types)
04087     return;
04088 
04089   if (work -> ntypes >= work -> typevec_size)
04090     {
04091       if (work -> typevec_size == 0)
04092        {
04093          work -> typevec_size = 3;
04094          work -> typevec = XNEWVEC (char *, work->typevec_size);
04095        }
04096       else
04097        {
04098          work -> typevec_size *= 2;
04099          work -> typevec
04100            = XRESIZEVEC (char *, work->typevec, work->typevec_size);
04101        }
04102     }
04103   tem = XNEWVEC (char, len + 1);
04104   memcpy (tem, start, len);
04105   tem[len] = '\0';
04106   work -> typevec[work -> ntypes++] = tem;
04107 }
04108 
04109 
04110 /* Remember a K type class qualifier. */
04111 static void
04112 remember_Ktype (struct work_stuff *work, const char *start, int len)
04113 {
04114   char *tem;
04115 
04116   if (work -> numk >= work -> ksize)
04117     {
04118       if (work -> ksize == 0)
04119        {
04120          work -> ksize = 5;
04121          work -> ktypevec = XNEWVEC (char *, work->ksize);
04122        }
04123       else
04124        {
04125          work -> ksize *= 2;
04126          work -> ktypevec
04127            = XRESIZEVEC (char *, work->ktypevec, work->ksize);
04128        }
04129     }
04130   tem = XNEWVEC (char, len + 1);
04131   memcpy (tem, start, len);
04132   tem[len] = '\0';
04133   work -> ktypevec[work -> numk++] = tem;
04134 }
04135 
04136 /* Register a B code, and get an index for it. B codes are registered
04137    as they are seen, rather than as they are completed, so map<temp<char> >
04138    registers map<temp<char> > as B0, and temp<char> as B1 */
04139 
04140 static int
04141 register_Btype (struct work_stuff *work)
04142 {
04143   int ret;
04144 
04145   if (work -> numb >= work -> bsize)
04146     {
04147       if (work -> bsize == 0)
04148        {
04149          work -> bsize = 5;
04150          work -> btypevec = XNEWVEC (char *, work->bsize);
04151        }
04152       else
04153        {
04154          work -> bsize *= 2;
04155          work -> btypevec
04156            = XRESIZEVEC (char *, work->btypevec, work->bsize);
04157        }
04158     }
04159   ret = work -> numb++;
04160   work -> btypevec[ret] = NULL;
04161   return(ret);
04162 }
04163 
04164 /* Store a value into a previously registered B code type. */
04165 
04166 static void
04167 remember_Btype (struct work_stuff *work, const char *start,
04168                 int len, int index)
04169 {
04170   char *tem;
04171 
04172   tem = XNEWVEC (char, len + 1);
04173   memcpy (tem, start, len);
04174   tem[len] = '\0';
04175   work -> btypevec[index] = tem;
04176 }
04177 
04178 /* Lose all the info related to B and K type codes. */
04179 static void
04180 forget_B_and_K_types (struct work_stuff *work)
04181 {
04182   int i;
04183 
04184   while (work -> numk > 0)
04185     {
04186       i = --(work -> numk);
04187       if (work -> ktypevec[i] != NULL)
04188        {
04189          free (work -> ktypevec[i]);
04190          work -> ktypevec[i] = NULL;
04191        }
04192     }
04193 
04194   while (work -> numb > 0)
04195     {
04196       i = --(work -> numb);
04197       if (work -> btypevec[i] != NULL)
04198        {
04199          free (work -> btypevec[i]);
04200          work -> btypevec[i] = NULL;
04201        }
04202     }
04203 }
04204 /* Forget the remembered types, but not the type vector itself.  */
04205 
04206 static void
04207 forget_types (struct work_stuff *work)
04208 {
04209   int i;
04210 
04211   while (work -> ntypes > 0)
04212     {
04213       i = --(work -> ntypes);
04214       if (work -> typevec[i] != NULL)
04215        {
04216          free (work -> typevec[i]);
04217          work -> typevec[i] = NULL;
04218        }
04219     }
04220 }
04221 
04222 /* Process the argument list part of the signature, after any class spec
04223    has been consumed, as well as the first 'F' character (if any).  For
04224    example:
04225 
04226    "__als__3fooRT0"         =>     process "RT0"
04227    "complexfunc5__FPFPc_PFl_i"     =>     process "PFPc_PFl_i"
04228 
04229    DECLP must be already initialised, usually non-empty.  It won't be freed
04230    on failure.
04231 
04232    Note that g++ differs significantly from ARM and lucid style mangling
04233    with regards to references to previously seen types.  For example, given
04234    the source fragment:
04235 
04236      class foo {
04237        public:
04238        foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
04239      };
04240 
04241      foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
04242      void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
04243 
04244    g++ produces the names:
04245 
04246      __3fooiRT0iT2iT2
04247      foo__FiR3fooiT1iT1
04248 
04249    while lcc (and presumably other ARM style compilers as well) produces:
04250 
04251      foo__FiR3fooT1T2T1T2
04252      __ct__3fooFiR3fooT1T2T1T2
04253 
04254    Note that g++ bases its type numbers starting at zero and counts all
04255    previously seen types, while lucid/ARM bases its type numbers starting
04256    at one and only considers types after it has seen the 'F' character
04257    indicating the start of the function args.  For lucid/ARM style, we
04258    account for this difference by discarding any previously seen types when
04259    we see the 'F' character, and subtracting one from the type number
04260    reference.
04261 
04262  */
04263 
04264 static int
04265 demangle_args (struct work_stuff *work, const char **mangled,
04266                string *declp)
04267 {
04268   string arg;
04269   int need_comma = 0;
04270   int r;
04271   int t;
04272   const char *tem;
04273   char temptype;
04274 
04275   if (PRINT_ARG_TYPES)
04276     {
04277       string_append (declp, "(");
04278       if (**mangled == '\0')
04279        {
04280          string_append (declp, "void");
04281        }
04282     }
04283 
04284   while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
04285         || work->nrepeats > 0)
04286     {
04287       if ((**mangled == 'N') || (**mangled == 'T'))
04288        {
04289          temptype = *(*mangled)++;
04290 
04291          if (temptype == 'N')
04292            {
04293              if (!get_count (mangled, &r))
04294               {
04295                 return (0);
04296               }
04297            }
04298          else
04299            {
04300              r = 1;
04301            }
04302           if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10)
04303             {
04304               /* If we have 10 or more types we might have more than a 1 digit
04305                  index so we'll have to consume the whole count here. This
04306                  will lose if the next thing is a type name preceded by a
04307                  count but it's impossible to demangle that case properly
04308                  anyway. Eg if we already have 12 types is T12Pc "(..., type1,
04309                  Pc, ...)"  or "(..., type12, char *, ...)" */
04310               if ((t = consume_count(mangled)) <= 0)
04311                 {
04312                   return (0);
04313                 }
04314             }
04315           else
04316            {
04317              if (!get_count (mangled, &t))
04318               {
04319                  return (0);
04320               }
04321            }
04322          if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
04323            {
04324              t--;
04325            }
04326          /* Validate the type index.  Protect against illegal indices from
04327             malformed type strings.  */
04328          if ((t < 0) || (t >= work -> ntypes))
04329            {
04330              return (0);
04331            }
04332          while (work->nrepeats > 0 || --r >= 0)
04333            {
04334              tem = work -> typevec[t];
04335              if (need_comma && PRINT_ARG_TYPES)
04336               {
04337                 string_append (declp, ", ");
04338               }
04339              if (!do_arg (work, &tem, &arg))
04340               {
04341                 return (0);
04342               }
04343              if (PRINT_ARG_TYPES)
04344               {
04345                 string_appends (declp, &arg);
04346               }
04347              string_delete (&arg);
04348              need_comma = 1;
04349            }
04350        }
04351       else
04352        {
04353          if (need_comma && PRINT_ARG_TYPES)
04354            string_append (declp, ", ");
04355          if (!do_arg (work, mangled, &arg))
04356            return (0);
04357          if (PRINT_ARG_TYPES)
04358            string_appends (declp, &arg);
04359          string_delete (&arg);
04360          need_comma = 1;
04361        }
04362     }
04363 
04364   if (**mangled == 'e')
04365     {
04366       (*mangled)++;
04367       if (PRINT_ARG_TYPES)
04368        {
04369          if (need_comma)
04370            {
04371              string_append (declp, ",");
04372            }
04373          string_append (declp, "...");
04374        }
04375     }
04376 
04377   if (PRINT_ARG_TYPES)
04378     {
04379       string_append (declp, ")");
04380     }
04381   return (1);
04382 }
04383 
04384 /* Like demangle_args, but for demangling the argument lists of function
04385    and method pointers or references, not top-level declarations.  */
04386 
04387 static int
04388 demangle_nested_args (struct work_stuff *work, const char **mangled,
04389                       string *declp)
04390 {
04391   string* saved_previous_argument;
04392   int result;
04393   int saved_nrepeats;
04394 
04395   /* The G++ name-mangling algorithm does not remember types on nested
04396      argument lists, unless -fsquangling is used, and in that case the
04397      type vector updated by remember_type is not used.  So, we turn
04398      off remembering of types here.  */
04399   ++work->forgetting_types;
04400 
04401   /* For the repeat codes used with -fsquangling, we must keep track of
04402      the last argument.  */
04403   saved_previous_argument = work->previous_argument;
04404   saved_nrepeats = work->nrepeats;
04405   work->previous_argument = 0;
04406   work->nrepeats = 0;
04407 
04408   /* Actually demangle the arguments.  */
04409   result = demangle_args (work, mangled, declp);
04410 
04411   /* Restore the previous_argument field.  */
04412   if (work->previous_argument)
04413     {
04414       string_delete (work->previous_argument);
04415       free ((char *) work->previous_argument);
04416     }
04417   work->previous_argument = saved_previous_argument;
04418   --work->forgetting_types;
04419   work->nrepeats = saved_nrepeats;
04420 
04421   return result;
04422 }
04423 
04424 static void
04425 demangle_function_name (struct work_stuff *work, const char **mangled,
04426                         string *declp, const char *scan)
04427 {
04428   size_t i;
04429   string type;
04430   const char *tem;
04431 
04432   string_appendn (declp, (*mangled), scan - (*mangled));
04433   string_need (declp, 1);
04434   *(declp -> p) = '\0';
04435 
04436   /* Consume the function name, including the "__" separating the name
04437      from the signature.  We are guaranteed that SCAN points to the
04438      separator.  */
04439 
04440   (*mangled) = scan + 2;
04441   /* We may be looking at an instantiation of a template function:
04442      foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a
04443      following _F marks the start of the function arguments.  Handle
04444      the template arguments first. */
04445 
04446   if (HP_DEMANGLING && (**mangled == 'X'))
04447     {
04448       demangle_arm_hp_template (work, mangled, 0, declp);
04449       /* This leaves MANGLED pointing to the 'F' marking func args */
04450     }
04451 
04452   if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
04453     {
04454 
04455       /* See if we have an ARM style constructor or destructor operator.
04456         If so, then just record it, clear the decl, and return.
04457         We can't build the actual constructor/destructor decl until later,
04458         when we recover the class name from the signature.  */
04459 
04460       if (strcmp (declp -> b, "__ct") == 0)
04461        {
04462          work -> constructor += 1;
04463          string_clear (declp);
04464          return;
04465        }
04466       else if (strcmp (declp -> b, "__dt") == 0)
04467        {
04468          work -> destructor += 1;
04469          string_clear (declp);
04470          return;
04471        }
04472     }
04473 
04474   if (declp->p - declp->b >= 3
04475       && declp->b[0] == 'o'
04476       && declp->b[1] == 'p'
04477       && strchr (cplus_markers, declp->b[2]) != NULL)
04478     {
04479       /* see if it's an assignment expression */
04480       if (declp->p - declp->b >= 10 /* op$assign_ */
04481          && memcmp (declp->b + 3, "assign_", 7) == 0)
04482        {
04483          for (i = 0; i < ARRAY_SIZE (optable); i++)
04484            {
04485              int len = declp->p - declp->b - 10;
04486              if ((int) strlen (optable[i].in) == len
04487                 && memcmp (optable[i].in, declp->b + 10, len) == 0)
04488               {
04489                 string_clear (declp);
04490                 string_append (declp, "operator");
04491                 string_append (declp, optable[i].out);
04492                 string_append (declp, "=");
04493                 break;
04494               }
04495            }
04496        }
04497       else
04498        {
04499          for (i = 0; i < ARRAY_SIZE (optable); i++)
04500            {
04501              int len = declp->p - declp->b - 3;
04502              if ((int) strlen (optable[i].in) == len
04503                 && memcmp (optable[i].in, declp->b + 3, len) == 0)
04504               {
04505                 string_clear (declp);
04506                 string_append (declp, "operator");
04507                 string_append (declp, optable[i].out);
04508                 break;
04509               }
04510            }
04511        }
04512     }
04513   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
04514           && strchr (cplus_markers, declp->b[4]) != NULL)
04515     {
04516       /* type conversion operator */
04517       tem = declp->b + 5;
04518       if (do_type (work, &tem, &type))
04519        {
04520          string_clear (declp);
04521          string_append (declp, "operator ");
04522          string_appends (declp, &type);
04523          string_delete (&type);
04524        }
04525     }
04526   else if (declp->b[0] == '_' && declp->b[1] == '_'
04527           && declp->b[2] == 'o' && declp->b[3] == 'p')
04528     {
04529       /* ANSI.  */
04530       /* type conversion operator.  */
04531       tem = declp->b + 4;
04532       if (do_type (work, &tem, &type))
04533        {
04534          string_clear (declp);
04535          string_append (declp, "operator ");
04536          string_appends (declp, &type);
04537          string_delete (&type);
04538        }
04539     }
04540   else if (declp->b[0] == '_' && declp->b[1] == '_'
04541           && ISLOWER((unsigned char)declp->b[2])
04542           && ISLOWER((unsigned char)declp->b[3]))
04543     {
04544       if (declp->b[4] == '\0')
04545        {
04546          /* Operator.  */
04547          for (i = 0; i < ARRAY_SIZE (optable); i++)
04548            {
04549              if (strlen (optable[i].in) == 2
04550                 && memcmp (optable[i].in, declp->b + 2, 2) == 0)
04551               {
04552                 string_clear (declp);
04553                 string_append (declp, "operator");
04554                 string_append (declp, optable[i].out);
04555                 break;
04556               }
04557            }
04558        }
04559       else
04560        {
04561          if (declp->b[2] == 'a' && declp->b[5] == '\0')
04562            {
04563              /* Assignment.  */
04564              for (i = 0; i < ARRAY_SIZE (optable); i++)
04565               {
04566                 if (strlen (optable[i].in) == 3
04567                     && memcmp (optable[i].in, declp->b + 2, 3) == 0)
04568                   {
04569                     string_clear (declp);
04570                     string_append (declp, "operator");
04571                     string_append (declp, optable[i].out);
04572                     break;
04573                   }
04574               }
04575            }
04576        }
04577     }
04578 }
04579 
04580 /* a mini string-handling package */
04581 
04582 static void
04583 string_need (string *s, int n)
04584 {
04585   int tem;
04586 
04587   if (s->b == NULL)
04588     {
04589       if (n < 32)
04590        {
04591          n = 32;
04592        }
04593       s->p = s->b = XNEWVEC (char, n);
04594       s->e = s->b + n;
04595     }
04596   else if (s->e - s->p < n)
04597     {
04598       tem = s->p - s->b;
04599       n += tem;
04600       n *= 2;
04601       s->b = XRESIZEVEC (char, s->b, n);
04602       s->p = s->b + tem;
04603       s->e = s->b + n;
04604     }
04605 }
04606 
04607 static void
04608 string_delete (string *s)
04609 {
04610   if (s->b != NULL)
04611     {
04612       free (s->b);
04613       s->b = s->e = s->p = NULL;
04614     }
04615 }
04616 
04617 static void
04618 string_init (string *s)
04619 {
04620   s->b = s->p = s->e = NULL;
04621 }
04622 
04623 static void
04624 string_clear (string *s)
04625 {
04626   s->p = s->b;
04627 }
04628 
04629 #if 0
04630 
04631 static int
04632 string_empty (string *s)
04633 {
04634   return (s->b == s->p);
04635 }
04636 
04637 #endif
04638 
04639 static void
04640 string_append (string *p, const char *s)
04641 {
04642   int n;
04643   if (s == NULL || *s == '\0')
04644     return;
04645   n = strlen (s);
04646   string_need (p, n);
04647   memcpy (p->p, s, n);
04648   p->p += n;
04649 }
04650 
04651 static void
04652 string_appends (string *p, string *s)
04653 {
04654   int n;
04655 
04656   if (s->b != s->p)
04657     {
04658       n = s->p - s->b;
04659       string_need (p, n);
04660       memcpy (p->p, s->b, n);
04661       p->p += n;
04662     }
04663 }
04664 
04665 static void
04666 string_appendn (string *p, const char *s, int n)
04667 {
04668   if (n != 0)
04669     {
04670       string_need (p, n);
04671       memcpy (p->p, s, n);
04672       p->p += n;
04673     }
04674 }
04675 
04676 static void
04677 string_prepend (string *p, const char *s)
04678 {
04679   if (s != NULL && *s != '\0')
04680     {
04681       string_prependn (p, s, strlen (s));
04682     }
04683 }
04684 
04685 static void
04686 string_prepends (string *p, string *s)
04687 {
04688   if (s->b != s->p)
04689     {
04690       string_prependn (p, s->b, s->p - s->b);
04691     }
04692 }
04693 
04694 static void
04695 string_prependn (string *p, const char *s, int n)
04696 {
04697   char *q;
04698 
04699   if (n != 0)
04700     {
04701       string_need (p, n);
04702       for (q = p->p - 1; q >= p->b; q--)
04703        {
04704          q[n] = q[0];
04705        }
04706       memcpy (p->b, s, n);
04707       p->p += n;
04708     }
04709 }
04710 
04711 static void
04712 string_append_template_idx (string *s, int idx)
04713 {
04714   char buf[INTBUF_SIZE + 1 /* 'T' */];
04715   sprintf(buf, "T%d", idx);
04716   string_append (s, buf);
04717 }