summaryrefslogtreecommitdiff
path: root/plugins/itanium
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/itanium')
-rw-r--r--plugins/itanium/Makefile.am32
-rw-r--r--plugins/itanium/abi.c3344
-rw-r--r--plugins/itanium/abi.h38
-rw-r--r--plugins/itanium/component-int.h137
-rw-r--r--plugins/itanium/component.c1842
-rw-r--r--plugins/itanium/component.h294
-rw-r--r--plugins/itanium/context.c516
-rw-r--r--plugins/itanium/context.h83
-rw-r--r--plugins/itanium/core.c64
-rw-r--r--plugins/itanium/core.h38
-rw-r--r--plugins/itanium/demangler.c174
-rw-r--r--plugins/itanium/demangler.h58
-rw-r--r--plugins/itanium/python/Makefile.am19
-rw-r--r--plugins/itanium/python/demangler.c145
-rw-r--r--plugins/itanium/python/demangler.h42
-rw-r--r--plugins/itanium/python/module.c61
-rw-r--r--plugins/itanium/python/module.h38
17 files changed, 6925 insertions, 0 deletions
diff --git a/plugins/itanium/Makefile.am b/plugins/itanium/Makefile.am
new file mode 100644
index 0000000..b4a9cb7
--- /dev/null
+++ b/plugins/itanium/Makefile.am
@@ -0,0 +1,32 @@
+
+lib_LTLIBRARIES = libitanium.la
+
+libdir = $(pluginsdir)
+
+libitanium_la_SOURCES = \
+ abi.h abi.c \
+ component-int.h \
+ component.h component.c \
+ context.h context.c \
+ core.h core.c \
+ demangler.h demangler.c
+
+libitanium_la_LIBADD = \
+ python/libitaniumpython.la
+
+libitanium_la_LDFLAGS = \
+ -L$(top_srcdir)/src/.libs -lchrysacore \
+ -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs \
+ -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libitanium_la_SOURCES:%c=)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS = python
diff --git a/plugins/itanium/abi.c b/plugins/itanium/abi.c
new file mode 100644
index 0000000..5f76342
--- /dev/null
+++ b/plugins/itanium/abi.c
@@ -0,0 +1,3344 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * abi.c - décodage des noms d'éléments selon l'ABI C++ Itanium
+ *
+ * Copyright (C) 2013-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "abi.h"
+
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+
+#include <analysis/types/basic.h>
+#include <analysis/types/cse.h>
+#include <common/cpp.h>
+#include <mangling/context-int.h>
+
+
+
+/* Liste des opérateurs reconnus */
+
+#define IDT_NL(s) s, sizeof(s) - 1
+
+const itanium_operator_info itanium_demangle_operators[] = {
+
+ { "aN", IDT_NL("&="), 2 },
+ { "aS", IDT_NL("="), 2 },
+ { "aa", IDT_NL("&&"), 2 },
+ { "ad", IDT_NL("&"), 1 },
+ { "an", IDT_NL("&"), 2 },
+ { "at", IDT_NL("alignof "), 1 },
+ { "az", IDT_NL("alignof "), 1 },
+ { "cc", IDT_NL("const_cast"), 2 },
+ { "cl", IDT_NL("()"), 2 },
+ { "cm", IDT_NL(","), 2 },
+ { "co", IDT_NL("~"), 1 },
+ { "dV", IDT_NL("/="), 2 },
+ { "da", IDT_NL("delete[] "), 1 },
+ { "dc", IDT_NL("dynamic_cast"), 2 },
+ { "de", IDT_NL("*"), 1 },
+ { "dl", IDT_NL("delete "), 1 },
+ { "ds", IDT_NL(".*"), 2 },
+ { "dt", IDT_NL("."), 2 },
+ { "dv", IDT_NL("/"), 2 },
+ { "eO", IDT_NL("^="), 2 },
+ { "eo", IDT_NL("^"), 2 },
+ { "eq", IDT_NL("=="), 2 },
+ { "ge", IDT_NL(">="), 2 },
+ { "gs", IDT_NL("::"), 1 },
+ { "gt", IDT_NL(">"), 2 },
+ { "ix", IDT_NL("[]"), 2 },
+ { "lS", IDT_NL("<<="), 2 },
+ { "le", IDT_NL("<="), 2 },
+ { "li", IDT_NL("operator\"\" "), 1 },
+ { "ls", IDT_NL("<<"), 2 },
+ { "lt", IDT_NL("<"), 2 },
+ { "mI", IDT_NL("-="), 2 },
+ { "mL", IDT_NL("*="), 2 },
+ { "mi", IDT_NL("-"), 2 },
+ { "ml", IDT_NL("*"), 2 },
+ { "mm", IDT_NL("--"), 1 },
+ { "na", IDT_NL("new[]"), 3 },
+ { "ne", IDT_NL("!="), 2 },
+ { "ng", IDT_NL("-"), 1 },
+ { "nt", IDT_NL("!"), 1 },
+ { "nw", IDT_NL("new"), 3 },
+ { "oR", IDT_NL("|="), 2 },
+ { "oo", IDT_NL("||"), 2 },
+ { "or", IDT_NL("|"), 2 },
+ { "pL", IDT_NL("+="), 2 },
+ { "pl", IDT_NL("+"), 2 },
+ { "pm", IDT_NL("->*"), 2 },
+ { "pp", IDT_NL("++"), 1 },
+ { "ps", IDT_NL("+"), 1 },
+ { "pt", IDT_NL("->"), 2 },
+ { "qu", IDT_NL("?"), 3 },
+ { "rM", IDT_NL("%="), 2 },
+ { "rS", IDT_NL(">>="), 2 },
+ { "rc", IDT_NL("reinterpret_cast"), 2 },
+ { "rm", IDT_NL("%"), 2 },
+ { "rs", IDT_NL(">>"), 2 },
+ { "sc", IDT_NL("static_cast"), 2 },
+ { "st", IDT_NL("sizeof "), 1 },
+ { "sz", IDT_NL("sizeof "), 1 }
+};
+
+/* Substitutions standards */
+
+typedef struct _itanium_std_subst_info
+{
+ char code; /* Identifiant associé */
+ const char *class; /* Classe visée dans l'espace */
+
+} itanium_std_subst_info;
+
+const itanium_std_subst_info itanium_standard_substitutions[] = {
+
+ { 't', NULL },
+ { 'a', "allocator" },
+ { 'b', "basic_string" },
+ { 's', "string" },
+ { 'i', "istream" },
+ { 'o', "ostream" },
+ { 'd', "iostream" }
+
+};
+
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_encoding(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_name(GItaniumDemangling *);
+
+/* Détermine si le composant suivant correspond à un type donné. */
+static bool is_itd_unscoped_name(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_unscoped_name(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_unscoped_template_name(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_nested_name(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_prefix(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_prefix_rec(GItaniumDemangling *, itanium_component *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_template_prefix(GItaniumDemangling *);
+
+/* Détermine si le composant suivant correspond à un type donné. */
+static bool is_itd_unqualified_name(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_unqualified_name(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_source_name(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static bool itd_number(GItaniumDemangling *, ssize_t *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_identifier(GItaniumDemangling *, size_t);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_operator_name(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_special_name(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_call_offset(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_nv_offset(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_v_offset(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_ctor_dtor_name(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_type(GItaniumDemangling *);
+
+/* Extrait une propriété de composant pour un contexte Itanium. */
+static TypeQualifier itd_cv_qualifiers(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_builtin_type(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_function_type(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_bare_function_type(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_class_enum_type(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_array_type(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_pointer_to_member_type(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_template_param(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_template_template_param(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_template_args(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_template_arg(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_expression(GItaniumDemangling *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_value_to_string(GItaniumDemangling *, bool);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_expr_primary(GItaniumDemangling *);
+
+
+
+
+/* Extrait un composant dans un contexte Itanium. */
+static bool itd_seq_id(GItaniumDemangling *, char, size_t *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_substitution(GItaniumDemangling *);
+
+
+
+
+
+
+#define itd_local_name(ctx) NULL
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_mangled_name(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <mangled-name> ::= _Z <encoding>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, '_'))
+ return NULL;
+
+ if (!check_input_buffer_char(ibuf, 'Z'))
+ return NULL;
+
+ result = itd_encoding(context);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_encoding(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ itanium_component *types; /* Composant 'bare-function...'*/
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <encoding> ::= <function name> <bare-function-type>
+ * ::= <data name>
+ * ::= <special-name>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'T' || peek == 'G')
+ result = itd_special_name(context);
+
+ else
+ {
+ result = itd_name(context);
+
+ if (result != NULL)
+ {
+ types = itd_bare_function_type(context);
+
+ if (types != NULL)
+ result = itd_make_binary(ICT_FUNCTION_ENCODING, result, types);
+
+ /**
+ * Si le chargement des types échoue, il peut y avoir deux explications :
+ * - on ne chargeait qu'un simple nom.
+ * - il y a eu une erreur de décodage pour les types.
+ *
+ * Le tampon aura été vidé dans le premier cas uniquement,
+ * donc on laisse le contexte détecter une éventuelle erreur.
+ */
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_name(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ itd_state saved; /* Position d'analyse courante */
+ itanium_component *tname; /* Composant '...template-name'*/
+ itanium_component *targs; /* Composant 'template-args' */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <name> ::= <nested-name>
+ * ::= <unscoped-name>
+ * ::= <unscoped-template-name> <template-args>
+ * ::= <local-name>
+ *
+ */
+
+ g_itanium_demangling_push_state(context, &saved);
+
+ result = itd_nested_name(context);
+
+ if (result == NULL)
+ {
+ g_itanium_demangling_pop_state(context, &saved);
+
+ tname = itd_unscoped_template_name(context);
+
+ if (tname != NULL)
+ {
+ targs = itd_template_args(context);
+
+ if (targs != NULL)
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, tname, targs);
+
+ else
+ itd_unref_comp(tname);
+
+ }
+
+ }
+
+ /**
+ * La règle <unscoped-name> doit être traitée après <unscoped-template-name>,
+ * car ces deux dernières ont une base commune et la seconde peut avoir besoin
+ * d'aller plus loin avec la règle <template-args>.
+ *
+ * On termine donc par moins gourmand si la règle la plus complexe n'a pas abouti.
+ */
+
+ if (result == NULL)
+ {
+ g_itanium_demangling_pop_state(context, &saved);
+ result = itd_unscoped_name(context);
+ }
+
+ if (result == NULL)
+ {
+ g_itanium_demangling_pop_state(context, &saved);
+ result = itd_local_name(context);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Détermine si le composant suivant correspond à un type donné.*
+* *
+* Retour : true si le décodage va à priori réussir, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool is_itd_unscoped_name(GItaniumDemangling *context)
+{
+ bool result; /* Bilan à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ char next_peek; /* Caractère après le prochain */
+
+ /**
+ * La règle anticipée ici est la suivante :
+ *
+ * <unscoped-name> ::= <unqualified-name>
+ * ::= St <unqualified-name> # ::std::
+ *
+ */
+
+ result = is_itd_unqualified_name(context);
+
+ if (!result)
+ {
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'S')
+ {
+ next_peek = peek_input_buffer_next_char(ibuf);
+
+ result = (next_peek == 't');
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_unscoped_name(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ char next_peek; /* Caractère après le prochain */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <unscoped-name> ::= <unqualified-name>
+ * ::= St <unqualified-name> # ::std::
+ *
+ */
+
+
+ if (is_itd_unqualified_name(context))
+ result = itd_unqualified_name(context);
+
+ else
+ {
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'S')
+ {
+ next_peek = peek_input_buffer_next_char(ibuf);
+
+ if (next_peek == 't')
+ {
+ advance_input_buffer(ibuf, 2);
+
+ result = itd_unqualified_name(context);
+
+ if (result != NULL)
+ result = itd_make_unary(ICT_STD_UNSCOPED_NAME, result);
+
+ }
+
+ else
+ result = NULL;
+
+ }
+
+ else
+ result = NULL;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_unscoped_template_name(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <unscoped-template-name> ::= <unscoped-name>
+ * ::= <substitution>
+ *
+ */
+
+ if (is_itd_unscoped_name(context))
+ {
+ result = itd_unscoped_name(context);
+
+ if (result != NULL)
+ g_itanium_demangling_add_substitution(context, result);
+
+ }
+
+ else
+ {
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'S')
+ result = itd_substitution(context);
+
+ else
+ result = NULL;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_nested_name(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ TypeQualifier qualifier; /* Propriétés supplémentaires */
+ itd_state saved; /* Position d'analyse courante */
+ itanium_component *left; /* Première partie */
+ itanium_component *right; /* Seconde partie */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
+ * ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'N'))
+ return NULL;
+
+ qualifier = itd_cv_qualifiers(context);
+
+ result = NULL;
+
+ g_itanium_demangling_push_state(context, &saved);
+
+ /**
+ * Comme <prefix> <unqualified-name> peut aussi être <template-prefix>,
+ * on commence par traiter la seconde règle.
+ */
+
+ left = itd_template_prefix(context);
+
+ if (left != NULL)
+ {
+ right = itd_template_args(context);
+
+ if (right != NULL)
+ {
+ if (check_input_buffer_char(ibuf, 'E'))
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, left, right);
+
+ else
+ {
+ if (left != NULL)
+ itd_unref_comp(left);
+ itd_unref_comp(right);
+ }
+
+ }
+
+ else if (left != NULL)
+ itd_unref_comp(left);
+
+ }
+
+ if (result == NULL)
+ {
+ g_itanium_demangling_pop_state(context, &saved);
+
+ left = itd_prefix(context);
+
+ /**
+ * Quand son traitement est un succès, <prefix> doit toujours
+ * se terminer par <unqualified-name>.
+ */
+
+ assert(left == NULL || (left != NULL && is_itd_unqualified_name(context)));
+
+ /**
+ * La règle <prefix> peut être vide, donc on se doit de tenter un
+ * <unqualified-name> dans tous les cas.
+ */
+
+ right = itd_unqualified_name(context);
+
+ if (right != NULL)
+ {
+ if (check_input_buffer_char(ibuf, 'E'))
+ result = itd_make_binary(ICT_NESTED_NAME, left, right);
+
+ else
+ {
+ if (left != NULL)
+ itd_unref_comp(left);
+ itd_unref_comp(right);
+ }
+
+ }
+
+ else if (left != NULL)
+ itd_unref_comp(left);
+
+ }
+
+ if (result != NULL)
+ itd_make_qualified_type(result, qualifier);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_prefix(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ itanium_component *targs; /* Composant 'template-args' */
+ itd_state saved; /* Position d'analyse courante */
+ itanium_component *further; /* Tentative de progression */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <prefix> ::= <prefix> <unqualified-name>
+ * ::= <template-prefix> <template-args>
+ * ::= <template-param>
+ * ::= # empty
+ * ::= <substitution>
+ *
+ * On note déjà la jolie petite boucle interne.
+ *
+ * Or on a également la règle voisine suivante :
+ *
+ * <template-prefix> ::= <prefix> <template unqualified-name>
+ * ::= <template-param>
+ * ::= <substitution>
+ *
+ * Pour éviter une récursivité qui ferait exploser la pile, on les fusionne
+ * en une nouvelle règle <prefix> étendue :
+ *
+ * <prefix> ::= <prefix> <unqualified-name>
+ * ::= <prefix> <unqualified-name> <template-args>
+ * ::= <template-param>
+ * ::= <template-param> <template-args>
+ * ::= <substitution>
+ * ::= <substitution> <template-args>
+ * ::= # empty
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (is_itd_unqualified_name(context))
+ result = itd_unqualified_name(context);
+
+ else
+ {
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'T')
+ result = itd_template_param(context);
+
+ else if (peek == 'S')
+ result = itd_substitution(context);
+
+ else
+ result = NULL;
+
+ }
+
+ if (result == NULL)
+ goto prefix_exit;
+
+ g_itanium_demangling_add_substitution(context, result);
+
+ /**
+ * Détection et traitement de <template-args>.
+ */
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'I')
+ {
+ /**
+ * Si la détection est avérée, on vient donc de traiter un cas <template-prefix>.
+ * On corrige donc le type au passage.
+ */
+ if (itd_get_component_type(result) == ICT_PREFIX_BINARY)
+ itd_set_type(result, ICT_TPREFIX_BINARY);
+
+ targs = itd_template_args(context);
+
+ if (targs != NULL)
+ {
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs);
+
+ g_itanium_demangling_add_substitution(context, result);
+
+ }
+
+ else
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ if (result == NULL)
+ goto prefix_exit;
+
+ /**
+ * Toutes les règles <prefix> sont suivie par un <[template] unqualified-name>.
+ *
+ * On vérifie donc que c'est le cas.
+ */
+
+ if (!is_itd_unqualified_name(context))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ goto prefix_exit;
+
+ }
+
+ /**
+ * Cette vérification passée, on peut se trouver dans l'un des cas suivants :
+ *
+ * <prefix> ::= <prefix> <unqualified-name>
+ * ::= <prefix> <template unqualified-name> <template-args>
+ *
+ * On tente donc une itération supplémentaire.
+ */
+
+ g_itanium_demangling_push_state(context, &saved);
+
+ further = itd_prefix_rec(context, result);
+
+ if (further != NULL)
+ result = further;
+
+ else
+ g_itanium_demangling_pop_state(context, &saved);
+
+ prefix_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* loop = consigne pour la poursuite de la boucle. [OUT] *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_prefix_rec(GItaniumDemangling *context, itanium_component *leaf)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ itanium_component *targs; /* Composant 'template-args' */
+ itd_state saved; /* Position d'analyse courante */
+ itanium_component *further; /* Tentative de progression */
+
+ /**
+ * La règle locale traitée ici est la suivante :
+ *
+ * <prefix> ::= <prefix> <unqualified-name>
+ * ::= <prefix> <unqualified-name> <template-args>
+ *
+ * Le premier <prefix> des règles est contenu dans l'arguement leaf.
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ /**
+ * La présence du <unqualified-name> intial doit être assurée
+ * par l'appelant.
+ *
+ * Mais comme le test ne vaut pas la création, on valide quand même derrière.
+ */
+
+ assert(is_itd_unqualified_name(context));
+
+ result = itd_unqualified_name(context);
+
+ if (result == NULL)
+ goto prefix_rec_exit;
+
+ result = itd_make_binary(ICT_PREFIX_BINARY, leaf, result);
+
+ g_itanium_demangling_add_substitution(context, result);
+
+ /**
+ * Détection et traitement de <template-args>.
+ */
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'I')
+ {
+ /**
+ * Si la détection est avérée, on vient donc de traiter un cas <template-prefix>.
+ * On corrige donc le type au passage.
+ */
+ if (itd_get_component_type(result) == ICT_PREFIX_BINARY)
+ itd_set_type(result, ICT_TPREFIX_BINARY);
+
+ targs = itd_template_args(context);
+
+ if (targs != NULL)
+ {
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs);
+
+ g_itanium_demangling_add_substitution(context, result);
+
+ }
+
+ else
+ {
+ itd_ref_comp(leaf);
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ if (result == NULL)
+ goto prefix_rec_exit;
+
+ /**
+ * Toutes les règles <prefix> sont suivie par un <[template] unqualified-name>.
+ *
+ * On vérifie donc que c'est le cas.
+ */
+
+ if (!is_itd_unqualified_name(context))
+ {
+ itd_ref_comp(leaf);
+ itd_unref_comp(result);
+ result = NULL;
+ goto prefix_rec_exit;
+ }
+
+ /**
+ * Cette vérification passée, on peut se trouver dans l'un des cas suivants :
+ *
+ * <prefix> ::= <prefix> <unqualified-name>
+ * ::= <prefix> <template unqualified-name> <template-args>
+ *
+ * On tente donc une itération supplémentaire.
+ */
+
+ g_itanium_demangling_push_state(context, &saved);
+
+ further = itd_prefix_rec(context, result);
+
+ if (further != NULL)
+ result = further;
+
+ else
+ g_itanium_demangling_pop_state(context, &saved);
+
+ prefix_rec_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_template_prefix(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ itanium_component *prefix; /* Premier d'un couple de comp.*/
+ itanium_component *name; /* Second d'un couple de comp. */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <template-prefix> ::= <prefix> <template unqualified-name>
+ * ::= <template-param>
+ * ::= <substitution>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'S')
+ result = itd_substitution(context);
+
+ else if (peek == 'T')
+ {
+ result = itd_template_param(context);
+
+ if (result != NULL)
+ g_itanium_demangling_add_substitution(context, result);
+
+ }
+
+ else
+ {
+ prefix = itd_prefix(context);
+
+ /**
+ * Quand son traitement est un succès, <prefix> doit toujours
+ * se terminer par <unqualified-name>.
+ */
+
+ assert(prefix == NULL || (prefix != NULL && is_itd_unqualified_name(context)));
+
+ /**
+ * Par ailleurs, la règle <prefix> peut être vide, donc on se doit
+ * de tenter un <unqualified-name> dans tous les cas.
+ */
+
+ name = itd_unqualified_name(context);
+
+ if (name != NULL)
+ {
+ result = itd_make_binary(ICT_TPREFIX_BINARY, prefix, name);
+
+ g_itanium_demangling_add_substitution(context, result);
+
+ }
+
+ else
+ {
+ result = NULL;
+
+ if (prefix != NULL)
+ itd_unref_comp(prefix);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Détermine si le composant suivant correspond à un type donné.*
+* *
+* Retour : true si le décodage va à priori réussir, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool is_itd_unqualified_name(GItaniumDemangling *context)
+{
+ bool result; /* Bilan à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+
+ /**
+ * La règle anticipée ici est la suivante :
+ *
+ * <unqualified-name> ::= <operator-name>
+ * ::= <ctor-dtor-name>
+ * ::= <source-name>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ result = islower(peek) /* <operator-name> */
+ || (peek == 'C' || peek == 'D') /* <ctor-dtor-name> */
+ || isdigit(peek); /* <source-name> */
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_unqualified_name(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <unqualified-name> ::= <operator-name>
+ * ::= <ctor-dtor-name>
+ * ::= <source-name>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (islower(peek))
+ result = itd_operator_name(context);
+
+ else if (peek == 'C' || peek == 'D')
+ result = itd_ctor_dtor_name(context);
+
+ else if (isdigit(peek))
+ result = itd_source_name(context);
+
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_source_name(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ ssize_t number; /* Taille positive */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <source-name> ::= <positive length number> <identifier>
+ *
+ */
+
+ if (!itd_number(context, &number))
+ return NULL;
+
+ if (number <= 0)
+ return NULL;
+
+ result = itd_identifier(context, number);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* size = taille positive ou non lue. [OUT] *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Bilan de l'opération (un chifre lu au moins). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool itd_number(GItaniumDemangling *context, ssize_t *size)
+{
+ bool result; /* Validité à renvoyer */
+ bool negative; /* Taille négative ? */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <number> ::= [n] <non-negative decimal integer>
+ *
+ */
+
+ result = false;
+
+ negative = false;
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'n')
+ {
+ negative = true;
+ advance_input_buffer(ibuf, 1);
+ peek = peek_input_buffer_char(ibuf);
+ }
+
+ *size = 0;
+
+ while (isdigit(peek))
+ {
+ result = true;
+ *size = *size * 10 + peek - '0';
+ advance_input_buffer(ibuf, 1);
+ peek = peek_input_buffer_char(ibuf);
+ }
+
+ if (negative)
+ *size *= -1;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* length = taille de l'identifiant à retrouver. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_identifier(GItaniumDemangling *context, size_t length)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ const char *data; /* Données restantes */
+ size_t remaining; /* Quantité d'octets */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <identifier> ::= <unqualified source code identifier>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ data = get_input_buffer_string(ibuf, &remaining);
+
+ if (length > remaining)
+ return NULL;
+
+ result = itd_make_name(data, length);
+
+ if (result != NULL)
+ advance_input_buffer(ibuf, length);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_operator_name(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char code[2]; /* Code à venir lire */
+ itanium_component *type; /* Type transtypé */
+ itanium_operator_info info; /* Clef des informations */
+ itanium_operator_info *found; /* Informations complètes */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <operator-name> ::= nw # new
+ * ::= na # new[]
+ * ::= dl # delete
+ * ::= da # delete[]
+ * ::= ps # + (unary)
+ * ::= ng # - (unary)
+ * ::= ad # & (unary)
+ * ::= de # * (unary)
+ * ::= co # ~
+ * ::= pl # +
+ * ::= mi # -
+ * ::= ml # *
+ * ::= dv # /
+ * ::= rm # %
+ * ::= an # &
+ * ::= or # |
+ * ::= eo # ^
+ * ::= aS # =
+ * ::= pL # +=
+ * ::= mI # -=
+ * ::= mL # *=
+ * ::= dV # /=
+ * ::= rM # %=
+ * ::= aN # &=
+ * ::= oR # |=
+ * ::= eO # ^=
+ * ::= ls # <<
+ * ::= rs # >>
+ * ::= lS # <<=
+ * ::= rS # >>=
+ * ::= eq # ==
+ * ::= ne # !=
+ * ::= lt # <
+ * ::= gt # >
+ * ::= le # <=
+ * ::= ge # >=
+ * ::= nt # !
+ * ::= aa # &&
+ * ::= oo # ||
+ * ::= pp # ++
+ * ::= mm # --
+ * ::= cm # ,
+ * ::= pm # ->*
+ * ::= pt # ->
+ * ::= cl # ()
+ * ::= ix # []
+ * ::= qu # ?
+ * ::= st # sizeof (a type)
+ * ::= sz # sizeof (an expression)
+ * ::= cv <type> # (cast)
+ * ::= v <digit> <source-name> # vendor extended operator
+ *
+ */
+
+ result = NULL;
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!get_input_buffer_next_char_carefully(ibuf, &code[0]))
+ goto itd_operator_name_exit;
+
+ if (code[0] == 'v')
+ {
+ type = itd_type(context);
+
+ if (type != NULL)
+ result = itd_make_cast_operator(type);
+ else
+ result = NULL;
+
+ goto itd_operator_name_exit;
+
+ }
+
+ if (!get_input_buffer_next_char_carefully(ibuf, &code[1]))
+ goto itd_operator_name_exit;
+
+ if (code[0] == 'c' && code[1] == 'v')
+ {
+ result = NULL;
+ goto itd_operator_name_exit;
+ }
+
+ /* Recherche dans la liste des opérateurs reconnus */
+
+ info.code = code;
+
+ int comp_itanium_operators(const itanium_operator_info *a, const itanium_operator_info *b)
+ {
+ int result; /* Bilan à renvoyer */
+
+ if (a->code[0] < b->code[0])
+ result = -1;
+ else if (a->code[0] > b->code[0])
+ result = 1;
+ else
+ {
+ if (a->code[1] < b->code[1])
+ result = -1;
+ else if (a->code[1] > b->code[1])
+ result = 1;
+ else
+ result = 0;
+ }
+
+ return result;
+
+ }
+
+ found = bsearch(&info, itanium_demangle_operators,
+ ARRAY_SIZE(itanium_demangle_operators),
+ sizeof(itanium_operator_info), (__compar_fn_t)comp_itanium_operators);
+
+ if (found != NULL)
+ result = itd_make_operator(found);
+
+ itd_operator_name_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_special_name(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char next; /* Caractère suivant */
+ char peek; /* Prochain caractère lu */
+ itanium_component *offset1; /* Décalage extrait #1 */
+ itanium_component *offset2; /* Décalage extrait #2 */
+ itanium_component *encoding; /* Encodage suivant */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <special-name> ::= TV <type> # virtual table
+ * ::= TT <type> # VTT structure (construction vtable index)
+ * ::= TI <type> # typeinfo structure
+ * ::= TS <type> # typeinfo name (null-terminated byte string)
+ * ::= Tc <call-offset> <call-offset> <base encoding>
+ * # base is the nominal target function of thunk
+ * # first call-offset is 'this' adjustment
+ * # second call-offset is result adjustment
+ * ::= T <call-offset> <base encoding>
+ * # base is the nominal target function of thunk
+ */
+
+ result = NULL;
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!get_input_buffer_next_char_carefully(ibuf, &next))
+ goto exit_eof;
+
+ if (next == 'T')
+ {
+ peek = peek_input_buffer_char(ibuf);
+
+ switch (peek)
+ {
+ case 'V':
+
+ advance_input_buffer(ibuf, 1);
+
+ result = itd_type(context);
+
+ if (result != NULL)
+ result = itd_make_unary(ICT_SPECIAL_NAME_VTABLE, result);
+
+ break;
+
+ case 'T':
+
+ advance_input_buffer(ibuf, 1);
+
+ result = itd_type(context);
+
+ if (result != NULL)
+ result = itd_make_unary(ICT_SPECIAL_NAME_VSTRUCT, result);
+
+ break;
+
+ case 'I':
+ advance_input_buffer(ibuf, 1);
+ result = itd_type(context);
+ break;
+
+ case 'S':
+ advance_input_buffer(ibuf, 1);
+ result = itd_type(context);
+ break;
+
+ case 'c':
+
+ advance_input_buffer(ibuf, 1);
+
+ offset1 = itd_call_offset(context);
+ if (offset1 == NULL) break;
+
+ offset2 = itd_call_offset(context);
+ if (offset2 == NULL)
+ {
+ itd_unref_comp(offset1);
+ break;
+ }
+
+ encoding = itd_encoding(context);
+
+ if (encoding == NULL)
+ {
+ itd_unref_comp(offset1);
+ itd_unref_comp(offset2);
+ }
+
+ else
+ result = itd_make_ternary(ICT_FUNCTION_COVARIANT_THUNK, encoding, offset1, offset2);
+
+ break;
+
+ case '\0':
+
+ /**
+ * Si on se trouve à la fin du tampon, on n'avance pas aveuglément !
+ */
+
+ result = NULL;
+ break;
+
+ default:
+
+ advance_input_buffer(ibuf, 1);
+
+ offset1 = itd_call_offset(context);
+ if (offset1 == NULL) break;
+
+ encoding = itd_encoding(context);
+
+ if (encoding == NULL)
+ itd_unref_comp(offset1);
+ else
+ result = itd_make_binary(ICT_FUNCTION_THUNK, encoding, offset1);
+
+ break;
+
+ }
+
+ }
+
+ exit_eof:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_call_offset(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char next; /* Caractère suivant */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <call-offset> ::= h <nv-offset> _
+ * ::= v <v-offset> _
+ */
+
+ result = NULL;
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (get_input_buffer_next_char_carefully(ibuf, &next))
+ goto exit_eof;
+
+ switch (next)
+ {
+ case 'h':
+ result = itd_nv_offset(context);
+ break;
+
+ case 'v':
+ result = itd_v_offset(context);
+ break;
+
+ }
+
+ if (result != NULL && !check_input_buffer_char(ibuf, '_'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ exit_eof:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_nv_offset(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ ssize_t offset; /* Décalage obtenu */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <nv-offset> ::= <offset number>
+ * # non-virtual base override
+ */
+
+ if (!itd_number(context, &offset))
+ return NULL;
+
+ result = itd_make_offset(ICT_NON_VIRTUAL_OFFSET, offset);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_v_offset(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ ssize_t offset; /* Décalage obtenu #1 */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ ssize_t voffset; /* Décalage obtenu #2 */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <v-offset> ::= <offset number> _ <virtual offset number>
+ * # virtual base override, with vcall offset
+ */
+
+ if (!itd_number(context, &offset))
+ return NULL;
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, '_'))
+ return NULL;
+
+ if (!itd_number(context, &voffset))
+ return NULL;
+
+ result = itd_make_binary(ICT_DOUBLE_OFFSET,
+ itd_make_offset(ICT_NON_VIRTUAL_OFFSET, offset),
+ itd_make_offset(ICT_VIRTUAL_OFFSET, voffset));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_ctor_dtor_name(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char next; /* Caractère suivant */
+ ItaniumComponentType type; /* Type de composant */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <ctor-dtor-name> ::= C1 # complete object constructor
+ * ::= C2 # base object constructor
+ * ::= C3 # complete object allocating constructor
+ * ::= D0 # deleting destructor
+ * ::= D1 # complete object destructor
+ * ::= D2 # base object destructor
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ next = peek_input_buffer_char(ibuf);
+
+ if (next == 'C')
+ type = ICT_CONSTRUCTOR;
+ else if (next == 'D')
+ type = ICT_DESSTRUCTOR;
+ else
+ return NULL;
+
+ advance_input_buffer(ibuf, 1);
+
+ next = peek_input_buffer_char(ibuf);
+
+ if (next != '0' && next != '1' && next != '2')
+ return NULL;
+
+ advance_input_buffer(ibuf, 1);
+
+ result = itd_make_with_type(type);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_type(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ TypeQualifier qualifier; /* Propriétés supplémentaires */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ bool handled; /* Prise en compte effectuée ? */
+ itanium_component *sub; /* Sous-type lié à associer */
+ itanium_component *vendor; /* Extension propriétaire */
+ GDataType *builtin; /* Type construit */
+ itd_state saved; /* Position d'analyse courante */
+ itanium_component *targs; /* Composant 'template-args' */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <type> ::= <builtin-type>
+ * ::= <function-type>
+ * ::= <class-enum-type>
+ * ::= <array-type>
+ * ::= <pointer-to-member-type>
+ * ::= <template-param>
+ * ::= <template-template-param> <template-args>
+ * ::= <substitution> # See Compression below
+ * ::= <CV-qualifiers> <type>
+ * ::= P <type> # pointer-to
+ * ::= R <type> # reference-to
+ * ::= O <type> # rvalue reference-to (C++0x)
+ * ::= C <type> # complex pair (C 2000)
+ * ::= G <type> # imaginary (C 2000)
+ * ::= U <source-name> <type> # vendor extended type qualifier
+ *
+ */
+
+ result = NULL;
+
+ qualifier = itd_cv_qualifiers(context);
+
+ if (qualifier != TQF_NONE)
+ {
+ result = itd_type(context);
+
+ if (result != NULL)
+ result = itd_make_qualified_type(result, qualifier);
+
+ goto itd_type_end;
+
+ }
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ handled = false;
+
+ switch (peek_input_buffer_char(ibuf))
+ {
+ case 'F':
+ result = itd_function_type(context);
+ handled = true;
+ break;
+
+ case 'A':
+ result = itd_array_type(context);
+ handled = true;
+ break;
+
+ case 'M':
+ result = itd_pointer_to_member_type(context);
+ handled = true;
+ break;
+
+ case 'P':
+
+ advance_input_buffer(ibuf, 1);
+
+ sub = itd_type(context);
+ if (sub == NULL) return NULL;
+
+ result = itd_make_unary(ICT_POINTER_TO, sub);
+ handled = true;
+ break;
+
+ case 'R':
+
+ advance_input_buffer(ibuf, 1);
+
+ sub = itd_type(context);
+ if (sub == NULL) return NULL;
+
+ result = itd_make_unary(ICT_REFERENCE_TO, sub);
+ handled = true;
+ break;
+
+ case 'O':
+
+ advance_input_buffer(ibuf, 1);
+
+ sub = itd_type(context);
+ if (sub == NULL) return NULL;
+
+ result = itd_make_unary(ICT_RVALUE_REFERENCE_TO, sub);
+ handled = true;
+ break;
+
+ case 'C':
+
+ advance_input_buffer(ibuf, 1);
+
+ sub = itd_type(context);
+ if (sub == NULL) return NULL;
+
+ result = itd_make_unary(ICT_COMPLEX_PAIR, sub);
+ handled = true;
+ break;
+
+ case 'G':
+
+ advance_input_buffer(ibuf, 1);
+
+ sub = itd_type(context);
+ if (sub == NULL) return NULL;
+
+ result = itd_make_unary(ICT_IMAGINARY, sub);
+ handled = true;
+ break;
+
+ case 'U':
+
+ advance_input_buffer(ibuf, 1);
+
+ result = NULL;
+
+ vendor = itd_source_name(context);
+
+ if (vendor == NULL)
+ result = NULL;
+
+ else
+ {
+ builtin = g_class_enum_type_new(CET_UNKNOWN, itd_translate_component(vendor, NULL));
+ result = itd_make_type(builtin);
+ itd_unref_comp(vendor);
+
+ sub = itd_type(context);
+
+ if (sub != NULL)
+ itd_unref_comp(sub);
+
+ else
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ handled = true;
+ break;
+
+ case 'T':
+
+ /**
+ * Comme on a la définition suivante :
+ *
+ * <template-template-param> ::= <template-param>
+ * ::= <substitution>
+ *
+ * On ne sait pas laquelle de ces deux directions prendre :
+ *
+ * <type> ::= <template-param>
+ * ::= <template-template-param> <template-args>
+ *
+ * Comme <template-args> commence toujour par un I, on teste
+ * le caractère courant après <template-param> et on revient
+ * un poil en arrière au besoin.
+ *
+ * Le cas <substitution> est traité de façon similaire après.
+ */
+
+ g_itanium_demangling_push_state(context, &saved);
+
+ result = itd_template_param(context);
+
+ if (result != NULL)
+ {
+ if (peek_input_buffer_char(ibuf) == 'I')
+ {
+ itd_unref_comp(result);
+
+ g_itanium_demangling_pop_state(context, &saved);
+
+ result = itd_template_template_param(context);
+
+ if (result != NULL)
+ {
+ targs = itd_template_args(context);
+
+ if (targs != NULL)
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs);
+
+ else
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ }
+
+ }
+
+ handled = true;
+ break;
+
+ }
+
+ if (handled) goto itd_type_end;
+
+ g_itanium_demangling_push_state(context, &saved);
+
+ result = itd_builtin_type(context);
+ if (result != NULL) goto itd_type_end;
+
+ g_itanium_demangling_pop_state(context, &saved);
+
+ result = itd_class_enum_type(context);
+ if (result != NULL) goto itd_type_end;
+
+ g_itanium_demangling_pop_state(context, &saved);
+
+ /**
+ * De façon similaire au cas <template-param> traité au dessus,
+ * on guette un usage de <substitution> via :
+ *
+ * <template-template-param> ::= <template-param>
+ * ::= <substitution>
+ *
+ * La distinction se réalise via une liste d'argument, et on tranche
+ * cette fois entre les deux directions suivantes :
+ *
+ * <type> ::= <template-template-param> <template-args>
+ * ::= <substitution> # See Compression below
+ */
+
+ g_itanium_demangling_push_state(context, &saved);
+
+ result = itd_substitution(context);
+
+ if (result != NULL && peek_input_buffer_char(ibuf) == 'I')
+ {
+ itd_unref_comp(result);
+
+ g_itanium_demangling_pop_state(context, &saved);
+
+ result = itd_template_template_param(context);
+
+ if (result != NULL)
+ {
+ targs = itd_template_args(context);
+
+ if (targs != NULL)
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs);
+
+ else
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ }
+
+ itd_type_end:
+
+ if (result != NULL)
+ {
+ /**
+ * Les spécifications (§ 5.1.9) précisent:
+ *
+ * There are two exceptions that appear to be substitution candidates
+ * from the grammar, but are explicitly excluded:
+ *
+ * <builtin-type> other than vendor extended types, and
+ * function and operator names other than extern "C" functions.
+ *
+ * On saute donc éventuelleement certains résultats.
+ */
+
+ if (itd_get_component_type(result) != ICT_TYPE)
+ g_itanium_demangling_add_substitution(context, result);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait une propriété de composant pour un contexte Itanium. *
+* *
+* Retour : Indication extraite. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static TypeQualifier itd_cv_qualifiers(GItaniumDemangling *context)
+{
+ TypeQualifier result; /* Valeur à remonter */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
+ *
+ */
+
+ result = TQF_NONE;
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ while (1)
+ switch (peek_input_buffer_char(ibuf))
+ {
+ case 'r':
+ result = TQF_RESTRICT;
+ advance_input_buffer(ibuf, 1);
+ break;
+
+ case 'V':
+ result = TQF_VOLATILE;
+ advance_input_buffer(ibuf, 1);
+ break;
+
+ case 'K':
+ result = TQF_CONST;
+ advance_input_buffer(ibuf, 1);
+ break;
+
+ default:
+ goto itd_cv_qualifiers_exit;
+ break;
+
+ }
+
+ itd_cv_qualifiers_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_builtin_type(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ BaseType type; /* Type reconnu ou BTP_INVALID */
+ itanium_component *vendor; /* Extension propriétaire */
+ GDataType *builtin; /* Type construit */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <builtin-type> ::= v # void
+ * ::= w # wchar_t
+ * ::= b # bool
+ * ::= c # char
+ * ::= a # signed char
+ * ::= h # unsigned char
+ * ::= s # short
+ * ::= t # unsigned short
+ * ::= i # int
+ * ::= j # unsigned int
+ * ::= l # long
+ * ::= m # unsigned long
+ * ::= x # long long, __int64
+ * ::= y # unsigned long long, __int64
+ * ::= n # __int128
+ * ::= o # unsigned __int128
+ * ::= f # float
+ * ::= d # double
+ * ::= e # long double, __float80
+ * ::= g # __float128
+ * ::= z # ellipsis
+ * ::= u <source-name> # vendor extended type
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ switch (peek_input_buffer_char(ibuf))
+ {
+ case 'v':
+ type = BTP_VOID;
+ break;
+ case 'w':
+ type = BTP_WCHAR_T;
+ break;
+ case 'b':
+ type = BTP_BOOL;
+ break;
+ case 'c':
+ type = BTP_CHAR;
+ break;
+ case 'a':
+ type = BTP_SCHAR;
+ break;
+ case 'h':
+ type = BTP_UCHAR;
+ break;
+ case 's':
+ type = BTP_SHORT;
+ break;
+ case 't':
+ type = BTP_USHORT;
+ break;
+ case 'i':
+ type = BTP_INT;
+ break;
+ case 'j':
+ type = BTP_UINT;
+ break;
+ case 'l':
+ type = BTP_LONG;
+ break;
+ case 'm':
+ type = BTP_ULONG;
+ break;
+ case 'x':
+ type = BTP_LONG_LONG;
+ break;
+ case 'y':
+ type = BTP_ULONG_LONG;
+ break;
+ case 'n':
+ type = BTP_INT128;
+ break;
+ case 'o':
+ type = BTP_UINT128;
+ break;
+ case 'f':
+ type = BTP_FLOAT;
+ break;
+ case 'd':
+ type = BTP_DOUBLE;
+ break;
+ case 'e':
+ type = BTP_LONG_DOUBLE;
+ break;
+ case 'g':
+ type = BTP_FLOAT128;
+ break;
+ case 'z':
+ type = BTP_ELLIPSIS;
+ break;
+ case 'u':
+
+ vendor = itd_source_name(context);
+
+ if (vendor == NULL)
+ result = NULL;
+ else
+ {
+ builtin = g_class_enum_type_new(CET_UNKNOWN, itd_translate_component(vendor, NULL));
+ result = itd_make_type(builtin);
+ itd_unref_comp(vendor);
+ }
+
+ goto done;
+ break;
+
+ default:
+ type = BTP_INVALID;
+ break;
+ }
+
+ if (type != BTP_INVALID)
+ {
+ builtin = g_basic_type_new(type);
+ result = itd_make_type(builtin);
+ advance_input_buffer(ibuf, 1);
+ }
+ else
+ result = NULL;
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_function_type(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère dispo. */
+ itanium_component *args; /* Liste des arguments */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <function-type> ::= F [Y] <bare-function-type> E
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'F'))
+ return NULL;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'Y')
+ advance_input_buffer(ibuf, 1);
+
+ args = itd_bare_function_type(context);
+
+ if (args == NULL)
+ result = NULL;
+
+ else
+ {
+ result = itd_make_function_type(peek == 'Y', args);
+
+ if (!check_input_buffer_char(ibuf, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_bare_function_type(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ itanium_component *type; /* Nouvel élément à intégrer */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ itd_state saved; /* Position d'analyse courante */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <bare-function-type> ::= <signature type>+
+ * # types are possible return type, then parameter types
+ *
+ */
+
+ type = itd_type(context);
+ if (type == NULL) return NULL;
+
+ result = itd_append_right_to_binary(ICT_TYPES_LIST, NULL, type);
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ while (count_input_buffer_remaining(ibuf) > 0)
+ {
+ g_itanium_demangling_push_state(context, &saved);
+
+ type = itd_type(context);
+
+ if (type == NULL)
+ {
+ g_itanium_demangling_pop_state(context, &saved);
+ break;
+ }
+
+ result = itd_append_right_to_binary(ICT_TYPES_LIST, result, type);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_class_enum_type(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <class-enum-type> ::= <name>
+ *
+ */
+
+ result = itd_name(context);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_array_type(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère dispo. */
+ itanium_component *dim_expr; /* Dimension via expression */
+ ssize_t dim_number; /* Dimension par un nombre */
+ itanium_component *type; /* Type du tableau */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <array-type> ::= A <positive dimension number> _ <element type>
+ * ::= A [<dimension expression>] _ <element type>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'A'))
+ return NULL;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == '[')
+ {
+ advance_input_buffer(ibuf, 1);
+
+ dim_expr = itd_expression(context);
+
+ if (dim_expr == NULL)
+ return NULL;
+
+ if (!check_input_buffer_char(ibuf, ']'))
+ return NULL;
+
+ if (!check_input_buffer_char(ibuf, '_'))
+ return NULL;
+
+ type = itd_type(context);
+
+ if (type == NULL)
+ {
+ itd_unref_comp(dim_expr);
+ return NULL;
+ }
+
+ result = itd_make_array_with_dim_expr(dim_expr, type);
+
+ if (result == NULL)
+ {
+ itd_unref_comp(dim_expr);
+ itd_unref_comp(type);
+ }
+
+ }
+
+ else
+ {
+ if (!itd_number(context, &dim_number))
+ return NULL;
+
+ if (!check_input_buffer_char(ibuf, '_'))
+ return NULL;
+
+ type = itd_type(context);
+
+ if (type == NULL)
+ return NULL;
+
+ result = itd_make_array_with_dim_number(dim_number, type);
+
+ if (result == NULL)
+ itd_unref_comp(type);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_pointer_to_member_type(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ itanium_component *class; /* Classe d'appatenance */
+ itanium_component *member; /* Membre représenté */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <pointer-to-member-type> ::= M <class type> <member type>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'M'))
+ return NULL;
+
+ class = itd_type(context);
+
+ if (class != NULL)
+ {
+ member = itd_type(context);
+
+ if (member != NULL)
+ result = itd_make_pointer_to_memeber_type(class, member);
+
+ else
+ {
+ itd_unref_comp(class);
+ result = NULL;
+ }
+
+ }
+
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_template_param(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char cur; /* Caractère analysé */
+ size_t id; /* Identifiant de substitution */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <template-param> ::= T_ # first template parameter
+ * ::= T <parameter-2 non-negative number> _
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'T'))
+ return NULL;
+
+ result = NULL;
+
+ if (get_input_buffer_next_char_carefully(ibuf, &cur))
+ {
+ if (cur == '_' || isdigit(cur) || isupper(cur))
+ {
+ if (!itd_seq_id(context, cur, &id))
+ return NULL;
+
+ result = g_itanium_demangling_get_template_arg(context, id);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_template_template_param(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère dispo. */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'T')
+ result = itd_template_param(context);
+
+ else
+ result = itd_substitution(context);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_template_args(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ itanium_component *arg; /* Nouvel argument extrait */
+ itd_state saved; /* Position d'analyse courante */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <template-args> ::= I <template-arg>+ E
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'I'))
+ return NULL;
+
+ arg = itd_template_arg(context);
+ if (arg == NULL) return NULL;
+
+ result = itd_append_right_to_binary(ICT_TYPES_LIST, NULL, arg);
+
+ while (1)
+ {
+ g_itanium_demangling_push_state(context, &saved);
+
+ arg = itd_template_arg(context);
+ if (arg == NULL)
+ {
+ g_itanium_demangling_pop_state(context, &saved);
+ break;
+ }
+
+ result = itd_append_right_to_binary(ICT_TYPES_LIST, result, arg);
+
+ }
+
+ if (!check_input_buffer_char(ibuf, 'E'))
+ {
+ itd_unref_comp(result);
+ return NULL;
+ }
+
+ result = itd_make_unary(ICT_TEMPLATE_ARGS, result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_template_arg(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <template-arg> ::= <type> # type or template
+ * ::= X <expression> E # expression
+ * ::= <expr-primary> # simple expressions
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'X')
+ {
+ advance_input_buffer(ibuf, 1);
+
+ result = itd_expression(context);
+
+ if (result != NULL && !check_input_buffer_char(ibuf, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ else if (peek == 'L')
+ result = itd_expr_primary(context);
+
+ else
+ result = itd_type(context);
+
+ if (result != NULL)
+ g_itanium_demangling_add_template_arg(context, result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_expression(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ char next_peek; /* Caractère après le prochain */
+ itanium_component *targs; /* Composant 'template-args' */
+ ItaniumOperatorType otype; /* Type d'opérateur */
+ const void *odata; /* Données associées */
+ const itanium_operator_info *simple; /* Données d'opérateur simple */
+ int i; /* Boucle de parcours */
+ itanium_component *list; /* Liste de sous-expressions */
+ itanium_component *sub; /* Sous-expression chargée */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <expression> ::= <unary operator-name> <expression>
+ * ::= <binary operator-name> <expression> <expression>
+ * ::= <trinary operator-name> <expression> <expression> <expression>
+ * ::= st <type>
+ * ::= <template-param>
+ * ::= sr <type> <unqualified-name> # dependent name
+ * ::= sr <type> <unqualified-name> <template-args> # dependent template-id
+ * ::= <expr-primary>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'T')
+ result = itd_template_param(context);
+
+ else if (peek == 'L')
+ result = itd_expr_primary(context);
+
+ else if (islower(peek))
+ {
+ next_peek = peek_input_buffer_next_char(ibuf);
+
+ if (peek == 's' && next_peek == 't')
+ {
+ advance_input_buffer(ibuf, 2);
+
+ result = itd_type(context);
+
+ }
+
+ else if (peek == 's' && next_peek == 'r')
+ {
+ advance_input_buffer(ibuf, 2);
+
+ result = itd_type(context);
+
+ if (result != NULL)
+ {
+ itd_unref_comp(result);
+
+ result = itd_unqualified_name(context);
+
+ if (result)
+ {
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'I')
+ {
+ targs = itd_template_args(context);
+
+ if (targs != NULL)
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs);
+
+ else
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ else
+ {
+ result = itd_operator_name(context);
+
+ if (result != NULL)
+ {
+ odata = itd_get_operator_info(result, &otype);
+
+ switch (otype)
+ {
+ case IOT_SIMPLE:
+
+ simple = (const itanium_operator_info *)odata;
+
+ list = NULL;
+
+ for (i = 0; i < simple->args; i++)
+ {
+ sub = itd_expression(context);
+
+ if (sub == NULL)
+ {
+ if (list != NULL)
+ {
+ itd_unref_comp(list);
+ list = NULL;
+ }
+
+ break;
+
+ }
+
+ list = itd_append_right_to_binary(ICT_EXPR_LIST, list, sub);
+
+ }
+
+ if (list == NULL)
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ else
+ result = itd_make_binary(ICT_OPERATED_EXPRESSION, result, list);
+
+ break;
+
+ case IOT_CAST:
+
+ sub = itd_expression(context);
+
+ if (sub == NULL)
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ else
+ {
+ list = itd_append_right_to_binary(ICT_EXPR_LIST, NULL, sub);
+ result = itd_make_binary(ICT_OPERATED_EXPRESSION, result, list);
+ }
+
+ break;
+
+ default:
+ assert(false);
+ itd_unref_comp(result);
+ result = NULL;
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* hex = prise en compte des caractères hexadécimaux ? *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_value_to_string(GItaniumDemangling *context, bool hex)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ const char *data; /* Données restantes */
+ itd_state saved; /* Position d'analyse initiale */
+ itd_state cur; /* Position d'analyse courante */
+ char peek; /* Prochain caractère lu */
+
+ /**
+ * Les règles traitées ici sont les suivantes :
+ *
+ * <value number> # integer literal
+ * <value float> # floating literal
+ *
+ */
+
+ result = NULL;
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ data = get_input_buffer_text_access(ibuf);
+
+ g_itanium_demangling_push_state(context, &saved);
+
+ while (1)
+ {
+ peek = peek_input_buffer_char(ibuf);
+
+ switch (peek)
+ {
+ case '0' ... '9':
+ advance_input_buffer(ibuf, 1);
+ break;
+
+ case 'a' ... 'f':
+ if (hex)
+ advance_input_buffer(ibuf, 1);
+ else
+ goto exit_iits;
+ break;
+
+ case 'E':
+ goto exit_loop;
+ break;
+
+ default:
+ goto exit_iits;
+
+ }
+
+ }
+
+ exit_loop:
+
+ g_itanium_demangling_push_state(context, &cur);
+
+ if ((cur.pos - saved.pos) > 0)
+ result = itd_make_name(data, cur.pos - saved.pos);
+
+ exit_iits:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_expr_primary(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ itd_state saved; /* Position d'analyse courante */
+ itanium_component *type; /* Type de valeur extrait */
+ itd_state saved_value; /* Position d'analyse courante */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <expr-primary> ::= L <type> <value number> E # integer literal
+ * ::= L <type> <value float> E # floating literal
+ * ::= L <mangled-name> E # external name
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'L'))
+ return NULL;
+
+ g_itanium_demangling_push_state(context, &saved);
+
+ type = itd_type(context);
+
+ if (type != NULL)
+ {
+ g_itanium_demangling_push_state(context, &saved_value);
+
+ /* Règle <type> <value number> */
+
+ result = itd_value_to_string(context, false);
+
+ if (result != NULL && !check_input_buffer_char(ibuf, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ /* Règle <type> <value float> */
+
+ if (result == NULL)
+ {
+ g_itanium_demangling_pop_state(context, &saved_value);
+
+ result = itd_value_to_string(context, true);
+
+ if (result != NULL && !check_input_buffer_char(ibuf, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ itd_unref_comp(type);
+
+ }
+ else
+ result = NULL;
+
+ /* Règle <mangled-name> */
+
+ if (result == NULL)
+ {
+ g_itanium_demangling_pop_state(context, &saved);
+ result = itd_mangled_name(context);
+
+ if (result != NULL && !check_input_buffer_char(ibuf, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* cur = caractère courant. *
+* id = identifiant lu en cas de succès. [OUT] *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool itd_seq_id(GItaniumDemangling *context, char cur, size_t *id)
+{
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <seq-id>
+ *
+ */
+
+ *id = 0;
+
+ /**
+ * La fonction n'est appelée que si un début de séquence est détecté.
+ * (ie, cur == '_' || isdigit(cur) || isupper(cur)).
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (cur != '_')
+ {
+ do
+ {
+ if (isdigit(cur))
+ *id = *id * 36 + cur - '0';
+ else if (isupper(cur))
+ *id = *id * 36 + cur - 'A' + 10;
+ else
+ return false;
+
+ if (!get_input_buffer_next_char_carefully(ibuf, &cur))
+ return false;
+
+ }
+ while (cur != '_');
+
+ (*id)++;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_substitution(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char cur; /* Caractère analysé */
+ size_t id; /* Identifiant de substitution */
+ size_t i; /* Boucle de parcours */
+ const itanium_std_subst_info *stdinfo; /* Raccourci de confort */
+ GDataType *std; /* Espace de noms */
+ GDataType *type; /* Type complet final */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <substitution> ::= S <seq-id> _
+ * ::= S_
+ * ::= St # ::std::
+ * ::= Sa # ::std::allocator
+ * ::= Sb # ::std::basic_string
+ * ::= Ss # ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
+ * ::= Si # ::std::basic_istream<char, std::char_traits<char>>
+ * ::= So # ::std::basic_ostream<char, std::char_traits<char>>
+ * ::= Sd # ::std::basic_iostream<char, std::char_traits<char>>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'S'))
+ return NULL;
+
+ result = NULL;
+
+ if (!get_input_buffer_next_char_carefully(ibuf, &cur))
+ goto exit_eof;
+
+ if (cur == '_' || isdigit(cur) || isupper(cur))
+ {
+ if (!itd_seq_id(context, cur, &id))
+ return NULL;
+
+ result = g_itanium_demangling_get_substitution(context, id);
+
+ }
+ else
+ {
+ for (i = 0; i < ARRAY_SIZE(itanium_standard_substitutions); i++)
+ {
+ stdinfo = &itanium_standard_substitutions[i];
+
+ if (stdinfo->code == cur)
+ {
+ std = g_class_enum_type_new(CET_NAMESPACE, strdup("std"));
+
+ if (stdinfo->class == NULL)
+ type = std;
+
+ else
+ {
+ type = g_class_enum_type_new(CET_CLASS, strdup(stdinfo->class));
+ g_data_type_set_namespace(type, std, "::");
+ }
+
+ result = itd_make_type(type);
+ itd_set_type(result, ICT_STD_SUBST);
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ exit_eof:
+
+ return result;
+
+}
diff --git a/plugins/itanium/abi.h b/plugins/itanium/abi.h
new file mode 100644
index 0000000..d286b2f
--- /dev/null
+++ b/plugins/itanium/abi.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * abi.h - prototypes pour le décodage des noms d'éléments selon l'ABI C++ Itanium
+ *
+ * Copyright (C) 2013-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_ABI_H
+#define _PLUGINS_ITANIUM_ABI_H
+
+
+#include "component.h"
+#include "context.h"
+
+
+
+/* Extrait un composant dans un contexte Itanium. */
+itanium_component *itd_mangled_name(GItaniumDemangling *);
+
+
+
+#endif /* _PLUGINS_ITANIUM_ABI_H */
diff --git a/plugins/itanium/component-int.h b/plugins/itanium/component-int.h
new file mode 100644
index 0000000..fb8c423
--- /dev/null
+++ b/plugins/itanium/component-int.h
@@ -0,0 +1,137 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * component-int.h - prototypes internes pour la description des composants Itanium
+ *
+ * Copyright (C) 2013-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_COMPONENT_INT_H
+#define _PLUGINS_ITANIUM_COMPONENT_INT_H
+
+
+#include "component.h"
+
+
+
+/* Composant extrait de l'encodage */
+struct _itanium_component
+{
+ ItaniumComponentType type; /* Type de composant */
+
+ unsigned int refcount; /* Compteur de références */
+
+ fnv64_t hash; /* Empreinte en cache */
+
+ union
+ {
+ /* ICT_NAME */
+ struct
+ {
+ const char *str;
+ size_t len;
+
+ } s_name;
+
+ /* ICT_OPERATOR_NAME */
+ struct
+ {
+ ItaniumOperatorType otype; /* Sélection dans l'union */
+
+ union
+ {
+ itanium_operator_info info; /* Opérateur simple */
+ itanium_component *trans; /* Type transtypé */
+
+ };
+
+ } operator;
+
+ /* ICT_NON_VIRTUAL_OFFSET */
+ /* ICT_VIRTUAL_OFFSET */
+ ssize_t offset; /* Décalage de fonction */
+
+ /* ICT_STD_SUBST */
+ /* ICT_TYPE */
+ GDataType *dtype; /* Type instancié */
+
+ /* ICT_QUALIFIED_TYPE */
+ struct
+ {
+ itanium_component *sub; /* Sous-élément */
+ TypeQualifier qualifier; /* Propriétés supplémentaires */
+
+ } qualified;
+
+ /* ICT_FUNCTION_TYPE */
+ struct
+ {
+ bool extern_c; /* Nature de la fonction */
+ itanium_component *args; /* Liste des arguments */
+
+ } function;
+
+ /* ICT_ARRAY */
+ struct
+ {
+ bool numbered_dim; /* Dimension numérique */
+ union
+ {
+ ssize_t dim_number; /* Taille du tableau */
+ itanium_component *dim_expr;/* La même, en expression */
+ };
+
+ itanium_component *atype; /* Type du tableau */
+
+ } array;
+
+ /* ICT_POINTER_TO_MEMBER */
+ struct
+ {
+ itanium_component *class; /* Classe d'appatenance */
+ itanium_component *member; /* Membre représenté */
+
+ } pmember;
+
+ /* ICT_* */
+ struct
+ {
+ itanium_component *left; /* Elément premier */
+ itanium_component *right; /* Elément second */
+
+ } binary;
+
+ /* ICT_* */
+ struct
+ {
+ itanium_component *first; /* Elément premier */
+ itanium_component *second; /* Elément second */
+ itanium_component *third; /* Elément troisième */
+
+ } ternary;
+
+ /* ICT_* */
+ itanium_component *unary; /* Sous-élément */
+
+ };
+
+};
+
+
+
+#endif /* _PLUGINS_ITANIUM_COMPONENT_INT_H */
diff --git a/plugins/itanium/component.c b/plugins/itanium/component.c
new file mode 100644
index 0000000..6e580f6
--- /dev/null
+++ b/plugins/itanium/component.c
@@ -0,0 +1,1842 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * component.c - représentation des composants extraits de l'ABI C++ Itanium
+ *
+ * Copyright (C) 2013-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "component.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <analysis/types/array.h>
+#include <analysis/types/cse.h>
+#include <analysis/types/expr.h>
+#include <analysis/types/override.h>
+#include <analysis/types/proto.h>
+#include <analysis/types/template.h>
+#include <common/extstr.h>
+#include <common/fnv1a.h>
+
+
+#include "component-int.h"
+
+
+
+
+/* Procédure à appliquer sur un composant visité */
+typedef void (* visit_comp_fc) (itanium_component *);
+
+
+#define reset_comp_hash(c) c->hash = 0
+
+
+/* Crée un composant de contexte Itanium complètement vierge. */
+static itanium_component *itd_alloc(void);
+
+/* Efface de la mémoire un composant de context Itanium. */
+static void itd_free(itanium_component *);
+
+/* Visite les composants en présence. */
+static void visit_comp(itanium_component *, visit_comp_fc);
+
+/* Traduit les composants de contexte Itanium en décalage. */
+static bool itd_translate_component_to_offset(const itanium_component *, call_offset_t *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un composant de contexte Itanium complètement vierge. *
+* *
+* Retour : Composant créé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_alloc(void)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = calloc(1, sizeof(itanium_component));
+
+ result->refcount = 1;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à supprimer. *
+* *
+* Description : Efface de la mémoire un composant de context Itanium. *
+* *
+* Retour : Composant créé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void itd_free(itanium_component *comp)
+{
+ free(comp);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à traiter. *
+* visitor = fonction à appliquer sur les composants présents. *
+* *
+* Description : Visite les composants en présence. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void visit_comp(itanium_component *comp, visit_comp_fc visitor)
+{
+ switch (comp->type)
+ {
+ case ICT_NAME:
+ break;
+
+ case ICT_STD_UNSCOPED_NAME:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_NESTED_NAME:
+ if (comp->binary.left != NULL)
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_TEMPLATE_NAME_ARGS:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_PREFIX_BINARY:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_TPREFIX_BINARY:
+ if (comp->binary.left != NULL)
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_OPERATOR_NAME:
+ if (comp->operator.otype == IOT_CAST)
+ visit_comp(comp->operator.trans, visitor);
+ break;
+
+ case ICT_SPECIAL_NAME_VTABLE:
+ case ICT_SPECIAL_NAME_VSTRUCT:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_NON_VIRTUAL_OFFSET:
+ case ICT_VIRTUAL_OFFSET:
+ break;
+
+ case ICT_DOUBLE_OFFSET:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+
+ case ICT_FUNCTION_THUNK:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_FUNCTION_COVARIANT_THUNK:
+ visit_comp(comp->ternary.first, visitor);
+ visit_comp(comp->ternary.second, visitor);
+ visit_comp(comp->ternary.third, visitor);
+ break;
+
+ case ICT_CONSTRUCTOR:
+ case ICT_DESSTRUCTOR:
+ break;
+
+ case ICT_TYPE:
+ break;
+
+ case ICT_QUALIFIED_TYPE:
+ visit_comp(comp->qualified.sub, visitor);
+ break;
+
+ case ICT_POINTER_TO:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_REFERENCE_TO:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_RVALUE_REFERENCE_TO:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_COMPLEX_PAIR:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_IMAGINARY:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_FUNCTION_TYPE:
+ visit_comp(comp->function.args, visitor);
+ break;
+
+ case ICT_FUNCTION_ENCODING:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_ARRAY:
+ if (!comp->array.numbered_dim)
+ visit_comp(comp->array.dim_expr, visitor);
+ visit_comp(comp->array.atype, visitor);
+ break;
+
+ case ICT_POINTER_TO_MEMBER:
+ visit_comp(comp->pmember.class, visitor);
+ visit_comp(comp->pmember.member, visitor);
+ break;
+
+ case ICT_TEMPLATE_ARGS:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_TYPES_LIST:
+
+ visit_comp(comp->binary.left, visitor);
+
+ if (comp->binary.right != NULL)
+ visit_comp(comp->binary.right, visitor);
+
+ break;
+
+ case ICT_EXPR_LIST:
+
+ visit_comp(comp->binary.left, visitor);
+
+ if (comp->binary.right != NULL)
+ visit_comp(comp->binary.right, visitor);
+
+ break;
+
+ case ICT_OPERATED_EXPRESSION:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_STD_SUBST:
+ break;
+
+ case ICT_COUNT:
+ break;
+
+ }
+
+ visitor(comp);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à mettre à jour. *
+* *
+* Description : Incrémente le nombre d'utilisation du composant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void itd_ref_comp(itanium_component *comp)
+{
+ void visit_for_ref(itanium_component *comp)
+ {
+ comp->refcount++;
+
+ }
+
+ visit_comp(comp, visit_for_ref);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à mettre à jour. *
+* *
+* Description : Décrémente le nombre d'utilisation du composant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void itd_unref_comp(itanium_component *comp)
+{
+ void visit_for_unref(itanium_component *comp)
+ {
+ if (--comp->refcount == 0)
+ {
+ if (comp->type == ICT_TYPE || comp->type == ICT_STD_SUBST)
+ g_object_unref(G_OBJECT(comp->dtype));
+
+ itd_free(comp);
+
+ }
+
+ }
+
+ visit_comp(comp, visit_for_unref);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à manipuler. *
+* *
+* Description : Détermine ou fournit l'empreinte d'un composant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+fnv64_t itd_hash_comp(itanium_component *comp)
+{
+ char *desc; /* Description du composant */
+
+ if (comp->hash == 0)
+ {
+ desc = itd_translate_component(comp, NULL);
+ comp->hash = fnv_64a_hash(desc);
+ free(desc);
+ }
+
+ return comp->hash;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type à définir pour le composant. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_with_type(ItaniumComponentType type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : str = chaîne de caractères à conserver. *
+* len = taille de l'identifiant à retrouver. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_name(const char *str, size_t len)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_NAME;
+ result->s_name.str = str;
+ result->s_name.len = len;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = information de base sur l'opérateur manipulé. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_operator(const itanium_operator_info *info)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_OPERATOR_NAME;
+ result->operator.otype = IOT_SIMPLE;
+ result->operator.info = *info;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = information de base sur l'opérateur manipulé. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_cast_operator(itanium_component *type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_OPERATOR_NAME;
+ result->operator.otype = IOT_CAST;
+ result->operator.trans = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium décodé à consulter. *
+* type = type d'opérateur représenté. *
+* *
+* Description : Donne des indications quant à un opérateur Itanium. *
+* *
+* Retour : Informations à interpréter selon le type transmis. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const void *itd_get_operator_info(const itanium_component *comp, ItaniumOperatorType *type)
+{
+ const void *result; /* Données à retourner */
+
+ assert(comp->type == ICT_OPERATOR_NAME);
+
+ *type = comp->operator.otype;
+
+ switch (*type)
+ {
+ case IOT_SIMPLE:
+ result = &comp->operator.info;
+ break;
+
+ case IOT_CAST:
+ result = comp->operator.trans;
+ break;
+
+ default:
+ assert(false);
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type exacte de décalage. *
+* offset = décalage extrait de l'encodage. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_offset(ItaniumComponentType type, ssize_t offset)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->offset = offset;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dtype = instance de type en place à conserver. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_type(GDataType *dtype)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_TYPE;
+ result->dtype = dtype;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : sub = composant de type en place à référencer. *
+* qualifier = propriétés supplémentaires pour le type. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_qualified_type(itanium_component *sub, TypeQualifier qualifier)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ if (qualifier == TQF_NONE)
+ result = sub;
+
+ else
+ {
+ result = itd_alloc();
+
+ result->type = ICT_QUALIFIED_TYPE;
+ result->qualified.sub = sub;
+ result->qualified.qualifier = qualifier;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : sub = composant de type en place à référencer. *
+* qualifier = propriétés supplémentaires pour le type. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_function_type(bool extern_c, itanium_component *args)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_FUNCTION_TYPE;
+ result->function.extern_c = extern_c;
+ result->function.args = args;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : number = dimension du tableau. *
+* type = type des membres du même tableau. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_array_with_dim_number(ssize_t number, itanium_component *type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_ARRAY;
+ result->array.numbered_dim = true;
+ result->array.dim_number = number;
+ result->array.atype = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = dimension du tableau. *
+* type = type des membres du même tableau. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_array_with_dim_expr(itanium_component *expr, itanium_component *type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_ARRAY;
+ result->array.numbered_dim = false;
+ result->array.dim_expr = expr;
+ result->array.atype = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe d'appatenance. *
+* member = membre représenté. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_pointer_to_memeber_type(itanium_component *class, itanium_component *member)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_POINTER_TO_MEMBER;
+ result->pmember.class = class;
+ result->pmember.member = member;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du composant à mettre en place. *
+* unary = sous-composant à associer. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_unary(ItaniumComponentType type, itanium_component *unary)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->unary = unary;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du composant à mettre en place. *
+* left = premier composant à associer. *
+* right = second composant à associer. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_binary(ItaniumComponentType type, itanium_component *left, itanium_component *right)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->binary.left = left;
+ result->binary.right = right;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du composant à mettre en place. *
+* left = second composant à associer. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_append_right_to_binary(ItaniumComponentType type, itanium_component *parent, itanium_component *left)
+{
+ itanium_component *result; /* Composant à renvoyer */
+ itanium_component *iter; /* Boucle de parcours */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->binary.left = left;
+ result->binary.right = NULL;
+
+ if (parent != NULL)
+ {
+ for (iter = parent; iter->binary.right != NULL; iter = iter->binary.right)
+ reset_comp_hash(iter);
+ iter->binary.right = result;
+ }
+
+ return (parent != NULL ? parent : result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du composant à mettre en place. *
+* c0 = premier composant à associer. *
+* c1 = second composant à associer. *
+* c2 = troisième composant à associer. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_ternary(ItaniumComponentType type, itanium_component *c0, itanium_component *c1, itanium_component *c2)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->ternary.first = c0;
+ result->ternary.second = c1;
+ result->ternary.third = c2;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à mettre à jour. *
+* type = type à redéfinir pour le composant. *
+* *
+* Description : Modifie légèrement le type d'un composant donné. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void itd_set_type(itanium_component *comp, ItaniumComponentType type)
+{
+ comp->type = type;
+
+ reset_comp_hash(comp);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à consulter. *
+* *
+* Description : Fournit le type d'un composant issu d'un contexte Itanium. *
+* *
+* Retour : Type enregistré. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+ItaniumComponentType itd_get_component_type(const itanium_component *comp)
+{
+ return comp->type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = second composant à associer. *
+* base = éventuelle base à compléter ou NULL si aucune. *
+* *
+* Description : Traduit les composants de contexte Itanium. *
+* *
+* Retour : Traduction en format humainement lisible effectuée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *itd_translate_component(const itanium_component *comp, char *base)
+{
+ char *result; /* Chaîne à retourner */
+ char *name; /* Désignation à copier */
+ const itanium_component *sub; /* Sous-partie de composant */
+ ItaniumOperatorType otype; /* Type d'opérateur */
+ const void *odata; /* Données associées */
+ const itanium_operator_info *simple; /* Données d'opérateur simple */
+ char *tmp; /* Transcription temporaire */
+
+ switch (comp->type)
+ {
+ case ICT_NAME:
+ result = strnadd(base, comp->s_name.str, comp->s_name.len);
+ break;
+
+ case ICT_STD_UNSCOPED_NAME:
+ result = stradd(base, "std::");
+ result = itd_translate_component(comp->unary, result);
+ break;
+
+ case ICT_NESTED_NAME:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ result = itd_translate_component(comp->binary.left, base);
+ result = itd_translate_component(comp->binary.right, result);
+ }
+
+ else
+ {
+ if (comp->binary.left != NULL)
+ {
+ result = itd_translate_component(comp->binary.left, base);
+ result = stradd(result, "::");
+ }
+ else
+ result = base;
+
+ result = itd_translate_component(comp->binary.right, result);
+
+ }
+
+ break;
+
+ case ICT_TEMPLATE_NAME_ARGS:
+ result = itd_translate_component(comp->binary.left, base);
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_PREFIX_BINARY:
+ result = itd_translate_component(comp->binary.left, base);
+ if (comp->binary.right->type != ICT_TEMPLATE_ARGS)
+ result = stradd(result, "::");
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_TPREFIX_BINARY:
+ if (comp->binary.left != NULL)
+ {
+ result = itd_translate_component(comp->binary.left, base);
+ if (comp->binary.right->type != ICT_TEMPLATE_ARGS)
+ result = stradd(result, "::");
+ }
+ else
+ result = base;
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_OPERATOR_NAME:
+ switch (comp->operator.otype)
+ {
+ case IOT_SIMPLE:
+ result = stradd(base, "operator");
+ result = stradd(result, comp->operator.info.name);
+ break;
+ case IOT_CAST:
+ result = stradd(base, "(");
+ sub = (const itanium_component *)odata;
+ result = itd_translate_component(comp->operator.trans, result);
+ result = stradd(result, ")");
+ break;
+ default:
+ result = NULL;
+ break;
+ }
+ break;
+
+ case ICT_SPECIAL_NAME_VTABLE:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, "::vtable");
+ break;
+
+ case ICT_SPECIAL_NAME_VSTRUCT:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, "::vstruct");
+ break;
+
+ case ICT_NON_VIRTUAL_OFFSET:
+ case ICT_VIRTUAL_OFFSET:
+ asprintf(&tmp, "%zd", comp->offset);
+ result = stradd(base, tmp);
+ free(tmp);
+ break;
+
+ case ICT_DOUBLE_OFFSET:
+ result = itd_translate_component(comp->binary.left, base);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_FUNCTION_THUNK:
+ result = itd_translate_component(comp->binary.left, base);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_FUNCTION_COVARIANT_THUNK:
+ result = itd_translate_component(comp->ternary.first, base);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->ternary.second, result);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->ternary.third, result);
+ break;
+
+ case ICT_CONSTRUCTOR:
+ result = stradd(base, "<ctor>");
+ break;
+
+ case ICT_DESSTRUCTOR:
+ result = stradd(base, "<dtor>");
+ break;
+
+ case ICT_TYPE:
+ name = g_data_type_to_string(comp->dtype, true);
+ result = stradd(base, name);
+ free(name);
+ break;
+
+ case ICT_QUALIFIED_TYPE:
+
+ switch (comp->qualified.qualifier)
+ {
+ case TQF_RESTRICT:
+ result = stradd(base, "restrict ");
+ break;
+ case TQF_VOLATILE:
+ result = stradd(base, "volatile ");
+ break;
+ case TQF_CONST:
+ result = stradd(base, "const ");
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ result = itd_translate_component(comp->qualified.sub, result);
+
+ break;
+
+ case ICT_POINTER_TO:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, " *");
+ break;
+
+ case ICT_REFERENCE_TO:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, " &");
+ break;
+
+ case ICT_RVALUE_REFERENCE_TO:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, " &");
+ break;
+
+ case ICT_COMPLEX_PAIR:
+ result = stradd(base, "<?>");
+ result = itd_translate_component(comp->unary, result);
+ break;
+
+ case ICT_IMAGINARY:
+ result = stradd(base, "<?>");
+ result = itd_translate_component(comp->unary, result);
+ break;
+
+ case ICT_FUNCTION_TYPE:
+ result = stradd(base, "(*) (");
+ result = itd_translate_component(comp->function.args, result);
+ result = stradd(result, ")");
+ break;
+
+ case ICT_FUNCTION_ENCODING:
+
+ result = stradd(base, "???");
+
+ result = stradd(result, " ");
+
+ result = itd_translate_component(comp->binary.left, result);
+
+ result = stradd(result, "(");
+
+ result = itd_translate_component(comp->binary.right, result);
+
+ result = stradd(result, ")");
+
+ break;
+
+ case ICT_ARRAY:
+
+ result = itd_translate_component(comp->array.atype, base);
+
+ result = stradd(result, "[");
+
+ if (comp->array.numbered_dim)
+ {
+ asprintf(&tmp, "%zd", comp->array.dim_number);
+ result = stradd(result, tmp);
+ free(tmp);
+ }
+
+ else
+ result = itd_translate_component(comp->array.dim_expr, result);
+
+ result = stradd(result, "]");
+
+ break;
+
+ case ICT_POINTER_TO_MEMBER:
+ result = itd_translate_component(comp->pmember.class, base);
+ result = stradd(result, "::");
+ result = itd_translate_component(comp->pmember.member, result);
+ break;
+
+ case ICT_TEMPLATE_ARGS:
+ result = stradd(base, "<");
+ result = itd_translate_component(comp->unary, result);
+ result = stradd(result, ">");
+ break;
+
+ case ICT_TYPES_LIST:
+
+ result = itd_translate_component(comp->binary.left, base);
+
+ if (comp->binary.right != NULL)
+ {
+ result = stradd(result, ", ");
+ result = itd_translate_component(comp->binary.right, result);
+ }
+
+ break;
+
+ case ICT_EXPR_LIST:
+
+ /**
+ * A priori traité en amont.
+ */
+
+ result = itd_translate_component(comp->binary.left, base);
+
+ if (comp->binary.right != NULL)
+ {
+ result = stradd(result, ", ");
+ result = itd_translate_component(comp->binary.right, result);
+ }
+
+ break;
+
+ case ICT_OPERATED_EXPRESSION:
+
+ odata = itd_get_operator_info(comp->binary.left, &otype);
+
+ sub = comp->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+
+ switch (otype)
+ {
+ case IOT_SIMPLE:
+
+ simple = (const itanium_operator_info *)odata;
+
+ switch (simple->args)
+ {
+ case 1:
+ result = stradd(base, simple->name);
+ result = itd_translate_component(sub->binary.left, result);
+ assert(sub->binary.right == NULL);
+ break;
+
+ case 2:
+
+ result = itd_translate_component(sub->binary.left, base);
+
+ result = stradd(result, simple->name);
+
+ sub = sub->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+ result = itd_translate_component(sub->binary.left, result);
+ assert(sub->binary.right == NULL);
+ break;
+
+ case 3:
+
+ result = itd_translate_component(sub->binary.left, base);
+
+ result = stradd(result, simple->name);
+
+ sub = sub->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+ result = itd_translate_component(sub->binary.left, result);
+
+ result = stradd(result, ":");
+
+ sub = sub->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+ result = itd_translate_component(sub->binary.left, result);
+ assert(sub->binary.right == NULL);
+
+ break;
+
+ }
+
+ break;
+
+ case IOT_CAST:
+ result = stradd(base, "(");
+ sub = (const itanium_component *)odata;
+ result = itd_translate_component(sub, result);
+ result = stradd(result, ")");
+ break;
+
+ default:
+ result = NULL;
+ break;
+
+ }
+
+ break;
+
+ case ICT_STD_SUBST:
+ name = g_data_type_to_string(comp->dtype, true);
+ result = stradd(base, name);
+ free(name);
+ break;
+
+ case ICT_COUNT:
+ result = base;
+ break;
+
+ }
+
+
+
+ return result;
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium à traduire en décalage. *
+* off = réceptacle pour les informations traduites. *
+* *
+* Description : Traduit les composants de contexte Itanium en décalage. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool itd_translate_component_to_offset(const itanium_component *comp, call_offset_t *off)
+{
+ bool result; /* Bilan à retourner */
+
+ if (comp->type == ICT_DOUBLE_OFFSET)
+ {
+ result = comp->binary.left->type == ICT_NON_VIRTUAL_OFFSET
+ && comp->binary.right->type == ICT_VIRTUAL_OFFSET;
+
+ assert(result);
+
+ if (result)
+ {
+ off->values[0] = comp->binary.left->offset;
+ off->values[1] = comp->binary.right->offset;
+ off->virtual = true;
+ }
+
+ }
+
+ else if (comp->type == ICT_NON_VIRTUAL_OFFSET)
+ {
+ result = true;
+
+ off->values[0] = comp->offset;
+ off->virtual = false;
+
+ }
+
+ else
+ result = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium à traduire en type. *
+* *
+* Description : Traduit les composants de contexte Itanium en type. *
+* *
+* Retour : Traduction en type décodé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDataType *itd_translate_component_to_type(const itanium_component *comp)
+{
+ GDataType *result; /* Type à retourner */
+ char *name; /* Attribution finale */
+ GDataType *ns; /* Espace de noms d'un type */
+ call_offset_t off0; /* Décalage #0 */
+ call_offset_t off1; /* Décalage #1 */
+ itanium_component *iter; /* Boucle de parcours */
+ GDataType *arg; /* Argument de prototype */
+ GDataType *members; /* Type de membres de tableau */
+ GDataType *param; /* Paramètre de gabarit */
+
+ /* Pour GCC !? */
+ result = NULL;
+
+ switch (comp->type)
+ {
+ case ICT_NAME:
+ name = itd_translate_component(comp, NULL);
+ result = g_class_enum_type_new(CET_STRUCT, name);
+ break;
+
+ case ICT_STD_UNSCOPED_NAME:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ {
+ ns = g_class_enum_type_new(CET_NAMESPACE, strdup("std"));
+ g_data_type_set_namespace(result, ns, "::");
+ }
+ break;
+
+ case ICT_NESTED_NAME:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ name = itd_translate_component(comp->binary.right, name);
+
+ result = g_class_enum_type_new(CET_CLASS, name);
+
+ }
+
+ else
+ {
+ if (comp->binary.left != NULL)
+ {
+ ns = itd_translate_component_to_type(comp->binary.left);
+ if (ns == NULL)
+ {
+ result = NULL;
+ break;
+ }
+ }
+ else
+ ns = NULL;
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL && ns != NULL)
+ g_data_type_set_namespace(result, ns, "::");
+
+ }
+
+ break;
+
+ case ICT_TEMPLATE_NAME_ARGS:
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ g_template_type_set_name(G_TEMPLATE_TYPE(result), name);
+ }
+
+ break;
+
+ case ICT_PREFIX_BINARY:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ name = itd_translate_component(comp->binary.right, name);
+
+ result = g_class_enum_type_new(CET_CLASS, name);
+
+ }
+
+ else
+ {
+ ns = itd_translate_component_to_type(comp->binary.left);
+ if (ns == NULL)
+ {
+ result = NULL;
+ break;
+ }
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL)
+ g_data_type_set_namespace(result, ns, "::");
+
+ }
+
+ break;
+
+ case ICT_TPREFIX_BINARY:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ name = itd_translate_component(comp->binary.right, name);
+
+ result = g_class_enum_type_new(CET_CLASS, name);
+
+ }
+
+ else
+ {
+ if (comp->binary.left != NULL)
+ {
+ ns = itd_translate_component_to_type(comp->binary.left);
+ if (ns == NULL)
+ {
+ result = NULL;
+ break;
+ }
+
+ }
+ else
+ ns = NULL;
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL)
+ {
+ if (ns != NULL)
+ g_data_type_set_namespace(result, ns, "::");
+ }
+ else
+ {
+ if (ns != NULL)
+ g_object_unref(G_OBJECT(ns));
+ }
+
+ }
+
+ break;
+
+ case ICT_OPERATOR_NAME:
+ result = NULL;
+ break;
+
+ case ICT_SPECIAL_NAME_VTABLE:
+
+ ns = itd_translate_component_to_type(comp->unary);
+
+ if (ns == NULL)
+ result = NULL;
+
+ else
+ {
+ result = g_class_enum_type_new(CET_VIRTUAL_TABLE, NULL);
+ g_data_type_set_namespace(result, ns, "::");
+ }
+
+ break;
+
+ case ICT_SPECIAL_NAME_VSTRUCT:
+
+ ns = itd_translate_component_to_type(comp->unary);
+
+ if (ns == NULL)
+ result = NULL;
+
+ else
+ {
+ result = g_class_enum_type_new(CET_VIRTUAL_STRUCT, NULL);
+ g_data_type_set_namespace(result, ns, "::");
+ }
+
+ break;
+
+ case ICT_NON_VIRTUAL_OFFSET:
+ case ICT_VIRTUAL_OFFSET:
+ case ICT_DOUBLE_OFFSET:
+ result = NULL;
+ break;
+
+ case ICT_FUNCTION_THUNK:
+
+ if (!itd_translate_component_to_offset(comp->binary.right, &off0))
+ {
+ result = NULL;
+ break;
+ }
+
+ result = itd_translate_component_to_type(comp->binary.left);
+
+ if (result != NULL)
+ result = g_override_type_new(result, &off0);
+
+ break;
+
+ case ICT_FUNCTION_COVARIANT_THUNK:
+
+ if (!itd_translate_component_to_offset(comp->ternary.second, &off0))
+ {
+ result = NULL;
+ break;
+ }
+
+ if (!itd_translate_component_to_offset(comp->ternary.third, &off1))
+ {
+ result = NULL;
+ break;
+ }
+
+ result = itd_translate_component_to_type(comp->ternary.first);
+
+ if (result != NULL)
+ result = g_override_type_new_with_covariant(result, &off0, &off1);
+
+ break;
+
+ case ICT_CONSTRUCTOR:
+ case ICT_DESSTRUCTOR:
+ result = NULL;
+ break;
+
+ case ICT_TYPE:
+ result = g_data_type_dup(comp->dtype);
+ break;
+
+ case ICT_QUALIFIED_TYPE:
+ result = itd_translate_component_to_type(comp->qualified.sub);
+ if (result != NULL)
+ g_data_type_add_qualifier(result, comp->qualified.qualifier);
+ break;
+
+ case ICT_POINTER_TO:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL && !G_IS_PROTO_TYPE(result))
+ result = g_encapsulated_type_new(ECT_POINTER, result);
+ break;
+
+ case ICT_REFERENCE_TO:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_REFERENCE, result);
+ break;
+
+ case ICT_RVALUE_REFERENCE_TO:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_RVALUE_REF, result);
+ break;
+
+ case ICT_COMPLEX_PAIR:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_COMPLEX, result);
+ break;
+
+ case ICT_IMAGINARY:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_IMAGINARY, result);
+ break;
+
+ case ICT_FUNCTION_TYPE:
+
+ result = g_proto_type_new();
+
+ assert(comp->function.args->type == ICT_TYPES_LIST);
+
+ for (iter = comp->function.args; iter != NULL && result != NULL; iter = iter->binary.right)
+ {
+ assert(iter->type == ICT_TYPES_LIST);
+
+ arg = itd_translate_component_to_type(iter->binary.left);
+
+ if (arg == NULL)
+ {
+ g_object_unref(G_OBJECT(result));
+ result = NULL;
+ }
+
+ else
+ {
+ if (iter == comp->function.args)
+ g_proto_type_set_return_type(G_PROTO_TYPE(result), arg);
+
+ else
+ g_proto_type_add_arg(G_PROTO_TYPE(result), arg);
+ }
+
+ }
+
+ break;
+
+ case ICT_FUNCTION_ENCODING:
+ result = NULL;
+ break;
+
+ case ICT_ARRAY:
+
+ members = itd_translate_component_to_type(comp->array.atype);
+
+ if (members == NULL)
+ result = NULL;
+
+ else
+ {
+ result = g_array_type_new(members);
+
+ if (comp->array.numbered_dim)
+ g_array_type_set_dimension_number(G_ARRAY_TYPE(result), comp->array.dim_number);
+
+ else
+ g_array_type_set_dimension_expression(G_ARRAY_TYPE(result),
+ itd_translate_component(comp, NULL));
+
+ }
+
+ break;
+
+ case ICT_POINTER_TO_MEMBER:
+
+ ns = itd_translate_component_to_type(comp->pmember.class);
+
+ if (ns == NULL)
+ result = NULL;
+
+ else
+ {
+ result = itd_translate_component_to_type(comp->pmember.member);
+
+ if (result == NULL)
+ g_object_unref(G_OBJECT(ns));
+
+ else
+ g_data_type_set_namespace(result, ns, "::");
+
+ }
+
+ break;
+
+ case ICT_TEMPLATE_ARGS:
+
+ assert(comp->unary->type == ICT_TYPES_LIST);
+
+ result = g_template_type_new();
+
+ for (iter = comp->unary; iter != NULL && result != NULL; iter = iter->binary.right)
+ {
+ assert(iter->type == ICT_TYPES_LIST);
+
+ param = itd_translate_component_to_type(iter->binary.left);
+
+ if (param == NULL)
+ {
+ g_object_unref(G_OBJECT(result));
+ result = NULL;
+ }
+ else
+ g_template_type_add_param(G_TEMPLATE_TYPE(result), param);
+
+ }
+
+ break;
+
+ case ICT_TYPES_LIST:
+
+ /**
+ * Les listes doient être rassemblées par l'appelant !
+ */
+
+ assert(false);
+ result = NULL;
+ break;
+
+ case ICT_EXPR_LIST:
+
+ /**
+ * Les listes doient être rassemblées par l'appelant !
+ */
+
+ assert(false);
+ result = NULL;
+ break;
+
+ case ICT_OPERATED_EXPRESSION:
+ result = g_expr_type_new(itd_translate_component(comp, NULL));
+ break;
+
+ case ICT_STD_SUBST:
+ result = g_data_type_dup(comp->dtype);
+ break;
+
+ case ICT_COUNT:
+ assert(false);
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium à traduire en routine. *
+* *
+* Description : Traduit les composants de contexte Itanium en routine. *
+* *
+* Retour : Traduction en routine décodée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinRoutine *itd_translate_component_to_routine(const itanium_component *comp)
+{
+ GBinRoutine *result; /* Routine à retourner */
+ bool has_ret; /* Type de retour présent ? */
+ itanium_component *name; /* Désignation de la routine */
+ char *desc; /* Description humaine */
+ GDataType *ns; /* Espace de noms de la routine*/
+ itanium_component *args; /* Liste de ses arguments */
+ itanium_component *iter; /* Boucle de parcours */
+ GDataType *type; /* Type d'un argument */
+ GBinVariable *arg; /* Argument à ajouter */
+
+ if (comp->type != ICT_FUNCTION_ENCODING)
+ goto bad_encoding;
+
+ result = g_binary_routine_new();
+
+ /* Nom de la routine */
+
+ name = comp->binary.left;
+
+ /**
+ * A la fin de § 5.1.3 ("Operator Encodings") est précisé :
+ *
+ * If the conversion operator is a member template, the result type will
+ * appear before the template parameters.
+ *
+ * On note donc cette particularité.
+ */
+
+ has_ret = (name->type == ICT_TEMPLATE_NAME_ARGS);
+
+ switch (name->type)
+ {
+ case ICT_NAME:
+ g_binary_routine_set_name(result, itd_translate_component(name, NULL));
+ break;
+
+ case ICT_NESTED_NAME:
+ case ICT_TEMPLATE_NAME_ARGS:
+
+ type = itd_translate_component_to_type(name);
+ if (type == NULL) goto unsupported_encoding;
+
+ ns = g_data_type_get_namespace(type);
+
+ g_data_type_set_namespace(type, NULL, NULL);
+
+ desc = g_data_type_to_string(type, true);
+
+ g_object_unref(G_OBJECT(type));
+
+ g_binary_routine_set_name(result, desc);
+
+ g_binary_routine_set_namespace(result, ns, "::");
+
+ break;
+
+ case ICT_OPERATOR_NAME:
+ g_binary_routine_set_name(result, itd_translate_component(name, NULL));
+ break;
+
+ default:
+ goto unsupported_encoding;
+ break;
+
+ }
+
+ /* Liste d'arguments */
+
+ args = comp->binary.right;
+
+ if (args->type != ICT_TYPES_LIST)
+ goto unsupported_encoding;
+
+ for (iter = args; iter != NULL; iter = iter->binary.right)
+ {
+ type = itd_translate_component_to_type(iter->binary.left);
+
+ if (type == NULL)
+ goto unsupported_encoding;
+
+ if (iter == args && has_ret)
+ g_binary_routine_set_return_type(result, type);
+
+ else
+ {
+ arg = g_binary_variable_new(type);
+ g_binary_routine_add_arg(result, arg);
+ }
+
+ }
+
+ return result;
+
+ unsupported_encoding:
+
+ g_object_unref(G_OBJECT(result));
+
+ bad_encoding:
+
+ return NULL;
+
+}
diff --git a/plugins/itanium/component.h b/plugins/itanium/component.h
new file mode 100644
index 0000000..f921ff9
--- /dev/null
+++ b/plugins/itanium/component.h
@@ -0,0 +1,294 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * component.h - prototypes pour la représentation des composants extraits de l'ABI C++ Itanium
+ *
+ * Copyright (C) 2013-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_COMPONENT_H
+#define _PLUGINS_ITANIUM_COMPONENT_H
+
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <sys/types.h>
+
+
+#include <analysis/routine.h>
+#include <analysis/type.h>
+#include <common/fnv1a.h>
+
+
+
+/* Type de composants */
+typedef enum _ItaniumComponentType
+{
+ /**
+ * Chaîne de caractère, terminée par un octet nul.
+ */
+ ICT_NAME,
+
+ /**
+ * Nom avec préfixe standard.
+ * Le nom en question est placé dans le champ unary.
+ */
+ ICT_STD_UNSCOPED_NAME,
+
+ /**
+ * Noms imbriqués, en deux parties : 'binary'.
+ * En cas de préfixe nul, le composant gauche peut être nul.
+ */
+ ICT_NESTED_NAME,
+
+ /**
+ * Noms imbriqués, en deux parties : 'binary'.
+ * C'est normalement le seul réceptacle pour les composants issus
+ * de itd_template_args (sur la branche droite).
+ */
+ ICT_TEMPLATE_NAME_ARGS,
+
+ /**
+ * Type avec préfixes : deux éléments, dans 'binary'
+ */
+ ICT_PREFIX_BINARY,
+
+ /**
+ * Préfixes à deux éléments.
+ * En cas de préfixe nul, le composant gauche peut être nul.
+ */
+ ICT_TPREFIX_BINARY,
+
+ /**
+ * Encodage d'un nom d'opérateur, consigné dans 'operator'.
+ */
+ ICT_OPERATOR_NAME,
+
+ /**
+ * Particularité des notions d'objets. Les informations utiles
+ * sont rassemblées dans le champ unary.
+ */
+ ICT_SPECIAL_NAME_VTABLE,
+ ICT_SPECIAL_NAME_VSTRUCT,
+
+ /**
+ * Fonctions virtuelles.
+ * -> décalage : 'offset'.
+ * -> double décalage : 'binary'.
+ * -> fonctions simples : 'binary'.
+ * -> fonctions complexes : 'ternary'.
+ */
+ ICT_NON_VIRTUAL_OFFSET,
+ ICT_VIRTUAL_OFFSET,
+ ICT_DOUBLE_OFFSET,
+ ICT_FUNCTION_THUNK,
+ ICT_FUNCTION_COVARIANT_THUNK,
+
+ /**
+ * Constructeur ou destructeur, sans plus de détail.
+ */
+ ICT_CONSTRUCTOR,
+ ICT_DESSTRUCTOR,
+
+ /**
+ * Type instanciable dans le programme.
+ */
+ ICT_TYPE,
+
+ /**
+ * Type qualifié ; les infos utilies sont explicitement
+ * conservées dans le champ qualified.
+ */
+ ICT_QUALIFIED_TYPE,
+
+ /**
+ * Différentes références vers un sous-type.
+ * Le champ impacté est 'unary'.
+ */
+ ICT_POINTER_TO,
+ ICT_REFERENCE_TO,
+ ICT_RVALUE_REFERENCE_TO,
+ ICT_COMPLEX_PAIR,
+ ICT_IMAGINARY,
+
+ /**
+ * Prototype de fonction.
+ * Le champ impacté est 'function'.
+ */
+ ICT_FUNCTION_TYPE,
+
+ /**
+ * Fonction (nom + retour/paramètres), sous forme binaire :
+ * -> left = function name
+ * -> right = bare-function-type
+ */
+ ICT_FUNCTION_ENCODING,
+
+ /**
+ * Définition d'un tableau. Les indications de dimensions peuvent
+ * prendre plusieurs formes, et sont rassemblées dans le champ array.
+ */
+ ICT_ARRAY,
+
+ /**
+ * Pointeur vers un membre. Comme l'espace de noms associé est encodé
+ * de façon spéciale, un champ est dédié à ce composant : pmember.
+ */
+ ICT_POINTER_TO_MEMBER,
+
+ /**
+ * Liste d'arguments pour templates, à encadrer par des chevrons.
+ * 'unary' pointe vers la liste des éléments.
+ */
+ ICT_TEMPLATE_ARGS,
+
+ /**
+ * Liste de types, sous forme binaire :
+ * -> left = élément de la liste de types.
+ * -> right = reste de la liste de types.
+ */
+ ICT_TYPES_LIST,
+
+ /**
+ * Liste d'expressions, sous forme binaire comme pour ICT_TYPES_LIST :
+ * -> left = élément de la liste de types.
+ * -> right = reste de la liste de types.
+ */
+ ICT_EXPR_LIST,
+
+ /**
+ * Liste de types, sous forme binaire :
+ * -> left = composant d'opérateur.
+ * -> right = liste d'expressions.
+ */
+ ICT_OPERATED_EXPRESSION,
+
+ /**
+ * Substitution avec préfixe standard. Le résultat est prêt dans le champ
+ * dtype.
+ */
+ ICT_STD_SUBST,
+
+ ICT_COUNT
+
+} ItaniumComponentType;
+
+
+/* Catégories d'opérateurs */
+typedef enum _ItaniumOperatorType
+{
+ IOT_SIMPLE, /* Présent dans la liste */
+ IOT_CAST, /* Conversion forcée */
+ IOT_VENDOR /* Défini par un vendeur */
+
+} ItaniumOperatorType;
+
+
+/* Enregistrement des opérateurs */
+typedef struct _itanium_operator_info
+{
+ const char *code; /* Nom encodé */
+ const char *name; /* Désignation humaine */
+ size_t name_len; /* Taille du nom humain */
+ int args; /* Nombre d'arguments */
+
+} itanium_operator_info;
+
+
+/* Composant extrait de l'encodage */
+typedef struct _itanium_component itanium_component;
+
+
+
+/* Incrémente le nombre d'utilisation du composant. */
+void itd_ref_comp(itanium_component *);
+
+/* Décrémente le nombre d'utilisation du composant. */
+void itd_unref_comp(itanium_component *);
+
+/* Détermine ou fournit l'empreinte d'un composant. */
+fnv64_t itd_hash_comp(itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_with_type(ItaniumComponentType);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_name(const char *, size_t);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_operator(const itanium_operator_info *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_cast_operator(itanium_component *);
+
+/* Donne des indications quant à un opérateur Itanium. */
+const void *itd_get_operator_info(const itanium_component *, ItaniumOperatorType *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_offset(ItaniumComponentType, ssize_t);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_type(GDataType *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_qualified_type(itanium_component *, TypeQualifier);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_function_type(bool, itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_array_with_dim_number(ssize_t, itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_array_with_dim_expr(itanium_component *, itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_pointer_to_memeber_type(itanium_component *, itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_unary(ItaniumComponentType, itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_binary(ItaniumComponentType, itanium_component *, itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_append_right_to_binary(ItaniumComponentType, itanium_component *, itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_ternary(ItaniumComponentType, itanium_component *, itanium_component *, itanium_component *);
+
+/* Modifie légèrement le type d'un composant donné. */
+void itd_set_type(itanium_component *, ItaniumComponentType);
+
+/* Fournit le type d'un composant issu d'un contexte Itanium. */
+ItaniumComponentType itd_get_component_type(const itanium_component *);
+
+/* Traduit les composants de contexte Itanium. */
+char *itd_translate_component(const itanium_component *, char *);
+
+/* Traduit les composants de contexte Itanium en type. */
+GDataType *itd_translate_component_to_type(const itanium_component *);
+
+/* Traduit les composants de contexte Itanium en routine. */
+GBinRoutine *itd_translate_component_to_routine(const itanium_component *);
+
+
+
+#endif /* _PLUGINS_ITANIUM_COMPONENT_H */
diff --git a/plugins/itanium/context.c b/plugins/itanium/context.c
new file mode 100644
index 0000000..1d2c365
--- /dev/null
+++ b/plugins/itanium/context.c
@@ -0,0 +1,516 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.c - contexte de décodage à la sauce ABI C++ Itanium
+ *
+ * Copyright (C) 2013-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "context.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <mangling/context-int.h>
+
+
+#include "abi.h"
+#include "component-int.h"
+
+
+
+/* Contexte de décodage Itanium (instance) */
+struct _GItaniumDemangling
+{
+ GDemanglingContext parent; /* A laisser en premier */
+
+ itanium_component **template_args; /* Paramètres de modèle */
+ size_t targs_count; /* Quantité utilisée */
+
+ itanium_component **substitutions; /* Table de substitutions */
+ size_t subst_count; /* Quantité utilisée */
+
+};
+
+/* Contexte de décodage Itanium (classe) */
+struct _GItaniumDemanglingClass
+{
+ GDemanglingContextClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des contextes de décodage. */
+static void g_itanium_demangling_class_init(GItaniumDemanglingClass *);
+
+/* Initialise une instance de contexte pour décodage. */
+static void g_itanium_demangling_init(GItaniumDemangling *);
+
+/* Supprime toutes les références externes. */
+static void g_itanium_demangling_dispose(GItaniumDemangling *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_itanium_demangling_finalize(GItaniumDemangling *);
+
+/* Prépare l'environnement de contexte pour un décodage Itanium. */
+static void g_itanium_demangling_prepare(GItaniumDemangling *);
+
+/* Valide un composant final issu d'un décodage Itanium. */
+static void g_itanium_demangling_check(GItaniumDemangling *, itanium_component **);
+
+/* Décode une définition de type pour Itanium. */
+static GDataType *g_itanium_demangling_decode_type(GItaniumDemangling *);
+
+/* Décode une définition de routine pour Itanium. */
+static GBinRoutine *g_itanium_demangling_decode_routine(GItaniumDemangling *);
+
+
+
+/* Indique le type défini pour un contexte de décodage. */
+G_DEFINE_TYPE(GItaniumDemangling, g_itanium_demangling, G_TYPE_DEMANGLING_CONTEXT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des contextes de décodage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangling_class_init(GItaniumDemanglingClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GDemanglingContextClass *context; /* Version de base du contexte */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_itanium_demangling_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_itanium_demangling_finalize;
+
+ context = G_DEMANGLING_CONTEXT_CLASS(klass);
+
+ context->decode_type = (decode_type_fc)g_itanium_demangling_decode_type;
+ context->decode_routine = (decode_routine_fc)g_itanium_demangling_decode_routine;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à initialiser. *
+* *
+* Description : Initialise une instance de contexte pour décodage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangling_init(GItaniumDemangling *context)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangling_dispose(GItaniumDemangling *context)
+{
+ G_OBJECT_CLASS(g_itanium_demangling_parent_class)->dispose(G_OBJECT(context));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangling_finalize(GItaniumDemangling *context)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < context->targs_count; i++)
+ itd_unref_comp(context->template_args[i]);
+
+ if (context->template_args != NULL)
+ free(context->template_args);
+
+ for (i = 0; i < context->subst_count; i++)
+ itd_unref_comp(context->substitutions[i]);
+
+ if (context->substitutions != NULL)
+ free(context->substitutions);
+
+ G_OBJECT_CLASS(g_itanium_demangling_parent_class)->finalize(G_OBJECT(context));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = environnement de décodage à manipuler. *
+* *
+* Description : Prépare l'environnement de contexte pour un décodage Itanium.*
+* *
+* Retour : - . *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangling_prepare(GItaniumDemangling *context)
+{
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ size_t len; /* Taille de chaîne à traiter */
+
+ /**
+ * On part du principe qu'il n'y aura jamais plus de paramètres de modèle
+ * ou de substitutions à enregistrer que de caractères dans la chaîne à traiter.
+ * Du coup, on peut tout allouer d'un coup !
+ */
+
+ assert(context->template_args == NULL);
+
+ assert(context->substitutions == NULL);
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ len = get_input_buffer_size(ibuf);
+
+ context->template_args = (itanium_component **)malloc(len * sizeof(itanium_component *));
+
+ context->substitutions = (itanium_component **)malloc(len * sizeof(itanium_component *));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = environnement de décodage à manipuler. *
+* comp = composant final à valider. [OUT] *
+* *
+* Description : Valide un composant final issu d'un décodage Itanium. *
+* *
+* Retour : - . *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangling_check(GItaniumDemangling *context, itanium_component **comp)
+{
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ size_t remaining; /* Données restant à consommer */
+
+ if (*comp != NULL)
+ {
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ remaining = count_input_buffer_remaining(ibuf);
+
+ if (remaining > 0)
+ {
+ itd_unref_comp(*comp);
+ *comp = NULL;
+ }
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = environnement de décodage à manipuler. *
+* *
+* Description : Décode une définition de type pour Itanium. *
+* *
+* Retour : Nouvelle instance créée ou NULL en cas d'erreur fatale. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GDataType *g_itanium_demangling_decode_type(GItaniumDemangling *context)
+{
+ GDataType *result; /* Type construit à retourner */
+ itanium_component *comp; /* Composants décodés */
+
+ g_itanium_demangling_prepare(context);
+
+ comp = itd_mangled_name(context);
+
+ g_itanium_demangling_check(context, &comp);
+
+ if (comp == NULL)
+ result = NULL;
+
+ else
+ {
+ result = itd_translate_component_to_type(comp);
+
+ itd_unref_comp(comp);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = environnement de décodage à manipuler. *
+* *
+* Description : Décode une définition de routine pour Itanium. *
+* *
+* Retour : Nouvelle instance créée ou NULL en cas d'erreur fatale. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GBinRoutine *g_itanium_demangling_decode_routine(GItaniumDemangling *context)
+{
+ GBinRoutine *result; /* Routine en place à retourner*/
+ itanium_component *comp; /* Composants décodés */
+
+ g_itanium_demangling_prepare(context);
+
+ comp = itd_mangled_name(context);
+
+ g_itanium_demangling_check(context, &comp);
+
+ if (comp == NULL)
+ result = NULL;
+
+ else
+ {
+ result = itd_translate_component_to_routine(comp);
+
+ itd_unref_comp(comp);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* state = état courant à sauvegarder. [OUT] *
+* *
+* Description : Fournit l'état courant à une fin de retour en arrière. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_itanium_demangling_push_state(const GItaniumDemangling *context, itd_state *state)
+{
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ save_input_buffer_pos(ibuf, &state->pos);
+ state->targs_count = context->targs_count;
+ state->subst_count = context->subst_count;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* state = état courant à restaurer. *
+* *
+* Description : Définit l'état courant suite à un retour en arrière. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_itanium_demangling_pop_state(GItaniumDemangling *context, const itd_state *state)
+{
+ size_t i; /* Boucle de parcours */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+
+ for (i = state->targs_count; i < context->targs_count; i++)
+ itd_unref_comp(context->template_args[i]);
+
+ for (i = state->subst_count; i < context->subst_count; i++)
+ itd_unref_comp(context->substitutions[i]);
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ restore_input_buffer_pos(ibuf, state->pos);
+ context->targs_count = state->targs_count;
+ context->subst_count = state->subst_count;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* comp = composant à conserver en mémoire. *
+* *
+* Description : Indexe un composant représentant un argument de modèle. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_itanium_demangling_add_template_arg(GItaniumDemangling *context, itanium_component *comp)
+{
+ assert(comp != NULL);
+
+ context->template_args[context->targs_count++] = comp;
+ itd_ref_comp(comp);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* index = indice de l'argument visé. *
+* *
+* Description : Fournit un composant représentant un argument de modèle. *
+* *
+* Retour : Composant déjà extrait et conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *context, size_t index)
+{
+ itanium_component *result; /* Composant à retourner */
+
+ if (index < context->targs_count)
+ {
+ result = context->template_args[index];
+ itd_ref_comp(result);
+ }
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* comp = composant à conserver en mémoire. *
+* *
+* Description : Indexe un composant comme future substitution potentielle. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_itanium_demangling_add_substitution(GItaniumDemangling *context, itanium_component *comp)
+{
+ fnv64_t hash; /* Empreinte du candidat */
+ size_t i; /* Boucle de parcours */
+
+ assert(comp != NULL);
+
+ hash = itd_hash_comp(comp);
+
+ for (i = 0; i < context->subst_count; i++)
+ if (cmp_fnv_64a(itd_hash_comp(context->substitutions[i]), hash) == 0)
+ break;
+
+ if (i == context->subst_count)
+ {
+ context->substitutions[context->subst_count++] = comp;
+ itd_ref_comp(comp);
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* index = indice de la substitution visée. *
+* *
+* Description : Fournit un composant en place pour une substitution. *
+* *
+* Retour : Composant déjà extrait et conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *g_itanium_demangling_get_substitution(GItaniumDemangling *context, size_t index)
+{
+ itanium_component *result; /* Composant à retourner */
+
+ if (index < context->subst_count)
+ {
+ result = context->substitutions[index];
+ itd_ref_comp(result);
+ }
+ else
+ result = NULL;
+
+ return result;
+
+}
diff --git a/plugins/itanium/context.h b/plugins/itanium/context.h
new file mode 100644
index 0000000..6ec65ae
--- /dev/null
+++ b/plugins/itanium/context.h
@@ -0,0 +1,83 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.h - prototypes pour le contexte de décodage à la sauce ABI C++ Itanium
+ *
+ * Copyright (C) 2013-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_CONTEXT_H
+#define _PLUGINS_ITANIUM_CONTEXT_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "component.h"
+
+
+
+#define G_TYPE_ITANIUM_DEMANGLING g_itanium_demangling_get_type()
+#define G_ITANIUM_DEMANGLING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ITANIUM_DEMANGLING, GItaniumDemangling))
+#define G_IS_ITANIUM_DEMANGLING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ITANIUM_DEMANGLING))
+#define G_ITANIUM_DEMANGLING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ITANIUM_DEMANGLING, GItaniumDemanglingClass))
+#define G_IS_ITANIUM_DEMANGLING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ITANIUM_DEMANGLING))
+#define G_ITANIUM_DEMANGLING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ITANIUM_DEMANGLING, GItaniumDemanglingClass))
+
+
+/* Contexte de décodage Itanium (instance) */
+typedef struct _GItaniumDemangling GItaniumDemangling;
+
+/* Contexte de décodage Itanium (classe) */
+typedef struct _GItaniumDemanglingClass GItaniumDemanglingClass;
+
+
+/* Indique le type défini pour un contexte de décodage. */
+GType g_itanium_demangling_get_type(void);
+
+/* Sauvegarde d'un état courant */
+typedef struct _itd_state
+{
+ size_t pos; /* Position courante */
+ size_t targs_count; /* Quantité utilisée */
+ size_t subst_count; /* Nombre de substitutions */
+
+} itd_state;
+
+/* Fournit l'état courant à une fin de retour en arrière. */
+void g_itanium_demangling_push_state(const GItaniumDemangling *, itd_state *);
+
+/* Définit l'état courant suite à un retour en arrière. */
+void g_itanium_demangling_pop_state(GItaniumDemangling *, const itd_state *);
+
+/* Indexe un composant représentant un argument de modèle. */
+void g_itanium_demangling_add_template_arg(GItaniumDemangling *, itanium_component *);
+
+/* Fournit un composant représentant un argument de modèle. */
+itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *, size_t);
+
+/* Indexe un composant comme future substitution potentielle. */
+void g_itanium_demangling_add_substitution(GItaniumDemangling *, itanium_component *);
+
+/* Fournit un composant en place pour une substitution. */
+itanium_component *g_itanium_demangling_get_substitution(GItaniumDemangling *, size_t);
+
+
+
+#endif /* _PLUGINS_ITANIUM_CONTEXT_H */
diff --git a/plugins/itanium/core.c b/plugins/itanium/core.c
new file mode 100644
index 0000000..ecfd7f0
--- /dev/null
+++ b/plugins/itanium/core.c
@@ -0,0 +1,64 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - intégration du décodage pour symboles Itanium
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <core/demanglers.h>
+#include <plugins/plugin-def.h>
+
+
+#include "demangler.h"
+#include "python/module.h"
+
+
+
+DEFINE_CHRYSALIDE_PLUGIN("itanium", "Symbol demangler for Itanium", "0.1.0",
+ RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
+
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
+* *
+* Description : Prend acte du chargement du greffon. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
+{
+ bool result; /* Bilan à retourner */
+
+ result = register_demangler_type("itanium", G_TYPE_ITANIUM_DEMANGLER);
+
+ if (result)
+ result = add_mangling_itanium_module_to_python_module();
+
+ return result;
+
+}
diff --git a/plugins/itanium/core.h b/plugins/itanium/core.h
new file mode 100644
index 0000000..f59f4e9
--- /dev/null
+++ b/plugins/itanium/core.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour l'intégration du décodage pour symboles Itanium
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_CORE_H
+#define _PLUGINS_ITANIUM_CORE_H
+
+
+#include <plugins/plugin.h>
+#include <plugins/plugin-int.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
+
+
+
+#endif /* _PLUGINS_ITANIUM_CORE_H */
diff --git a/plugins/itanium/demangler.c b/plugins/itanium/demangler.c
new file mode 100644
index 0000000..690f7c8
--- /dev/null
+++ b/plugins/itanium/demangler.c
@@ -0,0 +1,174 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * demangler.c - décodage des noms d'éléments Itanium
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "demangler.h"
+
+
+#include <mangling/demangler-int.h>
+
+
+#include "context.h"
+
+
+
+/* Décodeur de désignations Itanium (instance) */
+struct _GItaniumDemangler
+{
+ GCompDemangler parent; /* A laisser en premier */
+
+};
+
+/* Décodeur de désignations Itanium (classe) */
+struct _GItaniumDemanglerClass
+{
+ GCompDemanglerClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des décodeurs de désignations. */
+static void g_itanium_demangler_class_init(GItaniumDemanglerClass *);
+
+/* Initialise une instance de décodeur de désignations. */
+static void g_itanium_demangler_init(GItaniumDemangler *);
+
+/* Supprime toutes les références externes. */
+static void g_itanium_demangler_dispose(GItaniumDemangler *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_itanium_demangler_finalize(GItaniumDemangler *);
+
+
+
+/* Indique le type défini pour un décodeur de désignations. */
+G_DEFINE_TYPE(GItaniumDemangler, g_itanium_demangler, G_TYPE_COMP_DEMANGLER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des décodeurs de désignations Itanium. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangler_class_init(GItaniumDemanglerClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GCompDemanglerClass *demangler; /* Version parente basique */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_itanium_demangler_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_itanium_demangler_finalize;
+
+ demangler = G_COMP_DEMANGLER_CLASS(klass);
+
+ demangler->can_demangle = (can_be_demangled_fc)NULL;
+
+ demangler->context_type = G_TYPE_ITANIUM_DEMANGLING;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = instance à initialiser. *
+* *
+* Description : Initialise une instance de décodeur de désignations Itanium. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangler_init(GItaniumDemangler *demangler)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangler_dispose(GItaniumDemangler *demangler)
+{
+ G_OBJECT_CLASS(g_itanium_demangler_parent_class)->dispose(G_OBJECT(demangler));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangler_finalize(GItaniumDemangler *demangler)
+{
+ G_OBJECT_CLASS(g_itanium_demangler_parent_class)->finalize(G_OBJECT(demangler));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Met en place un nouveau décodeur de symboles pour Itanium. *
+* *
+* Retour : Instance obtenue ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GCompDemangler *g_itanium_demangler_new(void)
+{
+ GItaniumDemangler *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ITANIUM_DEMANGLER, NULL);
+
+ return G_COMP_DEMANGLER(result);
+
+}
diff --git a/plugins/itanium/demangler.h b/plugins/itanium/demangler.h
new file mode 100644
index 0000000..8b901cc
--- /dev/null
+++ b/plugins/itanium/demangler.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * demangler.h - prototypes pour le décodage des noms d'éléments Itanium
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_DEMANGLER_H
+#define _PLUGINS_ITANIUM_DEMANGLER_H
+
+
+#include <glib-object.h>
+
+
+#include <mangling/demangler.h>
+
+
+
+#define G_TYPE_ITANIUM_DEMANGLER g_itanium_demangler_get_type()
+#define G_ITANIUM_DEMANGLER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ITANIUM_DEMANGLER, GItaniumDemangler))
+#define G_IS_ITANIUM_DEMANGLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ITANIUM_DEMANGLER))
+#define G_ITANIUM_DEMANGLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ITANIUM_DEMANGLER, GItaniumDemanglerClass))
+#define G_IS_ITANIUM_DEMANGLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ITANIUM_DEMANGLER))
+#define G_ITANIUM_DEMANGLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ITANIUM_DEMANGLER, GItaniumDemanglerClass))
+
+
+/* Décodeur de désignations Itanium (instance) */
+typedef struct _GItaniumDemangler GItaniumDemangler;
+
+/* Décodeur de désignations Itanium (classe) */
+typedef struct _GItaniumDemanglerClass GItaniumDemanglerClass;
+
+
+/* Indique le type défini pour un décodeur de désignations Itanium. */
+GType g_itanium_demangler_get_type(void);
+
+/* Met en place un nouveau décodeur de symboles pour Itanium. */
+GCompDemangler *g_itanium_demangler_new(void);
+
+
+
+#endif /* _PLUGINS_ITANIUM_DEMANGLER_H */
diff --git a/plugins/itanium/python/Makefile.am b/plugins/itanium/python/Makefile.am
new file mode 100644
index 0000000..97abc50
--- /dev/null
+++ b/plugins/itanium/python/Makefile.am
@@ -0,0 +1,19 @@
+
+noinst_LTLIBRARIES = libitaniumpython.la
+
+libitaniumpython_la_SOURCES = \
+ demangler.h demangler.c \
+ module.h module.c
+
+libitaniumpython_la_LDFLAGS =
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libitaniumpython_la_SOURCES:%c=)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/itanium/python/demangler.c b/plugins/itanium/python/demangler.c
new file mode 100644
index 0000000..dfade68
--- /dev/null
+++ b/plugins/itanium/python/demangler.c
@@ -0,0 +1,145 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * demangler.c - équivalent Python du fichier "plugins/itanium/demangler.c"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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
+ */
+
+
+#include "demangler.h"
+
+
+#include <pygobject.h>
+
+
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/mangling/demangler.h>
+
+
+#include "../demangler.h"
+
+
+
+/* Crée un nouvel objet Python de type 'ItaniumDemangler'. */
+static PyObject *py_itanium_demangler_new(PyTypeObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type de l'objet à instancier. *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Crée un nouvel objet Python de type 'ItaniumDemangler'. *
+* *
+* Retour : Instance Python mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_itanium_demangler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Instance à retourner */
+ GCompDemangler *demangler; /* Instance à transposer */
+
+ demangler = g_itanium_demangler_new();
+
+ result = pygobject_new(G_OBJECT(demangler));
+
+ g_object_unref(G_OBJECT(demangler));
+
+ return (PyObject *)result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_itanium_demangler_type(void)
+{
+ static PyMethodDef py_itanium_demangler_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_itanium_demangler_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_itanium_demangler_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.mangling.ItaniumDemangler",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = "PyChrysalide Itanium demangler",
+
+ .tp_methods = py_itanium_demangler_methods,
+ .tp_getset = py_itanium_demangler_getseters,
+ .tp_new = (newfunc)py_itanium_demangler_new
+
+ };
+
+ return &py_itanium_demangler_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.....ItaniumDemangler'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_python_itanium_demangler(PyObject *module)
+{
+ PyTypeObject *py_itanium_demangler_type;/* Type 'ItaniumDemangler' */
+ PyObject *dict; /* Dictionnaire du module */
+
+ py_itanium_demangler_type = get_python_itanium_demangler_type();
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ITANIUM_DEMANGLER,
+ py_itanium_demangler_type, get_python_compiler_demangler_type()))
+ return false;
+
+ return true;
+
+}
diff --git a/plugins/itanium/python/demangler.h b/plugins/itanium/python/demangler.h
new file mode 100644
index 0000000..e84313a
--- /dev/null
+++ b/plugins/itanium/python/demangler.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * demangler.h - prototypes pour l'équivalent Python du fichier "plugins/itanium/demangler.h"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_PYTHON_DEMANGLER_H
+#define _PLUGINS_ITANIUM_PYTHON_DEMANGLER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_itanium_demangler_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.mangling.ItaniumDemangler'. */
+bool register_python_itanium_demangler(PyObject *);
+
+
+
+#endif /* _PLUGINS_ITANIUM_PYTHON_DEMANGLER_H */
diff --git a/plugins/itanium/python/module.c b/plugins/itanium/python/module.c
new file mode 100644
index 0000000..d42d783
--- /dev/null
+++ b/plugins/itanium/python/module.c
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire itanium en tant que module
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+
+
+#include "demangler.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Etend le module 'mangling' avec des compléments pour Itanium.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_mangling_itanium_module_to_python_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+
+ super = get_access_to_python_module("pychrysalide.mangling");
+
+ result = register_python_itanium_demangler(super);
+
+ return result;
+
+}
diff --git a/plugins/itanium/python/module.h b/plugins/itanium/python/module.h
new file mode 100644
index 0000000..7e35a81
--- /dev/null
+++ b/plugins/itanium/python/module.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire itanium en tant que module
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_PYTHON_MODULE_H
+#define _PLUGINS_ITANIUM_PYTHON_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Etend le module 'mangling' avec des compléments pour Itanium. */
+bool add_mangling_itanium_module_to_python_module(void);
+
+
+
+#endif /* _PLUGINS_ITANIUM_PYTHON_MODULE_H */