summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/cpp.h6
-rw-r--r--src/common/extstr.c41
-rw-r--r--src/common/extstr.h3
-rw-r--r--src/format/mangling/Makefile.am14
-rw-r--r--src/format/mangling/itanium.h62
-rwxr-xr-xsrc/format/mangling/itanium/Makefile.am18
-rw-r--r--src/format/mangling/itanium/abi.c2442
-rw-r--r--src/format/mangling/itanium/abi.h38
-rw-r--r--src/format/mangling/itanium/component-int.h79
-rw-r--r--src/format/mangling/itanium/component.c714
-rw-r--r--src/format/mangling/itanium/component.h213
-rw-r--r--src/format/mangling/itanium/context.c571
-rw-r--r--src/format/mangling/itanium/context.h117
-rw-r--r--src/format/mangling/itanium_gram.y1222
-rw-r--r--src/format/mangling/itanium_tok.l232
-rw-r--r--src/main.c4
16 files changed, 4248 insertions, 1528 deletions
diff --git a/src/common/cpp.h b/src/common/cpp.h
index b5e09c0..a658559 100644
--- a/src/common/cpp.h
+++ b/src/common/cpp.h
@@ -31,6 +31,12 @@
/**
+ * Fournit la taille d'un tableau statique.
+ */
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+
+/**
* Détermine la taille de la plus longue chaîne de caractères
* correspondant à un type donné.
*/
diff --git a/src/common/extstr.c b/src/common/extstr.c
index 8249515..309f487 100644
--- a/src/common/extstr.c
+++ b/src/common/extstr.c
@@ -47,9 +47,46 @@ char *stradd(char *str1, const char *str2)
{
char *result; /* Chaîne à renvoyer */
- result = (char *)realloc(str1, (strlen(str1) + strlen(str2) + 1) * sizeof(char));
+ if (str1 == NULL)
+ result = strdup(str2);
+
+ else
+ {
+ result = (char *)realloc(str1, (strlen(str1) + strlen(str2) + 1) * sizeof(char));
+ strcat(result, str2);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : str1 = chaîne de caractères à compléter. *
+* str2 = chaîne de caractères à ajouter. *
+* n = taille de la seconde chaîne. *
+* *
+* Description : Complète une chaîne de caractères avec une autre. *
+* *
+* Retour : Chaîne de caractères complétée, à libérer de la mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *strnadd(char *str1, const char *str2, size_t n)
+{
+ char *result; /* Chaîne à renvoyer */
- strcat(result, str2);
+ if (str1 == NULL)
+ result = strndup(str2, n);
+
+ else
+ {
+ result = (char *)realloc(str1, (strlen(str1) + n + 1) * sizeof(char));
+ strncat(result, str2, n);
+ }
return result;
diff --git a/src/common/extstr.h b/src/common/extstr.h
index 592719e..830e1fa 100644
--- a/src/common/extstr.h
+++ b/src/common/extstr.h
@@ -32,6 +32,9 @@
/* Complète une chaîne de caractères avec une autre. */
char *stradd(char *str1, const char *str2);
+/* Complète une chaîne de caractères avec une autre. */
+char *strnadd(char *, const char *, size_t);
+
/* Fait précéder une chaîne de caractères par une autre. */
char *strprep(char *, const char *);
diff --git a/src/format/mangling/Makefile.am b/src/format/mangling/Makefile.am
index 9774b73..53f4b70 100644
--- a/src/format/mangling/Makefile.am
+++ b/src/format/mangling/Makefile.am
@@ -1,5 +1,4 @@
-#BUILT_SOURCES = itanium_gram.h libjavamangling_la-java_gram.h
BUILT_SOURCES = libjavamangling_la-java_gram.h
AM_YFLAGS = -d
@@ -10,14 +9,12 @@ libformatmangling_la_SOURCES = \
context-int.h \
context.h context.c \
demangler.h demangler.c
-#itanium.h \
-#itanium_gram.y \
-#itanium_tok.l
libformatmangling_la_LDFLAGS =
libformatmangling_la_LIBADD = \
- libjavamangling.la
+ libjavamangling.la \
+ itanium/libformatmanglingitanium.la
# Partie Java
@@ -27,7 +24,7 @@ libjavamangling_la_SOURCES = \
java_gram.y \
java_tok.l
-libjavamangling_la_YFLAGS = -d -p java_ -o y.tab.c
+libjavamangling_la_YFLAGS = -d -p java_ -o y.tab.c3
libjavamangling_la_LFLAGS = -P java_ -o lex.yy.c
@@ -42,5 +39,6 @@ AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
# Automake fait les choses à moitié
-CLEANFILES = itanium_gram.h itanium_gram.c itanium_tok.c \
- java_gram.h java_gram.c libjavamangling_la-java_tok.c
+CLEANFILES = java_gram.h java_gram.c libjavamangling_la-java_tok.c
+
+SUBDIRS = itanium
diff --git a/src/format/mangling/itanium.h b/src/format/mangling/itanium.h
deleted file mode 100644
index 2d2fd59..0000000
--- a/src/format/mangling/itanium.h
+++ /dev/null
@@ -1,62 +0,0 @@
-
-/* OpenIDA - Outil d'analyse de fichiers binaires
- * itanium.h - prototypes pour le décodage des noms d'éléments selon Intel
- *
- * Copyright (C) 2009-2010 Cyrille Bagard
- *
- * This file is part of OpenIDA.
- *
- * OpenIDA 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.
- *
- * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _FORMAT_MANGLING_ITANIUM_H
-#define _FORMAT_MANGLING_ITANIUM_H
-
-
-#include <stdbool.h>
-
-
-#include "context.h"
-#include "demangler.h"
-
-
-
-/* --------------------- CONTEXTE POUR LE DECODAGE TYPE ITANIUM --------------------- */
-
-
-/* Contexte de décodage Itanium (instance) */
-typedef struct _GItaniumDContext GItaniumDContext;
-
-/* Contexte de décodage Itanium (classe) */
-typedef struct _GItaniumDContextClass GItaniumDContextClass;
-
-
-/* Prépare de quoi effectuer un décodage Itanium. */
-GDemanglingContext *g_itanium_dcontext_new(void);
-
-
-
-/* ------------------------ TRAITEMENT DE L'ENCODAGE ITANIUM ------------------------ */
-
-
-/* Indique si une chaîne peut être traitée par le décodeur. */
-bool can_be_itanium_demangled(const char *);
-
-/* Procède au décodage d'une chaîne de caractères. */
-bool demangle_itanium_routine(GItaniumDContext *, const char *);
-
-
-
-#endif /* _FORMAT_MANGLING_ITANIUM_H */
diff --git a/src/format/mangling/itanium/Makefile.am b/src/format/mangling/itanium/Makefile.am
new file mode 100755
index 0000000..6265691
--- /dev/null
+++ b/src/format/mangling/itanium/Makefile.am
@@ -0,0 +1,18 @@
+
+noinst_LTLIBRARIES = libformatmanglingitanium.la
+
+libformatmanglingitanium_la_SOURCES = \
+ abi.h abi.c \
+ component.h component.c \
+ context.h context.c
+
+libformatmanglingitanium_la_LIBADD =
+
+libformatmanglingitanium_la_LDFLAGS =
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS =
diff --git a/src/format/mangling/itanium/abi.c b/src/format/mangling/itanium/abi.c
new file mode 100644
index 0000000..75585df
--- /dev/null
+++ b/src/format/mangling/itanium/abi.c
@@ -0,0 +1,2442 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * abi.c - décodage des noms d'éléments selon l'ABI C++ Itanium
+ *
+ * Copyright (C) 2013 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA 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.
+ *
+ * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "abi.h"
+
+
+#include <ctype.h>
+#include <stdlib.h>
+
+
+
+#include "../../../analysis/types/basic.h"
+#include "../../../common/cpp.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 },
+ { "tr", IDT_NL("throw"), 0 },
+ { "tw", IDT_NL("throw "), 1 }
+};
+
+/* Substitutions standards */
+
+typedef struct _itanium_std_subst_info
+{
+ char code; /* Identifiant associé */
+
+ const char *simple; /* Représentation simple */
+ size_t simple_len; /* Taille de cette représentat°*/
+
+ const char *full; /* Représentation complète */
+ size_t full_len; /* Taille de cette représentat°*/
+
+ const char *last_name; /* Pour les (con|de)structeurs */
+ size_t last_name_len; /* Taille de cette indication */
+
+} itanium_std_subst_info;
+
+const itanium_std_subst_info itanium_standard_substitutions[] = {
+
+ {
+ 't',
+ IDT_NL("std"),
+ IDT_NL("std"),
+ NULL,
+ 0
+ },
+ {
+ 'a',
+ IDT_NL("std::allocator"),
+ IDT_NL("std::allocator"),
+ IDT_NL("allocator")
+ },
+ {
+ 'b',
+ IDT_NL("std::basic_string"),
+ IDT_NL("std::basic_string"),
+ IDT_NL("basic_string")
+ },
+ {
+ 's',
+ IDT_NL("std::string"),
+ IDT_NL("std::basic_string<char, std::char_traits<char>, std::allocator<char>>"),
+ IDT_NL("basic_string")
+ },
+ {
+ 'i',
+ IDT_NL("std::istream"),
+ IDT_NL("std::basic_istream<char, std::char_traits<char>>"),
+ IDT_NL("basic_istream")
+ },
+ {
+ 'o',
+ IDT_NL("std::ostream"),
+ IDT_NL("std::basic_ostream<char, std::char_traits<char>>"),
+ IDT_NL("basic_ostream")
+ },
+ {
+ 'd',
+ IDT_NL("std::iostream"),
+ IDT_NL("std::basic_iostream<char, std::char_traits<char>>"),
+ IDT_NL("basic_iostream")
+ }
+
+};
+
+
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_encoding(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_name(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_unscoped_name(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_unscoped_template_name(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_nested_name(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_prefix(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_template_prefix(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_unqualified_name(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_source_name(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static bool itd_number(GItaniumDContext *, ssize_t *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_identifier(GItaniumDContext *, size_t);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_operator_name(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_special_name(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_call_offset(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_nv_offset(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_v_offset(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_ctor_dtor_name(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_type(GItaniumDContext *);
+
+/* Extrait une propriété de composant pour un contexte Itanium. */
+static TypeQualifier itd_cv_qualifiers(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_builtin_type(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_bare_function_type(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_class_enum_type(GItaniumDContext *);
+
+
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_template_args(GItaniumDContext *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_template_arg(GItaniumDContext *);
+
+
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_value_to_string(GItaniumDContext *, bool);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_expr_primary(GItaniumDContext *);
+
+
+
+
+/* Extrait un composant dans un contexte Itanium. */
+static bool itd_seq_id(GItaniumDContext *, char, size_t *);
+
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_substitution(GItaniumDContext *);
+
+
+
+
+
+
+#define itd_template_param(ctx) NULL
+
+
+#define itd_local_name(ctx) NULL
+
+
+
+
+#define itd_expression(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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <mangled-name> ::= _Z <encoding>
+ *
+ */
+
+ if (!g_itanium_dcontext_check_char(context, '_'))
+ return NULL;
+
+ if (!g_itanium_dcontext_check_char(context, '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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ itd_state saved; /* Position d'analyse courante */
+ itanium_component *func; /* Composant 'function name' */
+ 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>
+ *
+ */
+
+ result = NULL;
+ g_itanium_dcontext_push_state(context, &saved);
+
+ func = itd_name(context);
+
+ if (func != NULL)
+ {
+ types = itd_bare_function_type(context);
+
+ if (types != NULL)
+ result = itd_make_binary(context, ICT_FUNCTION_ENCODING, func, types);
+ else
+ itd_unref_comp(func);
+
+ }
+ /*
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ result = itd_name(context);
+ }
+ */
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ result = itd_special_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_name(GItaniumDContext *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_dcontext_push_state(context, &saved);
+
+ result = itd_nested_name(context);
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+
+ tname = itd_unscoped_template_name(context);
+
+ if (tname != NULL)
+ {
+ targs = itd_template_args(context);
+
+ if (targs != NULL)
+ {
+ g_itanium_dcontext_add_substitution(context, tname);
+ result = itd_make_binary(context, 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_dcontext_pop_state(context, &saved);
+ result = itd_unscoped_name(context);
+ }
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ result = itd_local_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_unscoped_name(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <unscoped-name> ::= <unqualified-name>
+ * ::= St <unqualified-name> # ::std::
+ *
+ */
+
+
+ /* TODO : 'St' */
+
+
+ result = itd_unqualified_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_unscoped_template_name(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ itd_state saved; /* Position d'analyse courante */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <unscoped-template-name> ::= <unscoped-name>
+ * ::= <substitution>
+ *
+ */
+
+ g_itanium_dcontext_push_state(context, &saved);
+
+ result = itd_unscoped_name(context);
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ 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_nested_name(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ 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 */
+
+ static int inner = 0;
+
+ int val = inner++;
+
+ printf("\n ### (%d) NESTED>> '%s'\n", val,
+ g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
+
+ /**
+ * 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
+ *
+ */
+
+ if (!g_itanium_dcontext_check_char(context, 'N'))
+ return NULL;
+
+ qualifier = itd_cv_qualifiers(context);
+
+ result = NULL;
+
+ g_itanium_dcontext_push_state(context, &saved);
+
+
+ printf("\n ----- (%d) nested prefix '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
+
+
+
+ left = itd_prefix(context);
+
+ if (left != NULL)
+ {
+ if (itd_get_component_type(left) != ICT_EMPTY)
+ g_itanium_dcontext_add_substitution(context, left);
+
+ right = itd_unqualified_name(context);
+
+ if (right != NULL)
+ {
+ if (g_itanium_dcontext_check_char(context, 'E'))
+ result = itd_make_binary(context, ICT_NESTED_NAME, left, right);
+ else
+ printf("=== (%d) nested/prefix : BAD E\n\n", val);
+
+ //result = itd_make_binary(context, ICT_NESTED_NAME, left, right);
+
+ }
+ else
+ itd_unref_comp(left);
+
+ printf(" ---- (%d) nested prefix --> %p\n\n", val, result);
+
+ }
+
+
+ if (result == NULL)
+ {
+ printf("\n ----- (%d) nested template_arg '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
+
+ g_itanium_dcontext_pop_state(context, &saved);
+
+ left = itd_template_prefix(context);
+
+ if (left != NULL)
+ {
+ g_itanium_dcontext_add_substitution(context, left);
+
+ right = itd_template_args(context);
+
+ if (right != NULL)
+ {
+ if (g_itanium_dcontext_check_char(context, 'E'))
+ result = itd_make_binary(context, ICT_NESTED_NAME, left, right);
+ else
+ printf("=== (%d) nested/prefix : BAD E\n\n", val);
+ }
+ else
+ itd_unref_comp(left);
+
+ }
+
+ printf(" ---- (%d) nested template_arg --> %p\n\n", val, result);
+
+ }
+
+
+
+ printf("(%d) nested/E >> '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
+
+ /*
+ if (!g_itanium_dcontext_check_char(context, 'E'))
+ {
+ printf("=== (%d) NESTED : BAD E\n\n", val);
+
+ if (result != NULL)
+ itd_unref_comp(result);
+ return NULL;
+ }
+ */
+
+ if (result != NULL)
+ printf("=== (%d) NESTED OK (%p)\n\n", val, result);
+
+ inner--;
+
+ 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ itanium_component *looping_rule; /* Extraction d'une boucle */
+ itd_state saved; /* Position d'analyse courante */
+ itanium_component *left; /* Première partie */
+ itanium_component *right; /* Seconde partie */
+
+ itd_state next_name_saved; /* Position d'analyse courante */
+ itanium_component *next_name; /* Eventuel complément #1 */
+ itd_state next_targs_saved; /* Position d'analyse courante */
+ itanium_component *next_targs; /* Eventuel complément #2 */
+
+
+
+ itd_state expected_saved; /* Position d'analyse suivante */
+ itanium_component *expected; /* Nom non-qualifié en réserve */
+
+
+
+ /**
+ * Les deux règles traitées ici sont les suivantes :
+ *
+ * <prefix> ::= <prefix> <unqualified-name>
+ * ::= <template-prefix> <template-args>
+ * ::= <template-param>
+ * ::= # empty
+ * ::= <substitution>
+ *
+ * <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-args>
+ * ::= <substitution> <template-args>
+ * ::= <template-param>
+ * ::= # empty
+ * ::= <substitution>
+ *
+ * On découpe ainsi les traitements en deux parties :
+ * - extraction du socle non récursif.
+ * - extraction éventuelle d'un complément <unqualified-name> [<template-args>]
+ */
+
+ result = NULL;
+
+ while (1)
+ {
+ printf("loop....\n");
+
+ looping_rule = NULL;
+
+ /**
+ * Première partie.
+ */
+
+ g_itanium_dcontext_push_state(context, &saved);
+
+ /* <template-param> <template-args> */
+
+ left = itd_template_param(context);
+
+ if (left != NULL)
+ {
+ g_itanium_dcontext_add_substitution(context, left);
+
+ right = itd_template_args(context);
+
+ if (right != NULL)
+ looping_rule = itd_make_binary(context, ICT_PREFIX_BINARY, left, right);
+ else
+ itd_unref_comp(left);
+
+ }
+
+ /* <substitution> <template-args> */
+
+ if (looping_rule != NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+
+ left = itd_substitution(context);
+
+ if (left != NULL)
+ {
+ right = itd_template_args(context);
+
+ if (right != NULL)
+ looping_rule = itd_make_binary(context, ICT_PREFIX_BINARY, left, right);
+ else
+ itd_unref_comp(left);
+
+ }
+
+ }
+
+ /* <template-param> */
+
+ if (looping_rule == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ looping_rule = itd_template_param(context);
+ }
+
+ /* <substitution> */
+
+ if (looping_rule == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ looping_rule = itd_substitution(context);
+ }
+
+ printf("looping_rule = %p\n", looping_rule);
+
+ if (looping_rule != NULL)
+ {
+ if (result == NULL)
+ result = looping_rule;
+ else
+ result = itd_make_binary(context, ICT_PREFIX_BINARY, result, looping_rule);
+ }
+
+ /**
+ * Seconde partie (1/3) : recherche d'un éventuel complément.
+ */
+
+ if (looping_rule == NULL)
+ g_itanium_dcontext_pop_state(context, &saved);
+
+ /* <unqualified-name> */
+
+ g_itanium_dcontext_push_state(context, &next_name_saved);
+
+ next_name = itd_unqualified_name(context);
+
+ if (next_name == NULL)
+ {
+ /**
+ * Si on n'obtient pas de <unqualified-name> ici, rien ne sert de
+ * continuer. On se dirige donc vers la sortie avec ce que l'on a.
+ */
+
+ return NULL;
+
+ break;
+
+ }
+
+ /* <template-args> */
+
+ g_itanium_dcontext_push_state(context, &next_targs_saved);
+
+ next_targs = itd_template_args(context);
+
+ g_itanium_dcontext_pop_state(context, &next_targs_saved);
+
+ /**
+ * Seconde partie (2/3) : validation de la présence d'un jeton
+ * <unqualified-name> en réserve pour la règle <nested-name> parente.
+ */
+
+ g_itanium_dcontext_push_state(context, &expected_saved);
+
+ expected = itd_unqualified_name(context);
+
+ if (expected == NULL)
+ {
+ /**
+ * La lecture a été trop loin ici.
+ *
+ * Le dernier <unqualified-name> valide pour la règle parente est
+ * donc celui lu à une fin de recherche de complément.
+ *
+ * On revient donc à ce stade avant de se diriger vers la sortie.
+ */
+
+ itd_unref_comp(next_name);
+
+ if (next_targs != NULL)
+ itd_unref_comp(next_targs);
+
+ g_itanium_dcontext_pop_state(context, &next_name_saved);
+
+ break;
+
+ }
+
+ g_itanium_dcontext_pop_state(context, &expected_saved);
+
+ /**
+ * Seconde partie (3/3) : pleine inscription des composants extraits.
+ *
+ * On s'est manifestement retrouvé dans un des deux cas suivants :
+ * - <prefix> ::= <prefix> <unqualified-name>
+ * - <prefix> ::= <prefix> <template unqualified-name> <template-args>
+ *
+ * Or <prefix> est un candidat pour des substitutions futures, donc on
+ * procède à son enregistrement, s'il n'est pas nul.
+ */
+
+ if (result != NULL)
+ g_itanium_dcontext_add_substitution(context, result);
+
+ printf("result = %p - next_name = %p\n", result, next_name);
+
+
+ if (result == NULL)
+ result = next_name;
+ else
+ result = itd_make_binary(context, ICT_PREFIX_BINARY, result, next_name);
+
+ if (next_targs != NULL)
+ result = itd_make_binary(context, ICT_PREFIX_BINARY, result, next_targs);
+
+
+ printf(" > result = %p\n", result);
+
+ }
+
+ if (result == NULL)
+ result = itd_make_empty(context);
+ /*
+ if (itd_get_component_type(result) != ICT_PREFIX_BINARY)
+ result = itd_make_unary(context, ICT_PREFIX_UNARY, result);
+ */
+ //printf("<prefix> : %p\n", result);
+
+ printf("### FIN DE PREFIX ### '%s'\n",
+ g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
+
+ 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ itd_state saved; /* Position d'analyse courante */
+ 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>
+ *
+ */
+
+ result = NULL;
+ g_itanium_dcontext_push_state(context, &saved);
+
+ prefix = itd_prefix(context);
+
+ if (prefix != NULL)
+ {
+ name = itd_unqualified_name(context);
+
+ if (name != NULL)
+ result = itd_make_binary(context, ICT_TPREFIX_BINARY, prefix, name);
+ else
+ itd_unref_comp(prefix);
+
+ }
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ result = itd_template_param(context);
+ }
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ result = itd_substitution(context);
+ }
+
+ if (result != NULL && itd_get_component_type(result) != ICT_TPREFIX_BINARY)
+ result = itd_make_unary(context, ICT_TPREFIX_UNARY, 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_unqualified_name(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ itd_state saved; /* Position d'analyse courante */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <unqualified-name> ::= <operator-name>
+ * ::= <ctor-dtor-name>
+ * ::= <source-name>
+ *
+ */
+
+ g_itanium_dcontext_push_state(context, &saved);
+
+ result = itd_operator_name(context);
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ result = itd_ctor_dtor_name(context);
+ }
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ result = itd_source_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_source_name(GItaniumDContext *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(GItaniumDContext *context, ssize_t *size)
+{
+ bool result; /* Validité à renvoyer */
+ bool negative; /* Taille négative ? */
+ 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;
+
+ peek = g_itanium_dcontext_peek_char(context);
+
+ if (peek == 'n')
+ {
+ negative = true;
+ g_itanium_dcontext_advance(context, 1);
+ peek = g_itanium_dcontext_peek_char(context);
+ }
+
+ *size = 0;
+
+ while (isdigit(peek))
+ {
+ result = true;
+ *size = *size * 10 + peek - '0';
+ g_itanium_dcontext_advance(context, 1);
+ peek = g_itanium_dcontext_peek_char(context);
+ }
+
+ 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(GItaniumDContext *context, size_t length)
+{
+ itanium_component *result; /* Construction à retourner */
+ 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>
+ *
+ */
+
+ data = g_itanium_dcontext_get_string(context, &remaining);
+
+ if (length > remaining)
+ return NULL;
+
+ result = itd_make_name(context, data, length);
+
+ if (result != NULL)
+ g_itanium_dcontext_advance(context, 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ char code[2]; /* Code à venir lire */
+ 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;
+
+ code[0] = g_itanium_dcontext_next_char(context);
+
+ if (code[0] == 'v')
+ {
+
+ result = NULL; /* TODO */
+
+ goto itd_operator_name_exit;
+
+
+ }
+
+ code[1] = g_itanium_dcontext_next_char(context);
+
+ if (code[0] == 'c' && code[1] == 'v')
+ {
+
+ result = NULL; /* TODO */
+
+ 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(context, 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ char next; /* Caractère suivant */
+ char peek; /* Prochain caractère lu */
+ itanium_component *offset1; /* Décallage extrait #1 */
+ itanium_component *encoding; /* Encodage suivant */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <special-name> ::= T <call-offset> <base encoding>
+ * # base is the nominal target function of thunk
+ */
+
+ result = NULL;
+
+ next = g_itanium_dcontext_next_char(context);
+
+ if (next == 'T')
+ {
+ peek = g_itanium_dcontext_peek_char(context);
+
+ switch (peek)
+ {
+ case 'V':
+ result = NULL; /* TODO */
+ break;
+
+ case 'T':
+ result = NULL; /* TODO */
+ break;
+
+ case 'I':
+ result = NULL; /* TODO */
+ break;
+
+ case 'S':
+ result = NULL; /* TODO */
+ break;
+
+ case 'c':
+ result = NULL; /* TODO */
+ break;
+
+
+ default:
+
+ 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(context, ICT_FUNCTION_THUNK, offset1, encoding);
+
+ break;
+
+ }
+
+ }
+
+ 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ char next; /* Caractère suivant */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <call-offset> ::= h <nv-offset> _
+ * ::= v <v-offset> _
+ */
+
+ next = g_itanium_dcontext_next_char(context);
+
+ switch (next)
+ {
+ case 'h':
+ result = itd_nv_offset(context);
+ break;
+
+ case 'v':
+ result = itd_v_offset(context);
+ break;
+
+ default:
+ result = NULL;
+ break;
+
+ }
+
+ if (result != NULL && !g_itanium_dcontext_check_char(context, '_'))
+ {
+ 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_nv_offset(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ ssize_t offset; /* Décallage 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(context, 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ ssize_t offset; /* Décallage obtenu #1 */
+ ssize_t voffset; /* Décallage 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;
+
+ if (!g_itanium_dcontext_check_char(context, '_'))
+ return NULL;
+
+ if (!itd_number(context, &voffset))
+ return NULL;
+
+ result = itd_make_binary(context, ICT_VIRTUAL_OFFSET,
+ itd_make_offset(context, ICT_NON_VIRTUAL_OFFSET, offset),
+ itd_make_offset(context, 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ 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
+ */
+
+ next = g_itanium_dcontext_peek_char(context);
+
+ if (next == 'C')
+ type = ICT_CONSTRUCTOR;
+ else if (next == 'D')
+ type = ICT_DESSTRUCTOR;
+ else
+ return NULL;
+
+ g_itanium_dcontext_advance(context, 1);
+
+ next = g_itanium_dcontext_peek_char(context);
+
+ if (next != '0' && next != '1' && next != '2')
+ return NULL;
+
+ g_itanium_dcontext_advance(context, 1);
+
+ result = itd_make_empty(context);
+ itd_set_type(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_type(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ TypeQualifier qualifier; /* Propriétés supplémentaires */
+ itanium_component *sub; /* Sous-type lié à associer */
+ itd_state saved; /* Position d'analyse courante */
+
+ /**
+ * 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);
+
+ switch (g_itanium_dcontext_peek_char(context))
+ {
+ case 'P':
+
+ g_itanium_dcontext_advance(context, 1);
+
+ sub = itd_type(context);
+ if (sub == NULL) return NULL;
+
+ result = itd_make_unary(context, ICT_POINTER_TO, sub);
+ break;
+
+ case 'R':
+
+ g_itanium_dcontext_advance(context, 1);
+
+ sub = itd_type(context);
+ if (sub == NULL) return NULL;
+
+ result = itd_make_unary(context, ICT_REFERENCE_TO, sub);
+ break;
+
+ case 'O':
+
+ g_itanium_dcontext_advance(context, 1);
+
+ sub = itd_type(context);
+ if (sub == NULL) return NULL;
+
+ result = itd_make_unary(context, ICT_RVALUE_REFERENCE_TO, sub);
+ break;
+
+ case 'C':
+
+ g_itanium_dcontext_advance(context, 1);
+
+ sub = itd_type(context);
+ if (sub == NULL) return NULL;
+
+ result = itd_make_unary(context, ICT_COMPLEX_PAIR, sub);
+ break;
+
+ case 'G':
+
+ g_itanium_dcontext_advance(context, 1);
+
+ sub = itd_type(context);
+ if (sub == NULL) return NULL;
+
+ result = itd_make_unary(context, ICT_IMAGINARY, sub);
+ break;
+
+ case 'U':
+
+ g_itanium_dcontext_advance(context, 1);
+ /* TODO */
+ return NULL;
+ break;
+
+ }
+
+ if (result != NULL) goto itd_type_end;
+
+ g_itanium_dcontext_push_state(context, &saved);
+
+ result = itd_builtin_type(context);
+ if (result != NULL) goto itd_type_end;
+
+ g_itanium_dcontext_pop_state(context, &saved);
+
+ result = itd_class_enum_type(context);
+ if (result != NULL) goto itd_type_end;
+
+
+ g_itanium_dcontext_pop_state(context, &saved);
+
+ result = itd_substitution(context);
+ if (result != NULL) goto itd_type_end;
+
+
+
+
+ itd_type_end:
+
+ 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(GItaniumDContext *context)
+{
+ TypeQualifier result; /* Valeur à remonter */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
+ *
+ */
+
+ result = TQF_NONE;
+
+ while (1)
+ switch (g_itanium_dcontext_peek_char(context))
+ {
+ case 'r':
+ result = TQF_RESTRICT;
+ g_itanium_dcontext_advance(context, 1);
+ break;
+
+ case 'V':
+ result = TQF_VOLATILE;
+ g_itanium_dcontext_advance(context, 1);
+ break;
+
+ case 'K':
+ result = TQF_CONST;
+ g_itanium_dcontext_advance(context, 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ BaseType type; /* Type reconnu ou BTP_INVALID */
+ 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
+ *
+ */
+
+ switch (g_itanium_dcontext_peek_char(context))
+ {
+ 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':
+ type = BTP_OTHER;
+ /* FIXME */
+ /* <source-name> # vendor extended type */
+ break;
+ default:
+ type = BTP_INVALID;
+ break;
+ }
+
+ if (type != BTP_INVALID)
+ {
+ builtin = g_basic_type_new(type);
+ result = itd_make_type(context, builtin);
+ g_itanium_dcontext_advance(context, 1);
+ }
+ 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_bare_function_type(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ itanium_component *type; /* Nouvel élément à intégrer */
+ 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(context, ICT_TYPES_LIST, NULL, type);
+
+ while (1)
+ {
+ g_itanium_dcontext_push_state(context, &saved);
+
+ type = itd_type(context);
+ if (type == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ break;
+ }
+
+ result = itd_append_right_to_binary(context, 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(GItaniumDContext *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_template_args(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ itanium_component *arg; /* Nouvel argument extrait */
+ itd_state saved; /* Position d'analyse courante */
+
+ printf(">>> TA>> '%s'\n", g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <template-args> ::= I <template-arg>+ E
+ *
+ */
+
+ if (!g_itanium_dcontext_check_char(context, 'I'))
+ return NULL;
+
+ arg = itd_template_arg(context);
+ if (arg == NULL) return NULL;
+
+ result = itd_append_right_to_binary(context, ICT_TYPES_LIST, NULL, arg);
+
+ while (1)
+ {
+ g_itanium_dcontext_push_state(context, &saved);
+
+ arg = itd_template_arg(context);
+ if (arg == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ break;
+ }
+
+ result = itd_append_right_to_binary(context, ICT_TYPES_LIST, result, arg);
+
+ }
+
+ //printf(" ta/E >> '%s'\n", g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
+
+ if (!g_itanium_dcontext_check_char(context, 'E'))
+ {
+ //printf("=== TA : BAD E\n\n");
+
+ if (result != NULL)
+ itd_unref_comp(result);
+ return NULL;
+ }
+
+ //printf("=== TA >> %p\n\n", result);
+
+ result = itd_make_unary(context, 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ itd_state saved; /* Position d'analyse courante */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <template-arg> ::= <type> # type or template
+ * ::= X <expression> E # expression
+ * ::= <expr-primary> # simple expressions
+ *
+ */
+
+ g_itanium_dcontext_push_state(context, &saved);
+
+ result = itd_type(context);
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+
+ if (g_itanium_dcontext_check_char(context, 'X'))
+ {
+ result = itd_expression(context);
+
+ if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ }
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ result = itd_expr_primary(context);
+ }
+
+ 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(GItaniumDContext *context, bool hex)
+{
+ itanium_component *result; /* Construction à retourner */
+ 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;
+
+ data = g_itanium_dcontext_get_string(context, (size_t []) { 0 });
+
+ g_itanium_dcontext_push_state(context, &saved);
+
+ while (1)
+ {
+ peek = g_itanium_dcontext_peek_char(context);
+
+ switch (peek)
+ {
+ case '0' ... '9':
+ g_itanium_dcontext_advance(context, 1);
+ break;
+
+ case 'a' ... 'f':
+ if (hex)
+ g_itanium_dcontext_advance(context, 1);
+ else
+ goto exit_iits;
+ break;
+
+ case 'E':
+ goto exit_loop;
+ break;
+
+ default:
+ goto exit_iits;
+
+ }
+
+ }
+
+ exit_loop:
+
+ g_itanium_dcontext_push_state(context, &cur);
+
+ if ((cur.pos - saved.pos) > 0)
+ result = itd_make_name(context, 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ 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
+ *
+ */
+
+ printf("PRIMARY :: no L\n");
+
+ if (!g_itanium_dcontext_check_char(context, 'L'))
+ return NULL;
+
+ g_itanium_dcontext_push_state(context, &saved);
+
+ type = itd_type(context);
+
+ if (type != NULL)
+ {
+ g_itanium_dcontext_push_state(context, &saved_value);
+
+ /* Règle <type> <value number> */
+
+ result = itd_value_to_string(context, false);
+
+ if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ /* Règle <type> <value float> */
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved_value);
+
+ result = itd_value_to_string(context, true);
+
+ if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ itd_unref_comp(type);
+
+ }
+
+ /* Règle <mangled-name> */
+
+ if (result == NULL)
+ {
+ g_itanium_dcontext_pop_state(context, &saved);
+ result = itd_mangled_name(context);
+
+ if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ printf("PRIMARY :: %p\n", result);
+
+ 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(GItaniumDContext *context, char cur, size_t *id)
+{
+ /**
+ * 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)).
+ */
+
+ if (cur != '_')
+ {
+ do
+ {
+ if (isdigit(cur))
+ *id = *id * 36 + cur - '0';
+ else if (isupper(cur))
+ *id = *id * 36 + cur - 'A' + 10;
+ else
+ return false;
+
+ cur = g_itanium_dcontext_next_char(context);
+
+ }
+ 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(GItaniumDContext *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ char cur; /* Caractère analysé */
+ size_t id; /* Identifiant de substitution */
+ char peek; /* Prochain caractère lu */
+ bool verbose; /* Sélection du rendu idéal */
+ size_t i; /* Boucle de parcours */
+
+ /**
+ * 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>>
+ *
+ */
+
+ peek = g_itanium_dcontext_peek_char(context);
+
+ if (!g_itanium_dcontext_check_char(context, 'S'))
+ return NULL;
+
+ cur = g_itanium_dcontext_next_char(context);
+
+ if (cur == '_' || isdigit(cur) || isupper(cur))
+ {
+ if (!itd_seq_id(context, cur, &id))
+ return NULL;
+
+ printf("requesting... %zu\n", id);
+
+ result = g_itanium_dcontext_get_substitution(context, id);
+
+ }
+ else
+ {
+ result = NULL;
+
+ peek = g_itanium_dcontext_peek_char(context);
+ verbose = (peek == 'C' || peek == 'D'); /* TODO : prefixe ? */
+
+ for (i = 0; i < ARRAY_SIZE(itanium_standard_substitutions); i++)
+ if (itanium_standard_substitutions[i].code == cur)
+ {
+ /* TODO : constructeur... */
+
+ if (verbose)
+ result = itd_make_name(context,
+ itanium_standard_substitutions[i].full,
+ itanium_standard_substitutions[i].full_len);
+ else
+ result = itd_make_name(context,
+ itanium_standard_substitutions[i].simple,
+ itanium_standard_substitutions[i].simple_len);
+
+ itd_set_type(result, ICT_STD_SUBST);
+
+ break;
+
+ }
+
+ }
+
+ return result;
+
+}
diff --git a/src/format/mangling/itanium/abi.h b/src/format/mangling/itanium/abi.h
new file mode 100644
index 0000000..497ef7a
--- /dev/null
+++ b/src/format/mangling/itanium/abi.h
@@ -0,0 +1,38 @@
+
+/* OpenIDA - 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 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA 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.
+ *
+ * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _FORMAT_MANGLING_ITANIUM_ABI_H
+#define _FORMAT_MANGLING_ITANIUM_ABI_H
+
+
+#include "component.h"
+#include "context.h"
+
+
+
+/* Extrait un composant dans un contexte Itanium. */
+itanium_component *itd_mangled_name(GItaniumDContext *);
+
+
+
+#endif /* _FORMAT_MANGLING_ITANIUM_ABI_H */
diff --git a/src/format/mangling/itanium/component-int.h b/src/format/mangling/itanium/component-int.h
new file mode 100644
index 0000000..e6d86b6
--- /dev/null
+++ b/src/format/mangling/itanium/component-int.h
@@ -0,0 +1,79 @@
+
+
+#ifndef _FORMAT_MANGLING_ITANIUM_ABI2_H
+#define _FORMAT_MANGLING_ITANIUM_ABI2_H
+
+
+#include "component.h"
+
+
+
+/* Composant extrait de l'encodage */
+struct _itanium_component
+{
+ ItaniumComponentType type; /* Type de composant */
+
+ GItaniumDContext *context; /* Regroupement de composants */
+ 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 */
+
+
+ };
+
+ } operator;
+
+ /* ICT_NON_VIRTUAL_OFFSET */
+ /* ICT_VIRTUAL_OFFSET */
+ ssize_t offset; /* Décallage de fonction */
+
+ /* ICT_TYPE */
+ GDataType *dtype; /* Type instancié */
+
+
+ /* 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 /* _FORMAT_MANGLING_ITANIUM_ABI2_H */
diff --git a/src/format/mangling/itanium/component.c b/src/format/mangling/itanium/component.c
new file mode 100644
index 0000000..09e13e2
--- /dev/null
+++ b/src/format/mangling/itanium/component.c
@@ -0,0 +1,714 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * component.c - représentation des composants extraits de l'ABI C++ Itanium
+ *
+ * Copyright (C) 2013 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA 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.
+ *
+ * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "component.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "component-int.h"
+#include "../../../common/extstr.h"
+#include "../../../common/fnv1a.h"
+
+
+
+
+/* Procédure à appliquer sur un composant visité */
+typedef void (* visit_comp_fc) (itanium_component *);
+
+
+
+#define reset_comp_hash(c) c->hash = 0
+
+/* Visite les composants en présence. */
+static void visit_comp(itanium_component *, visit_comp_fc);
+
+
+
+/******************************************************************************
+* *
+* 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)
+{
+ itanium_component *sub; /* Sous-partie de composant */
+
+ switch (comp->type)
+ {
+ case ICT_NESTED_NAME:
+ case ICT_TEMPLATE_NAME_ARGS:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_PREFIX_UNARY:
+ case ICT_TPREFIX_UNARY:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_PREFIX_BINARY:
+ case ICT_TPREFIX_BINARY:
+ 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_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_ENCODING:
+
+ /* Retour ? */
+
+ sub = NULL;//IT_BINARY_COMP(IT_BINARY_COMP(comp).right).left;
+
+ if (sub != NULL)
+ visit_comp(sub, visitor);
+
+ /* Nom de la fonction */
+ visit_comp(comp->binary.left, visitor);
+
+ visit_comp(comp->binary.right, 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;
+
+ default:
+ 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)
+{
+ return;
+
+ void visit_for_unref(itanium_component *comp)
+ {
+ if (--comp->refcount == 0)
+ {
+ if (comp->type == ICT_TYPE)
+ g_object_unref(G_OBJECT(comp->dtype));
+
+ g_itanium_dcontext_mark_component_as_free(comp->context, 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->context, comp, NULL);
+ comp->hash = fnv_64a_hash(desc);
+ free(desc);
+ }
+
+ return comp->hash;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_empty(GItaniumDContext *context)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = g_itanium_dcontext_get_empty_component(context);
+
+ result->type = ICT_EMPTY;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* 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(GItaniumDContext *context, const char *str, size_t len)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = g_itanium_dcontext_get_empty_component(context);
+
+ result->type = ICT_NAME;
+ result->s_name.str = str;
+ result->s_name.len = len;
+
+ return result;
+
+}
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* 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(GItaniumDContext *context, const itanium_operator_info *info)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = g_itanium_dcontext_get_empty_component(context);
+
+ result->type = ICT_OPERATOR_NAME;
+ result->operator.otype = IOT_SIMPLE;
+ result->operator.info = *info;
+
+ return result;
+
+}
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* type = type exacte de décallage. *
+* offset = décallage 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(GItaniumDContext *context, ItaniumComponentType type, ssize_t offset)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = g_itanium_dcontext_get_empty_component(context);
+
+ result->type = type;
+ result->offset = offset;
+
+ return result;
+
+}
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* 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(GItaniumDContext *context, GDataType *dtype)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = g_itanium_dcontext_get_empty_component(context);
+
+ result->type = ICT_TYPE;
+ result->dtype = dtype;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* 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(GItaniumDContext *context, ItaniumComponentType type, itanium_component *left, itanium_component *right)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = g_itanium_dcontext_get_empty_component(context);
+
+ result->type = type;
+ result->binary.left = left;
+ result->binary.right = right;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* 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(GItaniumDContext *context, ItaniumComponentType type, itanium_component *parent, itanium_component *left)
+{
+ itanium_component *result; /* Composant à renvoyer */
+ itanium_component *iter; /* Boucle de parcours */
+
+ result = g_itanium_dcontext_get_empty_component(context);
+
+ result->type = type;
+ result->binary.left = left;
+
+ 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 : context = contexte de décodage à utiliser. *
+* 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(GItaniumDContext *context, ItaniumComponentType type, itanium_component *unary)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = g_itanium_dcontext_get_empty_component(context);
+
+ result->type = type;
+ result->unary = unary;
+
+ 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 : context = contexte de décodage à utiliser. *
+* 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(GItaniumDContext *context, const itanium_component *comp, char *base)
+{
+ char *result; /* Chaîne à retourner */
+ char *name; /* Désignation à copier */
+ const itanium_component *sub; /* Sous-partie de composant */
+
+ //if (base != NULL)
+ //printf(".... %s\n", base);
+
+ switch (comp->type)
+ {
+ case ICT_EMPTY:
+ result = base;
+ break;
+
+ case ICT_NAME:
+ case ICT_STD_SUBST:
+ result = strnadd(base, comp->s_name.str, comp->s_name.len);
+ break;
+
+ case ICT_NESTED_NAME:
+ result = itd_translate_component(context, comp->binary.left, base);
+ if (comp->binary.right->type != ICT_TEMPLATE_ARGS)
+ result = stradd(result, "::");
+ result = itd_translate_component(context, comp->binary.right, result);
+ break;
+
+ case ICT_TEMPLATE_NAME_ARGS:
+ result = itd_translate_component(context, comp->binary.left, base);
+ result = itd_translate_component(context, comp->binary.right, result);
+ break;
+
+ case ICT_PREFIX_UNARY:
+ case ICT_TPREFIX_UNARY:
+ result = stradd(base, "::");
+ result = itd_translate_component(context, comp->unary, result);
+ break;
+
+ case ICT_PREFIX_BINARY:
+ case ICT_TPREFIX_BINARY:
+ result = itd_translate_component(context, comp->binary.left, base);
+ result = stradd(result, "::");
+ result = itd_translate_component(context, comp->binary.right, result);
+ break;
+
+
+ case ICT_OPERATOR_NAME:
+ switch (comp->operator.otype)
+ {
+ case IOT_SIMPLE:
+ result = stradd(base, comp->operator.info.name);
+ break;
+ case IOT_CAST:
+ result = stradd(base, "TODO_CAST");
+ break;
+ case IOT_VENDOR:
+ result = stradd(base, "TODO_VENDOR");
+ break;
+ }
+ break;
+
+
+ case ICT_FUNCTION_THUNK:
+ result = itd_translate_component(context, comp->binary.right, base);
+ break;
+
+ case ICT_FUNCTION_COVARIANT_THUNK:
+ result = itd_translate_component(context, comp->ternary.third, base);
+ 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);
+
+ result = stradd(base, name);
+
+ free(name);
+
+ break;
+
+ case ICT_POINTER_TO:
+ result = itd_translate_component(context, comp->unary, base);
+ result = stradd(result, " *");
+ break;
+
+ case ICT_REFERENCE_TO:
+ result = itd_translate_component(context, comp->unary, base);
+ result = stradd(result, " &");
+ break;
+
+ case ICT_RVALUE_REFERENCE_TO:
+ result = itd_translate_component(context, comp->unary, base);
+ result = stradd(result, " &");
+ break;
+
+ case ICT_COMPLEX_PAIR:
+ result = stradd(base, "<?>");
+ result = itd_translate_component(context, comp->unary, result);
+ break;
+
+ case ICT_IMAGINARY:
+ result = stradd(base, "<?>");
+ result = itd_translate_component(context, comp->unary, result);
+ break;
+
+
+ case ICT_FUNCTION_ENCODING:
+
+ result = base;
+
+ /* Retour ? */
+
+ sub = NULL;//IT_BINARY_COMP(IT_BINARY_COMP(comp).right).left;
+
+ if (sub != NULL)
+ result = itd_translate_component(context, sub, result);
+ else
+ result = stradd(result, "???");
+
+ result = stradd(result, " ");
+
+ /* Nom de la fonction */
+ result = itd_translate_component(context, comp->binary.left, result);
+
+ result = stradd(result, "(");
+
+ result = itd_translate_component(context, comp->binary.right, result);
+
+ result = stradd(result, ")");
+
+
+ break;
+
+ case ICT_TEMPLATE_ARGS:
+ result = stradd(base, "<");
+ result = itd_translate_component(context, comp->unary, result);
+ result = stradd(result, ">");
+ break;
+
+ case ICT_TYPES_LIST:
+
+ result = itd_translate_component(context, comp->binary.left, base);
+
+ if (comp->binary.right != NULL)
+ {
+ result = stradd(result, ", ");
+ result = itd_translate_component(context, comp->binary.right, result);
+ }
+
+
+ //sub = IT_BINARY_COMP(IT_BINARY_COMP(comp).right).right;
+
+
+ break;
+
+
+ default: /* ICT_* */
+ result = base;
+ break;
+
+ }
+
+
+
+ return result;
+
+
+}
diff --git a/src/format/mangling/itanium/component.h b/src/format/mangling/itanium/component.h
new file mode 100644
index 0000000..99c93db
--- /dev/null
+++ b/src/format/mangling/itanium/component.h
@@ -0,0 +1,213 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * component.h - prototypes pour la représentation des composants extraits de l'ABI C++ Itanium
+ *
+ * Copyright (C) 2013 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA 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.
+ *
+ * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _FORMAT_MANGLING_ITANIUM_COMPONENT_H
+#define _FORMAT_MANGLING_ITANIUM_COMPONENT_H
+
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <sys/types.h>
+
+
+#include "context.h"
+#include "../../../analysis/type.h"
+#include "../../../common/fnv1a.h"
+
+
+
+/* Type de composants */
+typedef enum _ItaniumComponentType
+{
+ /**
+ * Représentation d'une règle vide.
+ */
+ ICT_EMPTY,
+
+ /**
+ * Chaîne de caractère, terminée par un octet nul.
+ */
+ ICT_NAME,
+ ICT_STD_SUBST,
+
+ /**
+ * Noms imbriqués, en deux parties : 'binary'.
+ */
+ ICT_NESTED_NAME,
+ ICT_TEMPLATE_NAME_ARGS,
+
+ /**
+ * Deux types de préfixes : un ou deux éléments.
+ * -> 'unary' ou 'binary'
+ */
+ ICT_PREFIX_UNARY,
+ ICT_PREFIX_BINARY,
+ ICT_TPREFIX_UNARY,
+ ICT_TPREFIX_BINARY,
+
+ /**
+ * Encodage d'un nom d'opérateur, consigné dans 'operator'.
+ */
+ ICT_OPERATOR_NAME,
+
+
+ /**
+ * Fonctions virtuelles.
+ * -> décallage : 'offset'.
+ * -> fonctions simples : 'binary'.
+ * -> fonctions complexes : 'ternary'.
+ */
+ ICT_NON_VIRTUAL_OFFSET,
+ ICT_VIRTUAL_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,
+
+ /**
+ * 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,
+
+ /**
+ * Fonction (nom + retour/paramètres), sous forme binaire :
+ * -> left = function name
+ * -> right = bare-function-type
+ */
+ ICT_FUNCTION_ENCODING,
+
+ /**
+ * 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,
+
+ 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 *);
+
+
+
+/* Marque un composant comme étant disponible pour un usage. */
+void itd_free_comp(GItaniumDContext *, itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_empty(GItaniumDContext *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_name(GItaniumDContext *, const char *, size_t);
+
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_operator(GItaniumDContext *, const itanium_operator_info *);
+
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_offset(GItaniumDContext *, ItaniumComponentType, ssize_t);
+
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_type(GItaniumDContext *, GDataType *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_binary(GItaniumDContext *, ItaniumComponentType, itanium_component *, itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_append_right_to_binary(GItaniumDContext *, ItaniumComponentType, itanium_component *, itanium_component *);
+
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_unary(GItaniumDContext *, ItaniumComponentType, 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(GItaniumDContext *, const itanium_component *, char *);
+
+
+
+#endif /* _FORMAT_MANGLING_ITANIUM_COMPONENT_H */
diff --git a/src/format/mangling/itanium/context.c b/src/format/mangling/itanium/context.c
new file mode 100644
index 0000000..8d2d29b
--- /dev/null
+++ b/src/format/mangling/itanium/context.c
@@ -0,0 +1,571 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * context.c - contexte de décodage à la sauce ABI C++ Itanium
+ *
+ * Copyright (C) 2013 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA 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.
+ *
+ * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "context.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "abi.h"
+#include "component-int.h"
+#include "../context-int.h"
+
+
+
+/* Taille des extensions d'allocation */
+#define ITCOMP_ALLOC_BULK 200
+
+/* Marqueur de fin pour les disponibilités */
+#define ITCOMP_INVALID ((size_t)-1)
+
+
+/* Contexte de décodage Itanium (instance) */
+struct _GItaniumDContext
+{
+ GDemanglingContext parent; /* A laisser en premier */
+
+ char *mangled; /* Caractères à traiter */
+ size_t len; /* Quantité de caractères */
+ size_t pos; /* Position d'analyse */
+
+ itanium_component *components; /* Tableaux des composants */
+ size_t *next_links; /* Chemins d'allocation */
+ size_t length; /* Taille allouée */
+ size_t last_used; /* Lien vers la disponibilité */
+
+ itanium_component **substitutions; /* Table de substitutions */
+ size_t subst_count; /* Quantité utilisée */
+
+};
+
+/* Contexte de décodage Itanium (classe) */
+struct _GItaniumDContextClass
+{
+ GDemanglingContextClass parent; /* A laisser en premier */
+
+};
+
+
+
+/* Indique le type défini pour un contexte de décodage. */
+G_DEFINE_TYPE(GItaniumDContext, g_itanium_dcontext, G_TYPE_DEMANGLING_CONTEXT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des contextes de décodage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_dcontext_class_init(GItaniumDContextClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à initialiser. *
+* *
+* Description : Initialise une instance de contexte pour décodage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_dcontext_init(GItaniumDContext *context)
+{
+ context->last_used = ITCOMP_INVALID;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prépare de quoi effectuer un décodage Itanium. *
+* *
+* Retour : Instance du contexte mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDemanglingContext *g_itanium_dcontext_new(void)
+{
+ GDemanglingContext *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ITANIUM_DCONTEXT, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage sur lequel s'appuyer. *
+* desc = chaîne de caractères à décoder. *
+* *
+* Description : Tente de décoder une chaîne de caractères donnée. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void /*GBinRoutine **/g_itanium_dcontext_demangle_routine(GItaniumDContext *context, const char *desc)
+{
+ itanium_component *comp;
+
+ char *str;
+
+ printf("<<== %s\n", desc);
+
+ context->mangled = strdup(desc);
+ context->len = strlen(desc);
+ context->pos = 0;
+
+
+ /**
+ * On part du principe qu'il n'y aura jamais plus de substitutions
+ * à enregistrer que de caractères dans la chaîne à traiter.
+ * Du coup, on peut tout allouer d'un coup !
+ */
+ context->substitutions = (itanium_component **)calloc(context->len, sizeof(itanium_component *));
+
+
+ comp = itd_mangled_name(context);
+
+
+ printf("Got :: %p\n", comp);
+
+ str = itd_translate_component(context, comp, NULL);
+
+ printf("==>> %s\n", str);
+
+}
+
+
+/******************************************************************************
+* *
+* 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_dcontext_push_state(const GItaniumDContext *context, itd_state *state)
+{
+ state->pos = context->pos;
+ 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_dcontext_pop_state(GItaniumDContext *context, const itd_state *state)
+{
+ size_t i; /* Boucle de parcours */
+
+ /*
+ printf("--deleting subst-- from %zu to %zu\n",
+ state->subst_count, context->subst_count);
+ */
+
+ for (i = state->subst_count; i < context->subst_count; i++)
+ itd_unref_comp(context->substitutions[i]);
+
+ context->pos = state->pos;
+ context->subst_count = state->subst_count;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Fournit la valeur du caractère courant. *
+* *
+* Retour : Caractère courant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char g_itanium_dcontext_peek_char(const GItaniumDContext *context)
+{
+ return *(context->mangled + context->pos);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* quantity = quantié de caractères à marquer comme traités. *
+* *
+* Description : Avance la tête de lecture courante. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_itanium_dcontext_advance(GItaniumDContext *context, size_t quantity)
+{
+ context->pos += quantity;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Fournit et avance la tête de lecture courante. *
+* *
+* Retour : Caractère courant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char g_itanium_dcontext_next_char(GItaniumDContext *context)
+{
+ return *(context->mangled + context->pos++);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* c = caractère à retrouver. *
+* *
+* Description : Vérifie la nature du caractère courant. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_itanium_dcontext_check_char(GItaniumDContext *context, char c)
+{
+ bool result; /* Validation à retourner */
+
+ if (g_itanium_dcontext_peek_char(context) == c)
+ {
+ result = true;
+ g_itanium_dcontext_advance(context, 1);
+ }
+ else
+ result = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* remaining = taille de la chaîne retournée. [OUT] *
+* *
+* Description : Fournit la chaîne de caractère restant à traiter. *
+* *
+* Retour : Pointeur vers les données courantes. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_itanium_dcontext_get_string(const GItaniumDContext *context, size_t *remaining)
+{
+ const char *result; /* Données à renvoyer */
+
+ *remaining = context->len - context->pos;
+
+ result = &context->mangled[context->pos];
+
+ return result;
+
+}
+
+
+
+
+
+/*
+
+################define d_peek_char(di) (*((di)->n))
+#define d_peek_next_char(di) ((di)->n[1])
+################define d_advance(di, i) ((di)->n += (i))
+################define d_check_char(di, c) (d_peek_char(di) == c ? ((di)->n++, 1) : 0)
+#define d_next_char(di) (d_peek_char(di) == '\0' ? '\0' : *((di)->n++))
+################define d_str(di) ((di)->n)
+
+
+*/
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* *
+* Description : Fournit un nouveau composant vierge. *
+* *
+* Retour : Composant prêt à être défini. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *g_itanium_dcontext_get_empty_component(GItaniumDContext *context)
+{
+ itanium_component *result; /* Disponibilité à retourner */
+ size_t i; /* Boucle de parcours */
+ size_t next; /* Indice de disponibilité */
+
+ if (context->last_used == ITCOMP_INVALID
+ || context->next_links[context->last_used] == ITCOMP_INVALID)
+ {
+ /* Création d'extensions */
+
+ context->components = (itanium_component *)
+ realloc(context->components,
+ (context->length + ITCOMP_ALLOC_BULK) * sizeof(itanium_component));
+
+ context->next_links = (size_t *)
+ realloc(context->next_links, (context->length + ITCOMP_ALLOC_BULK) * sizeof(size_t));
+
+ /* Inscription des liens d'allocation */
+
+ for (i = context->length; i < (context->length + ITCOMP_ALLOC_BULK - 1); i++)
+ context->next_links[i] = i + 1;
+
+ context->next_links[context->length + ITCOMP_ALLOC_BULK - 1] = ITCOMP_INVALID;
+
+ if (context->last_used != ITCOMP_INVALID)
+ context->next_links[context->last_used] = context->length;
+
+ /* Mise à jour globale */
+
+ context->length += ITCOMP_ALLOC_BULK;
+
+ }
+
+ /* Extraction d'un composant disponible */
+
+ if (context->last_used == ITCOMP_INVALID)
+ next = 0;
+ else
+ next = context->next_links[context->last_used];
+
+ result = &context->components[next];
+ context->last_used = next;
+
+ memset(result, 0, sizeof(itanium_component));
+
+ result->context = context;
+ g_object_ref(G_OBJECT(result->context));
+ result->refcount = 1;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* comp = composant à libérer. *
+* *
+* Description : Marque un composant comme étant disponible pour un usage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_itanium_dcontext_mark_component_as_free(GItaniumDContext *context, itanium_component *comp)
+{
+ size_t index; /* Indice du composant concerné*/
+
+ /*BUG_ON(comp->refcount != 0);*/
+
+ g_object_unref(G_OBJECT(comp->context));
+
+ index = comp - context->components;
+
+ context->next_links[index] = context->next_links[context->last_used];
+ context->next_links[context->last_used] = index;
+
+}
+
+
+/******************************************************************************
+* *
+* 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_dcontext_add_substitution(GItaniumDContext *context, itanium_component *comp)
+{
+ fnv64_t hash; /* Empreinte du candidat */
+ size_t i; /* Boucle de parcours */
+
+ hash = itd_hash_comp(comp);
+
+ for (i = 0; i < context->subst_count; i++)
+ if (cmp_fnv_64a(itd_hash_comp(context->substitutions[i]), hash))
+ break;
+
+ if (i == context->subst_count)
+ {
+
+ printf("[ADDING SUBST] [%zu] '%s'\n",
+ context->subst_count,
+ itd_translate_component(context, comp, NULL));
+
+
+ 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_dcontext_get_substitution(GItaniumDContext *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;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+void test_itanium(void)
+{
+
+
+
+
+#define TEST_DEMANG(v) \
+ do \
+ { \
+ GDemanglingContext *ctx; \
+ /*char *str;*/ \
+ ctx = g_itanium_dcontext_new(); \
+ /*str = */g_itanium_dcontext_demangle_routine(G_ITANIUM_DCONTEXT(ctx), v); \
+ /*printf("==> %s\n", str);*/ \
+ } \
+ while (0)
+
+
+ TEST_DEMANG("_Z3fooILi2EEvRAplT_Li1E_i");
+
+ exit(0);
+
+ TEST_DEMANG("_Z1fv");
+ TEST_DEMANG("_Z3foo3bar");
+
+
+}
diff --git a/src/format/mangling/itanium/context.h b/src/format/mangling/itanium/context.h
new file mode 100644
index 0000000..54c3294
--- /dev/null
+++ b/src/format/mangling/itanium/context.h
@@ -0,0 +1,117 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * context.h - prototypes pour le contexte de décodage à la sauce ABI C++ Itanium
+ *
+ * Copyright (C) 2013 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA 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.
+ *
+ * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _FORMAT_MANGLING_ITANIUM_CONTEXT_H
+#define _FORMAT_MANGLING_ITANIUM_CONTEXT_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+#include "../context.h"
+
+
+
+#define G_TYPE_ITANIUM_DCONTEXT g_itanium_dcontext_get_type()
+#define G_ITANIUM_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_itanium_dcontext_get_type(), GItaniumDContext))
+#define G_IS_ITANIUM_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_itanium_dcontext_get_type()))
+#define G_ITANIUM_DCONTEXT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_itanium_dcontext_get_type(), GItaniumDContextIface))
+#define G_ITANIUM_DCONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ITANIUM_DCONTEXT, GItaniumDContextClass))
+
+
+/* Contexte de décodage Itanium (instance) */
+typedef struct _GItaniumDContext GItaniumDContext;
+
+/* Contexte de décodage Itanium (classe) */
+typedef struct _GItaniumDContextClass GItaniumDContextClass;
+
+
+/* Indique le type défini pour un contexte de décodage. */
+GType g_itanium_dcontext_get_type(void);
+
+/* Prépare de quoi effectuer un décodage Itanium. */
+GDemanglingContext *g_itanium_dcontext_new(void);
+
+/* Tente de décoder une chaîne de caractères donnée. */
+void /*GBinRoutine **/g_itanium_dcontext_demangle_routine(GItaniumDContext *, const char *);
+
+/* Sauvegarde d'un état courant */
+typedef struct _itd_state
+{
+ size_t pos; /* Position courante */
+ size_t subst_count; /* Nombre de substitutions */
+
+} itd_state;
+
+/* Fournit l'état courant à une fin de retour en arrière. */
+void g_itanium_dcontext_push_state(const GItaniumDContext *, itd_state *);
+
+/* Définit l'état courant suite à un retour en arrière. */
+void g_itanium_dcontext_pop_state(GItaniumDContext *, const itd_state *);
+
+/* Fournit la valeur du caractère courant. */
+char g_itanium_dcontext_peek_char(const GItaniumDContext *);
+
+/* Avance la tête de lecture courante. */
+void g_itanium_dcontext_advance(GItaniumDContext *, size_t);
+
+/* Fournit et avance la tête de lecture courante. */
+char g_itanium_dcontext_next_char(GItaniumDContext *);
+
+/* Vérifie la nature du caractère courant. */
+bool g_itanium_dcontext_check_char(GItaniumDContext *, char);
+
+/* Fournit la chaîne de caractère restant à traiter. */
+const char *g_itanium_dcontext_get_string(const GItaniumDContext *, size_t *);
+
+
+
+
+/* Composant extrait de l'encodage */
+typedef struct _itanium_component itanium_component;
+
+
+/* Fournit un nouveau composant vierge. */
+itanium_component *g_itanium_dcontext_get_empty_component(GItaniumDContext *);
+
+/* Marque un composant comme étant disponible pour un usage. */
+void g_itanium_dcontext_mark_component_as_free(GItaniumDContext *, itanium_component *);
+
+/* Indexe un composant comme future substitution potentielle. */
+void g_itanium_dcontext_add_substitution(GItaniumDContext *, itanium_component *);
+
+/* Fournit un composant en place pour une substitution. */
+itanium_component *g_itanium_dcontext_get_substitution(GItaniumDContext *, size_t);
+
+
+
+
+
+
+void test_itanium(void);
+
+
+
+
+
+#endif /* _FORMAT_MANGLING_ITANIUM_CONTEXT_H */
diff --git a/src/format/mangling/itanium_gram.y b/src/format/mangling/itanium_gram.y
deleted file mode 100644
index 0fd3b2b..0000000
--- a/src/format/mangling/itanium_gram.y
+++ /dev/null
@@ -1,1222 +0,0 @@
-
-%{
-
-
-#include <malloc.h>
-#include <stdio.h>
-#include <string.h>
-
-
-#include "context-int.h"
-#include "itanium.h"
-#include "../../common/extstr.h"
-#include "../../analysis/types/cse.h"
-#include "../../analysis/types/template.h"
-
-
-
-/**
- * cf. http://www.codesourcery.com/cxx-abi/abi.html#mangling
- */
-
-
-
-/* --------------------- CONTEXTE POUR LE DECODAGE TYPE ITANIUM --------------------- */
-
-
-#define G_TYPE_ITANIUM_DCONTEXT g_itanium_dcontext_get_type()
-#define G_ITANIUM_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_itanium_dcontext_get_type(), GItaniumDContext))
-#define G_IS_ITANIUM_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_itanium_dcontext_get_type()))
-#define G_ITANIUM_DCONTEXT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_itanium_dcontext_get_type(), GItaniumDContextIface))
-#define G_ITANIUM_DCONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ITANIUM_DCONTEXT, GItaniumDContextClass))
-
-
-/* Contexte de décodage Itanium (instance) */
-struct _GItaniumDContext
-{
- GDemanglingContext parent; /* A laisser en premier */
-
- char *identifier; /* Identifiant en construction */
- size_t id_allocated; /* Taille allouée en mémoire */
- size_t id_used; /* Longueur de la chaîne */
-
- GSList *routines; /* Routines en cours de maj */
-
- GSList *substitutions; /* Empilement des types créés */
-
- bool start_args; /* Début de définitions d'args */
- unsigned int template_level; /* Compteur d'imbrications */
-
-};
-
-/* Contexte de décodage Itanium (classe) */
-struct _GItaniumDContextClass
-{
- GDemanglingContextClass parent; /* A laisser en premier */
-
-};
-
-
-/* Taille du bond pour les allocations */
-#define ITANIUM_ALLOC_CLUSTER 10
-
-
-/* Indique le type défini pour un contexte de décodage. */
-static GType g_itanium_dcontext_get_type(void);
-
-/* Initialise la classe des contextes de décodage. */
-static void g_itanium_dcontext_class_init(GItaniumDContextClass *);
-
-/* Initialise une instance de contexte pour décodage. */
-static void g_itanium_dcontext_init(GItaniumDContext *);
-
-/* Supprime toutes les références externes. */
-static void g_itanium_dcontext_dispose(GItaniumDContext *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_itanium_dcontext_finalize(GItaniumDContext *);
-
-/* Réinitialise le constructeur d'identifiants. */
-static void g_itanium_dcontext_reset_identifier(GItaniumDContext *);
-
-/* Construit à la volée un identifiant. */
-static void g_itanium_dcontext_build_identifier(GItaniumDContext *, char);
-
-/* Place sous le feu des projecteurs une nouvelle routine. */
-static GBinRoutine *g_itanium_dcontext_push_routine(GItaniumDContext *, GBinRoutine *);
-
-/* Remet une ancienne routine sous le feu des projecteurs. */
-static GBinRoutine *g_itanium_dcontext_pop_routine(GItaniumDContext *);
-
-/* Ajoute un élément dans une liste de substitutions. */
-static void g_itanium_dcontext_add_item(GItaniumDContext *, GDataType *);
-
-/* Fournit le nième élément d'une liste de substitutions. */
-static GDataType *g_itanium_dcontext_get_item(GItaniumDContext *, guint);
-
-/* Autorise ou non le dépilement des opérateurs. */
-static void g_itanium_dcontext_update(GItaniumDContext *);
-
-
-
-/* ------------------------ TRAITEMENT DE L'ENCODAGE ITANIUM ------------------------ */
-
-
-/* Fait sauter le premier argument en faveur du type de retour. */
-static void compute_routine_itanium_ret_type(GBinRoutine *);
-
-/* Recherche et fait sauter les premiers arguments rencontrés. */
-static void update_itanium_ret_type(GDataType *);
-
-
-
-
-
-
-
-
-
-/* Borne la longueur d'une chaîne à lire. */
-extern void set_itanium_text_length(unsigned int);
-
-/* Autorise la lecture des opérateurs. */
-extern void allow_itanium_operators(void);
-
-/* Autorise la lecture des opérateurs. */
-extern void exclude_itanium_operators(void);
-
-
-
-
-
-
-char *strmerge(char *str1, const char *sep, char *str2);
- char *strmerge(char *str1, const char *sep, char *str2)
-{
- char *result;
-
- if (str1 == NULL) result = str2;
- else if (str2 == NULL) result = str1;
- else
- {
- result = (char *)calloc(strlen(str1) + strlen(sep) + strlen(str2) + 1, sizeof(char));
-
- strcpy(result, str1);
- strcat(result, sep);
- strcat(result, str2);
-
- free(str1);
- free(str2);
-
- }
-
- return result;
-
-}
-
-
-
-%}
-
-
-%union {
-
- struct
- {
- union
- {
- char *str;
- void/*GDataType*/ *type;
- };
- int/*bool*/ is_string;
-
- } str_or_type;
-
- char car;
- char *text;
- unsigned int val;
- short/*s16_t*/ s16_val;
-
- void /*GDataType*/ *type;
- void /*GTemplateType*/ *templtype;
-
- void/*simple_variable*/ *simple;
- void/*complex_variable*/ *complex;
- void/*variable*/ *var;
-
- int/*VariableQualifier*/ qual;
-
- void/*GSList*/ *slist;
-
-}
-
-%parse-param { GItaniumDContext *context }
-%parse-param { GBinRoutine *routine }
-
-
-
-%token ITANIUM_SIGNATURE
-
-%token EE NN II FF LL
-
-%token C1 C2 C3 D1 D2 D3
-
-%token V W B C A H S T I J L M X Y N O F D E G Z DD DE DF DH DI DS U
-
-%token TP TR TO TC TG
-
-%token QR QV QK
-
-%token ST SA SB SS SI SO SD
-
-
-%token OPER_NEW OPER_NEW_ARRAY OPER_DELETE OPER_DELETE_ARRAY OPER_PLUS_UNARY OPER_NEG_UNARY
-%token OPER_AND_UNARY OPER_DE_UNARY OPER_COMPL OPER_PLUS OPER_MINUS OPER_MUL OPER_DIV OPER_MOD
-%token OPER_AND OPER_OR OPER_EXCL_OR OPER_AS OPER_PLUS_EQ OPER_MINUS_EQ OPER_MUL_EQ OPER_DIV_EQ
-%token OPER_MOD_EQ OPER_AND_EQ OPER_OR_EQ OPER_EXCL_OR_EQ OPER_LEFT_SHIFT OPER_RIGHT_SHIFT
-%token OPER_LEFT_SHIFT_EQ OPER_RIGHT_SHIFT_EQ OPER_EQUAL OPER_NOT_EQ OPER_LESS OPER_GREATER
-%token OPER_LESS_EQ OPER_GREATER_EQ OPER_NOT OPER_AND_AND OPER_OR_OR OPER_PLUS_PLUS OPER_MINUS_MINUS
-%token OPER_COMMA OPER_PRIV_MEMB OPER_POINTER_TO OPER_CLASS OPER_INDEX
-
-%token SUBSTI_FIRST SUBSTI_N
-
-%token TPARAM_FIRST TPARAM_N
-
-%token NUMBER CHAR
-
-
-
-
-
-
-
-
-
-%token LPART MPART RPART
-
-
-%token POSITION POSITION_ABS IMAGE
-
-%token RECT
-
-%token O_BRACKET C_BRACKET
-
-%token PATH
-%token DEC_16
-
-%token TEXT
-
-
-%type <text> TEXT PATH
-
-%type <s16_val> DEC_16
-
-
-%type <str_or_type> name
-
-%type <text> unscoped_name
-
-%type <type> nested_name
-
-%type <templtype> unscoped_template_name
-
-%type <text> unqualified_name operator_name
-
-%type <text> registered_prefix
-
-%type <type> prefix
-
-%type <text> template_prefix source_name
-
-%type <type> registered_template_prefix
-
-%type <type> template_param template_template_param
-
-%type <type> function_type type
-
-%type <qual> qualifiers
-
-%type <simple> builtin_type
-
-%type <type> class_enum_type
-
-
-%type <slist> template_args template_arg_list
-%type <type> template_arg expr_primary
-
-%type <type> substitution
-
-
-%type <car> CHAR
-%type <val> NUMBER SUBSTI_N TPARAM_N
-
-%{
-
-/* De lexi.c... */
-/*int yylex(YYSTYPE *, YYLTYPE *);*/
-void yyrestart(FILE *);
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-extern YY_BUFFER_STATE yy_scan_string(const char *);
-extern void yy_delete_buffer(YY_BUFFER_STATE);
-
-
-/* Affiche un message d'erreur concernant l'analyse. */
-/*int yyerror(const YYLTYPE *, bool, char **, unsigned char *, char *);*/
-
-%}
-
-
-%%
-
-
-
-
-input:
- ITANIUM_SIGNATURE encoding
- ;
-
-encoding:
- name { $1.is_string ? g_binary_routine_set_name(routine, $1.str) : g_binary_routine_set_name_from_type(routine, $1.type); }
- bare_function_type { ; }
- ;
-
-
-
-
-name:
- nested_name { $$.type = $1; $$.is_string = false; }
- | unscoped_name { $$.str = $1; $$.is_string = true; }
- | unscoped_template_name template_args {
-
- if (G_IS_TEMPLATE_TYPE($1))
- {
- g_template_type_add_params($1, $2);
-
- $$.type = $1;
- $$.is_string = false;
-
- }
-
- else
- {
- char *tmp;
-
- tmp = g_data_type_to_string($1);
-
- $$.type = g_template_type_new(tmp, $2);
- $$.is_string = false;
-
- free(tmp);
- g_object_unref(G_OBJECT($1));
-
- }
-
- //g_template_type_add_params($1, $2);
- printf(" [name tmp:: %s]\n", g_data_type_to_string($$.type));
- }
- ;
-
-unscoped_name:
- unqualified_name { $$ = $1; }
- | ST unqualified_name { $$ = strprep($2, "std::"); }
- ;
-
-unscoped_template_name:
- unscoped_name { $$ = g_template_type_new($1, NULL); g_itanium_dcontext_add_item(context, $$); }
- | substitution { $$ = $1; }
- ;
-
-
-nested_name:
- NN registered_prefix unqualified_name EE {
- $$ = ($3 != NULL ? strmerge($2, "::", $3) : $2); printf("passage nested p+uq = '%s'\n", $$);
- $$ = g_class_enum_type_new(CET_UNKNOWN, $$); g_itanium_dcontext_add_item(context, $$);
- }
- | NN qualifiers registered_prefix unqualified_name EE {
- $$ = ($4 != NULL ? strmerge($3, "::", $4) : $3); printf("passage nested p+uq = '%s'\n", $$);
- $$ = g_class_enum_type_new(CET_UNKNOWN, $$); g_itanium_dcontext_add_item(context, $$);
- }
- | NN registered_template_prefix template_args EE { $$ = $2; g_template_type_add_params($2, $3); printf(" [nested tmp:: %s]\n", g_data_type_to_string($$)); }
- | NN qualifiers registered_template_prefix template_args EE { $$ = $3; g_template_type_add_params($3, $4); printf(" [nested tmp:: %s]\n", g_data_type_to_string($$)); }
- ;
-
-
-
-registered_prefix:
- prefix {
- if ($1 == NULL) $$ = NULL;
- else
- {
- g_itanium_dcontext_add_item(context, $1);
- $$ = g_data_type_to_string($1);
- }
- }
- | substitution {
- $$ = g_data_type_to_string($1);
- printf("prefix substi :: %s\n", g_data_type_to_string($1));
- }
- ;
-
-prefix:
- /* vide */ { $$ = NULL; }
- | registered_prefix unqualified_name { $$ = ($2 != NULL ? g_class_enum_type_new(CET_CLASS, strmerge($1, "::", $2)) : $1); printf("passage p+uq = '%s'\n", g_data_type_to_string($$)); }
- | registered_template_prefix template_args { $$ = $1; g_template_type_add_params($1, $2); printf("passage p_tmp = '%s'\n", g_data_type_to_string($$)); }
- ;
-
-registered_template_prefix:
- template_prefix { $$ = g_template_type_new($1, NULL); /*g_itanium_dcontext_add_item(context, $$);*/ }
- ;
-
-template_prefix:
- registered_prefix unqualified_name {
- if ($1 != NULL) printf("$1 == '%s'\n", $1);
- //if ($1 != NULL) if (strcmp($1, "std") != 0) g_itanium_dcontext_add_item(context, g_class_enum_type_new(CET_CLASS, $1));
- $$ = ($2 != NULL ? strmerge($1, "::", $2) : $1);
- printf("$$ == '%s'\n", $$);
- g_itanium_dcontext_add_item(context, g_class_enum_type_new(CET_CLASS, $$));
- }
- | template_param {
- $$ = g_data_type_to_string($1);
- printf("[[ tmp param %s ]]\n", $$);
- g_object_unref(G_OBJECT($1));
- }
- | substitution {
- $$ = g_data_type_to_string($1);
- printf("template_prefix substi :: %s\n", $$);
- g_object_unref(G_OBJECT($1));
- }
- ;
-
-
-
-
-
-unqualified_name:
- operator_name { printf("dup :: '%s'\n", $1); fflush(NULL) ;$$ = strdup($1) ; }
- | ctor_dtor_name { printf("passage C\n"); $$ = NULL; }
- | source_name { $$ = $1; }
- ;
-
-
-
-source_name:
- NUMBER { set_itanium_text_length($1); g_itanium_dcontext_reset_identifier(context); }
- identifier { $$ = strdup(context->identifier); printf("==source name== :: %s\n", $$); }
- ;
-
-identifier:
- identifier CHAR { g_itanium_dcontext_build_identifier(context, $2); }
- | CHAR { g_itanium_dcontext_build_identifier(context, $1); }
- ;
-
-operator_name:
- OPER_NEW { $$ = "new"; }
- | OPER_NEW_ARRAY { $$ = "new[]"; }
- | OPER_DELETE { $$ = "delete"; }
- | OPER_DELETE_ARRAY { $$ = "delete[]"; }
- | OPER_PLUS_UNARY { $$ = "+"; }
- | OPER_NEG_UNARY { $$ = "-"; }
- | OPER_AND_UNARY { $$ = "&"; }
- | OPER_DE_UNARY { $$ = "*"; }
- | OPER_COMPL { $$ = "~"; }
- | OPER_PLUS { $$ = "+"; }
- | OPER_MINUS { $$ = "-"; }
- | OPER_MUL { $$ = "*"; }
- | OPER_DIV { $$ = "/"; }
- | OPER_MOD { $$ = "%"; }
- | OPER_AND { $$ = "&"; }
- | OPER_OR { $$ = "|"; }
- | OPER_EXCL_OR { $$ = "^"; }
- | OPER_AS { $$ = "="; }
- | OPER_PLUS_EQ { $$ = "+="; }
- | OPER_MINUS_EQ { $$ = "-="; }
- | OPER_MUL_EQ { $$ = "*="; }
- | OPER_DIV_EQ { $$ = "/="; }
- | OPER_MOD_EQ { $$ = "%)"; }
- | OPER_AND_EQ { $$ = "&="; }
- | OPER_OR_EQ { $$ = "|="; }
- | OPER_EXCL_OR_EQ { $$ = "^="; }
- | OPER_LEFT_SHIFT { $$ = "<<"; }
- | OPER_RIGHT_SHIFT { $$ = ">>"; }
- | OPER_LEFT_SHIFT_EQ { $$ = "<<="; }
- | OPER_RIGHT_SHIFT_EQ { $$ = ">>="; }
- | OPER_EQUAL { $$ = "=="; }
- | OPER_NOT_EQ { $$ = "!="; }
- | OPER_LESS { $$ = "<"; }
- | OPER_GREATER { $$ = ">"; }
- | OPER_LESS_EQ { $$ = "<="; }
- | OPER_GREATER_EQ { $$ = ">="; }
- | OPER_NOT { $$ = "!"; }
- | OPER_AND_AND { $$ = "&&"; }
- | OPER_OR_OR { $$ = "||"; }
- | OPER_PLUS_PLUS { $$ = "++"; }
- | OPER_MINUS_MINUS { $$ = "--"; }
- | OPER_COMMA { $$ = ","; }
- | OPER_PRIV_MEMB { $$ = "->*"; }
- | OPER_POINTER_TO { $$ = "->"; }
- | OPER_CLASS { $$ = "()"; }
- | OPER_INDEX { $$ = "[]"; }
- ;
-
-
-
-
-
-
-ctor_dtor_name:
- C1 { g_binary_routine_set_type(routine, RTT_CONSTRUCTOR); }
- | C2 { g_binary_routine_set_type(routine, RTT_CONSTRUCTOR); }
- | C3 { g_binary_routine_set_type(routine, RTT_CONSTRUCTOR); }
- | D1 { g_binary_routine_set_type(routine, RTT_DESTRUCTOR); }
- | D2 { g_binary_routine_set_type(routine, RTT_DESTRUCTOR); }
- | D3 { g_binary_routine_set_type(routine, RTT_DESTRUCTOR); }
- ;
-
-
-function_type:
- FF {
- routine = g_itanium_dcontext_push_routine(context, routine);
- context->start_args = true;
- g_itanium_dcontext_update(context);
- }
- bare_function_type EE {
- $$ = g_encapsulated_type_new(ECT_ROUTINE, routine);
- routine = g_itanium_dcontext_pop_routine(context);
- if (routine == NULL) YYERROR;
- }
- ;
-
-
-type:
- builtin_type { $$ = $1; printf("builtin '%s'\n", g_data_type_to_string($1)); }
- | class_enum_type { $$ = $1; printf("type :: %p\n", $1); fflush(NULL); g_itanium_dcontext_add_item(context, $1); }
- | substitution { $$ = $1; }
- | template_param { $$ = $1; }
- | template_template_param template_args {
- $$ = g_template_type_new(g_data_type_to_string($1), NULL);
- g_object_unref($1);
- g_template_type_add_params($$, $2);
- printf(" [type tmp:: %s]\n", g_data_type_to_string($$));
- }
- | function_type { $$ = $1; }
- | qualifiers type {
- $$ = g_data_type_dup($2);
- g_data_type_add_qualifier($$, $1);
- g_itanium_dcontext_add_item(context, $$);
- }
- | TP type { $$ = g_encapsulated_type_new(ECT_POINTER, $2); g_itanium_dcontext_add_item(context, $$); }
- | TR type { $$ = g_encapsulated_type_new(ECT_REFERENCE, $2); g_itanium_dcontext_add_item(context, $$); }
- | TO type { $$ = g_encapsulated_type_new(ECT_RVALUE_REF, $2); g_itanium_dcontext_add_item(context, $$); }
- | TC type { $$ = g_encapsulated_type_new(ECT_COMPLEX, $2); g_itanium_dcontext_add_item(context, $$); }
- | TG type { $$ = g_encapsulated_type_new(ECT_IMAGINARY, $2); g_itanium_dcontext_add_item(context, $$); }
- ;
-
-qualifiers:
- QR { $$ = TQF_RESTRICT; }
- | QV { $$ = TQF_VOLATILE; }
- | QK { $$ = TQF_CONST; }
- ;
-
-
-
-builtin_type:
- V { $$ = g_basic_type_new(BTP_VOID); }
- | W { $$ = g_basic_type_new(BTP_WCHAR_T); }
- | B { $$ = g_basic_type_new(BTP_BOOL); }
- | C { $$ = g_basic_type_new(BTP_CHAR); }
- | A { $$ = g_basic_type_new(BTP_SCHAR); }
- | H { $$ = g_basic_type_new(BTP_UCHAR); }
- | S { $$ = g_basic_type_new(BTP_SHORT); }
- | T { $$ = g_basic_type_new(BTP_USHORT); }
- | I { $$ = g_basic_type_new(BTP_INT); }
- | J { $$ = g_basic_type_new(BTP_UINT); }
- | L { $$ = g_basic_type_new(BTP_LONG); }
- | M { $$ = g_basic_type_new(BTP_ULONG); }
- | X { $$ = g_basic_type_new(BTP_LONG_LONG); }
- | Y { $$ = g_basic_type_new(BTP_ULONG_LONG); }
- | N { $$ = g_basic_type_new(BTP_INT128); }
- | O { $$ = g_basic_type_new(BTP_UINT128); }
- | F { $$ = g_basic_type_new(BTP_FLOAT); }
- | D { $$ = g_basic_type_new(BTP_DOUBLE); }
- | E { $$ = g_basic_type_new(BTP_LONG_DOUBLE); }
- | G { $$ = g_basic_type_new(BTP_FLOAT128); }
- | Z { $$ = g_basic_type_new(BTP_ELLIPSIS); }
- | DD { $$ = g_basic_type_new(BTP_754R_64); }
- | DE { $$ = g_basic_type_new(BTP_754R_128); }
- | DF { $$ = g_basic_type_new(BTP_754R_32); }
- | DH { $$ = g_basic_type_new(BTP_754R_16); }
- | DI { $$ = g_basic_type_new(BTP_CHAR32_T); }
- | DS { $$ = g_basic_type_new(BTP_CHAR16_T); }
- | U source_name { $$ = g_basic_type_new(BTP_OTHER); /* TODO */ ; free($2); }
- ;
-
-
-
-bare_function_type:
- bare_function_type type { g_binary_routine_add_arg(routine, g_binary_variable_new($2))/*TODO unref*/; }
- | type { g_binary_routine_add_arg(routine, g_binary_variable_new($1))/*TODO unref*/; }
- ;
-
-class_enum_type:
- name { printf("is str ?? %d (%p)\n", $1.is_string, $1.type); fflush(NULL); $$ = $1.is_string ? g_class_enum_type_new(CET_UNKNOWN, $1.str) : $1.type; }
- ;
-
-
-
-
-template_param:
- TPARAM_FIRST {
- const GDataType *type = g_binary_routine_get_type_from_name(routine);
- if (G_IS_TEMPLATE_TYPE(type))
- $$ = g_template_type_get_param(G_TEMPLATE_TYPE(type), 0);
- else $$ = NULL;
- if ($$ == NULL) YYERROR; if (!G_IS_BASIC_TYPE($$)) g_itanium_dcontext_add_item(context, $$);
- }
- | TPARAM_N {
- const GDataType *type = g_binary_routine_get_type_from_name(routine);
- if (G_IS_TEMPLATE_TYPE(type))
- $$ = g_template_type_get_param(G_TEMPLATE_TYPE(type), $1 + 1);
- else $$ = NULL;
- if ($$ == NULL) YYERROR; if (!G_IS_BASIC_TYPE($$)) g_itanium_dcontext_add_item(context, $$);
- }
- ;
-
-template_template_param:
- template_param { $$ = $1; }
- | substitution { $$ = $1; }
- ;
-
-template_args:
- use_templates template_arg_list EE { $$ = $2;
- context->template_level--;
- g_itanium_dcontext_update(context);
- }
- ;
-
-use_templates:
- II { printf("new template !!!\n"); /* FIXME : régle désormais inutile ! -> remme */
- context->template_level++;
- g_itanium_dcontext_update(context);
- }
- ;
-
-template_arg_list:
- template_arg_list template_arg { $$ = g_slist_prepend($1, $2); }
- | template_arg { $$ = g_slist_prepend(NULL, $1); }
- | template_args { g_class_enum_type_new(CET_UNKNOWN, "template params"); printf("??? tmp list\n"); }
- ;
-
-template_arg:
- type { $$ = $1; }
- | expr_primary { $$ = $1; }
- ;
-
-
-expr_primary:
- LL type NUMBER EE { $$ = $2; }
- ;
-
-
-substitution:
- ST { $$ = g_class_enum_type_new(CET_CLASS, "std"); }
- | SA { $$ = g_class_enum_type_new(CET_CLASS, "std::allocator"); }
- | SB { $$ = g_class_enum_type_new(CET_CLASS, "std::basic_string"); }
- | SS { $$ = g_class_enum_type_new(CET_CLASS, "std::string"); }
- | SI { $$ = g_class_enum_type_new(CET_CLASS, "std::istream"); }
- | SO { $$ = g_class_enum_type_new(CET_CLASS, "std::ostream"); }
- | SD { $$ = g_class_enum_type_new(CET_CLASS, "std::iostream"); }
- | SUBSTI_FIRST { $$ = g_itanium_dcontext_get_item(context, 0); if ($$ == NULL) YYERROR; }
- | SUBSTI_N { $$ = g_itanium_dcontext_get_item(context, $1 + 1); if ($$ == NULL) YYERROR; }
- ;
-
-
-
-
-
-
-
-%%
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* CONTEXTE POUR LE DECODAGE TYPE ITANIUM */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour un contexte de décodage. */
-G_DEFINE_TYPE(GItaniumDContext, g_itanium_dcontext, G_TYPE_DEMANGLING_CONTEXT);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des contextes de décodage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_itanium_dcontext_class_init(GItaniumDContextClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = g_itanium_dcontext_dispose;
- object->finalize = g_itanium_dcontext_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = instance à initialiser. *
-* *
-* Description : Initialise une instance de contexte pour décodage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_itanium_dcontext_init(GItaniumDContext *context)
-{
- context->substitutions = g_slist_alloc();
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_itanium_dcontext_dispose(GItaniumDContext *context)
-{
- gpointer data; /* Type à détacher */
- GBinRoutine *routine; /* Routine à détacher */
- gpointer obj_class; /* Classe parente */
-
- while ((data = g_slist_nth_data(context->substitutions, 0)) != NULL)
- {
- g_object_unref(G_OBJECT(data));
- context->substitutions = g_slist_remove(context->substitutions, data);
- }
-
- while ((routine = g_itanium_dcontext_pop_routine(context)) != NULL)
- g_object_unref(G_OBJECT(routine));
-
- obj_class = g_type_class_peek_parent(G_ITANIUM_DCONTEXT_GET_CLASS(context));
-
- G_OBJECT_CLASS(obj_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_dcontext_finalize(GItaniumDContext *context)
-{
- gpointer obj_class; /* Classe parente */
-
- if (context->identifier != NULL)
- free(context->identifier);
-
- obj_class = g_type_class_peek_parent(G_ITANIUM_DCONTEXT_GET_CLASS(context));
-
- G_OBJECT_CLASS(obj_class)->finalize(G_OBJECT(context));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Prépare de quoi effectuer un décodage Itanium. *
-* *
-* Retour : Instance du contexte mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GDemanglingContext *g_itanium_dcontext_new(void)
-{
- GDemanglingContext *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_ITANIUM_DCONTEXT, NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = décodeur à mettre à jour. *
-* *
-* Description : Réinitialise le constructeur d'identifiants. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_itanium_dcontext_reset_identifier(GItaniumDContext *context)
-{
- context->id_used = 0;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = décodeur à mettre à jour. *
-* value = caractère d'identifiant à mémoriser. *
-* *
-* Description : Construit à la volée un identifiant. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_itanium_dcontext_build_identifier(GItaniumDContext *context, char value)
-{
- if ((context->id_used + 2) > context->id_allocated)
- {
- context->id_allocated += ITANIUM_ALLOC_CLUSTER;
- context->identifier = (char *)realloc(context->identifier,
- context->id_allocated * sizeof(char));
- }
-
- context->identifier[context->id_used++] = value;
- context->identifier[context->id_used] = 0;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = décodeur à mettre à jour. *
-* previous = routine à sauvegarder. *
-* *
-* Description : Place sous le feu des projecteurs une nouvelle routine. *
-* *
-* Retour : Nouvelle routine à compléter. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GBinRoutine *g_itanium_dcontext_push_routine(GItaniumDContext *context, GBinRoutine *previous)
-{
- GBinRoutine *result; /* Routine nouvelle à renvoyer */
-
- result = g_binary_routine_new();
-
- context->routines = g_slist_append(context->routines, previous);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = décodeur à mettre à jour. *
-* *
-* Description : Remet une ancienne routine sous le feu des projecteurs. *
-* *
-* Retour : Routine sauvegardée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GBinRoutine *g_itanium_dcontext_pop_routine(GItaniumDContext *context)
-{
- GBinRoutine *result; /* Routine nouvelle à renvoyer */
- GSList *last; /* Dernier élément */
-
- last = g_slist_last(context->routines);
-
- if (last == NULL) result = NULL;
- else
- {
- result = G_BIN_ROUTINE(last->data);
- context->routines = g_slist_remove(context->routines, result);
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = décodeur à mettre à jour. *
-* type = élément à placer dans la liste des substitutions. *
-* *
-* Description : Ajoute un élément dans une liste de substitutions. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_itanium_dcontext_add_item(GItaniumDContext *context, GDataType *type)
-{
- g_object_ref(G_OBJECT(type));
-
- printf(" [[ %u ]] PUSH '%s' (%p)\n", g_slist_length(context->substitutions) - 1, g_data_type_to_string(type), type);
-
- context->substitutions = g_slist_append(context->substitutions, type);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = décodeur à consulter. *
-* n = indice de l'élément à fournir. *
-* *
-* Description : Fournit le nième élément d'une liste de substitutions. *
-* *
-* Retour : Type prêt à emploi. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GDataType *g_itanium_dcontext_get_item(GItaniumDContext *context, guint n)
-{
- printf("get [%u] == %p\n", n, g_slist_nth_data(context->substitutions, n + 1));
-
- return G_DATA_TYPE(g_slist_nth_data(context->substitutions, n + 1));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = décodeur à consulter. *
-* *
-* Description : Autorise ou non le dépilement des opérateurs. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_itanium_dcontext_update(GItaniumDContext *context)
-{
- if (context->start_args || context->template_level > 0)
- exclude_itanium_operators();
-
- else allow_itanium_operators();
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* TRAITEMENT DE L'ENCODAGE ITANIUM */
-/* ---------------------------------------------------------------------------------- */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**
- * Affiche un message d'erreur concernant l'analyse.
- * @param yyloc informations concernant les coordonnées du soucis.
- * @param hunt indique le type de passe réalisée.
- * @param ucode code résultant compilé.
- * @param index indice de commande à mettre à jour.
- * @param msg indications humaines sur l'événement.
- * @return 0.
- */
-int yyerror(/*const YYLTYPE *yyloc, bool hunt, char **ucode, unsigned char *index, */char *msg)
-{
-
-
-
- fprintf(stderr, "ERREUR !\n");
- fprintf(stderr, "%s\n", msg);
-
- return -1;
-
-}
-
-
-
-
-
-
-
-
-/******************************************************************************
-* *
-* Paramètres : desc = chaîne de caractères à décoder. *
-* *
-* Description : Indique si une chaîne peut être traitée par le décodeur. *
-* *
-* Retour : Bilan de l'analyse. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool can_be_itanium_demangled(const char *desc)
-{
- return (strncmp(desc, "_Z", 2) == 0);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = contexte de décodage à utiliser. *
-* desc = chaîne de caractères à décoder. *
-* *
-* Description : Procède au décodage d'une chaîne de caractères. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool demangle_itanium_routine(GItaniumDContext *context, const char *desc)
-{
- GBinRoutine *routine; /* Routine à construire */
- YY_BUFFER_STATE buffer; /* Tampon pour bison */
- int ret; /* Bilan de l'appel */
- GDataType *name_type; /* Nom basé sur un type ? */
-
- routine = g_demangling_context_get_decoded_routine(G_DEMANGLING_CONTEXT(context));
-
- allow_itanium_operators();
-
- buffer = yy_scan_string(desc);
- ret = yyparse(context, routine);
- yy_delete_buffer(buffer);
-
- if (ret == 0)
- {
- name_type = g_binary_routine_get_type_from_name(routine);
-
- if (name_type != NULL && G_IS_TEMPLATE_TYPE(name_type))
- compute_routine_itanium_ret_type(routine);
-
- }
-
- return (ret == 0);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : routine = routine à traiter si ce n'est pas déjà fait. *
-* *
-* Description : Fait sauter le premier argument en faveur du type de retour. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void compute_routine_itanium_ret_type(GBinRoutine *routine)
-{
- size_t count; /* Nombre d'arguments présents */
- size_t i; /* Boucle de parcours */
- GBinVariable *arg; /* Argument de la routine */
- GDataType *type; /* Type associé à l'argument */
-
- /* Traitement récursif des arguments */
-
- type = g_binary_routine_get_type_from_name(routine);
-
- if (type != NULL)
- {
- update_itanium_ret_type(type);
-
- /* On force une actualisation au cas où... */
- g_binary_routine_set_name(routine, NULL);
-
- }
-
- count = g_binary_routine_get_args_count(routine);
- if (count == 0) return;
-
- for (i = 0; i < count; i++)
- {
- arg = g_binary_routine_get_arg(routine, i);
- type = g_binary_variable_get_vtype(arg);
-
- update_itanium_ret_type(type);
-
- }
-
- /* Basculement du premier argument */
-
- /**
- * Avec les références de type partagées, il
- * se peut que la fonction soit déjà traitée.
- */
- if (g_binary_routine_get_return_type(routine) != NULL)
- return;
-
- arg = g_binary_routine_get_arg(routine, 0);
-
- type = g_binary_variable_get_vtype(arg);
- g_object_ref(G_OBJECT(type));
-
- g_binary_routine_remove_arg(routine, 0);
-
- g_binary_routine_set_return_type(routine, type);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : type = type à traiter si ce n'est pas déjà fait. *
-* *
-* Description : Recherche et fait sauter les premiers arguments rencontrés. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void update_itanium_ret_type(GDataType *type)
-{
- GTemplateType *template; /* Gabarit à analyser */
- size_t max; /* Nombre d'itérations */
- size_t i; /* Boucle de parcours */
- GDataType *subtype; /* Type à traiter */
- GEncapsulatedType *encaps; /* Encapsulation quelconque */
- GBinRoutine *routine; /* Routine à traiter */
-
- /* Gabarits */
- if (G_IS_TEMPLATE_TYPE(type))
- {
- template = G_TEMPLATE_TYPE(type);
- max = g_template_type_count_param(template);
-
- for (i = 0; i < max; i++)
- {
- subtype = g_template_type_get_param(template, i);
- update_itanium_ret_type(subtype);
- }
-
- }
-
- /* Encapsulations */
- else if (G_IS_ENCAPSULATED_TYPE(type))
- {
- encaps = G_ENCAPSULATED_TYPE(type);
-
- switch (g_encapsulated_type_get_etype(encaps))
- {
- case ECT_ROUTINE:
- g_encapsulated_type_get_item(encaps, &routine);
- compute_routine_itanium_ret_type(routine);
- break;
-
- default:
- g_encapsulated_type_get_item(encaps, &subtype);
- update_itanium_ret_type(subtype);
- break;
-
- }
-
- }
-
-}
diff --git a/src/format/mangling/itanium_tok.l b/src/format/mangling/itanium_tok.l
deleted file mode 100644
index 3c74410..0000000
--- a/src/format/mangling/itanium_tok.l
+++ /dev/null
@@ -1,232 +0,0 @@
-
-%{
-
-#include "itanium_gram.h"
-
-
-static unsigned int itanium_txt_length = 0;
-
-
-/* Borne la longueur d'une chaîne à lire. */
-void set_itanium_text_length(unsigned int);
-
-/* Autorise la lecture des opérateurs. */
-void allow_itanium_operators(void);
-
-/* Autorise la lecture des opérateurs. */
-void exclude_itanium_operators(void);
-
-
-
-%}
-
-
-%option noyywrap
-%option stack
-%option yylineno
-
-
-%x identifier
-%x operators
-
-
-%%
-
-
-<INITIAL,operators>{
-
-_Z { return ITANIUM_SIGNATURE; }
-
-E { return EE; }
-N { return NN; }
-I { return II; }
-F { return FF; }
-L { return LL; }
-
-C1 { return C1; }
-C2 { return C2; }
-C3 { return C3; }
-D0 { return C1; }
-D1 { return D2; }
-D2 { return D3; }
-
-v { return V; }
-w { return W; }
-b { return B; }
-c { return C; }
-a { return A; }
-h { return H; }
-s { return S; }
-t { return T; }
-i { return I; }
-j { return J; }
-l { return L; }
-m { return M; }
-x { return X; }
-y { return Y; }
-n { return N; }
-o { return O; }
-f { return F; }
-d { return D; }
-e { return E; }
-g { return G; }
-z { return Z; }
-Dd { return DD; }
-De { return DE; }
-Df { return DF; }
-Dh { return DH; }
-Di { return DI; }
-Ds { return DS; }
-u { return U; }
-
-P { return TP; }
-R { return TR; }
-O { return TO; }
-C { return TC; }
-G { return TG; }
-
-r { return QR; }
-V { return QV; }
-K { return QK; }
-
-St { return ST; }
-Sa { return SA; }
-Sb { return SB; }
-Ss { return SS; }
-Si { return SI; }
-So { return SO; }
-Sd { return SD; }
-
-} /* INITIAL,operators> */
-
-<operators>{
-
-nw { return OPER_NEW; }
-na { return OPER_NEW_ARRAY; }
-dl { return OPER_DELETE; }
-da { return OPER_DELETE_ARRAY; }
-ps { return OPER_PLUS_UNARY; }
-ng { return OPER_NEG_UNARY; }
-ad { return OPER_AND_UNARY; }
-de { return OPER_DE_UNARY; }
-co { return OPER_COMPL; }
-pl { return OPER_PLUS; }
-mi { return OPER_MINUS; }
-ml { return OPER_MUL; }
-dv { return OPER_DIV; }
-rm { return OPER_MOD; }
-an { return OPER_AND; }
-or { return OPER_OR; }
-eo { return OPER_EXCL_OR; }
-aS { return OPER_AS; }
-pL { return OPER_PLUS_EQ; }
-mI { return OPER_MINUS_EQ; }
-mL { return OPER_MUL_EQ; }
-dV { return OPER_DIV_EQ; }
-rM { return OPER_MOD_EQ; }
-aN { return OPER_AND_EQ; }
-oR { return OPER_OR_EQ; }
-eO { return OPER_EXCL_OR_EQ; }
-ls { return OPER_LEFT_SHIFT; }
-rs { return OPER_RIGHT_SHIFT; }
-lS { return OPER_LEFT_SHIFT_EQ; }
-rS { return OPER_RIGHT_SHIFT_EQ; }
-eq { return OPER_EQUAL; }
-ne { return OPER_NOT_EQ; }
-lt { return OPER_LESS; }
-gt { return OPER_GREATER; }
-le { return OPER_LESS_EQ; }
-ge { return OPER_GREATER_EQ; }
-nt { return OPER_NOT; }
-aa { return OPER_AND_AND; }
-oo { return OPER_OR_OR; }
-pp { return OPER_PLUS_PLUS; }
-mm { return OPER_MINUS_MINUS; }
-cm { return OPER_COMMA; }
-pm { return OPER_PRIV_MEMB; }
-pt { return OPER_POINTER_TO; }
-cl { return OPER_CLASS; }
-ix { return OPER_INDEX; }
-
-} /* operators */
-
-<INITIAL,operators>{
-
-S_ { return SUBSTI_FIRST; }
-S[0-9a-z]_ { yylval.val = atoi(yytext + 1); return SUBSTI_N; }
-
-T_ { return TPARAM_FIRST; }
-T[0-9]*_ { yylval.val = atoi(yytext + 1); return TPARAM_N; }
-
-
-
-[0-9]+ { yylval.val = atoi(yytext); return NUMBER; }
-
-} /* <INITIAL,operators> */
-
-<identifier>. { if (--itanium_txt_length == 0) yy_pop_state(); yylval.car = *yytext; return CHAR; }
-
-<INITIAL,operators>[ ]
-
-<*>. { printf("error : '%s'\n", yytext); }
-
-%%
-
-
-/******************************************************************************
-* *
-* Paramètres : length = taille de chaîne à lire. *
-* *
-* Description : Borne la longueur d'une chaîne à lire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void set_itanium_text_length(unsigned int length)
-{
- itanium_txt_length = length;
-
- yy_push_state(identifier);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Autorise la lecture des opérateurs. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void allow_itanium_operators(void)
-{
- BEGIN(operators);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Autorise la lecture des opérateurs. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void exclude_itanium_operators(void)
-{
- BEGIN(INITIAL);
-
-}
diff --git a/src/main.c b/src/main.c
index ef89cb7..18637ff 100644
--- a/src/main.c
+++ b/src/main.c
@@ -42,7 +42,7 @@
#include "../revision.h"
-#include "format/mangling/demangler.h"
+#include "format/mangling/itanium/abi.h"
/* params.c : configuration générale */
@@ -141,7 +141,7 @@ int main(int argc, char **argv)
/* Création de l'interface */
- //test_itanium_demangling();
+ //test_itanium();
//exit(-1);
editor = create_editor();