summaryrefslogtreecommitdiff
path: root/plugins/itanium/abi.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/itanium/abi.c')
-rw-r--r--plugins/itanium/abi.c3344
1 files changed, 3344 insertions, 0 deletions
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;
+
+}