"Fossies" - the Fresh Open Source Software Archive

Member "mpr-2.8/demangle/cp-demangle.c" (3 May 2003, 124720 Bytes) of package /linux/misc/old/mpr-2.8.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* Demangler for IA64 / g++ V3 ABI.
    2    Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
    3    Written by Alex Samuel <samuel@codesourcery.com>. 
    4 
    5    This file is part of GNU CC.
    6 
    7    This program is free software; you can redistribute it and/or modify
    8    it under the terms of the GNU General Public License as published by
    9    the Free Software Foundation; either version 2 of the License, or
   10    (at your option) any later version.
   11 
   12    In addition to the permissions in the GNU General Public License, the
   13    Free Software Foundation gives you unlimited permission to link the
   14    compiled version of this file into combinations with other programs,
   15    and to distribute those combinations without any restriction coming
   16    from the use of this file.  (The General Public License restrictions
   17    do apply in other respects; for example, they cover modification of
   18    the file, and distribution when not linked into a combined
   19    executable.)
   20 
   21    This program is distributed in the hope that it will be useful,
   22    but WITHOUT ANY WARRANTY; without even the implied warranty of
   23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24    GNU General Public License for more details.
   25 
   26    You should have received a copy of the GNU General Public License
   27    along with this program; if not, write to the Free Software
   28    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
   29 */
   30 
   31 /* This file implements demangling of C++ names mangled according to
   32    the IA64 / g++ V3 ABI.  Use the cp_demangle function to
   33    demangle a mangled name, or compile with the preprocessor macro
   34    STANDALONE_DEMANGLER defined to create a demangling filter
   35    executable (functionally similar to c++filt, but includes this
   36    demangler only).  */
   37 
   38 #ifdef HAVE_CONFIG_H
   39 #include "config.h"
   40 #endif
   41 
   42 #include <sys/types.h>
   43 
   44 #ifdef HAVE_STDLIB_H
   45 #include <stdlib.h>
   46 #endif
   47 
   48 #include <stdio.h>
   49 
   50 #ifdef HAVE_STRING_H
   51 #include <string.h>
   52 #endif
   53 
   54 #include <ctype.h>
   55 
   56 #include "ansidecl.h"
   57 #include "libiberty.h"
   58 #include "dyn-string.h"
   59 #include "demangle.h"
   60 
   61 /* If CP_DEMANGLE_DEBUG is defined, a trace of the grammar evaluation,
   62    and other debugging output, will be generated. */
   63 #ifdef CP_DEMANGLE_DEBUG
   64 #define DEMANGLE_TRACE(PRODUCTION, DM)                                  \
   65   fprintf (stderr, " -> %-24s at position %3d\n",                       \
   66            (PRODUCTION), current_position (DM));
   67 #else
   68 #define DEMANGLE_TRACE(PRODUCTION, DM)
   69 #endif
   70 
   71 /* Don't include <ctype.h>, to prevent additional unresolved symbols
   72    from being dragged into the C++ runtime library.  */
   73 #define IS_DIGIT(CHAR) ((CHAR) >= '0' && (CHAR) <= '9')
   74 #define IS_ALPHA(CHAR)                                                  \
   75   (((CHAR) >= 'a' && (CHAR) <= 'z')                                     \
   76    || ((CHAR) >= 'A' && (CHAR) <= 'Z'))
   77 
   78 /* The prefix prepended by GCC to an identifier represnting the
   79    anonymous namespace.  */
   80 #define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
   81 
   82 /* Character(s) to use for namespace separation in demangled output */
   83 #define NAMESPACE_SEPARATOR (dm->style == DMGL_JAVA ? "." : "::")
   84 
   85 /* If flag_verbose is zero, some simplifications will be made to the
   86    output to make it easier to read and supress details that are
   87    generally not of interest to the average C++ programmer.
   88    Otherwise, the demangled representation will attempt to convey as
   89    much information as the mangled form.  */
   90 static int flag_verbose;
   91 
   92 /* If flag_strict is non-zero, demangle strictly according to the
   93    specification -- don't demangle special g++ manglings.  */
   94 static int flag_strict;
   95 
   96 /* String_list_t is an extended form of dyn_string_t which provides a
   97    link field and a caret position for additions to the string.  A
   98    string_list_t may safely be cast to and used as a dyn_string_t.  */
   99 
  100 struct string_list_def
  101 {
  102   /* The dyn_string; must be first.  */
  103   struct dyn_string string;
  104 
  105   /* The position at which additional text is added to this string
  106      (using the result_add* macros).  This value is an offset from the
  107      end of the string, not the beginning (and should be
  108      non-positive).  */
  109   int caret_position;
  110 
  111   /* The next string in the list.  */
  112   struct string_list_def *next;
  113 };
  114 
  115 typedef struct string_list_def *string_list_t;
  116 
  117 /* Data structure representing a potential substitution.  */
  118 
  119 struct substitution_def
  120 {
  121   /* The demangled text of the substitution.  */
  122   dyn_string_t text;
  123 
  124   /* Whether this substitution represents a template item.  */
  125   int template_p : 1;
  126 };
  127 
  128 /* Data structure representing a template argument list.  */
  129 
  130 struct template_arg_list_def
  131 {
  132   /* The next (lower) template argument list in the stack of currently
  133      active template arguments.  */
  134   struct template_arg_list_def *next;
  135 
  136   /* The first element in the list of template arguments in
  137      left-to-right order.  */
  138   string_list_t first_argument;
  139 
  140   /* The last element in the arguments lists.  */
  141   string_list_t last_argument;
  142 };
  143 
  144 typedef struct template_arg_list_def *template_arg_list_t;
  145 
  146 /* Data structure to maintain the state of the current demangling.  */
  147 
  148 struct demangling_def
  149 {
  150   /* The full mangled name being mangled.  */
  151   const char *name;
  152 
  153   /* Pointer into name at the current position.  */
  154   const char *next;
  155 
  156   /* Stack for strings containing demangled result generated so far.
  157      Text is emitted to the topmost (first) string.  */
  158   string_list_t result;
  159 
  160   /* The number of presently available substitutions.  */
  161   int num_substitutions;
  162 
  163   /* The allocated size of the substitutions array.  */
  164   int substitutions_allocated;
  165 
  166   /* An array of available substitutions.  The number of elements in
  167      the array is given by num_substitions, and the allocated array
  168      size in substitutions_size.  
  169 
  170      The most recent substition is at the end, so
  171 
  172        - `S_'  corresponds to substititutions[num_substitutions - 1] 
  173        - `S0_' corresponds to substititutions[num_substitutions - 2]
  174 
  175      etc. */
  176   struct substitution_def *substitutions;
  177 
  178   /* The stack of template argument lists.  */
  179   template_arg_list_t template_arg_lists;
  180 
  181   /* The most recently demangled source-name.  */
  182   dyn_string_t last_source_name;
  183   
  184   /* Language style to use for demangled output. */
  185   int style;
  186 
  187   /* Set to non-zero iff this name is a constructor.  The actual value
  188      indicates what sort of constructor this is; see demangle.h.  */
  189   enum gnu_v3_ctor_kinds is_constructor;
  190 
  191   /* Set to non-zero iff this name is a destructor.  The actual value
  192      indicates what sort of destructor this is; see demangle.h.  */
  193   enum gnu_v3_dtor_kinds is_destructor;
  194 
  195 };
  196 
  197 typedef struct demangling_def *demangling_t;
  198 
  199 /* This type is the standard return code from most functions.  Values
  200    other than STATUS_OK contain descriptive messages.  */
  201 typedef const char *status_t;
  202 
  203 /* Special values that can be used as a status_t.  */
  204 #define STATUS_OK                       NULL
  205 #define STATUS_ERROR                    "Error."
  206 #define STATUS_UNIMPLEMENTED            "Unimplemented."
  207 #define STATUS_INTERNAL_ERROR           "Internal error."
  208 
  209 /* This status code indicates a failure in malloc or realloc.  */
  210 static const char *const status_allocation_failed = "Allocation failed.";
  211 #define STATUS_ALLOCATION_FAILED        status_allocation_failed
  212 
  213 /* Non-zero if STATUS indicates that no error has occurred.  */
  214 #define STATUS_NO_ERROR(STATUS)         ((STATUS) == STATUS_OK)
  215 
  216 /* Evaluate EXPR, which must produce a status_t.  If the status code
  217    indicates an error, return from the current function with that
  218    status code.  */
  219 #define RETURN_IF_ERROR(EXPR)                                           \
  220   do                                                                    \
  221     {                                                                   \
  222       status_t s = EXPR;                                                \
  223       if (!STATUS_NO_ERROR (s))                                         \
  224     return s;                                                       \
  225     }                                                                   \
  226   while (0)
  227 
  228 static status_t int_to_dyn_string 
  229   PARAMS ((int, dyn_string_t));
  230 static string_list_t string_list_new
  231   PARAMS ((int));
  232 static void string_list_delete
  233   PARAMS ((string_list_t));
  234 static status_t result_add_separated_char
  235   PARAMS ((demangling_t, int));
  236 static status_t result_push
  237   PARAMS ((demangling_t));
  238 static string_list_t result_pop
  239   PARAMS ((demangling_t));
  240 static int substitution_start
  241   PARAMS ((demangling_t));
  242 static status_t substitution_add
  243   PARAMS ((demangling_t, int, int));
  244 static dyn_string_t substitution_get
  245   PARAMS ((demangling_t, int, int *));
  246 #ifdef CP_DEMANGLE_DEBUG
  247 static void substitutions_print 
  248   PARAMS ((demangling_t, FILE *));
  249 #endif
  250 static template_arg_list_t template_arg_list_new
  251   PARAMS ((void));
  252 static void template_arg_list_delete
  253   PARAMS ((template_arg_list_t));
  254 static void template_arg_list_add_arg 
  255   PARAMS ((template_arg_list_t, string_list_t));
  256 static string_list_t template_arg_list_get_arg
  257   PARAMS ((template_arg_list_t, int));
  258 static void push_template_arg_list
  259   PARAMS ((demangling_t, template_arg_list_t));
  260 static void pop_to_template_arg_list
  261   PARAMS ((demangling_t, template_arg_list_t));
  262 #ifdef CP_DEMANGLE_DEBUG
  263 static void template_arg_list_print
  264   PARAMS ((template_arg_list_t, FILE *));
  265 #endif
  266 static template_arg_list_t current_template_arg_list
  267   PARAMS ((demangling_t));
  268 static demangling_t demangling_new
  269   PARAMS ((const char *, int));
  270 static void demangling_delete 
  271   PARAMS ((demangling_t));
  272 
  273 /* The last character of DS.  Warning: DS is evaluated twice.  */
  274 #define dyn_string_last_char(DS)                                        \
  275   (dyn_string_buf (DS)[dyn_string_length (DS) - 1])
  276 
  277 /* Append a space character (` ') to DS if it does not already end
  278    with one.  Evaluates to 1 on success, or 0 on allocation failure.  */
  279 #define dyn_string_append_space(DS)                                     \
  280       ((dyn_string_length (DS) > 0                                      \
  281         && dyn_string_last_char (DS) != ' ')                            \
  282        ? dyn_string_append_char ((DS), ' ')                             \
  283        : 1)
  284 
  285 /* Returns the index of the current position in the mangled name.  */
  286 #define current_position(DM)    ((DM)->next - (DM)->name)
  287 
  288 /* Returns the character at the current position of the mangled name.  */
  289 #define peek_char(DM)           (*((DM)->next))
  290 
  291 /* Returns the character one past the current position of the mangled
  292    name.  */
  293 #define peek_char_next(DM)                                              \
  294   (peek_char (DM) == '\0' ? '\0' : (*((DM)->next + 1)))
  295 
  296 /* Returns the character at the current position, and advances the
  297    current position to the next character.  */
  298 #define next_char(DM)           (*((DM)->next)++)
  299 
  300 /* Returns non-zero if the current position is the end of the mangled
  301    name, i.e. one past the last character.  */
  302 #define end_of_name_p(DM)       (peek_char (DM) == '\0')
  303 
  304 /* Advances the current position by one character.  */
  305 #define advance_char(DM)        (++(DM)->next)
  306 
  307 /* Returns the string containing the current demangled result.  */
  308 #define result_string(DM)       (&(DM)->result->string)
  309 
  310 /* Returns the position at which new text is inserted into the
  311    demangled result.  */
  312 #define result_caret_pos(DM)                                            \
  313   (result_length (DM) +                                                 \
  314    ((string_list_t) result_string (DM))->caret_position)
  315 
  316 /* Adds a dyn_string_t to the demangled result.  */
  317 #define result_add_string(DM, STRING)                                   \
  318   (dyn_string_insert (&(DM)->result->string,                            \
  319               result_caret_pos (DM), (STRING))                  \
  320    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
  321 
  322 /* Adds NUL-terminated string CSTR to the demangled result.    */
  323 #define result_add(DM, CSTR)                                            \
  324   (dyn_string_insert_cstr (&(DM)->result->string,                       \
  325                result_caret_pos (DM), (CSTR))               \
  326    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
  327 
  328 /* Adds character CHAR to the demangled result.  */
  329 #define result_add_char(DM, CHAR)                                       \
  330   (dyn_string_insert_char (&(DM)->result->string,                       \
  331                result_caret_pos (DM), (CHAR))               \
  332    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
  333 
  334 /* Inserts a dyn_string_t to the demangled result at position POS.  */
  335 #define result_insert_string(DM, POS, STRING)                           \
  336   (dyn_string_insert (&(DM)->result->string, (POS), (STRING))           \
  337    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
  338 
  339 /* Inserts NUL-terminated string CSTR to the demangled result at
  340    position POS.  */
  341 #define result_insert(DM, POS, CSTR)                                    \
  342   (dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR))        \
  343    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
  344 
  345 /* Inserts character CHAR to the demangled result at position POS.  */
  346 #define result_insert_char(DM, POS, CHAR)                               \
  347   (dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR))        \
  348    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
  349 
  350 /* The length of the current demangled result.  */
  351 #define result_length(DM)                                               \
  352   dyn_string_length (&(DM)->result->string)
  353 
  354 /* Appends a (less-than, greater-than) character to the result in DM
  355    to (open, close) a template argument or parameter list.  Appends a
  356    space first if necessary to prevent spurious elision of angle
  357    brackets with the previous character.  */
  358 #define result_open_template_list(DM) result_add_separated_char(DM, '<')
  359 #define result_close_template_list(DM) result_add_separated_char(DM, '>')
  360 
  361 /* Appends a base 10 representation of VALUE to DS.  STATUS_OK on
  362    success.  On failure, deletes DS and returns an error code.  */
  363 
  364 static status_t
  365 int_to_dyn_string (value, ds)
  366      int value;
  367      dyn_string_t ds;
  368 {
  369   int i;
  370   int mask = 1;
  371 
  372   /* Handle zero up front.  */
  373   if (value == 0)
  374     {
  375       if (!dyn_string_append_char (ds, '0'))
  376     return STATUS_ALLOCATION_FAILED;
  377       return STATUS_OK;
  378     }
  379 
  380   /* For negative numbers, emit a minus sign.  */
  381   if (value < 0)
  382     {
  383       if (!dyn_string_append_char (ds, '-'))
  384     return STATUS_ALLOCATION_FAILED;
  385       value = -value;
  386     }
  387   
  388   /* Find the power of 10 of the first digit.  */
  389   i = value;
  390   while (i > 9)
  391     {
  392       mask *= 10;
  393       i /= 10;
  394     }
  395 
  396   /* Write the digits.  */
  397   while (mask > 0)
  398     {
  399       int digit = value / mask;
  400 
  401       if (!dyn_string_append_char (ds, '0' + digit))
  402     return STATUS_ALLOCATION_FAILED;
  403 
  404       value -= digit * mask;
  405       mask /= 10;
  406     }
  407 
  408   return STATUS_OK;
  409 }
  410 
  411 /* Creates a new string list node.  The contents of the string are
  412    empty, but the initial buffer allocation is LENGTH.  The string
  413    list node should be deleted with string_list_delete.  Returns NULL
  414    if allocation fails.  */
  415 
  416 static string_list_t 
  417 string_list_new (length)
  418      int length;
  419 {
  420   string_list_t s = (string_list_t) malloc (sizeof (struct string_list_def));
  421   s->caret_position = 0;
  422   if (s == NULL)
  423     return NULL;
  424   if (!dyn_string_init ((dyn_string_t) s, length))
  425     return NULL;
  426   return s;
  427 }  
  428 
  429 /* Deletes the entire string list starting at NODE.  */
  430 
  431 static void
  432 string_list_delete (node)
  433      string_list_t node;
  434 {
  435   while (node != NULL)
  436     {
  437       string_list_t next = node->next;
  438       dyn_string_delete ((dyn_string_t) node);
  439       node = next;
  440     }
  441 }
  442 
  443 /* Appends CHARACTER to the demangled result.  If the current trailing
  444    character of the result is CHARACTER, a space is inserted first.  */
  445 
  446 static status_t
  447 result_add_separated_char (dm, character)
  448      demangling_t dm;
  449      int character;
  450 {
  451   char *result = dyn_string_buf (result_string (dm));
  452   int caret_pos = result_caret_pos (dm);
  453 
  454   /* Add a space if the last character is already the character we
  455      want to add.  */
  456   if (caret_pos > 0 && result[caret_pos - 1] == character)
  457     RETURN_IF_ERROR (result_add_char (dm, ' '));
  458   /* Add the character.  */
  459   RETURN_IF_ERROR (result_add_char (dm, character));
  460 
  461   return STATUS_OK;
  462 }
  463 
  464 /* Allocates and pushes a new string onto the demangled results stack
  465    for DM.  Subsequent demangling with DM will emit to the new string.
  466    Returns STATUS_OK on success, STATUS_ALLOCATION_FAILED on
  467    allocation failure.  */
  468 
  469 static status_t
  470 result_push (dm)
  471      demangling_t dm;
  472 {
  473   string_list_t new_string = string_list_new (0);
  474   if (new_string == NULL)
  475     /* Allocation failed.  */
  476     return STATUS_ALLOCATION_FAILED;
  477 
  478   /* Link the new string to the front of the list of result strings.  */
  479   new_string->next = (string_list_t) dm->result;
  480   dm->result = new_string;
  481   return STATUS_OK;
  482 }
  483 
  484 /* Removes and returns the topmost element on the demangled results
  485    stack for DM.  The caller assumes ownership for the returned
  486    string.  */
  487 
  488 static string_list_t
  489 result_pop (dm)
  490      demangling_t dm;
  491 {
  492   string_list_t top = dm->result;
  493   dm->result = top->next;
  494   return top;
  495 }
  496 
  497 /* Returns the current value of the caret for the result string.  The
  498    value is an offet from the end of the result string.  */
  499 
  500 static int
  501 result_get_caret (dm)
  502      demangling_t dm;
  503 {
  504   return ((string_list_t) result_string (dm))->caret_position;
  505 }
  506 
  507 /* Sets the value of the caret for the result string, counted as an
  508    offet from the end of the result string.  */
  509 
  510 static void
  511 result_set_caret (dm, position)
  512      demangling_t dm;
  513      int position;
  514 {
  515   ((string_list_t) result_string (dm))->caret_position = position;
  516 }
  517 
  518 /* Shifts the position of the next addition to the result by
  519    POSITION_OFFSET.  A negative value shifts the caret to the left.  */
  520 
  521 static void
  522 result_shift_caret (dm, position_offset)
  523      demangling_t dm;
  524      int position_offset;
  525 {
  526   ((string_list_t) result_string (dm))->caret_position += position_offset;
  527 }
  528 
  529 /* Returns non-zero if the character that comes right before the place
  530    where text will be added to the result is a space.  In this case,
  531    the caller should supress adding another space.  */
  532 
  533 static int
  534 result_previous_char_is_space (dm)
  535      demangling_t dm;
  536 {
  537   char *result = dyn_string_buf (result_string (dm));
  538   int pos = result_caret_pos (dm);
  539   return pos > 0 && result[pos - 1] == ' ';
  540 }
  541 
  542 /* Returns the start position of a fragment of the demangled result
  543    that will be a substitution candidate.  Should be called at the
  544    start of productions that can add substitutions.  */
  545 
  546 static int
  547 substitution_start (dm)
  548      demangling_t dm;
  549 {
  550   return result_caret_pos (dm);
  551 }
  552 
  553 /* Adds the suffix of the current demangled result of DM starting at
  554    START_POSITION as a potential substitution.  If TEMPLATE_P is
  555    non-zero, this potential substitution is a template-id.  */
  556 
  557 static status_t
  558 substitution_add (dm, start_position, template_p)
  559      demangling_t dm;
  560      int start_position;
  561      int template_p;
  562 {
  563   dyn_string_t result = result_string (dm);
  564   dyn_string_t substitution = dyn_string_new (0);
  565   int i;
  566 
  567   if (substitution == NULL)
  568     return STATUS_ALLOCATION_FAILED;
  569 
  570   /* Extract the substring of the current demangling result that
  571      represents the subsitution candidate.  */
  572   if (!dyn_string_substring (substitution, 
  573                  result, start_position, result_caret_pos (dm)))
  574     {
  575       dyn_string_delete (substitution);
  576       return STATUS_ALLOCATION_FAILED;
  577     }
  578 
  579   /* If there's no room for the new entry, grow the array.  */
  580   if (dm->substitutions_allocated == dm->num_substitutions)
  581     {
  582       size_t new_array_size;
  583       if (dm->substitutions_allocated > 0)
  584     dm->substitutions_allocated *= 2;
  585       else
  586     dm->substitutions_allocated = 2;
  587       new_array_size = 
  588     sizeof (struct substitution_def) * dm->substitutions_allocated;
  589 
  590       dm->substitutions = (struct substitution_def *)
  591     realloc (dm->substitutions, new_array_size);
  592       if (dm->substitutions == NULL)
  593     /* Realloc failed.  */
  594     {
  595       dyn_string_delete (substitution);
  596       return STATUS_ALLOCATION_FAILED;
  597     }
  598     }
  599 
  600   /* Add the substitution to the array.  */
  601   i = dm->num_substitutions++;
  602   dm->substitutions[i].text = substitution;
  603   dm->substitutions[i].template_p = template_p;
  604 
  605 #ifdef CP_DEMANGLE_DEBUG
  606   substitutions_print (dm, stderr);
  607 #endif
  608 
  609   return STATUS_OK;
  610 }
  611 
  612 /* Returns the Nth-most-recent substitution.  Sets *TEMPLATE_P to
  613    non-zero if the substitution is a template-id, zero otherwise.  
  614    N is numbered from zero.  DM retains ownership of the returned
  615    string.  If N is negative, or equal to or greater than the current
  616    number of substitution candidates, returns NULL.  */
  617 
  618 static dyn_string_t
  619 substitution_get (dm, n, template_p)
  620      demangling_t dm;
  621      int n;
  622      int *template_p;
  623 {
  624   struct substitution_def *sub;
  625 
  626   /* Make sure N is in the valid range.  */
  627   if (n < 0 || n >= dm->num_substitutions)
  628     return NULL;
  629 
  630   sub = &(dm->substitutions[n]);
  631   *template_p = sub->template_p;
  632   return sub->text;
  633 }
  634 
  635 #ifdef CP_DEMANGLE_DEBUG
  636 /* Debugging routine to print the current substitutions to FP.  */
  637 
  638 static void
  639 substitutions_print (dm, fp)
  640      demangling_t dm;
  641      FILE *fp;
  642 {
  643   int seq_id;
  644   int num = dm->num_substitutions;
  645 
  646   fprintf (fp, "SUBSTITUTIONS:\n");
  647   for (seq_id = -1; seq_id < num - 1; ++seq_id)
  648     {
  649       int template_p;
  650       dyn_string_t text = substitution_get (dm, seq_id + 1, &template_p);
  651 
  652       if (seq_id == -1)
  653     fprintf (fp, " S_ ");
  654       else
  655     fprintf (fp, " S%d_", seq_id);
  656       fprintf (fp, " %c: %s\n", template_p ? '*' : ' ', dyn_string_buf (text));
  657     }
  658 }
  659 
  660 #endif /* CP_DEMANGLE_DEBUG */
  661 
  662 /* Creates a new template argument list.  Returns NULL if allocation
  663    fails.  */
  664 
  665 static template_arg_list_t
  666 template_arg_list_new ()
  667 {
  668   template_arg_list_t new_list =
  669     (template_arg_list_t) malloc (sizeof (struct template_arg_list_def));
  670   if (new_list == NULL)
  671     return NULL;
  672   /* Initialize the new list to have no arguments.  */
  673   new_list->first_argument = NULL;
  674   new_list->last_argument = NULL;
  675   /* Return the new list.  */
  676   return new_list;
  677 }
  678 
  679 /* Deletes a template argument list and the template arguments it
  680    contains.  */
  681 
  682 static void
  683 template_arg_list_delete (list)
  684      template_arg_list_t list;
  685 {
  686   /* If there are any arguments on LIST, delete them.  */
  687   if (list->first_argument != NULL)
  688     string_list_delete (list->first_argument);
  689   /* Delete LIST.  */
  690   free (list);
  691 }
  692 
  693 /* Adds ARG to the template argument list ARG_LIST.  */
  694 
  695 static void 
  696 template_arg_list_add_arg (arg_list, arg)
  697      template_arg_list_t arg_list;
  698      string_list_t arg;
  699 {
  700   if (arg_list->first_argument == NULL)
  701     /* If there were no arguments before, ARG is the first one.  */
  702     arg_list->first_argument = arg;
  703   else
  704     /* Make ARG the last argument on the list.  */
  705     arg_list->last_argument->next = arg;
  706   /* Make ARG the last on the list.  */
  707   arg_list->last_argument = arg;
  708   arg->next = NULL;
  709 }
  710 
  711 /* Returns the template arugment at position INDEX in template
  712    argument list ARG_LIST.  */
  713 
  714 static string_list_t
  715 template_arg_list_get_arg (arg_list, index)
  716      template_arg_list_t arg_list;
  717      int index;
  718 {
  719   string_list_t arg = arg_list->first_argument;
  720   /* Scan down the list of arguments to find the one at position
  721      INDEX.  */
  722   while (index--)
  723     {
  724       arg = arg->next;
  725       if (arg == NULL)
  726     /* Ran out of arguments before INDEX hit zero.  That's an
  727        error.  */
  728     return NULL;
  729     }
  730   /* Return the argument at position INDEX.  */
  731   return arg;
  732 }
  733 
  734 /* Pushes ARG_LIST onto the top of the template argument list stack.  */
  735 
  736 static void
  737 push_template_arg_list (dm, arg_list)
  738      demangling_t dm;
  739      template_arg_list_t arg_list;
  740 {
  741   arg_list->next = dm->template_arg_lists;
  742   dm->template_arg_lists = arg_list;
  743 #ifdef CP_DEMANGLE_DEBUG
  744   fprintf (stderr, " ** pushing template arg list\n");
  745   template_arg_list_print (arg_list, stderr);
  746 #endif 
  747 }
  748 
  749 /* Pops and deletes elements on the template argument list stack until
  750    arg_list is the topmost element.  If arg_list is NULL, all elements
  751    are popped and deleted.  */
  752 
  753 static void
  754 pop_to_template_arg_list (dm, arg_list)
  755      demangling_t dm;
  756      template_arg_list_t arg_list;
  757 {
  758   while (dm->template_arg_lists != arg_list)
  759     {
  760       template_arg_list_t top = dm->template_arg_lists;
  761       /* Disconnect the topmost element from the list.  */
  762       dm->template_arg_lists = top->next;
  763       /* Delete the popped element.  */
  764       template_arg_list_delete (top);
  765 #ifdef CP_DEMANGLE_DEBUG
  766       fprintf (stderr, " ** removing template arg list\n");
  767 #endif
  768     }
  769 }
  770 
  771 #ifdef CP_DEMANGLE_DEBUG
  772 
  773 /* Prints the contents of ARG_LIST to FP.  */
  774 
  775 static void
  776 template_arg_list_print (arg_list, fp)
  777   template_arg_list_t arg_list;
  778   FILE *fp;
  779 {
  780   string_list_t arg;
  781   int index = -1;
  782 
  783   fprintf (fp, "TEMPLATE ARGUMENT LIST:\n");
  784   for (arg = arg_list->first_argument; arg != NULL; arg = arg->next)
  785     {
  786       if (index == -1)
  787     fprintf (fp, " T_  : ");
  788       else
  789     fprintf (fp, " T%d_ : ", index);
  790       ++index;
  791       fprintf (fp, "%s\n", dyn_string_buf ((dyn_string_t) arg));
  792     }
  793 }
  794 
  795 #endif /* CP_DEMANGLE_DEBUG */
  796 
  797 /* Returns the topmost element on the stack of template argument
  798    lists.  If there is no list of template arguments, returns NULL.  */
  799 
  800 static template_arg_list_t
  801 current_template_arg_list (dm)
  802      demangling_t dm;
  803 {
  804   return dm->template_arg_lists;
  805 }
  806 
  807 /* Allocates a demangling_t object for demangling mangled NAME.  A new
  808    result must be pushed before the returned object can be used.
  809    Returns NULL if allocation fails.  */
  810 
  811 static demangling_t
  812 demangling_new (name, style)
  813      const char *name;
  814      int style;
  815 {
  816   demangling_t dm;
  817   dm = (demangling_t) malloc (sizeof (struct demangling_def));
  818   if (dm == NULL)
  819     return NULL;
  820 
  821   dm->name = name;
  822   dm->next = name;
  823   dm->result = NULL;
  824   dm->num_substitutions = 0;
  825   dm->substitutions_allocated = 10;
  826   dm->template_arg_lists = NULL;
  827   dm->last_source_name = dyn_string_new (0);
  828   if (dm->last_source_name == NULL)
  829     return NULL;
  830   dm->substitutions = (struct substitution_def *)
  831     malloc (dm->substitutions_allocated * sizeof (struct substitution_def));
  832   if (dm->substitutions == NULL)
  833     {
  834       dyn_string_delete (dm->last_source_name);
  835       return NULL;
  836     }
  837   dm->style = style;
  838   dm->is_constructor = (enum gnu_v3_ctor_kinds) 0;
  839   dm->is_destructor = (enum gnu_v3_dtor_kinds) 0;
  840 
  841   return dm;
  842 }
  843 
  844 /* Deallocates a demangling_t object and all memory associated with
  845    it.  */
  846 
  847 static void
  848 demangling_delete (dm)
  849      demangling_t dm;
  850 {
  851   int i;
  852   template_arg_list_t arg_list = dm->template_arg_lists;
  853 
  854   /* Delete the stack of template argument lists.  */
  855   while (arg_list != NULL)
  856     {
  857       template_arg_list_t next = arg_list->next;
  858       template_arg_list_delete (arg_list);
  859       arg_list = next;
  860     }
  861   /* Delete the list of substitutions.  */
  862   for (i = dm->num_substitutions; --i >= 0; )
  863     dyn_string_delete (dm->substitutions[i].text);
  864   free (dm->substitutions);
  865   /* Delete the demangled result.  */
  866   string_list_delete (dm->result);
  867   /* Delete the stored identifier name.  */
  868   dyn_string_delete (dm->last_source_name);
  869   /* Delete the context object itself.  */
  870   free (dm);
  871 }
  872 
  873 /* These functions demangle an alternative of the corresponding
  874    production in the mangling spec.  The first argument of each is a
  875    demangling context structure for the current demangling
  876    operation.  Most emit demangled text directly to the topmost result
  877    string on the result string stack in the demangling context
  878    structure.  */
  879 
  880 static status_t demangle_char
  881   PARAMS ((demangling_t, int));
  882 static status_t demangle_mangled_name 
  883   PARAMS ((demangling_t));
  884 static status_t demangle_encoding
  885   PARAMS ((demangling_t));
  886 static status_t demangle_name
  887   PARAMS ((demangling_t, int *));
  888 static status_t demangle_nested_name
  889   PARAMS ((demangling_t, int *));
  890 static status_t demangle_prefix
  891   PARAMS ((demangling_t, int *));
  892 static status_t demangle_unqualified_name
  893   PARAMS ((demangling_t, int *));
  894 static status_t demangle_source_name
  895   PARAMS ((demangling_t));
  896 static status_t demangle_number
  897   PARAMS ((demangling_t, int *, int, int));
  898 static status_t demangle_number_literally
  899   PARAMS ((demangling_t, dyn_string_t, int, int));
  900 static status_t demangle_identifier
  901   PARAMS ((demangling_t, int, dyn_string_t));
  902 static status_t demangle_operator_name
  903   PARAMS ((demangling_t, int, int *, int *));
  904 static status_t demangle_nv_offset
  905   PARAMS ((demangling_t));
  906 static status_t demangle_v_offset
  907   PARAMS ((demangling_t));
  908 static status_t demangle_call_offset
  909   PARAMS ((demangling_t));
  910 static status_t demangle_special_name
  911   PARAMS ((demangling_t));
  912 static status_t demangle_ctor_dtor_name
  913   PARAMS ((demangling_t));
  914 static status_t demangle_type_ptr
  915   PARAMS ((demangling_t, int *, int));
  916 static status_t demangle_type
  917   PARAMS ((demangling_t));
  918 static status_t demangle_CV_qualifiers
  919   PARAMS ((demangling_t, dyn_string_t));
  920 static status_t demangle_builtin_type
  921   PARAMS ((demangling_t));
  922 static status_t demangle_function_type
  923   PARAMS ((demangling_t, int *));
  924 static status_t demangle_bare_function_type
  925   PARAMS ((demangling_t, int *));
  926 static status_t demangle_class_enum_type
  927   PARAMS ((demangling_t, int *));
  928 static status_t demangle_array_type
  929   PARAMS ((demangling_t, int *));
  930 static status_t demangle_template_param
  931   PARAMS ((demangling_t));
  932 static status_t demangle_template_args
  933   PARAMS ((demangling_t));
  934 static status_t demangle_literal
  935   PARAMS ((demangling_t));
  936 static status_t demangle_template_arg
  937   PARAMS ((demangling_t));
  938 static status_t demangle_expression
  939   PARAMS ((demangling_t));
  940 static status_t demangle_scope_expression
  941   PARAMS ((demangling_t));
  942 static status_t demangle_expr_primary
  943   PARAMS ((demangling_t));
  944 static status_t demangle_substitution
  945   PARAMS ((demangling_t, int *));
  946 static status_t demangle_local_name
  947   PARAMS ((demangling_t));
  948 static status_t demangle_discriminator 
  949   PARAMS ((demangling_t, int));
  950 static status_t cp_demangle
  951   PARAMS ((const char *, dyn_string_t, int));
  952 static status_t cp_demangle_type
  953   PARAMS ((const char*, dyn_string_t));
  954 
  955 /* When passed to demangle_bare_function_type, indicates that the
  956    function's return type is not encoded before its parameter types.  */
  957 #define BFT_NO_RETURN_TYPE    NULL
  958 
  959 /* Check that the next character is C.  If so, consume it.  If not,
  960    return an error.  */
  961 
  962 static status_t
  963 demangle_char (dm, c)
  964      demangling_t dm;
  965      int c;
  966 {
  967   static char *error_message = NULL;
  968 
  969   if (peek_char (dm) == c)
  970     {
  971       advance_char (dm);
  972       return STATUS_OK;
  973     }
  974   else
  975     {
  976       if (error_message == NULL)
  977     error_message = (char *) strdup ("Expected ?");
  978       error_message[9] = c;
  979       return error_message;
  980     }
  981 }
  982 
  983 /* Demangles and emits a <mangled-name>.  
  984 
  985     <mangled-name>      ::= _Z <encoding>  */
  986 
  987 static status_t
  988 demangle_mangled_name (dm)
  989      demangling_t dm;
  990 {
  991   DEMANGLE_TRACE ("mangled-name", dm);
  992   RETURN_IF_ERROR (demangle_char (dm, '_'));
  993   RETURN_IF_ERROR (demangle_char (dm, 'Z'));
  994   RETURN_IF_ERROR (demangle_encoding (dm));
  995   return STATUS_OK;
  996 }
  997 
  998 /* Demangles and emits an <encoding>.  
  999 
 1000     <encoding>      ::= <function name> <bare-function-type>
 1001             ::= <data name>
 1002             ::= <special-name>  */
 1003 
 1004 static status_t
 1005 demangle_encoding (dm)
 1006      demangling_t dm;
 1007 {
 1008   int encode_return_type;
 1009   int start_position;
 1010   template_arg_list_t old_arg_list = current_template_arg_list (dm);
 1011   char peek = peek_char (dm);
 1012 
 1013   DEMANGLE_TRACE ("encoding", dm);
 1014   
 1015   /* Remember where the name starts.  If it turns out to be a template
 1016      function, we'll have to insert the return type here.  */
 1017   start_position = result_caret_pos (dm);
 1018 
 1019   if (peek == 'G' || peek == 'T')
 1020     RETURN_IF_ERROR (demangle_special_name (dm));
 1021   else
 1022     {
 1023       /* Now demangle the name.  */
 1024       RETURN_IF_ERROR (demangle_name (dm, &encode_return_type));
 1025 
 1026       /* If there's anything left, the name was a function name, with
 1027      maybe its return type, and its parameter types, following.  */
 1028       if (!end_of_name_p (dm) 
 1029       && peek_char (dm) != 'E')
 1030     {
 1031       if (encode_return_type)
 1032         /* Template functions have their return type encoded.  The
 1033            return type should be inserted at start_position.  */
 1034         RETURN_IF_ERROR 
 1035           (demangle_bare_function_type (dm, &start_position));
 1036       else
 1037         /* Non-template functions don't have their return type
 1038            encoded.  */
 1039         RETURN_IF_ERROR 
 1040           (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE)); 
 1041     }
 1042     }
 1043 
 1044   /* Pop off template argument lists that were built during the
 1045      mangling of this name, to restore the old template context.  */
 1046   pop_to_template_arg_list (dm, old_arg_list);
 1047 
 1048   return STATUS_OK;
 1049 }
 1050 
 1051 /* Demangles and emits a <name>.
 1052 
 1053     <name>              ::= <unscoped-name>
 1054                         ::= <unscoped-template-name> <template-args>
 1055             ::= <nested-name>
 1056                         ::= <local-name>
 1057 
 1058     <unscoped-name>     ::= <unqualified-name>
 1059             ::= St <unqualified-name>   # ::std::
 1060 
 1061     <unscoped-template-name>    
 1062                         ::= <unscoped-name>
 1063                         ::= <substitution>  */
 1064 
 1065 static status_t
 1066 demangle_name (dm, encode_return_type)
 1067      demangling_t dm;
 1068      int *encode_return_type;
 1069 {
 1070   int start = substitution_start (dm);
 1071   char peek = peek_char (dm);
 1072   int is_std_substitution = 0;
 1073 
 1074   /* Generally, the return type is encoded if the function is a
 1075      template-id, and suppressed otherwise.  There are a few cases,
 1076      though, in which the return type is not encoded even for a
 1077      templated function.  In these cases, this flag is set.  */
 1078   int suppress_return_type = 0;
 1079 
 1080   DEMANGLE_TRACE ("name", dm);
 1081 
 1082   switch (peek)
 1083     {
 1084     case 'N':
 1085       /* This is a <nested-name>.  */
 1086       RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type));
 1087       break;
 1088 
 1089     case 'Z':
 1090       RETURN_IF_ERROR (demangle_local_name (dm));
 1091       *encode_return_type = 0;
 1092       break;
 1093 
 1094     case 'S':
 1095       /* The `St' substitution allows a name nested in std:: to appear
 1096      without being enclosed in a nested name.  */
 1097       if (peek_char_next (dm) == 't') 
 1098     {
 1099       (void) next_char (dm);
 1100       (void) next_char (dm);
 1101       RETURN_IF_ERROR (result_add (dm, "std::"));
 1102       RETURN_IF_ERROR 
 1103         (demangle_unqualified_name (dm, &suppress_return_type));
 1104       is_std_substitution = 1;
 1105     }
 1106       else
 1107     RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
 1108       /* Check if a template argument list immediately follows.
 1109      If so, then we just demangled an <unqualified-template-name>.  */
 1110       if (peek_char (dm) == 'I') 
 1111     {
 1112       /* A template name of the form std::<unqualified-name> is a
 1113              substitution candidate.  */
 1114       if (is_std_substitution)
 1115         RETURN_IF_ERROR (substitution_add (dm, start, 0));
 1116       /* Demangle the <template-args> here.  */
 1117       RETURN_IF_ERROR (demangle_template_args (dm));
 1118       *encode_return_type = !suppress_return_type;
 1119     }
 1120       else
 1121     *encode_return_type = 0;
 1122 
 1123       break;
 1124 
 1125     default:
 1126       /* This is an <unscoped-name> or <unscoped-template-name>.  */
 1127       RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type));
 1128 
 1129       /* If the <unqualified-name> is followed by template args, this
 1130      is an <unscoped-template-name>.  */
 1131       if (peek_char (dm) == 'I')
 1132     {
 1133       /* Add a substitution for the unqualified template name.  */
 1134       RETURN_IF_ERROR (substitution_add (dm, start, 0));
 1135 
 1136       RETURN_IF_ERROR (demangle_template_args (dm));
 1137       *encode_return_type = !suppress_return_type;
 1138     }
 1139       else
 1140     *encode_return_type = 0;
 1141 
 1142       break;
 1143     }
 1144 
 1145   return STATUS_OK;
 1146 }
 1147 
 1148 /* Demangles and emits a <nested-name>. 
 1149 
 1150     <nested-name>     ::= N [<CV-qualifiers>] <prefix> <unqulified-name> E  */
 1151 
 1152 static status_t
 1153 demangle_nested_name (dm, encode_return_type)
 1154      demangling_t dm;
 1155      int *encode_return_type;
 1156 {
 1157   char peek;
 1158 
 1159   DEMANGLE_TRACE ("nested-name", dm);
 1160 
 1161   RETURN_IF_ERROR (demangle_char (dm, 'N'));
 1162 
 1163   peek = peek_char (dm);
 1164   if (peek == 'r' || peek == 'V' || peek == 'K')
 1165     {
 1166       dyn_string_t cv_qualifiers;
 1167       status_t status;
 1168 
 1169       /* Snarf up CV qualifiers.  */
 1170       cv_qualifiers = dyn_string_new (24);
 1171       if (cv_qualifiers == NULL)
 1172     return STATUS_ALLOCATION_FAILED;
 1173       demangle_CV_qualifiers (dm, cv_qualifiers);
 1174 
 1175       /* Emit them, preceded by a space.  */
 1176       status = result_add_char (dm, ' ');
 1177       if (STATUS_NO_ERROR (status)) 
 1178     status = result_add_string (dm, cv_qualifiers);
 1179       /* The CV qualifiers that occur in a <nested-name> will be
 1180      qualifiers for member functions.  These are placed at the end
 1181      of the function.  Therefore, shift the caret to the left by
 1182      the length of the qualifiers, so other text is inserted
 1183      before them and they stay at the end.  */
 1184       result_shift_caret (dm, -dyn_string_length (cv_qualifiers) - 1);
 1185       /* Clean up.  */
 1186       dyn_string_delete (cv_qualifiers);
 1187       RETURN_IF_ERROR (status);
 1188     }
 1189 
 1190   RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type));
 1191   /* No need to demangle the final <unqualified-name>; demangle_prefix
 1192      will handle it.  */
 1193   RETURN_IF_ERROR (demangle_char (dm, 'E'));
 1194 
 1195   return STATUS_OK;
 1196 }
 1197 
 1198 /* Demangles and emits a <prefix>.
 1199 
 1200     <prefix>            ::= <prefix> <unqualified-name>
 1201                         ::= <template-prefix> <template-args>
 1202             ::= # empty
 1203             ::= <substitution>
 1204 
 1205     <template-prefix>   ::= <prefix>
 1206                         ::= <substitution>  */
 1207 
 1208 static status_t
 1209 demangle_prefix (dm, encode_return_type)
 1210      demangling_t dm;
 1211      int *encode_return_type;
 1212 {
 1213   int start = substitution_start (dm);
 1214   int nested = 0;
 1215 
 1216   /* ENCODE_RETURN_TYPE is updated as we decend the nesting chain.
 1217      After <template-args>, it is set to non-zero; after everything
 1218      else it is set to zero.  */
 1219 
 1220   /* Generally, the return type is encoded if the function is a
 1221      template-id, and suppressed otherwise.  There are a few cases,
 1222      though, in which the return type is not encoded even for a
 1223      templated function.  In these cases, this flag is set.  */
 1224   int suppress_return_type = 0;
 1225 
 1226   DEMANGLE_TRACE ("prefix", dm);
 1227 
 1228   while (1)
 1229     {
 1230       char peek;
 1231 
 1232       if (end_of_name_p (dm))
 1233     return "Unexpected end of name in <compound-name>.";
 1234 
 1235       peek = peek_char (dm);
 1236       
 1237       /* We'll initialize suppress_return_type to false, and set it to true
 1238      if we end up demangling a constructor name.  However, make
 1239      sure we're not actually about to demangle template arguments
 1240      -- if so, this is the <template-args> following a
 1241      <template-prefix>, so we'll want the previous flag value
 1242      around.  */
 1243       if (peek != 'I')
 1244     suppress_return_type = 0;
 1245 
 1246       if (IS_DIGIT ((unsigned char) peek)
 1247       || (peek >= 'a' && peek <= 'z')
 1248       || peek == 'C' || peek == 'D'
 1249       || peek == 'S')
 1250     {
 1251       /* We have another level of scope qualification.  */
 1252       if (nested)
 1253         RETURN_IF_ERROR (result_add (dm, NAMESPACE_SEPARATOR));
 1254       else
 1255         nested = 1;
 1256 
 1257       if (peek == 'S')
 1258         /* The substitution determines whether this is a
 1259            template-id.  */
 1260         RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
 1261       else
 1262         {
 1263           /* It's just a name.  */
 1264           RETURN_IF_ERROR 
 1265         (demangle_unqualified_name (dm, &suppress_return_type));
 1266           *encode_return_type = 0;
 1267         }
 1268     }
 1269       else if (peek == 'Z')
 1270     RETURN_IF_ERROR (demangle_local_name (dm));
 1271       else if (peek == 'I')
 1272     {
 1273       RETURN_IF_ERROR (demangle_template_args (dm));
 1274 
 1275       /* Now we want to indicate to the caller that we've
 1276          demangled template arguments, thus the prefix was a
 1277          <template-prefix>.  That's so that the caller knows to
 1278          demangle the function's return type, if this turns out to
 1279          be a function name.  But, if it's a member template
 1280          constructor or a templated conversion operator, report it
 1281          as untemplated.  Those never get encoded return types.  */
 1282       *encode_return_type = !suppress_return_type;
 1283     }
 1284       else if (peek == 'E')
 1285     /* All done.  */
 1286     return STATUS_OK;
 1287       else
 1288     return "Unexpected character in <compound-name>.";
 1289 
 1290       if (peek != 'S'
 1291       && peek_char (dm) != 'E')
 1292     /* Add a new substitution for the prefix thus far.  */
 1293     RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type));
 1294     }
 1295 }
 1296 
 1297 /* Demangles and emits an <unqualified-name>.  If this
 1298    <unqualified-name> is for a special function type that should never
 1299    have its return type encoded (particularly, a constructor or
 1300    conversion operator), *SUPPRESS_RETURN_TYPE is set to 1; otherwise,
 1301    it is set to zero.
 1302 
 1303     <unqualified-name>  ::= <operator-name>
 1304             ::= <special-name>  
 1305             ::= <source-name>  */
 1306 
 1307 static status_t
 1308 demangle_unqualified_name (dm, suppress_return_type)
 1309      demangling_t dm;
 1310      int *suppress_return_type;
 1311 {
 1312   char peek = peek_char (dm);
 1313 
 1314   DEMANGLE_TRACE ("unqualified-name", dm);
 1315 
 1316   /* By default, don't force suppression of the return type (though
 1317      non-template functions still don't get a return type encoded).  */ 
 1318   *suppress_return_type = 0;
 1319 
 1320   if (IS_DIGIT ((unsigned char) peek))
 1321     RETURN_IF_ERROR (demangle_source_name (dm));
 1322   else if (peek >= 'a' && peek <= 'z')
 1323     {
 1324       int num_args;
 1325 
 1326       /* Conversion operators never have a return type encoded.  */
 1327       if (peek == 'c' && peek_char_next (dm) == 'v')
 1328     *suppress_return_type = 1;
 1329 
 1330       RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args, NULL));
 1331     }
 1332   else if (peek == 'C' || peek == 'D')
 1333     {
 1334       /* Constructors never have a return type encoded.  */
 1335       if (peek == 'C')
 1336     *suppress_return_type = 1;
 1337 
 1338       RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
 1339     }
 1340   else
 1341     return "Unexpected character in <unqualified-name>.";
 1342 
 1343   return STATUS_OK;
 1344 }
 1345 
 1346 /* Demangles and emits <source-name>.  
 1347 
 1348     <source-name> ::= <length number> <identifier>  */
 1349 
 1350 static status_t
 1351 demangle_source_name (dm)
 1352      demangling_t dm;
 1353 {
 1354   int length;
 1355 
 1356   DEMANGLE_TRACE ("source-name", dm);
 1357 
 1358   /* Decode the length of the identifier.  */
 1359   RETURN_IF_ERROR (demangle_number (dm, &length, 10, 0));
 1360   if (length == 0)
 1361     return "Zero length in <source-name>.";
 1362 
 1363   /* Now the identifier itself.  It's placed into last_source_name,
 1364      where it can be used to build a constructor or destructor name.  */
 1365   RETURN_IF_ERROR (demangle_identifier (dm, length, 
 1366                     dm->last_source_name));
 1367 
 1368   /* Emit it.  */
 1369   RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
 1370 
 1371   return STATUS_OK;
 1372 }
 1373 
 1374 /* Demangles a number, either a <number> or a <positive-number> at the
 1375    current position, consuming all consecutive digit characters.  Sets
 1376    *VALUE to the resulting numberand returns STATUS_OK.  The number is
 1377    interpreted as BASE, which must be either 10 or 36.  If IS_SIGNED
 1378    is non-zero, negative numbers -- prefixed with `n' -- are accepted.
 1379 
 1380     <number> ::= [n] <positive-number>
 1381 
 1382     <positive-number> ::= <decimal integer>  */
 1383 
 1384 static status_t
 1385 demangle_number (dm, value, base, is_signed)
 1386      demangling_t dm;
 1387      int *value;
 1388      int base;
 1389      int is_signed;
 1390 {
 1391   dyn_string_t number = dyn_string_new (10);
 1392 
 1393   DEMANGLE_TRACE ("number", dm);
 1394 
 1395   if (number == NULL)
 1396     return STATUS_ALLOCATION_FAILED;
 1397 
 1398   demangle_number_literally (dm, number, base, is_signed);
 1399   *value = strtol (dyn_string_buf (number), NULL, base);
 1400   dyn_string_delete (number);
 1401 
 1402   return STATUS_OK;
 1403 }
 1404 
 1405 /* Demangles a number at the current position.  The digits (and minus
 1406    sign, if present) that make up the number are appended to STR.
 1407    Only base-BASE digits are accepted; BASE must be either 10 or 36.
 1408    If IS_SIGNED, negative numbers -- prefixed with `n' -- are
 1409    accepted.  Does not consume a trailing underscore or other
 1410    terminating character.  */
 1411 
 1412 static status_t
 1413 demangle_number_literally (dm, str, base, is_signed)
 1414      demangling_t dm;
 1415      dyn_string_t str;
 1416      int base;
 1417      int is_signed;
 1418 {
 1419   DEMANGLE_TRACE ("number*", dm);
 1420 
 1421   if (base != 10 && base != 36)
 1422     return STATUS_INTERNAL_ERROR;
 1423 
 1424   /* An `n' denotes a negative number.  */
 1425   if (is_signed && peek_char (dm) == 'n')
 1426     {
 1427       /* Skip past the n.  */
 1428       advance_char (dm);
 1429       /* The normal way to write a negative number is with a minus
 1430      sign.  */
 1431       if (!dyn_string_append_char (str, '-'))
 1432     return STATUS_ALLOCATION_FAILED;
 1433     }
 1434 
 1435   /* Loop until we hit a non-digit.  */
 1436   while (1)
 1437     {
 1438       char peek = peek_char (dm);
 1439       if (IS_DIGIT ((unsigned char) peek)
 1440       || (base == 36 && peek >= 'A' && peek <= 'Z'))
 1441     {
 1442       /* Accumulate digits.  */
 1443       if (!dyn_string_append_char (str, next_char (dm)))
 1444         return STATUS_ALLOCATION_FAILED;
 1445     }
 1446       else
 1447     /* Not a digit?  All done.  */
 1448     break;
 1449     }
 1450 
 1451   return STATUS_OK;
 1452 }
 1453 
 1454 /* Demangles an identifier at the current position of LENGTH
 1455    characters and places it in IDENTIFIER.  */
 1456 
 1457 static status_t
 1458 demangle_identifier (dm, length, identifier)
 1459      demangling_t dm;
 1460      int length;
 1461      dyn_string_t identifier;
 1462 {
 1463   DEMANGLE_TRACE ("identifier", dm);
 1464 
 1465   dyn_string_clear (identifier);
 1466   if (!dyn_string_resize (identifier, length))
 1467     return STATUS_ALLOCATION_FAILED;
 1468 
 1469   while (length-- > 0)
 1470     {
 1471       int ch;
 1472       if (end_of_name_p (dm))
 1473     return "Unexpected end of name in <identifier>.";
 1474       ch = next_char (dm);
 1475 
 1476       /* Handle extended Unicode characters.  We encode them as __U{hex}_,
 1477          where {hex} omits leading 0's.  For instance, '$' is encoded as
 1478          "__U24_".  */
 1479       if (ch == '_'
 1480       && peek_char (dm) == '_'
 1481       && peek_char_next (dm) == 'U')
 1482     {
 1483       char buf[10];
 1484       int pos = 0;
 1485       advance_char (dm); advance_char (dm); length -= 2;
 1486       while (length-- > 0)
 1487         {
 1488           ch = next_char (dm);
 1489           if (!isxdigit (ch))
 1490         break;
 1491           buf[pos++] = ch;
 1492         }
 1493       if (ch != '_' || length < 0)
 1494         return STATUS_ERROR;
 1495       if (pos == 0)
 1496         {
 1497           /* __U_ just means __U.  */
 1498           if (!dyn_string_append_cstr (identifier, "__U"))
 1499         return STATUS_ALLOCATION_FAILED;
 1500           continue;
 1501         }
 1502       else
 1503         {
 1504           buf[pos] = '\0';
 1505           ch = strtol (buf, 0, 16);
 1506         }
 1507     }
 1508 
 1509       if (!dyn_string_append_char (identifier, ch))
 1510     return STATUS_ALLOCATION_FAILED;
 1511     }
 1512 
 1513   /* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.'
 1514      followed by the source file name and some random characters.
 1515      Unless we're in strict mode, decipher these names appropriately.  */
 1516   if (!flag_strict)
 1517     {
 1518       char *name = dyn_string_buf (identifier);
 1519       int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);
 1520 
 1521       /* Compare the first, fixed part.  */
 1522       if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0)
 1523         {
 1524       name += prefix_length;
 1525       /* The next character might be a period, an underscore, or
 1526          dollar sign, depending on the target architecture's
 1527          assembler's capabilities.  After that comes an `N'.  */
 1528       if ((*name == '.' || *name == '_' || *name == '$')
 1529           && *(name + 1) == 'N')
 1530         /* This looks like the anonymous namespace identifier.
 1531            Replace it with something comprehensible.  */
 1532         dyn_string_copy_cstr (identifier, "(anonymous namespace)");
 1533     }
 1534     }
 1535 
 1536   return STATUS_OK;
 1537 }
 1538 
 1539 /* Demangles and emits an <operator-name>.  If SHORT_NAME is non-zero,
 1540    the short form is emitted; otherwise the full source form
 1541    (`operator +' etc.) is emitted.  *NUM_ARGS is set to the number of
 1542    operands that the operator takes.  If TYPE_ARG is non-NULL,
 1543    *TYPE_ARG is set to 1 if the first argument is a type and 0
 1544    otherwise.
 1545 
 1546     <operator-name>
 1547                   ::= nw        # new           
 1548                   ::= na        # new[]
 1549                   ::= dl        # delete        
 1550                   ::= da        # delete[]      
 1551           ::= ps        # + (unary)
 1552                   ::= ng        # - (unary)     
 1553                   ::= ad        # & (unary)     
 1554                   ::= de        # * (unary)     
 1555                   ::= co        # ~             
 1556                   ::= pl        # +             
 1557                   ::= mi        # -             
 1558                   ::= ml        # *             
 1559                   ::= dv        # /             
 1560                   ::= rm        # %             
 1561                   ::= an        # &             
 1562                   ::= or        # |             
 1563                   ::= eo        # ^             
 1564                   ::= aS        # =             
 1565                   ::= pL        # +=            
 1566                   ::= mI        # -=            
 1567                   ::= mL        # *=            
 1568                   ::= dV        # /=            
 1569                   ::= rM        # %=            
 1570                   ::= aN        # &=            
 1571                   ::= oR        # |=            
 1572                   ::= eO        # ^=            
 1573                   ::= ls        # <<            
 1574                   ::= rs        # >>            
 1575                   ::= lS        # <<=           
 1576                   ::= rS        # >>=           
 1577                   ::= eq        # ==            
 1578                   ::= ne        # !=            
 1579                   ::= lt        # <             
 1580                   ::= gt        # >             
 1581                   ::= le        # <=            
 1582                   ::= ge        # >=            
 1583                   ::= nt        # !             
 1584                   ::= aa        # &&            
 1585                   ::= oo        # ||            
 1586                   ::= pp        # ++            
 1587                   ::= mm        # --            
 1588                   ::= cm        # ,             
 1589                   ::= pm        # ->*           
 1590                   ::= pt        # ->            
 1591                   ::= cl        # ()            
 1592                   ::= ix        # []            
 1593                   ::= qu        # ?
 1594           ::= st        # sizeof (a type)
 1595                   ::= sz        # sizeof (an expression)
 1596                   ::= cv <type> # cast        
 1597           ::= v [0-9] <source-name>  # vendor extended operator  */
 1598 
 1599 static status_t
 1600 demangle_operator_name (dm, short_name, num_args, type_arg)
 1601      demangling_t dm;
 1602      int short_name;
 1603      int *num_args;
 1604      int *type_arg;
 1605 {
 1606   struct operator_code
 1607   {
 1608     /* The mangled code for this operator.  */
 1609     const char *const code;
 1610     /* The source name of this operator.  */
 1611     const char *const name;
 1612     /* The number of arguments this operator takes.  */
 1613     const int num_args;
 1614   };
 1615 
 1616   static const struct operator_code operators[] = 
 1617   {
 1618     { "aN", "&="       , 2 },
 1619     { "aS", "="        , 2 },
 1620     { "aa", "&&"       , 2 },
 1621     { "ad", "&"        , 1 },
 1622     { "an", "&"        , 2 },
 1623     { "cl", "()"       , 0 },
 1624     { "cm", ","        , 2 },
 1625     { "co", "~"        , 1 },
 1626     { "dV", "/="       , 2 },
 1627     { "da", " delete[]", 1 },
 1628     { "de", "*"        , 1 },
 1629     { "dl", " delete"  , 1 },
 1630     { "dv", "/"        , 2 },
 1631     { "eO", "^="       , 2 },
 1632     { "eo", "^"        , 2 },
 1633     { "eq", "=="       , 2 },
 1634     { "ge", ">="       , 2 },
 1635     { "gt", ">"        , 2 },
 1636     { "ix", "[]"       , 2 },
 1637     { "lS", "<<="      , 2 },
 1638     { "le", "<="       , 2 },
 1639     { "ls", "<<"       , 2 },
 1640     { "lt", "<"        , 2 },
 1641     { "mI", "-="       , 2 },
 1642     { "mL", "*="       , 2 },
 1643     { "mi", "-"        , 2 },
 1644     { "ml", "*"        , 2 },
 1645     { "mm", "--"       , 1 },
 1646     { "na", " new[]"   , 1 },
 1647     { "ne", "!="       , 2 },
 1648     { "ng", "-"        , 1 },
 1649     { "nt", "!"        , 1 },
 1650     { "nw", " new"     , 1 },
 1651     { "oR", "|="       , 2 },
 1652     { "oo", "||"       , 2 },
 1653     { "or", "|"        , 2 },
 1654     { "pL", "+="       , 2 },
 1655     { "pl", "+"        , 2 },
 1656     { "pm", "->*"      , 2 },
 1657     { "pp", "++"       , 1 },
 1658     { "ps", "+"        , 1 },
 1659     { "pt", "->"       , 2 },
 1660     { "qu", "?"        , 3 },
 1661     { "rM", "%="       , 2 },
 1662     { "rS", ">>="      , 2 },
 1663     { "rm", "%"        , 2 },
 1664     { "rs", ">>"       , 2 },
 1665     { "sz", " sizeof"  , 1 }
 1666   };
 1667 
 1668   const int num_operators = 
 1669     sizeof (operators) / sizeof (struct operator_code);
 1670 
 1671   int c0 = next_char (dm);
 1672   int c1 = next_char (dm);
 1673   const struct operator_code* p1 = operators;
 1674   const struct operator_code* p2 = operators + num_operators;
 1675 
 1676   DEMANGLE_TRACE ("operator-name", dm);
 1677 
 1678   /* Assume the first argument is not a type.  */
 1679   if (type_arg)
 1680     *type_arg = 0;
 1681 
 1682   /* Is this a vendor-extended operator?  */
 1683   if (c0 == 'v' && IS_DIGIT (c1))
 1684     {
 1685       RETURN_IF_ERROR (result_add (dm, "operator "));
 1686       RETURN_IF_ERROR (demangle_source_name (dm));
 1687       *num_args = 0;
 1688       return STATUS_OK;
 1689     }
 1690 
 1691   /* Is this a conversion operator?  */
 1692   if (c0 == 'c' && c1 == 'v')
 1693     {
 1694       RETURN_IF_ERROR (result_add (dm, "operator "));
 1695       /* Demangle the converted-to type.  */
 1696       RETURN_IF_ERROR (demangle_type (dm));
 1697       *num_args = 0;
 1698       return STATUS_OK;
 1699     }
 1700 
 1701   /* Is it the sizeof variant that takes a type?  */
 1702   if (c0 == 's' && c1 == 't')
 1703     {
 1704       RETURN_IF_ERROR (result_add (dm, " sizeof"));
 1705       *num_args = 1;
 1706       if (type_arg)
 1707     *type_arg = 1;
 1708       return STATUS_OK;
 1709     }
 1710 
 1711   /* Perform a binary search for the operator code.  */
 1712   while (1)
 1713     {
 1714       const struct operator_code* p = p1 + (p2 - p1) / 2;
 1715       char match0 = p->code[0];
 1716       char match1 = p->code[1];
 1717 
 1718       if (c0 == match0 && c1 == match1)
 1719     /* Found it.  */
 1720     {
 1721       if (!short_name)
 1722         RETURN_IF_ERROR (result_add (dm, "operator"));
 1723       RETURN_IF_ERROR (result_add (dm, p->name));
 1724       *num_args = p->num_args;
 1725 
 1726       return STATUS_OK;
 1727     }
 1728 
 1729       if (p == p1)
 1730     /* Couldn't find it.  */
 1731     return "Unknown code in <operator-name>.";
 1732 
 1733       /* Try again.  */
 1734       if (c0 < match0 || (c0 == match0 && c1 < match1))
 1735     p2 = p;
 1736       else
 1737     p1 = p;
 1738     }
 1739 }
 1740 
 1741 /* Demangles and omits an <nv-offset>.
 1742 
 1743     <nv-offset> ::= <offset number>   # non-virtual base override  */
 1744 
 1745 static status_t
 1746 demangle_nv_offset (dm)
 1747      demangling_t dm;
 1748 {
 1749   dyn_string_t number;
 1750   status_t status = STATUS_OK;
 1751 
 1752   DEMANGLE_TRACE ("h-offset", dm);
 1753 
 1754   /* Demangle the offset.  */
 1755   number = dyn_string_new (4);
 1756   if (number == NULL)
 1757     return STATUS_ALLOCATION_FAILED;
 1758   demangle_number_literally (dm, number, 10, 1);
 1759 
 1760   /* Don't display the offset unless in verbose mode.  */
 1761   if (flag_verbose)
 1762     {
 1763       status = result_add (dm, " [nv:");
 1764       if (STATUS_NO_ERROR (status))
 1765     status = result_add_string (dm, number);
 1766       if (STATUS_NO_ERROR (status))
 1767     status = result_add_char (dm, ']');
 1768     }
 1769 
 1770   /* Clean up.  */
 1771   dyn_string_delete (number);
 1772   RETURN_IF_ERROR (status);
 1773   return STATUS_OK;
 1774 }
 1775 
 1776 /* Demangles and emits a <v-offset>. 
 1777 
 1778     <v-offset>  ::= <offset number> _ <virtual offset number>
 1779             # virtual base override, with vcall offset  */
 1780 
 1781 static status_t
 1782 demangle_v_offset (dm)
 1783      demangling_t dm;
 1784 {
 1785   dyn_string_t number;
 1786   status_t status = STATUS_OK;
 1787 
 1788   DEMANGLE_TRACE ("v-offset", dm);
 1789 
 1790   /* Demangle the offset.  */
 1791   number = dyn_string_new (4);
 1792   if (number == NULL)
 1793     return STATUS_ALLOCATION_FAILED;
 1794   demangle_number_literally (dm, number, 10, 1);
 1795 
 1796   /* Don't display the offset unless in verbose mode.  */
 1797   if (flag_verbose)
 1798     {
 1799       status = result_add (dm, " [v:");
 1800       if (STATUS_NO_ERROR (status))
 1801     status = result_add_string (dm, number);
 1802       if (STATUS_NO_ERROR (status))
 1803     result_add_char (dm, ',');
 1804     }
 1805   dyn_string_delete (number);
 1806   RETURN_IF_ERROR (status);
 1807 
 1808   /* Demangle the separator.  */
 1809   RETURN_IF_ERROR (demangle_char (dm, '_'));
 1810 
 1811   /* Demangle the vcall offset.  */
 1812   number = dyn_string_new (4);
 1813   if (number == NULL)
 1814     return STATUS_ALLOCATION_FAILED;
 1815   demangle_number_literally (dm, number, 10, 1);
 1816 
 1817   /* Don't display the vcall offset unless in verbose mode.  */
 1818   if (flag_verbose)
 1819     {
 1820       status = result_add_string (dm, number);
 1821       if (STATUS_NO_ERROR (status))
 1822     status = result_add_char (dm, ']');
 1823     }
 1824   dyn_string_delete (number);
 1825   RETURN_IF_ERROR (status);
 1826 
 1827   return STATUS_OK;
 1828 }
 1829 
 1830 /* Demangles and emits a <call-offset>.
 1831 
 1832     <call-offset> ::= h <nv-offset> _
 1833           ::= v <v-offset> _  */
 1834 
 1835 static status_t
 1836 demangle_call_offset (dm)
 1837      demangling_t dm;
 1838 {
 1839   DEMANGLE_TRACE ("call-offset", dm);
 1840 
 1841   switch (peek_char (dm))
 1842     {
 1843     case 'h':
 1844       advance_char (dm);
 1845       /* Demangle the offset.  */
 1846       RETURN_IF_ERROR (demangle_nv_offset (dm));
 1847       /* Demangle the separator.  */
 1848       RETURN_IF_ERROR (demangle_char (dm, '_'));
 1849       break;
 1850 
 1851     case 'v':
 1852       advance_char (dm);
 1853       /* Demangle the offset.  */
 1854       RETURN_IF_ERROR (demangle_v_offset (dm));
 1855       /* Demangle the separator.  */
 1856       RETURN_IF_ERROR (demangle_char (dm, '_'));
 1857       break;
 1858 
 1859     default:
 1860       return "Unrecognized <call-offset>.";
 1861     }
 1862 
 1863   return STATUS_OK;
 1864 }
 1865 
 1866 /* Demangles and emits a <special-name>.  
 1867 
 1868     <special-name> ::= GV <object name>   # Guard variable
 1869                    ::= TV <type>          # virtual table
 1870                    ::= TT <type>          # VTT
 1871                    ::= TI <type>          # typeinfo structure
 1872            ::= TS <type>          # typeinfo name  
 1873 
 1874    Other relevant productions include thunks:
 1875 
 1876     <special-name> ::= T <call-offset> <base encoding>
 1877              # base is the nominal target function of thunk
 1878 
 1879     <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
 1880              # base is the nominal target function of thunk
 1881              # first call-offset is 'this' adjustment
 1882              # second call-offset is result adjustment
 1883 
 1884    where
 1885 
 1886     <call-offset>  ::= h <nv-offset> _
 1887            ::= v <v-offset> _
 1888 
 1889    Also demangles the special g++ manglings,
 1890 
 1891     <special-name> ::= TC <type> <offset number> _ <base type>
 1892                                           # construction vtable
 1893            ::= TF <type>      # typeinfo function (old ABI only)
 1894            ::= TJ <type>      # java Class structure  */
 1895 
 1896 static status_t
 1897 demangle_special_name (dm)
 1898      demangling_t dm;
 1899 {
 1900   dyn_string_t number;
 1901   int unused;
 1902   char peek = peek_char (dm);
 1903 
 1904   DEMANGLE_TRACE ("special-name", dm);
 1905 
 1906   if (peek == 'G')
 1907     {
 1908       /* Consume the G.  */
 1909       advance_char (dm);
 1910       switch (peek_char (dm))
 1911     {
 1912     case 'V':
 1913       /* A guard variable name.  */
 1914       advance_char (dm);
 1915       RETURN_IF_ERROR (result_add (dm, "guard variable for "));
 1916       RETURN_IF_ERROR (demangle_name (dm, &unused));
 1917       break;
 1918 
 1919     case 'R':
 1920       /* A reference temporary.  */
 1921       advance_char (dm);
 1922       RETURN_IF_ERROR (result_add (dm, "reference temporary for "));
 1923       RETURN_IF_ERROR (demangle_name (dm, &unused));
 1924       break;
 1925       
 1926     default:
 1927       return "Unrecognized <special-name>.";
 1928     }
 1929     }
 1930   else if (peek == 'T')
 1931     {
 1932       status_t status = STATUS_OK;
 1933 
 1934       /* Other C++ implementation miscellania.  Consume the T.  */
 1935       advance_char (dm);
 1936 
 1937       switch (peek_char (dm))
 1938     {
 1939     case 'V':
 1940       /* Virtual table.  */
 1941       advance_char (dm);
 1942       RETURN_IF_ERROR (result_add (dm, "vtable for "));
 1943       RETURN_IF_ERROR (demangle_type (dm));
 1944       break;
 1945 
 1946     case 'T':
 1947       /* VTT structure.  */
 1948       advance_char (dm);
 1949       RETURN_IF_ERROR (result_add (dm, "VTT for "));
 1950       RETURN_IF_ERROR (demangle_type (dm));
 1951       break;
 1952 
 1953     case 'I':
 1954       /* Typeinfo structure.  */
 1955       advance_char (dm);
 1956       RETURN_IF_ERROR (result_add (dm, "typeinfo for "));
 1957       RETURN_IF_ERROR (demangle_type (dm));
 1958       break;
 1959 
 1960     case 'F':
 1961       /* Typeinfo function.  Used only in old ABI with new mangling.  */
 1962       advance_char (dm);
 1963       RETURN_IF_ERROR (result_add (dm, "typeinfo fn for "));
 1964       RETURN_IF_ERROR (demangle_type (dm));
 1965       break;
 1966 
 1967     case 'S':
 1968       /* Character string containing type name, used in typeinfo. */
 1969       advance_char (dm);
 1970       RETURN_IF_ERROR (result_add (dm, "typeinfo name for "));
 1971       RETURN_IF_ERROR (demangle_type (dm));
 1972       break;
 1973 
 1974     case 'J':
 1975       /* The java Class variable corresponding to a C++ class.  */
 1976       advance_char (dm);
 1977       RETURN_IF_ERROR (result_add (dm, "java Class for "));
 1978       RETURN_IF_ERROR (demangle_type (dm));
 1979       break;
 1980 
 1981     case 'h':
 1982       /* Non-virtual thunk.  */
 1983       advance_char (dm);
 1984       RETURN_IF_ERROR (result_add (dm, "non-virtual thunk"));
 1985       RETURN_IF_ERROR (demangle_nv_offset (dm));
 1986       /* Demangle the separator.  */
 1987       RETURN_IF_ERROR (demangle_char (dm, '_'));
 1988       /* Demangle and emit the target name and function type.  */
 1989       RETURN_IF_ERROR (result_add (dm, " to "));
 1990       RETURN_IF_ERROR (demangle_encoding (dm));
 1991       break;
 1992 
 1993     case 'v':
 1994       /* Virtual thunk.  */
 1995       advance_char (dm);
 1996       RETURN_IF_ERROR (result_add (dm, "virtual thunk"));
 1997       RETURN_IF_ERROR (demangle_v_offset (dm));
 1998       /* Demangle the separator.  */
 1999       RETURN_IF_ERROR (demangle_char (dm, '_'));
 2000       /* Demangle and emit the target function.  */
 2001       RETURN_IF_ERROR (result_add (dm, " to "));
 2002       RETURN_IF_ERROR (demangle_encoding (dm));
 2003       break;
 2004 
 2005     case 'c':
 2006       /* Covariant return thunk.  */
 2007       advance_char (dm);
 2008       RETURN_IF_ERROR (result_add (dm, "covariant return thunk"));
 2009       RETURN_IF_ERROR (demangle_call_offset (dm));
 2010       RETURN_IF_ERROR (demangle_call_offset (dm));
 2011       /* Demangle and emit the target function.  */
 2012       RETURN_IF_ERROR (result_add (dm, " to "));
 2013       RETURN_IF_ERROR (demangle_encoding (dm));
 2014       break;
 2015 
 2016     case 'C':
 2017       /* TC is a special g++ mangling for a construction vtable. */
 2018       if (!flag_strict)
 2019         {
 2020           dyn_string_t derived_type;
 2021 
 2022           advance_char (dm);
 2023           RETURN_IF_ERROR (result_add (dm, "construction vtable for "));
 2024 
 2025           /* Demangle the derived type off to the side.  */
 2026           RETURN_IF_ERROR (result_push (dm));
 2027           RETURN_IF_ERROR (demangle_type (dm));
 2028           derived_type = (dyn_string_t) result_pop (dm);
 2029 
 2030           /* Demangle the offset.  */
 2031           number = dyn_string_new (4);
 2032           if (number == NULL)
 2033         {
 2034           dyn_string_delete (derived_type);
 2035           return STATUS_ALLOCATION_FAILED;
 2036         }
 2037           demangle_number_literally (dm, number, 10, 1);
 2038           /* Demangle the underscore separator.  */
 2039           status = demangle_char (dm, '_');
 2040 
 2041           /* Demangle the base type.  */
 2042           if (STATUS_NO_ERROR (status))
 2043         status = demangle_type (dm);
 2044 
 2045           /* Emit the derived type.  */
 2046           if (STATUS_NO_ERROR (status))
 2047         status = result_add (dm, "-in-");
 2048           if (STATUS_NO_ERROR (status))
 2049         status = result_add_string (dm, derived_type);
 2050           dyn_string_delete (derived_type);
 2051 
 2052           /* Don't display the offset unless in verbose mode.  */
 2053           if (flag_verbose)
 2054         {
 2055           status = result_add_char (dm, ' ');
 2056           if (STATUS_NO_ERROR (status))
 2057             result_add_string (dm, number);
 2058         }
 2059           dyn_string_delete (number);
 2060           RETURN_IF_ERROR (status);
 2061           break;
 2062         }
 2063       /* If flag_strict, fall through.  */
 2064 
 2065     default:
 2066       return "Unrecognized <special-name>.";
 2067     }
 2068     }
 2069   else
 2070     return STATUS_ERROR;
 2071 
 2072   return STATUS_OK;
 2073 }
 2074 
 2075 /* Demangles and emits a <ctor-dtor-name>.  
 2076    
 2077     <ctor-dtor-name>
 2078                    ::= C1  # complete object (in-charge) ctor
 2079                    ::= C2  # base object (not-in-charge) ctor
 2080                    ::= C3  # complete object (in-charge) allocating ctor
 2081                    ::= D0  # deleting (in-charge) dtor
 2082                    ::= D1  # complete object (in-charge) dtor
 2083                    ::= D2  # base object (not-in-charge) dtor  */
 2084 
 2085 static status_t
 2086 demangle_ctor_dtor_name (dm)
 2087      demangling_t dm;
 2088 {
 2089   static const char *const ctor_flavors[] = 
 2090   {
 2091     "in-charge",
 2092     "not-in-charge",
 2093     "allocating"
 2094   };
 2095   static const char *const dtor_flavors[] = 
 2096   {
 2097     "in-charge deleting",
 2098     "in-charge",
 2099     "not-in-charge"
 2100   };
 2101 
 2102   int flavor;
 2103   char peek = peek_char (dm);
 2104 
 2105   DEMANGLE_TRACE ("ctor-dtor-name", dm);
 2106   
 2107   if (peek == 'C')
 2108     {
 2109       /* A constructor name.  Consume the C.  */
 2110       advance_char (dm);
 2111       flavor = next_char (dm);
 2112       if (flavor < '1' || flavor > '3')
 2113     return "Unrecognized constructor.";
 2114       RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
 2115       switch (flavor)
 2116     {
 2117     case '1': dm->is_constructor = gnu_v3_complete_object_ctor;
 2118       break;
 2119     case '2': dm->is_constructor = gnu_v3_base_object_ctor;
 2120       break;
 2121     case '3': dm->is_constructor = gnu_v3_complete_object_allocating_ctor;
 2122       break;
 2123     }
 2124       /* Print the flavor of the constructor if in verbose mode.  */
 2125       if (flag_verbose)
 2126     {
 2127       RETURN_IF_ERROR (result_add (dm, "["));
 2128       RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor - '1']));
 2129       RETURN_IF_ERROR (result_add_char (dm, ']'));
 2130     }
 2131     }
 2132   else if (peek == 'D')
 2133     {
 2134       /* A destructor name.  Consume the D.  */
 2135       advance_char (dm);
 2136       flavor = next_char (dm);
 2137       if (flavor < '0' || flavor > '2')
 2138     return "Unrecognized destructor.";
 2139       RETURN_IF_ERROR (result_add_char (dm, '~'));
 2140       RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
 2141       switch (flavor)
 2142     {
 2143     case '0': dm->is_destructor = gnu_v3_deleting_dtor;
 2144       break;
 2145     case '1': dm->is_destructor = gnu_v3_complete_object_dtor;
 2146       break;
 2147     case '2': dm->is_destructor = gnu_v3_base_object_dtor;
 2148       break;
 2149     }
 2150       /* Print the flavor of the destructor if in verbose mode.  */
 2151       if (flag_verbose)
 2152     {
 2153       RETURN_IF_ERROR (result_add (dm, " ["));
 2154       RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor - '0']));
 2155       RETURN_IF_ERROR (result_add_char (dm, ']'));
 2156     }
 2157     }
 2158   else
 2159     return STATUS_ERROR;
 2160 
 2161   return STATUS_OK;
 2162 }
 2163 
 2164 /* Handle pointer, reference, and pointer-to-member cases for
 2165    demangle_type.  All consecutive `P's, `R's, and 'M's are joined to
 2166    build a pointer/reference type.  We snarf all these, plus the
 2167    following <type>, all at once since we need to know whether we have
 2168    a pointer to data or pointer to function to construct the right
 2169    output syntax.  C++'s pointer syntax is hairy.  
 2170 
 2171    This function adds substitution candidates for every nested
 2172    pointer/reference type it processes, including the outermost, final
 2173    type, assuming the substitution starts at SUBSTITUTION_START in the
 2174    demangling result.  For example, if this function demangles
 2175    `PP3Foo', it will add a substitution for `Foo', `Foo*', and
 2176    `Foo**', in that order.
 2177 
 2178    *INSERT_POS is a quantity used internally, when this function calls
 2179    itself recursively, to figure out where to insert pointer
 2180    punctuation on the way up.  On entry to this function, INSERT_POS
 2181    should point to a temporary value, but that value need not be
 2182    initialized.
 2183 
 2184      <type> ::= P <type>
 2185             ::= R <type>
 2186             ::= <pointer-to-member-type>
 2187 
 2188      <pointer-to-member-type> ::= M </class/ type> </member/ type>  */
 2189 
 2190 static status_t
 2191 demangle_type_ptr (dm, insert_pos, substitution_start)
 2192      demangling_t dm;
 2193      int *insert_pos;
 2194      int substitution_start;
 2195 {
 2196   status_t status;
 2197   int is_substitution_candidate = 1;
 2198 
 2199   DEMANGLE_TRACE ("type*", dm);
 2200 
 2201   /* Scan forward, collecting pointers and references into symbols,
 2202      until we hit something else.  Then emit the type.  */
 2203   switch (peek_char (dm))
 2204     {
 2205     case 'P':
 2206       /* A pointer.  Snarf the `P'.  */
 2207       advance_char (dm);
 2208       /* Demangle the underlying type.  */
 2209       RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos, 
 2210                       substitution_start));
 2211       /* Insert an asterisk where we're told to; it doesn't
 2212      necessarily go at the end.  If we're doing Java style output, 
 2213      there is no pointer symbol.  */
 2214       if (dm->style != DMGL_JAVA)
 2215     RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
 2216       /* The next (outermost) pointer or reference character should go
 2217      after this one.  */
 2218       ++(*insert_pos);
 2219       break;
 2220 
 2221     case 'R':
 2222       /* A reference.  Snarf the `R'.  */
 2223       advance_char (dm);
 2224       /* Demangle the underlying type.  */
 2225       RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos, 
 2226                       substitution_start));
 2227       /* Insert an ampersand where we're told to; it doesn't
 2228      necessarily go at the end.  */
 2229       RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
 2230       /* The next (outermost) pointer or reference character should go
 2231      after this one.  */
 2232       ++(*insert_pos);
 2233       break;
 2234 
 2235     case 'M':
 2236     {
 2237       /* A pointer-to-member.  */
 2238       dyn_string_t class_type;
 2239       
 2240       /* Eat the 'M'.  */
 2241       advance_char (dm);
 2242       
 2243       /* Capture the type of which this is a pointer-to-member.  */
 2244       RETURN_IF_ERROR (result_push (dm));
 2245       RETURN_IF_ERROR (demangle_type (dm));
 2246       class_type = (dyn_string_t) result_pop (dm);
 2247       
 2248       if (peek_char (dm) == 'F')
 2249     /* A pointer-to-member function.  We want output along the
 2250        lines of `void (C::*) (int, int)'.  Demangle the function
 2251        type, which would in this case give `void () (int, int)'
 2252        and set *insert_pos to the spot between the first
 2253        parentheses.  */
 2254     status = demangle_type_ptr (dm, insert_pos, substitution_start);
 2255       else if (peek_char (dm) == 'A')
 2256     /* A pointer-to-member array variable.  We want output that
 2257        looks like `int (Klass::*) [10]'.  Demangle the array type
 2258        as `int () [10]', and set *insert_pos to the spot between
 2259        the parentheses.  */
 2260     status = demangle_array_type (dm, insert_pos);
 2261       else
 2262         {
 2263       /* A pointer-to-member variable.  Demangle the type of the
 2264              pointed-to member.  */
 2265       status = demangle_type (dm);
 2266       /* Make it pretty.  */
 2267       if (STATUS_NO_ERROR (status)
 2268           && !result_previous_char_is_space (dm))
 2269         status = result_add_char (dm, ' ');
 2270       /* The pointer-to-member notation (e.g. `C::*') follows the
 2271              member's type.  */
 2272       *insert_pos = result_caret_pos (dm);
 2273     }
 2274 
 2275       /* Build the pointer-to-member notation.  */
 2276       if (STATUS_NO_ERROR (status))
 2277     status = result_insert (dm, *insert_pos, "::*");
 2278       if (STATUS_NO_ERROR (status))
 2279     status = result_insert_string (dm, *insert_pos, class_type);
 2280       /* There may be additional levels of (pointer or reference)
 2281      indirection in this type.  If so, the `*' and `&' should be
 2282      added after the pointer-to-member notation (e.g. `C::*&' for
 2283      a reference to a pointer-to-member of class C).  */
 2284       *insert_pos += dyn_string_length (class_type) + 3;
 2285 
 2286       /* Clean up. */
 2287       dyn_string_delete (class_type);
 2288 
 2289       RETURN_IF_ERROR (status);
 2290     }
 2291     break;
 2292 
 2293     case 'F':
 2294       /* Ooh, tricky, a pointer-to-function.  When we demangle the
 2295      function type, the return type should go at the very
 2296      beginning.  */
 2297       *insert_pos = result_caret_pos (dm);
 2298       /* The parentheses indicate this is a function pointer or
 2299      reference type.  */
 2300       RETURN_IF_ERROR (result_add (dm, "()"));
 2301       /* Now demangle the function type.  The return type will be
 2302      inserted before the `()', and the argument list will go after
 2303      it.  */
 2304       RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
 2305       /* We should now have something along the lines of 
 2306      `void () (int, int)'.  The pointer or reference characters
 2307      have to inside the first set of parentheses.  *insert_pos has
 2308      already been updated to point past the end of the return
 2309      type.  Move it one character over so it points inside the
 2310      `()'.  */
 2311       ++(*insert_pos);
 2312       break;
 2313 
 2314     case 'A':
 2315       /* An array pointer or reference.  demangle_array_type will figure
 2316      out where the asterisks and ampersands go.  */
 2317       RETURN_IF_ERROR (demangle_array_type (dm, insert_pos));
 2318       break;
 2319 
 2320     default:
 2321       /* No more pointer or reference tokens; this is therefore a
 2322      pointer to data.  Finish up by demangling the underlying
 2323      type.  */
 2324       RETURN_IF_ERROR (demangle_type (dm));
 2325       /* The pointer or reference characters follow the underlying
 2326      type, as in `int*&'.  */
 2327       *insert_pos = result_caret_pos (dm);
 2328       /* Because of the production <type> ::= <substitution>,
 2329      demangle_type will already have added the underlying type as
 2330      a substitution candidate.  Don't do it again.  */
 2331       is_substitution_candidate = 0;
 2332       break;
 2333     }
 2334   
 2335   if (is_substitution_candidate)
 2336     RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
 2337   
 2338   return STATUS_OK;
 2339 }
 2340 
 2341 /* Demangles and emits a <type>.  
 2342 
 2343     <type> ::= <builtin-type>
 2344        ::= <function-type>
 2345        ::= <class-enum-type>
 2346        ::= <array-type>
 2347        ::= <pointer-to-member-type>
 2348        ::= <template-param>
 2349        ::= <template-template-param> <template-args>
 2350            ::= <CV-qualifiers> <type>
 2351        ::= P <type>   # pointer-to
 2352        ::= R <type>   # reference-to
 2353        ::= C <type>   # complex pair (C 2000)
 2354        ::= G <type>   # imaginary (C 2000)
 2355        ::= U <source-name> <type>     # vendor extended type qualifier
 2356        ::= <substitution>  */
 2357 
 2358 static status_t
 2359 demangle_type (dm)
 2360      demangling_t dm;
 2361 {
 2362   int start = substitution_start (dm);
 2363   char peek = peek_char (dm);
 2364   char peek_next;
 2365   int encode_return_type = 0;
 2366   template_arg_list_t old_arg_list = current_template_arg_list (dm);
 2367   int insert_pos;
 2368 
 2369   /* A <type> can be a <substitution>; therefore, this <type> is a
 2370      substitution candidate unless a special condition holds (see
 2371      below).  */
 2372   int is_substitution_candidate = 1;
 2373 
 2374   DEMANGLE_TRACE ("type", dm);
 2375 
 2376   /* A <class-enum-type> can start with a digit (a <source-name>), an
 2377      N (a <nested-name>), or a Z (a <local-name>).  */
 2378   if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
 2379     RETURN_IF_ERROR (demangle_class_enum_type (dm, &encode_return_type));
 2380   /* Lower-case letters begin <builtin-type>s, except for `r', which
 2381      denotes restrict.  */
 2382   else if (peek >= 'a' && peek <= 'z' && peek != 'r')
 2383     {
 2384       RETURN_IF_ERROR (demangle_builtin_type (dm));
 2385       /* Built-in types are not substitution candidates.  */
 2386       is_substitution_candidate = 0;
 2387     }
 2388   else
 2389     switch (peek)
 2390       {
 2391       case 'r':
 2392       case 'V':
 2393       case 'K':
 2394     /* CV-qualifiers (including restrict).  We have to demangle
 2395        them off to the side, since C++ syntax puts them in a funny
 2396        place for qualified pointer and reference types.  */
 2397     {
 2398       status_t status;
 2399       dyn_string_t cv_qualifiers = dyn_string_new (24);
 2400       int old_caret_position = result_get_caret (dm);
 2401 
 2402       if (cv_qualifiers == NULL)
 2403         return STATUS_ALLOCATION_FAILED;
 2404 
 2405       /* Decode all adjacent CV qualifiers.  */
 2406       demangle_CV_qualifiers (dm, cv_qualifiers);
 2407       /* Emit them, and shift the caret left so that the
 2408          underlying type will be emitted before the qualifiers.  */
 2409       status = result_add_string (dm, cv_qualifiers);
 2410       result_shift_caret (dm, -dyn_string_length (cv_qualifiers));
 2411       /* Clean up.  */
 2412       dyn_string_delete (cv_qualifiers);
 2413       RETURN_IF_ERROR (status);
 2414       /* Also prepend a blank, if needed.  */
 2415       RETURN_IF_ERROR (result_add_char (dm, ' '));
 2416       result_shift_caret (dm, -1);
 2417 
 2418       /* Demangle the underlying type.  It will be emitted before
 2419          the CV qualifiers, since we moved the caret.  */
 2420       RETURN_IF_ERROR (demangle_type (dm));
 2421 
 2422       /* Put the caret back where it was previously.  */
 2423       result_set_caret (dm, old_caret_position);
 2424     }
 2425     break;
 2426 
 2427       case 'F':
 2428     return "Non-pointer or -reference function type.";
 2429 
 2430       case 'A':
 2431     RETURN_IF_ERROR (demangle_array_type (dm, NULL));
 2432     break;
 2433 
 2434       case 'T':
 2435     /* It's either a <template-param> or a
 2436        <template-template-param>.  In either case, demangle the
 2437        `T' token first.  */
 2438     RETURN_IF_ERROR (demangle_template_param (dm));
 2439 
 2440     /* Check for a template argument list; if one is found, it's a
 2441          <template-template-param> ::= <template-param>
 2442                                        ::= <substitution>  */
 2443     if (peek_char (dm) == 'I')
 2444       {
 2445         /* Add a substitution candidate.  The template parameter
 2446            `T' token is a substitution candidate by itself,
 2447            without the template argument list.  */
 2448         RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
 2449 
 2450         /* Now demangle the template argument list.  */
 2451         RETURN_IF_ERROR (demangle_template_args (dm));
 2452         /* The entire type, including the template template
 2453            parameter and its argument list, will be added as a
 2454            substitution candidate below.  */
 2455       }
 2456 
 2457     break;
 2458 
 2459       case 'S':
 2460     /* First check if this is a special substitution.  If it is,
 2461        this is a <class-enum-type>.  Special substitutions have a
 2462        letter following the `S'; other substitutions have a digit
 2463        or underscore.  */
 2464     peek_next = peek_char_next (dm);
 2465     if (IS_DIGIT (peek_next) || peek_next == '_')
 2466       {
 2467         RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type));
 2468         
 2469         /* The substituted name may have been a template name.
 2470            Check if template arguments follow, and if so, demangle
 2471            them.  */
 2472         if (peek_char (dm) == 'I')
 2473           RETURN_IF_ERROR (demangle_template_args (dm));
 2474         else
 2475           /* A substitution token is not itself a substitution
 2476          candidate.  (However, if the substituted template is
 2477          instantiated, the resulting type is.)  */
 2478           is_substitution_candidate = 0;
 2479       }
 2480     else
 2481       {
 2482         /* Now some trickiness.  We have a special substitution
 2483            here.  Often, the special substitution provides the
 2484            name of a template that's subsequently instantiated,
 2485            for instance `SaIcE' => std::allocator<char>.  In these
 2486            cases we need to add a substitution candidate for the
 2487            entire <class-enum-type> and thus don't want to clear
 2488            the is_substitution_candidate flag.
 2489 
 2490            However, it's possible that what we have here is a
 2491            substitution token representing an entire type, such as
 2492            `Ss' => std::string.  In this case, we mustn't add a
 2493            new substitution candidate for this substitution token.
 2494            To detect this case, remember where the start of the
 2495            substitution token is.  */
 2496         const char *next = dm->next;
 2497         /* Now demangle the <class-enum-type>.  */
 2498         RETURN_IF_ERROR 
 2499           (demangle_class_enum_type (dm, &encode_return_type));
 2500         /* If all that was just demangled is the two-character
 2501            special substitution token, supress the addition of a
 2502            new candidate for it.  */
 2503         if (dm->next == next + 2)
 2504           is_substitution_candidate = 0;
 2505       }
 2506 
 2507     break;
 2508 
 2509       case 'P':
 2510       case 'R':
 2511       case 'M':
 2512     RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
 2513     /* demangle_type_ptr adds all applicable substitution
 2514        candidates.  */
 2515     is_substitution_candidate = 0;
 2516     break;
 2517 
 2518       case 'C':
 2519     /* A C99 complex type.  */
 2520     RETURN_IF_ERROR (result_add (dm, "complex "));
 2521     advance_char (dm);
 2522     RETURN_IF_ERROR (demangle_type (dm));
 2523     break;
 2524 
 2525       case 'G':
 2526     /* A C99 imaginary type.  */
 2527     RETURN_IF_ERROR (result_add (dm, "imaginary "));
 2528     advance_char (dm);
 2529     RETURN_IF_ERROR (demangle_type (dm));
 2530     break;
 2531 
 2532       case 'U':
 2533     /* Vendor-extended type qualifier.  */
 2534     advance_char (dm);
 2535     RETURN_IF_ERROR (demangle_source_name (dm));
 2536     RETURN_IF_ERROR (result_add_char (dm, ' '));
 2537     RETURN_IF_ERROR (demangle_type (dm));
 2538     break;
 2539 
 2540       default:
 2541     return "Unexpected character in <type>.";
 2542       }
 2543 
 2544   if (is_substitution_candidate)
 2545     /* Add a new substitution for the type. If this type was a
 2546        <template-param>, pass its index since from the point of
 2547        substitutions; a <template-param> token is a substitution
 2548        candidate distinct from the type that is substituted for it.  */
 2549     RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
 2550 
 2551   /* Pop off template argument lists added during mangling of this
 2552      type.  */
 2553   pop_to_template_arg_list (dm, old_arg_list);
 2554 
 2555   return STATUS_OK;
 2556 }
 2557 
 2558 /* C++ source names of builtin types, indexed by the mangled code
 2559    letter's position in the alphabet ('a' -> 0, 'b' -> 1, etc).  */
 2560 static const char *const builtin_type_names[26] = 
 2561 {
 2562   "signed char",              /* a */
 2563   "bool",                     /* b */
 2564   "char",                     /* c */
 2565   "double",                   /* d */
 2566   "long double",              /* e */
 2567   "float",                    /* f */
 2568   "__float128",               /* g */
 2569   "unsigned char",            /* h */
 2570   "int",                      /* i */
 2571   "unsigned",                 /* j */
 2572   NULL,                       /* k */
 2573   "long",                     /* l */
 2574   "unsigned long",            /* m */
 2575   "__int128",                 /* n */
 2576   "unsigned __int128",        /* o */
 2577   NULL,                       /* p */
 2578   NULL,                       /* q */
 2579   NULL,                       /* r */
 2580   "short",                    /* s */
 2581   "unsigned short",           /* t */
 2582   NULL,                       /* u */
 2583   "void",                     /* v */
 2584   "wchar_t",                  /* w */
 2585   "long long",                /* x */
 2586   "unsigned long long",       /* y */
 2587   "..."                       /* z */
 2588 };
 2589 
 2590 /* Java source names of builtin types.  Types that arn't valid in Java
 2591    are also included here - we don't fail if someone attempts to demangle a 
 2592    C++ symbol in Java style. */
 2593 static const char *const java_builtin_type_names[26] = 
 2594 {
 2595   "signed char",                /* a */
 2596   "boolean", /* C++ "bool" */   /* b */
 2597   "byte", /* C++ "char" */      /* c */
 2598   "double",                     /* d */
 2599   "long double",                /* e */
 2600   "float",                      /* f */
 2601   "__float128",                 /* g */
 2602   "unsigned char",              /* h */
 2603   "int",                        /* i */
 2604   "unsigned",                   /* j */
 2605   NULL,                         /* k */
 2606   "long",                       /* l */
 2607   "unsigned long",              /* m */
 2608   "__int128",                   /* n */
 2609   "unsigned __int128",          /* o */
 2610   NULL,                         /* p */
 2611   NULL,                         /* q */
 2612   NULL,                         /* r */
 2613   "short",                      /* s */
 2614   "unsigned short",             /* t */
 2615   NULL,                         /* u */
 2616   "void",                       /* v */
 2617   "char", /* C++ "wchar_t" */   /* w */
 2618   "long", /* C++ "long long" */ /* x */
 2619   "unsigned long long",         /* y */
 2620   "..."                         /* z */
 2621 };
 2622 
 2623 /* Demangles and emits a <builtin-type>.  
 2624 
 2625     <builtin-type> ::= v  # void
 2626            ::= w  # wchar_t
 2627            ::= b  # bool
 2628            ::= c  # char
 2629            ::= a  # signed char
 2630            ::= h  # unsigned char
 2631            ::= s  # short
 2632            ::= t  # unsigned short
 2633            ::= i  # int
 2634            ::= j  # unsigned int
 2635            ::= l  # long
 2636            ::= m  # unsigned long
 2637            ::= x  # long long, __int64
 2638            ::= y  # unsigned long long, __int64
 2639            ::= n  # __int128
 2640            ::= o  # unsigned __int128
 2641            ::= f  # float
 2642            ::= d  # double
 2643            ::= e  # long double, __float80
 2644            ::= g  # __float128
 2645            ::= z  # ellipsis
 2646            ::= u <source-name>    # vendor extended type  */
 2647 
 2648 static status_t
 2649 demangle_builtin_type (dm)
 2650      demangling_t dm;
 2651 {
 2652 
 2653   char code = peek_char (dm);
 2654 
 2655   DEMANGLE_TRACE ("builtin-type", dm);
 2656 
 2657   if (code == 'u')
 2658     {
 2659       advance_char (dm);
 2660       RETURN_IF_ERROR (demangle_source_name (dm));
 2661       return STATUS_OK;
 2662     }
 2663   else if (code >= 'a' && code <= 'z')
 2664     {
 2665       const char *type_name;
 2666       /* Java uses different names for some built-in types. */
 2667       if (dm->style == DMGL_JAVA)
 2668         type_name = java_builtin_type_names[code - 'a'];
 2669       else
 2670         type_name = builtin_type_names[code - 'a'];
 2671       if (type_name == NULL)
 2672     return "Unrecognized <builtin-type> code.";
 2673 
 2674       RETURN_IF_ERROR (result_add (dm, type_name));
 2675       advance_char (dm);
 2676       return STATUS_OK;
 2677     }
 2678   else
 2679     return "Non-alphabetic <builtin-type> code.";
 2680 }
 2681 
 2682 /* Demangles all consecutive CV-qualifiers (const, volatile, and
 2683    restrict) at the current position.  The qualifiers are appended to
 2684    QUALIFIERS.  Returns STATUS_OK.  */
 2685 
 2686 static status_t
 2687 demangle_CV_qualifiers (dm, qualifiers)
 2688      demangling_t dm;
 2689      dyn_string_t qualifiers;
 2690 {
 2691   DEMANGLE_TRACE ("CV-qualifiers", dm);
 2692 
 2693   while (1)
 2694     {
 2695       switch (peek_char (dm))
 2696     {
 2697     case 'r':
 2698       if (!dyn_string_append_space (qualifiers))
 2699         return STATUS_ALLOCATION_FAILED;
 2700       if (!dyn_string_append_cstr (qualifiers, "restrict"))
 2701         return STATUS_ALLOCATION_FAILED;
 2702       break;
 2703 
 2704     case 'V':
 2705       if (!dyn_string_append_space (qualifiers))
 2706         return STATUS_ALLOCATION_FAILED;
 2707       if (!dyn_string_append_cstr (qualifiers, "volatile"))
 2708         return STATUS_ALLOCATION_FAILED;
 2709       break;
 2710 
 2711     case 'K':
 2712       if (!dyn_string_append_space (qualifiers))
 2713         return STATUS_ALLOCATION_FAILED;
 2714       if (!dyn_string_append_cstr (qualifiers, "const"))
 2715         return STATUS_ALLOCATION_FAILED;
 2716       break;
 2717 
 2718     default:
 2719       return STATUS_OK;
 2720     }
 2721 
 2722       advance_char (dm);
 2723     }
 2724 }
 2725 
 2726 /* Demangles and emits a <function-type>.  *FUNCTION_NAME_POS is the
 2727    position in the result string of the start of the function
 2728    identifier, at which the function's return type will be inserted;
 2729    *FUNCTION_NAME_POS is updated to position past the end of the
 2730    function's return type.
 2731 
 2732     <function-type> ::= F [Y] <bare-function-type> E  */
 2733 
 2734 static status_t
 2735 demangle_function_type (dm, function_name_pos)
 2736      demangling_t dm;
 2737      int *function_name_pos;
 2738 {
 2739   DEMANGLE_TRACE ("function-type", dm);
 2740   RETURN_IF_ERROR (demangle_char (dm, 'F'));  
 2741   if (peek_char (dm) == 'Y')
 2742     {
 2743       /* Indicate this function has C linkage if in verbose mode.  */
 2744       if (flag_verbose)
 2745     RETURN_IF_ERROR (result_add (dm, " [extern \"C\"] "));
 2746       advance_char (dm);
 2747     }
 2748   RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));
 2749   RETURN_IF_ERROR (demangle_char (dm, 'E'));
 2750   return STATUS_OK;
 2751 }
 2752 
 2753 /* Demangles and emits a <bare-function-type>.  RETURN_TYPE_POS is the
 2754    position in the result string at which the function return type
 2755    should be inserted.  If RETURN_TYPE_POS is BFT_NO_RETURN_TYPE, the
 2756    function's return type is assumed not to be encoded.  
 2757 
 2758     <bare-function-type> ::= <signature type>+  */
 2759 
 2760 static status_t
 2761 demangle_bare_function_type (dm, return_type_pos)
 2762      demangling_t dm;
 2763      int *return_type_pos;
 2764 {
 2765   /* Sequence is the index of the current function parameter, counting
 2766      from zero.  The value -1 denotes the return type.  */
 2767   int sequence = 
 2768     (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1);
 2769 
 2770   DEMANGLE_TRACE ("bare-function-type", dm);
 2771 
 2772   RETURN_IF_ERROR (result_add_char (dm, '('));
 2773   while (!end_of_name_p (dm) && peek_char (dm) != 'E')
 2774     {
 2775       if (sequence == -1)
 2776     /* We're decoding the function's return type.  */
 2777     {
 2778       dyn_string_t return_type;
 2779       status_t status = STATUS_OK;
 2780 
 2781       /* Decode the return type off to the side.  */
 2782       RETURN_IF_ERROR (result_push (dm));
 2783       RETURN_IF_ERROR (demangle_type (dm));
 2784       return_type = (dyn_string_t) result_pop (dm);
 2785 
 2786       /* Add a space to the end of the type.  Insert the return
 2787              type where we've been asked to. */
 2788       if (!dyn_string_append_space (return_type))
 2789         status = STATUS_ALLOCATION_FAILED;
 2790       if (STATUS_NO_ERROR (status))
 2791         {
 2792           if (!dyn_string_insert (result_string (dm), *return_type_pos, 
 2793                       return_type))
 2794         status = STATUS_ALLOCATION_FAILED;
 2795           else
 2796         *return_type_pos += dyn_string_length (return_type);
 2797         }
 2798 
 2799       dyn_string_delete (return_type);
 2800       RETURN_IF_ERROR (status);
 2801     }
 2802       else 
 2803     {
 2804       /* Skip `void' parameter types.  One should only occur as
 2805          the only type in a parameter list; in that case, we want
 2806          to print `foo ()' instead of `foo (void)'.  */
 2807       if (peek_char (dm) == 'v')
 2808         /* Consume the v.  */
 2809         advance_char (dm);
 2810       else
 2811         {
 2812           /* Separate parameter types by commas.  */
 2813           if (sequence > 0)
 2814         RETURN_IF_ERROR (result_add (dm, ", "));
 2815           /* Demangle the type.  */
 2816           RETURN_IF_ERROR (demangle_type (dm));
 2817         }
 2818     }
 2819 
 2820       ++sequence;
 2821     }
 2822   RETURN_IF_ERROR (result_add_char (dm, ')'));
 2823 
 2824   /* We should have demangled at least one parameter type (which would
 2825      be void, for a function that takes no parameters), plus the
 2826      return type, if we were supposed to demangle that.  */
 2827   if (sequence == -1)
 2828     return "Missing function return type.";
 2829   else if (sequence == 0)
 2830     return "Missing function parameter.";
 2831 
 2832   return STATUS_OK;
 2833 }
 2834 
 2835 /* Demangles and emits a <class-enum-type>.  *ENCODE_RETURN_TYPE is set to
 2836    non-zero if the type is a template-id, zero otherwise.  
 2837 
 2838     <class-enum-type> ::= <name>  */
 2839 
 2840 static status_t
 2841 demangle_class_enum_type (dm, encode_return_type)
 2842      demangling_t dm;
 2843      int *encode_return_type;
 2844 {
 2845   DEMANGLE_TRACE ("class-enum-type", dm);
 2846 
 2847   RETURN_IF_ERROR (demangle_name (dm, encode_return_type));
 2848   return STATUS_OK;
 2849 }
 2850 
 2851 /* Demangles and emits an <array-type>.  
 2852 
 2853    If PTR_INSERT_POS is not NULL, the array type is formatted as a
 2854    pointer or reference to an array, except that asterisk and
 2855    ampersand punctuation is omitted (since it's not know at this
 2856    point).  *PTR_INSERT_POS is set to the position in the demangled
 2857    name at which this punctuation should be inserted.  For example,
 2858    `A10_i' is demangled to `int () [10]' and *PTR_INSERT_POS points
 2859    between the parentheses.
 2860 
 2861    If PTR_INSERT_POS is NULL, the array type is assumed not to be
 2862    pointer- or reference-qualified.  Then, for example, `A10_i' is
 2863    demangled simply as `int[10]'.  
 2864 
 2865     <array-type> ::= A [<dimension number>] _ <element type>  
 2866                  ::= A <dimension expression> _ <element type>  */
 2867 
 2868 static status_t
 2869 demangle_array_type (dm, ptr_insert_pos)
 2870      demangling_t dm;
 2871      int *ptr_insert_pos;
 2872 {
 2873   status_t status = STATUS_OK;
 2874   dyn_string_t array_size = NULL;
 2875   char peek;
 2876 
 2877   DEMANGLE_TRACE ("array-type", dm);
 2878 
 2879   RETURN_IF_ERROR (demangle_char (dm, 'A'));
 2880 
 2881   /* Demangle the array size into array_size.  */
 2882   peek = peek_char (dm);
 2883   if (peek == '_')
 2884     /* Array bound is omitted.  This is a C99-style VLA.  */
 2885     ;
 2886   else if (IS_DIGIT (peek_char (dm))) 
 2887     {
 2888       /* It looks like a constant array bound.  */
 2889       array_size = dyn_string_new (10);
 2890       if (array_size == NULL)
 2891     return STATUS_ALLOCATION_FAILED;
 2892       status = demangle_number_literally (dm, array_size, 10, 0);
 2893     }
 2894   else
 2895     {
 2896       /* Anything is must be an expression for a nont-constant array
 2897      bound.  This happens if the array type occurs in a template
 2898      and the array bound references a template parameter.  */
 2899       RETURN_IF_ERROR (result_push (dm));
 2900       RETURN_IF_ERROR (demangle_expression (dm));
 2901       array_size = (dyn_string_t) result_pop (dm);
 2902     }
 2903   /* array_size may have been allocated by now, so we can't use
 2904      RETURN_IF_ERROR until it's been deallocated.  */
 2905 
 2906   /* Demangle the base type of the array.  */
 2907   if (STATUS_NO_ERROR (status))
 2908     status = demangle_char (dm, '_');
 2909   if (STATUS_NO_ERROR (status))
 2910     status = demangle_type (dm);
 2911 
 2912   if (ptr_insert_pos != NULL)
 2913     {
 2914       /* This array is actually part of an pointer- or
 2915      reference-to-array type.  Format appropriately, except we
 2916      don't know which and how much punctuation to use.  */
 2917       if (STATUS_NO_ERROR (status))
 2918     status = result_add (dm, " () ");
 2919       /* Let the caller know where to insert the punctuation.  */
 2920       *ptr_insert_pos = result_caret_pos (dm) - 2;
 2921     }
 2922 
 2923   /* Emit the array dimension syntax.  */
 2924   if (STATUS_NO_ERROR (status))
 2925     status = result_add_char (dm, '[');
 2926   if (STATUS_NO_ERROR (status) && array_size != NULL)
 2927     status = result_add_string (dm, array_size);
 2928   if (STATUS_NO_ERROR (status))
 2929     status = result_add_char (dm, ']');
 2930   if (array_size != NULL)
 2931     dyn_string_delete (array_size);
 2932   
 2933   RETURN_IF_ERROR (status);
 2934 
 2935   return STATUS_OK;
 2936 }
 2937 
 2938 /* Demangles and emits a <template-param>.  
 2939 
 2940     <template-param> ::= T_       # first template parameter
 2941                      ::= T <parameter-2 number> _  */
 2942 
 2943 static status_t
 2944 demangle_template_param (dm)
 2945      demangling_t dm;
 2946 {
 2947   int parm_number;
 2948   template_arg_list_t current_arg_list = current_template_arg_list (dm);
 2949   string_list_t arg;
 2950 
 2951   DEMANGLE_TRACE ("template-param", dm);
 2952 
 2953   /* Make sure there is a template argmust list in which to look up
 2954      this parameter reference.  */
 2955   if (current_arg_list == NULL)
 2956     return "Template parameter outside of template.";
 2957 
 2958   RETURN_IF_ERROR (demangle_char (dm, 'T'));
 2959   if (peek_char (dm) == '_')
 2960     parm_number = 0;
 2961   else
 2962     {
 2963       RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0));
 2964       ++parm_number;
 2965     }
 2966   RETURN_IF_ERROR (demangle_char (dm, '_'));
 2967 
 2968   arg = template_arg_list_get_arg (current_arg_list, parm_number);
 2969   if (arg == NULL)
 2970     /* parm_number exceeded the number of arguments in the current
 2971        template argument list.  */
 2972     return "Template parameter number out of bounds.";
 2973   RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
 2974 
 2975   return STATUS_OK;
 2976 }
 2977 
 2978 /* Demangles and emits a <template-args>.  
 2979 
 2980     <template-args> ::= I <template-arg>+ E  */
 2981 
 2982 static status_t
 2983 demangle_template_args (dm)
 2984      demangling_t dm;
 2985 {
 2986   int first = 1;
 2987   dyn_string_t old_last_source_name;
 2988   template_arg_list_t arg_list = template_arg_list_new ();
 2989 
 2990   if (arg_list == NULL)
 2991     return STATUS_ALLOCATION_FAILED;
 2992 
 2993   /* Preserve the most recently demangled source name.  */
 2994   old_last_source_name = dm->last_source_name;
 2995   dm->last_source_name = dyn_string_new (0);
 2996 
 2997   DEMANGLE_TRACE ("template-args", dm);
 2998 
 2999   if (dm->last_source_name == NULL)
 3000     return STATUS_ALLOCATION_FAILED;
 3001 
 3002   RETURN_IF_ERROR (demangle_char (dm, 'I'));
 3003   RETURN_IF_ERROR (result_open_template_list (dm));
 3004   do
 3005     {
 3006       string_list_t arg;
 3007 
 3008       if (first)
 3009     first = 0;
 3010       else
 3011     RETURN_IF_ERROR (result_add (dm, ", "));
 3012 
 3013       /* Capture the template arg.  */
 3014       RETURN_IF_ERROR (result_push (dm));
 3015       RETURN_IF_ERROR (demangle_template_arg (dm));
 3016       arg = result_pop (dm);
 3017 
 3018       /* Emit it in the demangled name.  */
 3019       RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
 3020 
 3021       /* Save it for use in expanding <template-param>s.  */
 3022       template_arg_list_add_arg (arg_list, arg);
 3023     }
 3024   while (peek_char (dm) != 'E');
 3025   /* Append the '>'.  */
 3026   RETURN_IF_ERROR (result_close_template_list (dm));
 3027 
 3028   /* Consume the 'E'.  */
 3029   advance_char (dm);
 3030 
 3031   /* Restore the most recent demangled source name.  */
 3032   dyn_string_delete (dm->last_source_name);
 3033   dm->last_source_name = old_last_source_name;
 3034 
 3035   /* Push the list onto the top of the stack of template argument
 3036      lists, so that arguments from it are used from now on when
 3037      expanding <template-param>s.  */
 3038   push_template_arg_list (dm, arg_list);
 3039 
 3040   return STATUS_OK;
 3041 }
 3042 
 3043 /* This function, which does not correspond to a production in the
 3044    mangling spec, handles the `literal' production for both
 3045    <template-arg> and <expr-primary>.  It does not expect or consume
 3046    the initial `L' or final `E'.  The demangling is given by:
 3047 
 3048      <literal> ::= <type> </value/ number>
 3049 
 3050    and the emitted output is `(type)number'.  */
 3051 
 3052 static status_t
 3053 demangle_literal (dm)
 3054      demangling_t dm;
 3055 {
 3056   char peek = peek_char (dm);
 3057   dyn_string_t value_string;
 3058   status_t status;
 3059 
 3060   DEMANGLE_TRACE ("literal", dm);
 3061 
 3062   if (!flag_verbose && peek >= 'a' && peek <= 'z')
 3063     {
 3064       /* If not in verbose mode and this is a builtin type, see if we
 3065      can produce simpler numerical output.  In particular, for
 3066      integer types shorter than `long', just write the number
 3067      without type information; for bools, write `true' or `false'.
 3068      Other refinements could be made here too.  */
 3069 
 3070       /* This constant string is used to map from <builtin-type> codes
 3071      (26 letters of the alphabet) to codes that determine how the 
 3072      value will be displayed.  The codes are:
 3073        b: display as bool
 3074        i: display as int
 3075            l: display as long
 3076      A space means the value will be represented using cast
 3077      notation. */
 3078       static const char *const code_map = "ibi    iii ll     ii  i  ";
 3079 
 3080       char code = code_map[peek - 'a'];
 3081       /* FIXME: Implement demangling of floats and doubles.  */
 3082       if (code == 'u')
 3083     return STATUS_UNIMPLEMENTED;
 3084       if (code == 'b')
 3085     {
 3086       /* It's a boolean.  */
 3087       char value;
 3088 
 3089       /* Consume the b.  */
 3090       advance_char (dm);
 3091       /* Look at the next character.  It should be 0 or 1,
 3092          corresponding to false or true, respectively.  */
 3093       value = peek_char (dm);
 3094       if (value == '0')
 3095         RETURN_IF_ERROR (result_add (dm, "false"));
 3096       else if (value == '1')
 3097         RETURN_IF_ERROR (result_add (dm, "true"));
 3098       else
 3099         return "Unrecognized bool constant.";
 3100       /* Consume the 0 or 1.  */
 3101       advance_char (dm);
 3102       return STATUS_OK;
 3103     }
 3104       else if (code == 'i' || code == 'l')
 3105     {
 3106       /* It's an integer or long.  */
 3107 
 3108       /* Consume the type character.  */
 3109       advance_char (dm);
 3110 
 3111       /* Demangle the number and write it out.  */
 3112       value_string = dyn_string_new (0);
 3113       status = demangle_number_literally (dm, value_string, 10, 1);
 3114       if (STATUS_NO_ERROR (status))
 3115         status = result_add_string (dm, value_string);
 3116       /* For long integers, append an l.  */
 3117       if (code == 'l' && STATUS_NO_ERROR (status))
 3118         status = result_add_char (dm, code);
 3119       dyn_string_delete (value_string);
 3120 
 3121       RETURN_IF_ERROR (status);
 3122       return STATUS_OK;
 3123     }
 3124       /* ...else code == ' ', so fall through to represent this
 3125      literal's type explicitly using cast syntax.  */
 3126     }
 3127 
 3128   RETURN_IF_ERROR (result_add_char (dm, '('));
 3129   RETURN_IF_ERROR (demangle_type (dm));
 3130   RETURN_IF_ERROR (result_add_char (dm, ')'));
 3131 
 3132   value_string = dyn_string_new (0);
 3133   if (value_string == NULL)
 3134     return STATUS_ALLOCATION_FAILED;
 3135 
 3136   status = demangle_number_literally (dm, value_string, 10, 1);
 3137   if (STATUS_NO_ERROR (status))
 3138     status = result_add_string (dm, value_string);
 3139   dyn_string_delete (value_string);
 3140   RETURN_IF_ERROR (status);
 3141 
 3142   return STATUS_OK;
 3143 }
 3144 
 3145 /* Demangles and emits a <template-arg>.  
 3146 
 3147     <template-arg> ::= <type>                     # type
 3148                    ::= L <type> <value number> E  # literal
 3149                    ::= LZ <encoding> E            # external name
 3150                    ::= X <expression> E           # expression  */
 3151 
 3152 static status_t
 3153 demangle_template_arg (dm)
 3154      demangling_t dm;
 3155 {
 3156   DEMANGLE_TRACE ("template-arg", dm);
 3157 
 3158   switch (peek_char (dm))
 3159     {
 3160     case 'L':
 3161       advance_char (dm);
 3162 
 3163       if (peek_char (dm) == 'Z')
 3164     {
 3165       /* External name.  */
 3166       advance_char (dm);
 3167       /* FIXME: Standard is contradictory here.  */
 3168       RETURN_IF_ERROR (demangle_encoding (dm));
 3169     }
 3170       else
 3171     RETURN_IF_ERROR (demangle_literal (dm));
 3172       RETURN_IF_ERROR (demangle_char (dm, 'E'));
 3173       break;
 3174 
 3175     case 'X':
 3176       /* Expression.  */
 3177       advance_char (dm);
 3178       RETURN_IF_ERROR (demangle_expression (dm));
 3179       RETURN_IF_ERROR (demangle_char (dm, 'E'));
 3180       break;
 3181 
 3182     default:
 3183       RETURN_IF_ERROR (demangle_type (dm));
 3184       break;
 3185     }
 3186 
 3187   return STATUS_OK;
 3188 }
 3189 
 3190 /* Demangles and emits an <expression>.
 3191 
 3192     <expression> ::= <unary operator-name> <expression>
 3193          ::= <binary operator-name> <expression> <expression>
 3194          ::= <expr-primary>  
 3195                  ::= <scope-expression>  */
 3196 
 3197 static status_t
 3198 demangle_expression (dm)
 3199      demangling_t dm;
 3200 {
 3201   char peek = peek_char (dm);
 3202 
 3203   DEMANGLE_TRACE ("expression", dm);
 3204 
 3205   if (peek == 'L' || peek == 'T')
 3206     RETURN_IF_ERROR (demangle_expr_primary (dm));
 3207   else if (peek == 's' && peek_char_next (dm) == 'r')
 3208     RETURN_IF_ERROR (demangle_scope_expression (dm));
 3209   else
 3210     /* An operator expression.  */
 3211     {
 3212       int num_args;
 3213       int type_arg;
 3214       status_t status = STATUS_OK;
 3215       dyn_string_t operator_name;
 3216 
 3217       /* We have an operator name.  Since we want to output binary
 3218      operations in infix notation, capture the operator name
 3219      first.  */
 3220       RETURN_IF_ERROR (result_push (dm));
 3221       RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args,
 3222                            &type_arg));
 3223       operator_name = (dyn_string_t) result_pop (dm);
 3224 
 3225       /* If it's binary, do an operand first.  */
 3226       if (num_args > 1)
 3227     {
 3228       status = result_add_char (dm, '(');
 3229       if (STATUS_NO_ERROR (status))
 3230         status = demangle_expression (dm);
 3231       if (STATUS_NO_ERROR (status))
 3232         status = result_add_char (dm, ')');
 3233     }
 3234 
 3235       /* Emit the operator.  */  
 3236       if (STATUS_NO_ERROR (status))
 3237     status = result_add_string (dm, operator_name);
 3238       dyn_string_delete (operator_name);
 3239       RETURN_IF_ERROR (status);
 3240       
 3241       /* Emit its second (if binary) or only (if unary) operand.  */
 3242       RETURN_IF_ERROR (result_add_char (dm, '('));
 3243       if (type_arg)
 3244     RETURN_IF_ERROR (demangle_type (dm));
 3245       else
 3246     RETURN_IF_ERROR (demangle_expression (dm));
 3247       RETURN_IF_ERROR (result_add_char (dm, ')'));
 3248 
 3249       /* The ternary operator takes a third operand.  */
 3250       if (num_args == 3)
 3251     {
 3252       RETURN_IF_ERROR (result_add (dm, ":("));
 3253       RETURN_IF_ERROR (demangle_expression (dm));
 3254       RETURN_IF_ERROR (result_add_char (dm, ')'));
 3255     }
 3256     }
 3257 
 3258   return STATUS_OK;
 3259 }
 3260 
 3261 /* Demangles and emits a <scope-expression>.  
 3262 
 3263     <scope-expression> ::= sr <qualifying type> <source-name>
 3264                        ::= sr <qualifying type> <encoding>  */
 3265 
 3266 static status_t
 3267 demangle_scope_expression (dm)
 3268      demangling_t dm;
 3269 {
 3270   RETURN_IF_ERROR (demangle_char (dm, 's'));
 3271   RETURN_IF_ERROR (demangle_char (dm, 'r'));
 3272   RETURN_IF_ERROR (demangle_type (dm));
 3273   RETURN_IF_ERROR (result_add (dm, "::"));
 3274   RETURN_IF_ERROR (demangle_encoding (dm));
 3275   return STATUS_OK;
 3276 }
 3277 
 3278 /* Demangles and emits an <expr-primary>.  
 3279 
 3280     <expr-primary> ::= <template-param>
 3281            ::= L <type> <value number> E  # literal
 3282            ::= L <mangled-name> E         # external name  */
 3283 
 3284 static status_t
 3285 demangle_expr_primary (dm)
 3286      demangling_t dm;
 3287 {
 3288   char peek = peek_char (dm);
 3289 
 3290   DEMANGLE_TRACE ("expr-primary", dm);
 3291 
 3292   if (peek == 'T')
 3293     RETURN_IF_ERROR (demangle_template_param (dm));
 3294   else if (peek == 'L')
 3295     {
 3296       /* Consume the `L'.  */
 3297       advance_char (dm);
 3298       peek = peek_char (dm);
 3299 
 3300       if (peek == '_')
 3301     RETURN_IF_ERROR (demangle_mangled_name (dm));
 3302       else
 3303     RETURN_IF_ERROR (demangle_literal (dm));
 3304 
 3305       RETURN_IF_ERROR (demangle_char (dm, 'E'));
 3306     }
 3307   else
 3308     return STATUS_ERROR;
 3309 
 3310   return STATUS_OK;
 3311 }
 3312 
 3313 /* Demangles and emits a <substitution>.  Sets *TEMPLATE_P to non-zero
 3314    if the substitution is the name of a template, zero otherwise. 
 3315 
 3316      <substitution> ::= S <seq-id> _
 3317                     ::= S_
 3318 
 3319                     ::= St   # ::std::
 3320                     ::= Sa   # ::std::allocator
 3321                     ::= Sb   # ::std::basic_string
 3322                     ::= Ss   # ::std::basic_string<char,
 3323                                ::std::char_traits<char>,
 3324                            ::std::allocator<char> >
 3325                     ::= Si   # ::std::basic_istream<char,  
 3326                                                     std::char_traits<char> >
 3327                     ::= So   # ::std::basic_ostream<char,  
 3328                                                     std::char_traits<char> >
 3329                     ::= Sd   # ::std::basic_iostream<char, 
 3330                                                     std::char_traits<char> >
 3331 */
 3332 
 3333 static status_t
 3334 demangle_substitution (dm, template_p)
 3335      demangling_t dm;
 3336      int *template_p;
 3337 {
 3338   int seq_id;
 3339   int peek;
 3340   dyn_string_t text;
 3341 
 3342   DEMANGLE_TRACE ("substitution", dm);
 3343 
 3344   RETURN_IF_ERROR (demangle_char (dm, 'S'));
 3345 
 3346   /* Scan the substitution sequence index.  A missing number denotes
 3347      the first index.  */
 3348   peek = peek_char (dm);
 3349   if (peek == '_')
 3350     seq_id = -1;
 3351   /* If the following character is 0-9 or a capital letter, interpret
 3352      the sequence up to the next underscore as a base-36 substitution
 3353      index.  */
 3354   else if (IS_DIGIT ((unsigned char) peek) 
 3355        || (peek >= 'A' && peek <= 'Z'))
 3356     RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0));
 3357   else 
 3358     {
 3359       const char *new_last_source_name = NULL;
 3360 
 3361       switch (peek)
 3362     {
 3363     case 't':
 3364       RETURN_IF_ERROR (result_add (dm, "std"));
 3365       break;
 3366 
 3367     case 'a':
 3368       RETURN_IF_ERROR (result_add (dm, "std::allocator"));
 3369       new_last_source_name = "allocator";
 3370       *template_p = 1;
 3371       break;
 3372 
 3373     case 'b':
 3374       RETURN_IF_ERROR (result_add (dm, "std::basic_string"));
 3375       new_last_source_name = "basic_string";
 3376       *template_p = 1;
 3377       break;
 3378       
 3379     case 's':
 3380       if (!flag_verbose)
 3381         {
 3382           RETURN_IF_ERROR (result_add (dm, "std::string"));
 3383           new_last_source_name = "string";
 3384         }
 3385       else
 3386         {
 3387           RETURN_IF_ERROR (result_add (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
 3388           new_last_source_name = "basic_string";
 3389         }
 3390       *template_p = 0;
 3391       break;
 3392 
 3393     case 'i':
 3394       if (!flag_verbose)
 3395         {
 3396           RETURN_IF_ERROR (result_add (dm, "std::istream"));
 3397           new_last_source_name = "istream";
 3398         }
 3399       else
 3400         {
 3401           RETURN_IF_ERROR (result_add (dm, "std::basic_istream<char, std::char_traits<char> >"));
 3402           new_last_source_name = "basic_istream";
 3403         }
 3404       *template_p = 0;
 3405       break;
 3406 
 3407     case 'o':
 3408       if (!flag_verbose)
 3409         {
 3410           RETURN_IF_ERROR (result_add (dm, "std::ostream"));
 3411           new_last_source_name = "ostream";
 3412         }
 3413       else
 3414         {
 3415           RETURN_IF_ERROR (result_add (dm, "std::basic_ostream<char, std::char_traits<char> >"));
 3416           new_last_source_name = "basic_ostream";
 3417         }
 3418       *template_p = 0;
 3419       break;
 3420 
 3421     case 'd':
 3422       if (!flag_verbose) 
 3423         {
 3424           RETURN_IF_ERROR (result_add (dm, "std::iostream"));
 3425           new_last_source_name = "iostream";
 3426         }
 3427       else
 3428         {
 3429           RETURN_IF_ERROR (result_add (dm, "std::basic_iostream<char, std::char_traits<char> >"));
 3430           new_last_source_name = "basic_iostream";
 3431         }
 3432       *template_p = 0;
 3433       break;
 3434 
 3435     default:
 3436       return "Unrecognized <substitution>.";
 3437     }
 3438       
 3439       /* Consume the character we just processed.  */
 3440       advance_char (dm);
 3441 
 3442       if (new_last_source_name != NULL)
 3443     {
 3444       if (!dyn_string_copy_cstr (dm->last_source_name, 
 3445                      new_last_source_name))
 3446         return STATUS_ALLOCATION_FAILED;
 3447     }
 3448 
 3449       return STATUS_OK;
 3450     }
 3451 
 3452   /* Look up the substitution text.  Since `S_' is the most recent
 3453      substitution, `S0_' is the second-most-recent, etc., shift the
 3454      numbering by one.  */
 3455   text = substitution_get (dm, seq_id + 1, template_p);
 3456   if (text == NULL) 
 3457     return "Substitution number out of range.";
 3458 
 3459   /* Emit the substitution text.  */
 3460   RETURN_IF_ERROR (result_add_string (dm, text));
 3461 
 3462   RETURN_IF_ERROR (demangle_char (dm, '_'));
 3463   return STATUS_OK;
 3464 }
 3465 
 3466 /* Demangles and emits a <local-name>.  
 3467 
 3468     <local-name> := Z <function encoding> E <entity name> [<discriminator>]
 3469                  := Z <function encoding> E s [<discriminator>]  */
 3470 
 3471 static status_t
 3472 demangle_local_name (dm)
 3473      demangling_t dm;
 3474 {
 3475   DEMANGLE_TRACE ("local-name", dm);
 3476 
 3477   RETURN_IF_ERROR (demangle_char (dm, 'Z'));
 3478   RETURN_IF_ERROR (demangle_encoding (dm));
 3479   RETURN_IF_ERROR (demangle_char (dm, 'E'));
 3480   RETURN_IF_ERROR (result_add (dm, "::"));
 3481 
 3482   if (peek_char (dm) == 's')
 3483     {
 3484       /* Local character string literal.  */
 3485       RETURN_IF_ERROR (result_add (dm, "string literal"));
 3486       /* Consume the s.  */
 3487       advance_char (dm);
 3488       RETURN_IF_ERROR (demangle_discriminator (dm, 0));
 3489     }
 3490   else
 3491     {
 3492       int unused;
 3493       /* Local name for some other entity.  Demangle its name.  */
 3494       RETURN_IF_ERROR (demangle_name (dm, &unused));
 3495       RETURN_IF_ERROR (demangle_discriminator (dm, 1));
 3496      }
 3497 
 3498    return STATUS_OK;
 3499  }
 3500 
 3501  /* Optimonally demangles and emits a <discriminator>.  If there is no
 3502     <discriminator> at the current position in the mangled string, the
 3503     descriminator is assumed to be zero.  Emit the discriminator number
 3504     in parentheses, unless SUPPRESS_FIRST is non-zero and the
 3505     discriminator is zero.  
 3506 
 3507      <discriminator> ::= _ <number>  */
 3508 
 3509 static status_t
 3510 demangle_discriminator (dm, suppress_first)
 3511      demangling_t dm;
 3512      int suppress_first;
 3513 {
 3514   /* Output for <discriminator>s to the demangled name is completely
 3515      suppressed if not in verbose mode.  */
 3516 
 3517   if (peek_char (dm) == '_')
 3518     {
 3519       /* Consume the underscore.  */
 3520       advance_char (dm);
 3521       if (flag_verbose)
 3522     RETURN_IF_ERROR (result_add (dm, " [#"));
 3523       /* Check if there's a number following the underscore.  */
 3524       if (IS_DIGIT ((unsigned char) peek_char (dm)))
 3525     {
 3526       int discriminator;
 3527       /* Demangle the number.  */
 3528       RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0));
 3529       if (flag_verbose)
 3530         /* Write the discriminator.  The mangled number is two
 3531            less than the discriminator ordinal, counting from
 3532            zero.  */
 3533         RETURN_IF_ERROR (int_to_dyn_string (discriminator + 1,
 3534                         (dyn_string_t) dm->result));
 3535     }
 3536       else
 3537     return STATUS_ERROR;
 3538       if (flag_verbose)
 3539     RETURN_IF_ERROR (result_add_char (dm, ']'));
 3540     }
 3541   else if (!suppress_first)
 3542     {
 3543       if (flag_verbose)
 3544     RETURN_IF_ERROR (result_add (dm, " [#0]"));
 3545     }
 3546 
 3547   return STATUS_OK;
 3548 }
 3549 
 3550 /* Demangle NAME into RESULT, which must be an initialized
 3551    dyn_string_t.  On success, returns STATUS_OK.  On failure, returns
 3552    an error message, and the contents of RESULT are unchanged.  */
 3553 
 3554 static status_t
 3555 cp_demangle (name, result, style)
 3556      const char *name;
 3557      dyn_string_t result;
 3558      int style;
 3559 {
 3560   status_t status;
 3561   int length = strlen (name);
 3562 
 3563   if (length > 2 && name[0] == '_' && name[1] == 'Z')
 3564     {
 3565       demangling_t dm = demangling_new (name, style);
 3566       if (dm == NULL)
 3567     return STATUS_ALLOCATION_FAILED;
 3568 
 3569       status = result_push (dm);
 3570       if (status != STATUS_OK)
 3571     {
 3572       demangling_delete (dm);
 3573       return status;
 3574     }
 3575 
 3576       status = demangle_mangled_name (dm);
 3577       if (STATUS_NO_ERROR (status))
 3578     {
 3579       dyn_string_t demangled = (dyn_string_t) result_pop (dm);
 3580       if (!dyn_string_copy (result, demangled))
 3581         return STATUS_ALLOCATION_FAILED;
 3582       dyn_string_delete (demangled);
 3583     }
 3584       
 3585       demangling_delete (dm);
 3586     }
 3587   else
 3588     {
 3589       /* It's evidently not a mangled C++ name.  It could be the name
 3590      of something with C linkage, though, so just copy NAME into
 3591      RESULT.  */
 3592       if (!dyn_string_copy_cstr (result, name))
 3593     return STATUS_ALLOCATION_FAILED;
 3594       status = STATUS_OK;
 3595     }
 3596 
 3597   return status; 
 3598 }
 3599 
 3600 /* Demangle TYPE_NAME into RESULT, which must be an initialized
 3601    dyn_string_t.  On success, returns STATUS_OK.  On failiure, returns
 3602    an error message, and the contents of RESULT are unchanged.  */
 3603 
 3604 static status_t
 3605 cp_demangle_type (type_name, result)
 3606      const char* type_name;
 3607      dyn_string_t result;
 3608 {
 3609   status_t status;
 3610   demangling_t dm = demangling_new (type_name, DMGL_GNU_V3);
 3611   
 3612   if (dm == NULL)
 3613     return STATUS_ALLOCATION_FAILED;
 3614 
 3615   /* Demangle the type name.  The demangled name is stored in dm.  */
 3616   status = result_push (dm);
 3617   if (status != STATUS_OK)
 3618     {
 3619       demangling_delete (dm);
 3620       return status;
 3621     }
 3622 
 3623   status = demangle_type (dm);
 3624 
 3625   if (STATUS_NO_ERROR (status))
 3626     {
 3627       /* The demangling succeeded.  Pop the result out of dm and copy
 3628      it into RESULT.  */
 3629       dyn_string_t demangled = (dyn_string_t) result_pop (dm);
 3630       if (!dyn_string_copy (result, demangled))
 3631     return STATUS_ALLOCATION_FAILED;
 3632       dyn_string_delete (demangled);
 3633     }
 3634 
 3635   /* Clean up.  */
 3636   demangling_delete (dm);
 3637 
 3638   return status;
 3639 }
 3640 
 3641 #if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
 3642 extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
 3643 
 3644 /* ia64 ABI-mandated entry point in the C++ runtime library for performing
 3645    demangling.  MANGLED_NAME is a NUL-terminated character string
 3646    containing the name to be demangled.  
 3647 
 3648    OUTPUT_BUFFER is a region of memory, allocated with malloc, of
 3649    *LENGTH bytes, into which the demangled name is stored.  If
 3650    OUTPUT_BUFFER is not long enough, it is expanded using realloc.
 3651    OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
 3652    is placed in a region of memory allocated with malloc.  
 3653 
 3654    If LENGTH is non-NULL, the length of the buffer conaining the
 3655    demangled name, is placed in *LENGTH.  
 3656 
 3657    The return value is a pointer to the start of the NUL-terminated
 3658    demangled name, or NULL if the demangling fails.  The caller is
 3659    responsible for deallocating this memory using free.  
 3660 
 3661    *STATUS is set to one of the following values:
 3662       0: The demangling operation succeeded.
 3663      -1: A memory allocation failiure occurred.
 3664      -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
 3665      -3: One of the arguments is invalid.
 3666 
 3667    The demagling is performed using the C++ ABI mangling rules, with
 3668    GNU extensions.  */
 3669 
 3670 char *
 3671 __cxa_demangle (mangled_name, output_buffer, length, status)
 3672      const char *mangled_name;
 3673      char *output_buffer;
 3674      size_t *length;
 3675      int *status;
 3676 {
 3677   struct dyn_string demangled_name;
 3678   status_t result;
 3679 
 3680   if (status == NULL)
 3681     return NULL;
 3682 
 3683   if (mangled_name == NULL) {
 3684     *status = -3;
 3685     return NULL;
 3686   }
 3687 
 3688   /* Did the caller provide a buffer for the demangled name?  */
 3689   if (output_buffer == NULL) {
 3690     /* No; dyn_string will malloc a buffer for us.  */
 3691     if (!dyn_string_init (&demangled_name, 0)) 
 3692       {
 3693     *status = -1;
 3694     return NULL;
 3695       }
 3696   }
 3697   else {
 3698     /* Yes.  Check that the length was provided.  */
 3699     if (length == NULL) {
 3700       *status = -3;
 3701       return NULL;
 3702     }
 3703     /* Install the buffer into a dyn_string.  */
 3704     demangled_name.allocated = *length;
 3705     demangled_name.length = 0;
 3706     demangled_name.s = output_buffer;
 3707   }
 3708 
 3709   if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
 3710     /* MANGLED_NAME apprears to be a function or variable name.
 3711        Demangle it accordingly.  */
 3712     result = cp_demangle (mangled_name, &demangled_name, 0);
 3713   else
 3714     /* Try to demangled MANGLED_NAME as the name of a type.  */
 3715     result = cp_demangle_type (mangled_name, &demangled_name);
 3716 
 3717   if (result == STATUS_OK) 
 3718     /* The demangling succeeded.  */
 3719     {
 3720       /* If LENGTH isn't NULL, store the allocated buffer length
 3721      there; the buffer may have been realloced by dyn_string
 3722      functions.  */
 3723       if (length != NULL)
 3724     *length = demangled_name.allocated;
 3725       /* The operation was a success.  */
 3726       *status = 0;
 3727       return dyn_string_buf (&demangled_name);
 3728     }
 3729   else if (result == STATUS_ALLOCATION_FAILED)
 3730     /* A call to malloc or realloc failed during the demangling
 3731        operation.  */
 3732     {
 3733       *status = -1;
 3734       return NULL;
 3735     }
 3736   else
 3737     /* The demangling failed for another reason, most probably because
 3738        MANGLED_NAME isn't a valid mangled name.  */
 3739     {
 3740       /* If the buffer containing the demangled name wasn't provided
 3741      by the caller, free it.  */
 3742       if (output_buffer == NULL)
 3743     free (dyn_string_buf (&demangled_name));
 3744       *status = -2;
 3745       return NULL;
 3746     }
 3747 }
 3748 
 3749 #else /* ! (IN_LIBGCC2 || IN_GLIBCPP_V3) */
 3750 
 3751 /* Variant entry point for integration with the existing cplus-dem
 3752    demangler.  Attempts to demangle MANGLED.  If the demangling
 3753    succeeds, returns a buffer, allocated with malloc, containing the
 3754    demangled name.  The caller must deallocate the buffer using free.
 3755    If the demangling failes, returns NULL.  */
 3756 
 3757 char *
 3758 cplus_demangle_v3 (mangled, options)
 3759      const char* mangled;
 3760      int options;
 3761 {
 3762   dyn_string_t demangled;
 3763   status_t status;
 3764   int type = !!(options & DMGL_TYPES);
 3765 
 3766   if (mangled[0] == '_' && mangled[1] == 'Z')
 3767     /* It is not a type.  */
 3768     type = 0;
 3769   else
 3770     {
 3771       /* It is a type. Stop if we don't want to demangle types. */
 3772       if (!type)
 3773     return NULL;
 3774     }
 3775 
 3776   flag_verbose = !!(options & DMGL_VERBOSE);
 3777 
 3778   /* Create a dyn_string to hold the demangled name.  */
 3779   demangled = dyn_string_new (0);
 3780   /* Attempt the demangling.  */
 3781   if (!type)
 3782     /* Appears to be a function or variable name.  */
 3783     status = cp_demangle (mangled, demangled, 0);
 3784   else
 3785     /* Try to demangle it as the name of a type.  */
 3786     status = cp_demangle_type (mangled, demangled);
 3787 
 3788   if (STATUS_NO_ERROR (status))
 3789     /* Demangling succeeded.  */
 3790     {
 3791       /* Grab the demangled result from the dyn_string.  It was
 3792      allocated with malloc, so we can return it directly.  */
 3793       char *return_value = dyn_string_release (demangled);
 3794       /* Hand back the demangled name.  */
 3795       return return_value;
 3796     }
 3797   else if (status == STATUS_ALLOCATION_FAILED)
 3798     {
 3799       fprintf (stderr, "Memory allocation failed.\n");
 3800       abort ();
 3801     }
 3802   else
 3803     /* Demangling failed.  */
 3804     {
 3805       dyn_string_delete (demangled);
 3806       return NULL;
 3807     }
 3808 }
 3809 
 3810 /* Demangle a Java symbol.  Java uses a subset of the V3 ABI C++ mangling 
 3811    conventions, but the output formatting is a little different.
 3812    This instructs the C++ demangler not to emit pointer characters ("*"), and 
 3813    to use Java's namespace separator symbol ("." instead of "::").  It then 
 3814    does an additional pass over the demangled output to replace instances 
 3815    of JArray<TYPE> with TYPE[].  */
 3816 
 3817 char *
 3818 java_demangle_v3 (mangled)
 3819      const char* mangled;
 3820 {
 3821   dyn_string_t demangled;
 3822   char *next;
 3823   char *end;
 3824   int len;
 3825   status_t status;
 3826   int nesting = 0;
 3827   char *cplus_demangled;
 3828   char *return_value;
 3829     
 3830   /* Create a dyn_string to hold the demangled name.  */
 3831   demangled = dyn_string_new (0);
 3832 
 3833   /* Attempt the demangling.  */
 3834   status = cp_demangle ((char *) mangled, demangled, DMGL_JAVA);
 3835 
 3836   if (STATUS_NO_ERROR (status))
 3837     /* Demangling succeeded.  */
 3838     {
 3839       /* Grab the demangled result from the dyn_string. */
 3840       cplus_demangled = dyn_string_release (demangled);
 3841     }
 3842   else if (status == STATUS_ALLOCATION_FAILED)
 3843     {
 3844       fprintf (stderr, "Memory allocation failed.\n");
 3845       abort ();
 3846     }
 3847   else
 3848     /* Demangling failed.  */
 3849     {
 3850       dyn_string_delete (demangled);
 3851       return NULL;
 3852     }
 3853   
 3854   len = strlen (cplus_demangled);
 3855   next = cplus_demangled;
 3856   end = next + len;
 3857   demangled = NULL;
 3858 
 3859   /* Replace occurances of JArray<TYPE> with TYPE[]. */
 3860   while (next < end)
 3861     {
 3862       char *open_str = strstr (next, "JArray<");
 3863       char *close_str = NULL;
 3864       if (nesting > 0)
 3865     close_str = strchr (next, '>');
 3866     
 3867       if (open_str != NULL && (close_str == NULL || close_str > open_str))
 3868         {
 3869       ++nesting;
 3870       
 3871       if (!demangled)
 3872         demangled = dyn_string_new(len);
 3873 
 3874           /* Copy prepending symbols, if any. */
 3875       if (open_str > next)
 3876         {
 3877           open_str[0] = 0;
 3878           dyn_string_append_cstr (demangled, next);
 3879         }     
 3880       next = open_str + 7;
 3881     }
 3882       else if (close_str != NULL)
 3883         {
 3884       --nesting;
 3885       
 3886           /* Copy prepending type symbol, if any. Squash any spurious 
 3887          whitespace. */
 3888       if (close_str > next && next[0] != ' ')
 3889         {
 3890           close_str[0] = 0;
 3891           dyn_string_append_cstr (demangled, next);
 3892         }
 3893       dyn_string_append_cstr (demangled, "[]");   
 3894       next = close_str + 1;
 3895     }
 3896       else
 3897         {
 3898       /* There are no more arrays. Copy the rest of the symbol, or
 3899          simply return the original symbol if no changes were made. */
 3900       if (next == cplus_demangled)
 3901         return cplus_demangled;
 3902 
 3903           dyn_string_append_cstr (demangled, next);
 3904       next = end;
 3905     }
 3906     }
 3907 
 3908   free (cplus_demangled);
 3909   
 3910   if (demangled)
 3911     return_value = dyn_string_release (demangled);
 3912   else
 3913     return_value = NULL;
 3914 
 3915   return return_value;
 3916 }
 3917 
 3918 #endif /* IN_LIBGCC2 || IN_GLIBCPP_V3 */
 3919 
 3920 
 3921 #ifndef IN_GLIBCPP_V3
 3922 /* Demangle NAME in the G++ V3 ABI demangling style, and return either
 3923    zero, indicating that some error occurred, or a demangling_t
 3924    holding the results.  */
 3925 static demangling_t
 3926 demangle_v3_with_details (name)
 3927      const char *name;
 3928 {
 3929   demangling_t dm;
 3930   status_t status;
 3931 
 3932   if (strncmp (name, "_Z", 2))
 3933     return 0;
 3934 
 3935   dm = demangling_new (name, DMGL_GNU_V3);
 3936   if (dm == NULL)
 3937     {
 3938       fprintf (stderr, "Memory allocation failed.\n");
 3939       abort ();
 3940     }
 3941 
 3942   status = result_push (dm);
 3943   if (! STATUS_NO_ERROR (status))
 3944     {
 3945       demangling_delete (dm);
 3946       fprintf (stderr, "%s\n", status);
 3947       abort ();
 3948     }
 3949 
 3950   status = demangle_mangled_name (dm);
 3951   if (STATUS_NO_ERROR (status))
 3952     return dm;
 3953 
 3954   demangling_delete (dm);
 3955   return 0;
 3956 }
 3957 
 3958 
 3959 /* Return non-zero iff NAME is the mangled form of a constructor name
 3960    in the G++ V3 ABI demangling style.  Specifically, return:
 3961    - '1' if NAME is a complete object constructor,
 3962    - '2' if NAME is a base object constructor, or
 3963    - '3' if NAME is a complete object allocating constructor.  */
 3964 enum gnu_v3_ctor_kinds
 3965 is_gnu_v3_mangled_ctor (name)
 3966      const char *name;
 3967 {
 3968   demangling_t dm = demangle_v3_with_details (name);
 3969 
 3970   if (dm)
 3971     {
 3972       enum gnu_v3_ctor_kinds result = dm->is_constructor;
 3973       demangling_delete (dm);
 3974       return result;
 3975     }
 3976   else
 3977     return (enum gnu_v3_ctor_kinds) 0;
 3978 }
 3979 
 3980 
 3981 /* Return non-zero iff NAME is the mangled form of a destructor name
 3982    in the G++ V3 ABI demangling style.  Specifically, return:
 3983    - '0' if NAME is a deleting destructor,
 3984    - '1' if NAME is a complete object destructor, or
 3985    - '2' if NAME is a base object destructor.  */
 3986 enum gnu_v3_dtor_kinds
 3987 is_gnu_v3_mangled_dtor (name)
 3988      const char *name;
 3989 {
 3990   demangling_t dm = demangle_v3_with_details (name);
 3991 
 3992   if (dm)
 3993     {
 3994       enum gnu_v3_dtor_kinds result = dm->is_destructor;
 3995       demangling_delete (dm);
 3996       return result;
 3997     }
 3998   else
 3999     return (enum gnu_v3_dtor_kinds) 0;
 4000 }
 4001 #endif /* IN_GLIBCPP_V3 */
 4002 
 4003 
 4004 #ifdef STANDALONE_DEMANGLER
 4005 
 4006 #include "getopt.h"
 4007 
 4008 static void print_usage
 4009   PARAMS ((FILE* fp, int exit_value));
 4010 
 4011 /* Non-zero if CHAR is a character than can occur in a mangled name.  */
 4012 #define is_mangled_char(CHAR)                                           \
 4013   (IS_ALPHA (CHAR) || IS_DIGIT (CHAR)                                   \
 4014    || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
 4015 
 4016 /* The name of this program, as invoked.  */
 4017 const char* program_name;
 4018 
 4019 /* Prints usage summary to FP and then exits with EXIT_VALUE.  */
 4020 
 4021 static void
 4022 print_usage (fp, exit_value)
 4023      FILE* fp;
 4024      int exit_value;
 4025 {
 4026   fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
 4027   fprintf (fp, "Options:\n");
 4028   fprintf (fp, "  -h,--help       Display this message.\n");
 4029   fprintf (fp, "  -s,--strict     Demangle standard names only.\n");
 4030   fprintf (fp, "  -v,--verbose    Produce verbose demanglings.\n");
 4031   fprintf (fp, "If names are provided, they are demangled.  Otherwise filters standard input.\n");
 4032 
 4033   exit (exit_value);
 4034 }
 4035 
 4036 /* Option specification for getopt_long.  */
 4037 static const struct option long_options[] = 
 4038 {
 4039   { "help",    no_argument, NULL, 'h' },
 4040   { "strict",  no_argument, NULL, 's' },
 4041   { "verbose", no_argument, NULL, 'v' },
 4042   { NULL,      no_argument, NULL, 0   },
 4043 };
 4044 
 4045 /* Main entry for a demangling filter executable.  It will demangle
 4046    its command line arguments, if any.  If none are provided, it will
 4047    filter stdin to stdout, replacing any recognized mangled C++ names
 4048    with their demangled equivalents.  */
 4049 
 4050 int
 4051 main (argc, argv)
 4052      int argc;
 4053      char *argv[];
 4054 {
 4055   status_t status;
 4056   int i;
 4057   int opt_char;
 4058 
 4059   /* Use the program name of this program, as invoked.  */
 4060   program_name = argv[0];
 4061 
 4062   /* Parse options.  */
 4063   do 
 4064     {
 4065       opt_char = getopt_long (argc, argv, "hsv", long_options, NULL);
 4066       switch (opt_char)
 4067     {
 4068     case '?':  /* Unrecognized option.  */
 4069       print_usage (stderr, 1);
 4070       break;
 4071 
 4072     case 'h':
 4073       print_usage (stdout, 0);
 4074       break;
 4075 
 4076     case 's':
 4077       flag_strict = 1;
 4078       break;
 4079 
 4080     case 'v':
 4081       flag_verbose = 1;
 4082       break;
 4083     }
 4084     }
 4085   while (opt_char != -1);
 4086 
 4087   if (optind == argc) 
 4088     /* No command line arguments were provided.  Filter stdin.  */
 4089     {
 4090       dyn_string_t mangled = dyn_string_new (3);
 4091       dyn_string_t demangled = dyn_string_new (0);
 4092       status_t status;
 4093 
 4094       /* Read all of input.  */
 4095       while (!feof (stdin))
 4096     {
 4097       char c = getchar ();
 4098 
 4099       /* The first character of a mangled name is an underscore.  */
 4100       if (feof (stdin))
 4101         break;
 4102       if (c != '_')
 4103         {
 4104           /* It's not a mangled name.  Print the character and go
 4105          on.  */
 4106           putchar (c);
 4107           continue;
 4108         }
 4109       c = getchar ();
 4110       
 4111       /* The second character of a mangled name is a capital `Z'.  */
 4112       if (feof (stdin))
 4113         break;
 4114       if (c != 'Z')
 4115         {
 4116           /* It's not a mangled name.  Print the previous
 4117          underscore, the `Z', and go on.  */
 4118           putchar ('_');
 4119           putchar (c);
 4120           continue;
 4121         }
 4122 
 4123       /* Start keeping track of the candidate mangled name.  */
 4124       dyn_string_append_char (mangled, '_');
 4125       dyn_string_append_char (mangled, 'Z');
 4126 
 4127       /* Pile characters into mangled until we hit one that can't
 4128          occur in a mangled name.  */
 4129       c = getchar ();
 4130       while (!feof (stdin) && is_mangled_char (c))
 4131         {
 4132           dyn_string_append_char (mangled, c);
 4133           if (feof (stdin))
 4134         break;
 4135           c = getchar ();
 4136         }
 4137 
 4138       /* Attempt to demangle the name.  */
 4139       status = cp_demangle (dyn_string_buf (mangled), demangled, 0);
 4140 
 4141       /* If the demangling succeeded, great!  Print out the
 4142          demangled version.  */
 4143       if (STATUS_NO_ERROR (status))
 4144         fputs (dyn_string_buf (demangled), stdout);
 4145       /* Abort on allocation failures.  */
 4146       else if (status == STATUS_ALLOCATION_FAILED)
 4147         {
 4148           fprintf (stderr, "Memory allocation failed.\n");
 4149           abort ();
 4150         }
 4151       /* Otherwise, it might not have been a mangled name.  Just
 4152          print out the original text.  */
 4153       else
 4154         fputs (dyn_string_buf (mangled), stdout);
 4155 
 4156       /* If we haven't hit EOF yet, we've read one character that
 4157          can't occur in a mangled name, so print it out.  */
 4158       if (!feof (stdin))
 4159         putchar (c);
 4160 
 4161       /* Clear the candidate mangled name, to start afresh next
 4162          time we hit a `_Z'.  */
 4163       dyn_string_clear (mangled);
 4164     }
 4165 
 4166       dyn_string_delete (mangled);
 4167       dyn_string_delete (demangled);
 4168     }
 4169   else
 4170     /* Demangle command line arguments.  */
 4171     {
 4172       dyn_string_t result = dyn_string_new (0);
 4173 
 4174       /* Loop over command line arguments.  */
 4175       for (i = optind; i < argc; ++i)
 4176     {
 4177       /* Attempt to demangle.  */
 4178       status = cp_demangle (argv[i], result, 0);
 4179 
 4180       /* If it worked, print the demangled name.  */
 4181       if (STATUS_NO_ERROR (status))
 4182         printf ("%s\n", dyn_string_buf (result));
 4183       /* Abort on allocaiton failures.  */
 4184       else if (status == STATUS_ALLOCATION_FAILED)
 4185         {
 4186           fprintf (stderr, "Memory allocation failed.\n");
 4187           abort ();
 4188         }
 4189       /* If not, print the error message to stderr instead.  */
 4190       else 
 4191         fprintf (stderr, "%s\n", status);
 4192     }
 4193       dyn_string_delete (result);
 4194     }
 4195 
 4196   return 0;
 4197 }
 4198 
 4199 #endif /* STANDALONE_DEMANGLER */