| /* Demangler component interface functions. | 
 |    Copyright (C) 2004-2024 Free Software Foundation, Inc. | 
 |    Written by Ian Lance Taylor <ian@wasabisystems.com>. | 
 |  | 
 |    This file is part of the libiberty library, which is part of GCC. | 
 |  | 
 |    This file 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. | 
 |  | 
 |    In addition to the permissions in the GNU General Public License, the | 
 |    Free Software Foundation gives you unlimited permission to link the | 
 |    compiled version of this file into combinations with other programs, | 
 |    and to distribute those combinations without any restriction coming | 
 |    from the use of this file.  (The General Public License restrictions | 
 |    do apply in other respects; for example, they cover modification of | 
 |    the file, and distribution when not linked into a combined | 
 |    executable.) | 
 |  | 
 |    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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  | 
 | */ | 
 |  | 
 | /* This file implements a few interface functions which are provided | 
 |    for use with struct demangle_component trees.  These functions are | 
 |    declared in demangle.h.  These functions are closely tied to the | 
 |    demangler code in cp-demangle.c, and other interface functions can | 
 |    be found in that file.  We put these functions in a separate file | 
 |    because they are not needed by the demangler, and so we avoid | 
 |    having them pulled in by programs which only need the | 
 |    demangler.  */ | 
 |  | 
 | #ifdef HAVE_CONFIG_H | 
 | #include "config.h" | 
 | #endif | 
 |  | 
 | #ifdef HAVE_STDLIB_H | 
 | #include <stdlib.h> | 
 | #endif | 
 | #ifdef HAVE_STRING_H | 
 | #include <string.h> | 
 | #endif | 
 |  | 
 | #include "ansidecl.h" | 
 | #include "libiberty.h" | 
 | #include "demangle.h" | 
 | #include "cp-demangle.h" | 
 |  | 
 | /* Fill in most component types.  */ | 
 |  | 
 | int | 
 | cplus_demangle_fill_component (struct demangle_component *p, | 
 |                                enum demangle_component_type type, | 
 |                                struct demangle_component *left, | 
 |                                 struct demangle_component *right) | 
 | { | 
 |   if (p == NULL) | 
 |     return 0; | 
 |   switch (type) | 
 |     { | 
 |     case DEMANGLE_COMPONENT_QUAL_NAME: | 
 |     case DEMANGLE_COMPONENT_LOCAL_NAME: | 
 |     case DEMANGLE_COMPONENT_TYPED_NAME: | 
 |     case DEMANGLE_COMPONENT_TEMPLATE: | 
 |     case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: | 
 |     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: | 
 |     case DEMANGLE_COMPONENT_FUNCTION_TYPE: | 
 |     case DEMANGLE_COMPONENT_ARRAY_TYPE: | 
 |     case DEMANGLE_COMPONENT_PTRMEM_TYPE: | 
 |     case DEMANGLE_COMPONENT_ARGLIST: | 
 |     case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: | 
 |     case DEMANGLE_COMPONENT_UNARY: | 
 |     case DEMANGLE_COMPONENT_BINARY: | 
 |     case DEMANGLE_COMPONENT_BINARY_ARGS: | 
 |     case DEMANGLE_COMPONENT_TRINARY: | 
 |     case DEMANGLE_COMPONENT_TRINARY_ARG1: | 
 |     case DEMANGLE_COMPONENT_TRINARY_ARG2: | 
 |     case DEMANGLE_COMPONENT_LITERAL: | 
 |     case DEMANGLE_COMPONENT_LITERAL_NEG: | 
 |       break; | 
 |  | 
 |       /* These component types only have one subtree.  */ | 
 |     case DEMANGLE_COMPONENT_VTABLE: | 
 |     case DEMANGLE_COMPONENT_VTT: | 
 |     case DEMANGLE_COMPONENT_TYPEINFO: | 
 |     case DEMANGLE_COMPONENT_TYPEINFO_NAME: | 
 |     case DEMANGLE_COMPONENT_TYPEINFO_FN: | 
 |     case DEMANGLE_COMPONENT_THUNK: | 
 |     case DEMANGLE_COMPONENT_VIRTUAL_THUNK: | 
 |     case DEMANGLE_COMPONENT_COVARIANT_THUNK: | 
 |     case DEMANGLE_COMPONENT_JAVA_CLASS: | 
 |     case DEMANGLE_COMPONENT_GUARD: | 
 |     case DEMANGLE_COMPONENT_REFTEMP: | 
 |     case DEMANGLE_COMPONENT_RESTRICT: | 
 |     case DEMANGLE_COMPONENT_VOLATILE: | 
 |     case DEMANGLE_COMPONENT_CONST: | 
 |     case DEMANGLE_COMPONENT_RESTRICT_THIS: | 
 |     case DEMANGLE_COMPONENT_VOLATILE_THIS: | 
 |     case DEMANGLE_COMPONENT_CONST_THIS: | 
 |     case DEMANGLE_COMPONENT_POINTER: | 
 |     case DEMANGLE_COMPONENT_REFERENCE: | 
 |     case DEMANGLE_COMPONENT_RVALUE_REFERENCE: | 
 |     case DEMANGLE_COMPONENT_COMPLEX: | 
 |     case DEMANGLE_COMPONENT_IMAGINARY: | 
 |     case DEMANGLE_COMPONENT_VENDOR_TYPE: | 
 |     case DEMANGLE_COMPONENT_CAST: | 
 |     case DEMANGLE_COMPONENT_CONVERSION: | 
 |       if (right != NULL) | 
 | 	return 0; | 
 |       break; | 
 |  | 
 |     default: | 
 |       /* Other types do not use subtrees.  */ | 
 |       return 0; | 
 |     } | 
 |  | 
 |   p->type = type; | 
 |   p->u.s_binary.left = left; | 
 |   p->u.s_binary.right = right; | 
 |   p->d_printing = 0; | 
 |   p->d_counting = 0; | 
 |  | 
 |   return 1; | 
 | } | 
 |  | 
 | /* Fill in a DEMANGLE_COMPONENT_BUILTIN_TYPE.  */ | 
 |  | 
 | int | 
 | cplus_demangle_fill_builtin_type (struct demangle_component *p, | 
 |                                   const char *type_name) | 
 | { | 
 |   int len; | 
 |   unsigned int i; | 
 |  | 
 |   if (p == NULL || type_name == NULL) | 
 |     return 0; | 
 |   len = strlen (type_name); | 
 |   for (i = 0; i < D_BUILTIN_TYPE_COUNT; ++i) | 
 |     { | 
 |       if (len == cplus_demangle_builtin_types[i].len | 
 | 	  && strcmp (type_name, cplus_demangle_builtin_types[i].name) == 0) | 
 | 	{ | 
 | 	  p->type = DEMANGLE_COMPONENT_BUILTIN_TYPE; | 
 | 	  p->u.s_builtin.type = &cplus_demangle_builtin_types[i]; | 
 | 	  p->d_printing = 0; | 
 | 	  p->d_counting = 0; | 
 | 	  return 1; | 
 | 	} | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Fill in a DEMANGLE_COMPONENT_OPERATOR.  */ | 
 |  | 
 | int | 
 | cplus_demangle_fill_operator (struct demangle_component *p, | 
 |                               const char *opname, int args) | 
 | { | 
 |   int len; | 
 |   unsigned int i; | 
 |  | 
 |   if (p == NULL || opname == NULL) | 
 |     return 0; | 
 |   len = strlen (opname); | 
 |   for (i = 0; cplus_demangle_operators[i].name != NULL; ++i) | 
 |     { | 
 |       if (len == cplus_demangle_operators[i].len | 
 | 	  && args == cplus_demangle_operators[i].args | 
 | 	  && strcmp (opname, cplus_demangle_operators[i].name) == 0) | 
 | 	{ | 
 | 	  p->type = DEMANGLE_COMPONENT_OPERATOR; | 
 | 	  p->u.s_operator.op = &cplus_demangle_operators[i]; | 
 | 	  p->d_printing = 0; | 
 | 	  p->d_counting = 0; | 
 | 	  return 1; | 
 | 	} | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Translate a mangled name into components.  */ | 
 |  | 
 | struct demangle_component * | 
 | cplus_demangle_v3_components (const char *mangled, int options, void **mem) | 
 | { | 
 |   size_t len; | 
 |   int type; | 
 |   struct d_info di; | 
 |   struct demangle_component *dc; | 
 |  | 
 |   len = strlen (mangled); | 
 |  | 
 |   if (mangled[0] == '_' && mangled[1] == 'Z') | 
 |     type = 0; | 
 |   else | 
 |     { | 
 |       if ((options & DMGL_TYPES) == 0) | 
 | 	return NULL; | 
 |       type = 1; | 
 |     } | 
 |  | 
 |   cplus_demangle_init_info (mangled, options, len, &di); | 
 |  | 
 |   di.comps = ((struct demangle_component *) | 
 | 	      malloc (di.num_comps * sizeof (struct demangle_component))); | 
 |   di.subs = ((struct demangle_component **) | 
 | 	     malloc (di.num_subs * sizeof (struct demangle_component *))); | 
 |   if (di.comps == NULL || di.subs == NULL) | 
 |     { | 
 |       free (di.comps); | 
 |       free (di.subs); | 
 |       return NULL; | 
 |     } | 
 |  | 
 |   if (! type) | 
 |     dc = cplus_demangle_mangled_name (&di, 1); | 
 |   else | 
 |     dc = cplus_demangle_type (&di); | 
 |  | 
 |   /* If DMGL_PARAMS is set, then if we didn't consume the entire | 
 |      mangled string, then we didn't successfully demangle it.  */ | 
 |   if ((options & DMGL_PARAMS) != 0 && d_peek_char (&di) != '\0') | 
 |     dc = NULL; | 
 |  | 
 |   free (di.subs); | 
 |  | 
 |   if (dc != NULL) | 
 |     *mem = di.comps; | 
 |   else | 
 |     free (di.comps); | 
 |  | 
 |   return dc; | 
 | } |