cp-demangle.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,161 行 · 第 1/5 页

C
2,161
字号
/* Demangler for IA64 / g++ V3 ABI.   Copyright (C) 2000 Free Software Foundation, Inc.   Written by Alex Samuel <samuel@codesourcery.com>.    This file is part of GNU CC.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* This file implements demangling of C++ names mangled according to   the IA64 / g++ V3 ABI.  Use the cp_demangle function to   demangle a mangled name, or compile with the preprocessor macro   STANDALONE_DEMANGLER defined to create a demangling filter   executable (functionally similar to c++filt, but includes this   demangler only).  */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <sys/types.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#include <stdio.h>#ifdef HAVE_STRING_H#include <string.h>#endif#include "ansidecl.h"#include "libiberty.h"#include "dyn-string.h"#include "demangle.h"/* If CP_DEMANGLE_DEBUG is defined, a trace of the grammar evaluation,   and other debugging output, will be generated. */#ifdef CP_DEMANGLE_DEBUG#define DEMANGLE_TRACE(PRODUCTION, DM)                                  \  fprintf (stderr, " -> %-24s at position %3d\n",                       \           (PRODUCTION), current_position (DM));#else#define DEMANGLE_TRACE(PRODUCTION, DM)#endif/* Don't include <ctype.h>, to prevent additional unresolved symbols   from being dragged into the C++ runtime library.  */#define IS_DIGIT(CHAR) ((CHAR) >= '0' && (CHAR) <= '9')#define IS_ALPHA(CHAR)                                                  \  (((CHAR) >= 'a' && (CHAR) <= 'z')                                     \   || ((CHAR) >= 'A' && (CHAR) <= 'Z'))/* The prefix prepended by GCC to an identifier represnting the   anonymous namespace.  */#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"/* If flag_verbose is zero, some simplifications will be made to the   output to make it easier to read and supress details that are   generally not of interest to the average C++ programmer.   Otherwise, the demangled representation will attempt to convey as   much information as the mangled form.  */static int flag_verbose;/* If flag_strict is non-zero, demangle strictly according to the   specification -- don't demangle special g++ manglings.  */static int flag_strict;/* String_list_t is an extended form of dyn_string_t which provides a   link field and a caret position for additions to the string.  A   string_list_t may safely be cast to and used as a dyn_string_t.  */struct string_list_def{  /* The dyn_string; must be first.  */  struct dyn_string string;  /* The position at which additional text is added to this string     (using the result_add* macros).  This value is an offset from the     end of the string, not the beginning (and should be     non-positive).  */  int caret_position;  /* The next string in the list.  */  struct string_list_def *next;};typedef struct string_list_def *string_list_t;/* Data structure representing a potential substitution.  */struct substitution_def{  /* The demangled text of the substitution.  */  dyn_string_t text;  /* Whether this substitution represents a template item.  */  int template_p : 1;};/* Data structure representing a template argument list.  */struct template_arg_list_def{  /* The next (lower) template argument list in the stack of currently     active template arguments.  */  struct template_arg_list_def *next;  /* The first element in the list of template arguments in     left-to-right order.  */  string_list_t first_argument;  /* The last element in the arguments lists.  */  string_list_t last_argument;};typedef struct template_arg_list_def *template_arg_list_t;/* Data structure to maintain the state of the current demangling.  */struct demangling_def{  /* The full mangled name being mangled.  */  const char *name;  /* Pointer into name at the current position.  */  const char *next;  /* Stack for strings containing demangled result generated so far.     Text is emitted to the topmost (first) string.  */  string_list_t result;  /* The number of presently available substitutions.  */  int num_substitutions;  /* The allocated size of the substitutions array.  */  int substitutions_allocated;  /* An array of available substitutions.  The number of elements in     the array is given by num_substitions, and the allocated array     size in substitutions_size.       The most recent substition is at the end, so       - `S_'  corresponds to substititutions[num_substitutions - 1]        - `S0_' corresponds to substititutions[num_substitutions - 2]     etc. */  struct substitution_def *substitutions;  /* The stack of template argument lists.  */  template_arg_list_t template_arg_lists;  /* The most recently demangled source-name.  */  dyn_string_t last_source_name;};typedef struct demangling_def *demangling_t;/* This type is the standard return code from most functions.  Values   other than STATUS_OK contain descriptive messages.  */typedef const char *status_t;/* Special values that can be used as a status_t.  */#define STATUS_OK                       NULL#define STATUS_ERROR                    "Error."#define STATUS_UNIMPLEMENTED            "Unimplemented."#define STATUS_INTERNAL_ERROR           "Internal error."/* This status code indicates a failure in malloc or realloc.  */static const char *const status_allocation_failed = "Allocation failed.";#define STATUS_ALLOCATION_FAILED        status_allocation_failed/* Non-zero if STATUS indicates that no error has occurred.  */#define STATUS_NO_ERROR(STATUS)         ((STATUS) == STATUS_OK)/* Evaluate EXPR, which must produce a status_t.  If the status code   indicates an error, return from the current function with that   status code.  */#define RETURN_IF_ERROR(EXPR)                                           \  do                                                                    \    {                                                                   \      status_t s = EXPR;                                                \      if (!STATUS_NO_ERROR (s))                                         \	return s;                                                       \    }                                                                   \  while (0)static status_t int_to_dyn_string   PARAMS ((int, dyn_string_t));static string_list_t string_list_new  PARAMS ((int));static void string_list_delete  PARAMS ((string_list_t));static status_t result_add_separated_char  PARAMS ((demangling_t, int));static status_t result_push  PARAMS ((demangling_t));static string_list_t result_pop  PARAMS ((demangling_t));static int substitution_start  PARAMS ((demangling_t));static status_t substitution_add  PARAMS ((demangling_t, int, int));static dyn_string_t substitution_get  PARAMS ((demangling_t, int, int *));#ifdef CP_DEMANGLE_DEBUGstatic void substitutions_print   PARAMS ((demangling_t, FILE *));#endifstatic template_arg_list_t template_arg_list_new  PARAMS ((void));static void template_arg_list_delete  PARAMS ((template_arg_list_t));static void template_arg_list_add_arg   PARAMS ((template_arg_list_t, string_list_t));static string_list_t template_arg_list_get_arg  PARAMS ((template_arg_list_t, int));static void push_template_arg_list  PARAMS ((demangling_t, template_arg_list_t));static void pop_to_template_arg_list  PARAMS ((demangling_t, template_arg_list_t));#ifdef CP_DEMANGLE_DEBUGstatic void template_arg_list_print  PARAMS ((template_arg_list_t, FILE *));#endifstatic template_arg_list_t current_template_arg_list  PARAMS ((demangling_t));static demangling_t demangling_new  PARAMS ((const char *));static void demangling_delete   PARAMS ((demangling_t));/* The last character of DS.  Warning: DS is evaluated twice.  */#define dyn_string_last_char(DS)                                        \  (dyn_string_buf (DS)[dyn_string_length (DS) - 1])/* Append a space character (` ') to DS if it does not already end   with one.  Evaluates to 1 on success, or 0 on allocation failure.  */#define dyn_string_append_space(DS)                                     \      ((dyn_string_length (DS) > 0                                      \        && dyn_string_last_char (DS) != ' ')                            \       ? dyn_string_append_char ((DS), ' ')                             \       : 1)/* Returns the index of the current position in the mangled name.  */#define current_position(DM)    ((DM)->next - (DM)->name)/* Returns the character at the current position of the mangled name.  */#define peek_char(DM)           (*((DM)->next))/* Returns the character one past the current position of the mangled   name.  */#define peek_char_next(DM)                                              \  (peek_char (DM) == '\0' ? '\0' : (*((DM)->next + 1)))/* Returns the character at the current position, and advances the   current position to the next character.  */#define next_char(DM)           (*((DM)->next)++)/* Returns non-zero if the current position is the end of the mangled   name, i.e. one past the last character.  */#define end_of_name_p(DM)       (peek_char (DM) == '\0')/* Advances the current position by one character.  */#define advance_char(DM)        (++(DM)->next)/* Returns the string containing the current demangled result.  */#define result_string(DM)       (&(DM)->result->string)/* Returns the position at which new text is inserted into the   demangled result.  */#define result_caret_pos(DM)                                            \  (result_length (DM) +                                                 \   ((string_list_t) result_string (DM))->caret_position)/* Adds a dyn_string_t to the demangled result.  */#define result_add_string(DM, STRING)                                   \  (dyn_string_insert (&(DM)->result->string,                            \		      result_caret_pos (DM), (STRING))                  \   ? STATUS_OK : STATUS_ALLOCATION_FAILED)/* Adds NUL-terminated string CSTR to the demangled result.    */#define result_add(DM, CSTR)                                            \  (dyn_string_insert_cstr (&(DM)->result->string,                       \			   result_caret_pos (DM), (CSTR))               \   ? STATUS_OK : STATUS_ALLOCATION_FAILED)/* Adds character CHAR to the demangled result.  */#define result_add_char(DM, CHAR)                                       \  (dyn_string_insert_char (&(DM)->result->string,                       \			   result_caret_pos (DM), (CHAR))               \   ? STATUS_OK : STATUS_ALLOCATION_FAILED)/* Inserts a dyn_string_t to the demangled result at position POS.  */#define result_insert_string(DM, POS, STRING)                           \  (dyn_string_insert (&(DM)->result->string, (POS), (STRING))           \   ? STATUS_OK : STATUS_ALLOCATION_FAILED)/* Inserts NUL-terminated string CSTR to the demangled result at   position POS.  */#define result_insert(DM, POS, CSTR)                                    \  (dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR))        \   ? STATUS_OK : STATUS_ALLOCATION_FAILED)/* Inserts character CHAR to the demangled result at position POS.  */#define result_insert_char(DM, POS, CHAR)                               \  (dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR))        \   ? STATUS_OK : STATUS_ALLOCATION_FAILED)/* The length of the current demangled result.  */#define result_length(DM)                                               \  dyn_string_length (&(DM)->result->string)/* Appends a (less-than, greater-than) character to the result in DM   to (open, close) a template argument or parameter list.  Appends a   space first if necessary to prevent spurious elision of angle   brackets with the previous character.  */#define result_open_template_list(DM) result_add_separated_char(DM, '<')#define result_close_template_list(DM) result_add_separated_char(DM, '>')/* Appends a base 10 representation of VALUE to DS.  STATUS_OK on   success.  On failure, deletes DS and returns an error code.  */static status_tint_to_dyn_string (value, ds)     int value;     dyn_string_t ds;{  int i;  int mask = 1;  /* Handle zero up front.  */  if (value == 0)    {      if (!dyn_string_append_char (ds, '0'))	return STATUS_ALLOCATION_FAILED;      return STATUS_OK;    }  /* For negative numbers, emit a minus sign.  */  if (value < 0)    {      if (!dyn_string_append_char (ds, '-'))	return STATUS_ALLOCATION_FAILED;      value = -value;    }    /* Find the power of 10 of the first digit.  */  i = value;  while (i > 9)    {      mask *= 10;      i /= 10;    }  /* Write the digits.  */  while (mask > 0)    {      int digit = value / mask;      if (!dyn_string_append_char (ds, '0' + digit))	return STATUS_ALLOCATION_FAILED;      value -= digit * mask;      mask /= 10;    }  return STATUS_OK;}/* Creates a new string list node.  The contents of the string are   empty, but the initial buffer allocation is LENGTH.  The string   list node should be deleted with string_list_delete.  Returns NULL   if allocation fails.  */static string_list_t string_list_new (length)     int length;{  string_list_t s = (string_list_t) malloc (sizeof (struct string_list_def));  s->caret_position = 0;  if (s == NULL)    return NULL;  if (!dyn_string_init ((dyn_string_t) s, length))    return NULL;  return s;}  /* Deletes the entire string list starting at NODE.  */static voidstring_list_delete (node)     string_list_t node;{  while (node != NULL)    {      string_list_t next = node->next;      free (node);      node = next;    }}/* Appends CHARACTER to the demangled result.  If the current trailing   character of the result is CHARACTER, a space is inserted first.  */static status_tresult_add_separated_char (dm, character)     demangling_t dm;     int character;{  char *result = dyn_string_buf (result_string (dm));  int caret_pos = result_caret_pos (dm);  /* Add a space if the last character is already the character we     want to add.  */  if (caret_pos > 0 && result[caret_pos - 1] == character)    RETURN_IF_ERROR (result_add_char (dm, ' '));  /* Add the character.  */  RETURN_IF_ERROR (result_add_char (dm, character));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?