summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-07-02 22:46:14 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-07-02 22:46:14 (GMT)
commit8dc83465a6ca2d5b94b983b39f6c06d37e4126a0 (patch)
treeb5594fe7cd0d9e9a9269eaa3454412da2bd9dd5a
parentde2cb8e2fad4a3031d7b7c2cb189a6dbdaf8d5a9 (diff)
Improved the Itanium C++ demangling.
-rw-r--r--configure.ac3
-rw-r--r--plugins/Makefile.am2
-rw-r--r--plugins/dexbnf/context.c6
-rw-r--r--plugins/dexbnf/demangler.c2
-rw-r--r--plugins/dexbnf/python/demangler.c2
-rw-r--r--plugins/dexbnf/python/demangler.h2
-rw-r--r--plugins/itanium/Makefile.am32
-rw-r--r--plugins/itanium/abi.c (renamed from src/mangling/itanium/abi.c)2098
-rw-r--r--plugins/itanium/abi.h (renamed from src/mangling/itanium/abi.h)8
-rw-r--r--plugins/itanium/component-int.h137
-rw-r--r--plugins/itanium/component.c1842
-rw-r--r--plugins/itanium/component.h (renamed from src/mangling/itanium/component.h)135
-rw-r--r--plugins/itanium/context.c (renamed from src/mangling/itanium/context.c)463
-rw-r--r--plugins/itanium/context.h83
-rw-r--r--plugins/itanium/core.c64
-rw-r--r--plugins/itanium/core.h38
-rw-r--r--plugins/itanium/demangler.c174
-rw-r--r--plugins/itanium/demangler.h58
-rw-r--r--plugins/itanium/python/Makefile.am19
-rw-r--r--plugins/itanium/python/demangler.c145
-rw-r--r--plugins/itanium/python/demangler.h42
-rw-r--r--plugins/itanium/python/module.c61
-rw-r--r--plugins/itanium/python/module.h38
-rw-r--r--src/common/ibuf.c213
-rw-r--r--src/common/ibuf.h22
-rw-r--r--src/mangling/Makefile.am5
-rw-r--r--src/mangling/itanium/Makefile.am24
-rw-r--r--src/mangling/itanium/component-int.h79
-rw-r--r--src/mangling/itanium/component.c717
-rw-r--r--src/mangling/itanium/context.h118
-rw-r--r--tests/mangling/itanium.py111
-rw-r--r--tools/afl/Makefile13
-rwxr-xr-xtools/afl/demangler.sh27
-rw-r--r--tools/afl/itanium.c69
34 files changed, 5011 insertions, 1841 deletions
diff --git a/configure.ac b/configure.ac
index 400818b..fb16dcc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -353,6 +353,8 @@ AC_CONFIG_FILES([Makefile
plugins/elf/Makefile
plugins/elf/python/Makefile
plugins/fmtp/Makefile
+ plugins/itanium/Makefile
+ plugins/itanium/python/Makefile
plugins/libcsem/Makefile
plugins/lnxsyscalls/Makefile
plugins/mobicore/Makefile
@@ -414,7 +416,6 @@ AC_CONFIG_FILES([Makefile
src/gui/panels/Makefile
src/gui/tb/Makefile
src/mangling/Makefile
- src/mangling/itanium/Makefile
src/plugins/Makefile
tools/Makefile
tools/d2c/Makefile
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 257e0d5..6b0c295 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -4,4 +4,4 @@ if HAVE_PYTHON3_CONFIG
endif
# androhelpers
-SUBDIRS = $(PYTHON3_SUBDIRS) arm dex dalvik devdbg dexbnf elf fmtp libcsem lnxsyscalls mobicore readdex readelf readmc ropgadgets
+SUBDIRS = $(PYTHON3_SUBDIRS) arm dex dalvik devdbg dexbnf elf fmtp itanium libcsem lnxsyscalls mobicore readdex readelf readmc ropgadgets
diff --git a/plugins/dexbnf/context.c b/plugins/dexbnf/context.c
index ebf7c0d..2daeb52 100644
--- a/plugins/dexbnf/context.c
+++ b/plugins/dexbnf/context.c
@@ -121,7 +121,7 @@ static void g_dex_demangling_init(GDexDemangling *context)
/******************************************************************************
* *
-* Paramètres : demangler = instance d'objet GLib à traiter. *
+* Paramètres : context = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -140,7 +140,7 @@ static void g_dex_demangling_dispose(GDexDemangling *context)
/******************************************************************************
* *
-* Paramètres : demangler = instance d'objet GLib à traiter. *
+* Paramètres : context = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -197,7 +197,7 @@ static GDataType *g_dex_demangling_decode_type(GDexDemangling *context)
static GBinRoutine *g_dex_demangling_decode_routine(GDexDemangling *context)
{
- GBinRoutine *result; /* Routine en place à retourner */
+ GBinRoutine *result; /* Routine en place à retourner*/
GDemanglingContext *base; /* Autre version du contexte */
base = G_DEMANGLING_CONTEXT(context);
diff --git a/plugins/dexbnf/demangler.c b/plugins/dexbnf/demangler.c
index 32aa36f..3489f15 100644
--- a/plugins/dexbnf/demangler.c
+++ b/plugins/dexbnf/demangler.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * demangler.c - décodage des noms d'éléments
+ * demangler.c - décodage des noms d'éléments Dex
*
* Copyright (C) 2018 Cyrille Bagard
*
diff --git a/plugins/dexbnf/python/demangler.c b/plugins/dexbnf/python/demangler.c
index f47eefe..e9dba41 100644
--- a/plugins/dexbnf/python/demangler.c
+++ b/plugins/dexbnf/python/demangler.c
@@ -129,7 +129,7 @@ PyTypeObject *get_python_dex_demangler_type(void)
bool register_python_dex_demangler(PyObject *module)
{
- PyTypeObject *py_dex_demangler_type; /* Type Python 'ElfFormat' */
+ PyTypeObject *py_dex_demangler_type; /* Type Python 'DexDemangler' */
PyObject *dict; /* Dictionnaire du module */
py_dex_demangler_type = get_python_dex_demangler_type();
diff --git a/plugins/dexbnf/python/demangler.h b/plugins/dexbnf/python/demangler.h
index af56289..f2cd964 100644
--- a/plugins/dexbnf/python/demangler.h
+++ b/plugins/dexbnf/python/demangler.h
@@ -34,7 +34,7 @@
/* Fournit un accès à une définition de type à diffuser. */
PyTypeObject *get_python_dex_demangler_type(void);
-/* Prend en charge l'objet 'pychrysalide.format.elf.ElfFormat'. */
+/* Prend en charge l'objet 'pychrysalide.format.mangling.DexDemangler'. */
bool register_python_dex_demangler(PyObject *);
diff --git a/plugins/itanium/Makefile.am b/plugins/itanium/Makefile.am
new file mode 100644
index 0000000..b4a9cb7
--- /dev/null
+++ b/plugins/itanium/Makefile.am
@@ -0,0 +1,32 @@
+
+lib_LTLIBRARIES = libitanium.la
+
+libdir = $(pluginsdir)
+
+libitanium_la_SOURCES = \
+ abi.h abi.c \
+ component-int.h \
+ component.h component.c \
+ context.h context.c \
+ core.h core.c \
+ demangler.h demangler.c
+
+libitanium_la_LIBADD = \
+ python/libitaniumpython.la
+
+libitanium_la_LDFLAGS = \
+ -L$(top_srcdir)/src/.libs -lchrysacore \
+ -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs \
+ -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libitanium_la_SOURCES:%c=)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS = python
diff --git a/src/mangling/itanium/abi.c b/plugins/itanium/abi.c
index 8d15ad4..5f76342 100644
--- a/src/mangling/itanium/abi.c
+++ b/plugins/itanium/abi.c
@@ -24,13 +24,15 @@
#include "abi.h"
+#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
-
-#include "../../analysis/types/basic.h"
-#include "../../common/cpp.h"
+#include <analysis/types/basic.h>
+#include <analysis/types/cse.h>
+#include <common/cpp.h>
+#include <mangling/context-int.h>
@@ -63,7 +65,7 @@ const itanium_operator_info itanium_demangle_operators[] = {
{ "eo", IDT_NL("^"), 2 },
{ "eq", IDT_NL("=="), 2 },
{ "ge", IDT_NL(">="), 2 },
- { "gs", IDT_NL("::"), 1 },
+ { "gs", IDT_NL("::"), 1 },
{ "gt", IDT_NL(">"), 2 },
{ "ix", IDT_NL("[]"), 2 },
{ "lS", IDT_NL("<<="), 2 },
@@ -98,9 +100,7 @@ const itanium_operator_info itanium_demangle_operators[] = {
{ "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 }
+ { "sz", IDT_NL("sizeof "), 1 }
};
/* Substitutions standards */
@@ -108,165 +108,140 @@ const itanium_operator_info itanium_demangle_operators[] = {
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 */
+ const char *class; /* Classe visée dans l'espace */
} 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")
- }
+ { 't', NULL },
+ { 'a', "allocator" },
+ { 'b', "basic_string" },
+ { 's', "string" },
+ { 'i', "istream" },
+ { 'o', "ostream" },
+ { 'd', "iostream" }
};
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_encoding(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_encoding(GItaniumDContext *);
+static itanium_component *itd_name(GItaniumDemangling *);
+
+/* Détermine si le composant suivant correspond à un type donné. */
+static bool is_itd_unscoped_name(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_name(GItaniumDContext *);
+static itanium_component *itd_unscoped_name(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_unscoped_name(GItaniumDContext *);
+static itanium_component *itd_unscoped_template_name(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_unscoped_template_name(GItaniumDContext *);
+static itanium_component *itd_nested_name(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_nested_name(GItaniumDContext *);
+static itanium_component *itd_prefix(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_prefix(GItaniumDContext *);
+static itanium_component *itd_prefix_rec(GItaniumDemangling *, itanium_component *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_template_prefix(GItaniumDContext *);
+static itanium_component *itd_template_prefix(GItaniumDemangling *);
+
+/* Détermine si le composant suivant correspond à un type donné. */
+static bool is_itd_unqualified_name(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_unqualified_name(GItaniumDContext *);
+static itanium_component *itd_unqualified_name(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_source_name(GItaniumDContext *);
+static itanium_component *itd_source_name(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static bool itd_number(GItaniumDContext *, ssize_t *);
+static bool itd_number(GItaniumDemangling *, ssize_t *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_identifier(GItaniumDContext *, size_t);
+static itanium_component *itd_identifier(GItaniumDemangling *, size_t);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_operator_name(GItaniumDContext *);
+static itanium_component *itd_operator_name(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_special_name(GItaniumDContext *);
+static itanium_component *itd_special_name(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_call_offset(GItaniumDContext *);
+static itanium_component *itd_call_offset(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_nv_offset(GItaniumDContext *);
+static itanium_component *itd_nv_offset(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_v_offset(GItaniumDContext *);
+static itanium_component *itd_v_offset(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_ctor_dtor_name(GItaniumDContext *);
+static itanium_component *itd_ctor_dtor_name(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_type(GItaniumDContext *);
+static itanium_component *itd_type(GItaniumDemangling *);
/* Extrait une propriété de composant pour un contexte Itanium. */
-static TypeQualifier itd_cv_qualifiers(GItaniumDContext *);
+static TypeQualifier itd_cv_qualifiers(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_builtin_type(GItaniumDContext *);
+static itanium_component *itd_builtin_type(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_bare_function_type(GItaniumDContext *);
+static itanium_component *itd_function_type(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_class_enum_type(GItaniumDContext *);
+static itanium_component *itd_bare_function_type(GItaniumDemangling *);
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_class_enum_type(GItaniumDemangling *);
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_array_type(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_template_args(GItaniumDContext *);
+static itanium_component *itd_pointer_to_member_type(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_template_arg(GItaniumDContext *);
+static itanium_component *itd_template_param(GItaniumDemangling *);
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_template_template_param(GItaniumDemangling *);
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_template_args(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_value_to_string(GItaniumDContext *, bool);
+static itanium_component *itd_template_arg(GItaniumDemangling *);
/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_expr_primary(GItaniumDContext *);
+static itanium_component *itd_expression(GItaniumDemangling *);
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_value_to_string(GItaniumDemangling *, bool);
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_expr_primary(GItaniumDemangling *);
-/* Extrait un composant dans un contexte Itanium. */
-static bool itd_seq_id(GItaniumDContext *, char, size_t *);
-/* Extrait un composant dans un contexte Itanium. */
-static itanium_component *itd_substitution(GItaniumDContext *);
+/* Extrait un composant dans un contexte Itanium. */
+static bool itd_seq_id(GItaniumDemangling *, char, size_t *);
+/* Extrait un composant dans un contexte Itanium. */
+static itanium_component *itd_substitution(GItaniumDemangling *);
-#define itd_template_param(ctx) NULL
#define itd_local_name(ctx) NULL
@@ -274,8 +249,6 @@ static itanium_component *itd_substitution(GItaniumDContext *);
-#define itd_expression(ctx) NULL
-
@@ -291,9 +264,10 @@ static itanium_component *itd_substitution(GItaniumDContext *);
* *
******************************************************************************/
-itanium_component *itd_mangled_name(GItaniumDContext *context)
+itanium_component *itd_mangled_name(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
/**
* La règle traitée ici est la suivante :
@@ -302,10 +276,12 @@ itanium_component *itd_mangled_name(GItaniumDContext *context)
*
*/
- if (!g_itanium_dcontext_check_char(context, '_'))
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, '_'))
return NULL;
- if (!g_itanium_dcontext_check_char(context, 'Z'))
+ if (!check_input_buffer_char(ibuf, 'Z'))
return NULL;
result = itd_encoding(context);
@@ -327,11 +303,11 @@ itanium_component *itd_mangled_name(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_encoding(GItaniumDContext *context)
+static itanium_component *itd_encoding(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
- itd_state saved; /* Position d'analyse courante */
- itanium_component *func; /* Composant 'function name' */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
itanium_component *types; /* Composant 'bare-function...'*/
/**
@@ -343,32 +319,35 @@ static itanium_component *itd_encoding(GItaniumDContext *context)
*
*/
- result = NULL;
- g_itanium_dcontext_push_state(context, &saved);
-
- func = itd_name(context);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
- if (func != NULL)
- {
- types = itd_bare_function_type(context);
+ peek = peek_input_buffer_char(ibuf);
- if (types != NULL)
- result = itd_make_binary(context, ICT_FUNCTION_ENCODING, func, types);
- else
- itd_unref_comp(func);
+ if (peek == 'T' || peek == 'G')
+ result = itd_special_name(context);
- }
- /*
- if (result == NULL)
+ else
{
- 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);
+
+ if (result != NULL)
+ {
+ types = itd_bare_function_type(context);
+
+ if (types != NULL)
+ result = itd_make_binary(ICT_FUNCTION_ENCODING, result, types);
+
+ /**
+ * Si le chargement des types échoue, il peut y avoir deux explications :
+ * - on ne chargeait qu'un simple nom.
+ * - il y a eu une erreur de décodage pour les types.
+ *
+ * Le tampon aura été vidé dans le premier cas uniquement,
+ * donc on laisse le contexte détecter une éventuelle erreur.
+ */
+
+ }
+
}
return result;
@@ -388,7 +367,7 @@ static itanium_component *itd_encoding(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_name(GItaniumDContext *context)
+static itanium_component *itd_name(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
itd_state saved; /* Position d'analyse courante */
@@ -405,13 +384,13 @@ static itanium_component *itd_name(GItaniumDContext *context)
*
*/
- g_itanium_dcontext_push_state(context, &saved);
+ g_itanium_demangling_push_state(context, &saved);
result = itd_nested_name(context);
if (result == NULL)
{
- g_itanium_dcontext_pop_state(context, &saved);
+ g_itanium_demangling_pop_state(context, &saved);
tname = itd_unscoped_template_name(context);
@@ -420,10 +399,7 @@ static itanium_component *itd_name(GItaniumDContext *context)
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);
- }
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, tname, targs);
else
itd_unref_comp(tname);
@@ -442,13 +418,13 @@ static itanium_component *itd_name(GItaniumDContext *context)
if (result == NULL)
{
- g_itanium_dcontext_pop_state(context, &saved);
+ g_itanium_demangling_pop_state(context, &saved);
result = itd_unscoped_name(context);
}
if (result == NULL)
{
- g_itanium_dcontext_pop_state(context, &saved);
+ g_itanium_demangling_pop_state(context, &saved);
result = itd_local_name(context);
}
@@ -461,6 +437,56 @@ static itanium_component *itd_name(GItaniumDContext *context)
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
+* Description : Détermine si le composant suivant correspond à un type donné.*
+* *
+* Retour : true si le décodage va à priori réussir, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool is_itd_unscoped_name(GItaniumDemangling *context)
+{
+ bool result; /* Bilan à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ char next_peek; /* Caractère après le prochain */
+
+ /**
+ * La règle anticipée ici est la suivante :
+ *
+ * <unscoped-name> ::= <unqualified-name>
+ * ::= St <unqualified-name> # ::std::
+ *
+ */
+
+ result = is_itd_unqualified_name(context);
+
+ if (!result)
+ {
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'S')
+ {
+ next_peek = peek_input_buffer_next_char(ibuf);
+
+ result = (next_peek == 't');
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
@@ -469,9 +495,12 @@ static itanium_component *itd_name(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_unscoped_name(GItaniumDContext *context)
+static itanium_component *itd_unscoped_name(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ char next_peek; /* Caractère après le prochain */
/**
* La règle traitée ici est la suivante :
@@ -482,11 +511,39 @@ static itanium_component *itd_unscoped_name(GItaniumDContext *context)
*/
- /* TODO : 'St' */
+ if (is_itd_unqualified_name(context))
+ result = itd_unqualified_name(context);
+
+ else
+ {
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+ peek = peek_input_buffer_char(ibuf);
- result = itd_unqualified_name(context);
+ if (peek == 'S')
+ {
+ next_peek = peek_input_buffer_next_char(ibuf);
+
+ if (next_peek == 't')
+ {
+ advance_input_buffer(ibuf, 2);
+
+ result = itd_unqualified_name(context);
+ if (result != NULL)
+ result = itd_make_unary(ICT_STD_UNSCOPED_NAME, result);
+
+ }
+
+ else
+ result = NULL;
+
+ }
+
+ else
+ result = NULL;
+
+ }
return result;
@@ -505,10 +562,11 @@ static itanium_component *itd_unscoped_name(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_unscoped_template_name(GItaniumDContext *context)
+static itanium_component *itd_unscoped_template_name(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
- itd_state saved; /* Position d'analyse courante */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
/**
* La règle traitée ici est la suivante :
@@ -518,14 +576,27 @@ static itanium_component *itd_unscoped_template_name(GItaniumDContext *context)
*
*/
- g_itanium_dcontext_push_state(context, &saved);
+ if (is_itd_unscoped_name(context))
+ {
+ result = itd_unscoped_name(context);
- result = itd_unscoped_name(context);
+ if (result != NULL)
+ g_itanium_demangling_add_substitution(context, result);
- if (result == NULL)
+ }
+
+ else
{
- g_itanium_dcontext_pop_state(context, &saved);
- result = itd_substitution(context);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'S')
+ result = itd_substitution(context);
+
+ else
+ result = NULL;
+
}
return result;
@@ -545,21 +616,15 @@ static itanium_component *itd_unscoped_template_name(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_nested_name(GItaniumDContext *context)
+static itanium_component *itd_nested_name(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
TypeQualifier qualifier; /* Propriétés supplémentaires */
itd_state saved; /* Position d'analyse courante */
itanium_component *left; /* Première partie */
itanium_component *right; /* Seconde partie */
- 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 :
*
@@ -568,96 +633,88 @@ static itanium_component *itd_nested_name(GItaniumDContext *context)
*
*/
- if (!g_itanium_dcontext_check_char(context, 'N'))
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, '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 }));
-
+ g_itanium_demangling_push_state(context, &saved);
+ /**
+ * Comme <prefix> <unqualified-name> peut aussi être <template-prefix>,
+ * on commence par traiter la seconde règle.
+ */
- left = itd_prefix(context);
+ left = itd_template_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);
+ 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);
+ if (check_input_buffer_char(ibuf, 'E'))
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, left, right);
- //result = itd_make_binary(context, ICT_NESTED_NAME, left, right);
+ else
+ {
+ if (left != NULL)
+ itd_unref_comp(left);
+ itd_unref_comp(right);
+ }
}
- else
- itd_unref_comp(left);
- printf(" ---- (%d) nested prefix --> %p\n\n", val, result);
+ else if (left != NULL)
+ itd_unref_comp(left);
}
-
if (result == NULL)
{
- printf("\n ----- (%d) nested template_arg '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
+ g_itanium_demangling_pop_state(context, &saved);
+
+ left = itd_prefix(context);
- g_itanium_dcontext_pop_state(context, &saved);
+ /**
+ * Quand son traitement est un succès, <prefix> doit toujours
+ * se terminer par <unqualified-name>.
+ */
- left = itd_template_prefix(context);
+ assert(left == NULL || (left != NULL && is_itd_unqualified_name(context)));
- if (left != NULL)
- {
- g_itanium_dcontext_add_substitution(context, left);
+ /**
+ * La règle <prefix> peut être vide, donc on se doit de tenter un
+ * <unqualified-name> dans tous les cas.
+ */
+
+ right = itd_unqualified_name(context);
- right = itd_template_args(context);
+ if (right != NULL)
+ {
+ if (check_input_buffer_char(ibuf, 'E'))
+ result = itd_make_binary(ICT_NESTED_NAME, left, right);
- if (right != NULL)
+ else
{
- 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);
+ if (left != NULL)
+ itd_unref_comp(left);
+ itd_unref_comp(right);
}
- 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);
+ else if (left != NULL)
+ itd_unref_comp(left);
- if (result != NULL)
- itd_unref_comp(result);
- return NULL;
}
- */
if (result != NULL)
- printf("=== (%d) NESTED OK (%p)\n\n", val, result);
-
- inner--;
+ itd_make_qualified_type(result, qualifier);
return result;
@@ -676,28 +733,17 @@ static itanium_component *itd_nested_name(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_prefix(GItaniumDContext *context)
+static itanium_component *itd_prefix(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
- itanium_component *looping_rule; /* Extraction d'une boucle */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ itanium_component *targs; /* Composant 'template-args' */
itd_state saved; /* Position d'analyse courante */
- itanium_component *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 */
-
-
+ itanium_component *further; /* Tentative de progression */
/**
- * Les deux règles traitées ici sont les suivantes :
+ * La règle traitée ici est la suivante :
*
* <prefix> ::= <prefix> <unqualified-name>
* ::= <template-prefix> <template-args>
@@ -705,6 +751,10 @@ static itanium_component *itd_prefix(GItaniumDContext *context)
* ::= # empty
* ::= <substitution>
*
+ * On note déjà la jolie petite boucle interne.
+ *
+ * Or on a également la règle voisine suivante :
+ *
* <template-prefix> ::= <prefix> <template unqualified-name>
* ::= <template-param>
* ::= <substitution>
@@ -714,202 +764,237 @@ static itanium_component *itd_prefix(GItaniumDContext *context)
*
* <prefix> ::= <prefix> <unqualified-name>
* ::= <prefix> <unqualified-name> <template-args>
+ * ::= <template-param>
* ::= <template-param> <template-args>
+ * ::= <substitution>
* ::= <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;
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
- while (1)
+ if (is_itd_unqualified_name(context))
+ result = itd_unqualified_name(context);
+
+ else
{
- printf("loop....\n");
+ peek = peek_input_buffer_char(ibuf);
- looping_rule = NULL;
+ if (peek == 'T')
+ result = itd_template_param(context);
- /**
- * Première partie.
- */
+ else if (peek == 'S')
+ result = itd_substitution(context);
- g_itanium_dcontext_push_state(context, &saved);
+ else
+ result = NULL;
- /* <template-param> <template-args> */
+ }
- left = itd_template_param(context);
+ if (result == NULL)
+ goto prefix_exit;
- if (left != NULL)
- {
- g_itanium_dcontext_add_substitution(context, left);
+ g_itanium_demangling_add_substitution(context, result);
- right = itd_template_args(context);
+ /**
+ * Détection et traitement de <template-args>.
+ */
- if (right != NULL)
- looping_rule = itd_make_binary(context, ICT_PREFIX_BINARY, left, right);
- else
- itd_unref_comp(left);
+ peek = peek_input_buffer_char(ibuf);
- }
+ if (peek == 'I')
+ {
+ /**
+ * Si la détection est avérée, on vient donc de traiter un cas <template-prefix>.
+ * On corrige donc le type au passage.
+ */
+ if (itd_get_component_type(result) == ICT_PREFIX_BINARY)
+ itd_set_type(result, ICT_TPREFIX_BINARY);
- /* <substitution> <template-args> */
+ targs = itd_template_args(context);
- if (looping_rule != NULL)
+ if (targs != NULL)
{
- g_itanium_dcontext_pop_state(context, &saved);
-
- left = itd_substitution(context);
-
- if (left != NULL)
- {
- right = itd_template_args(context);
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs);
- if (right != NULL)
- looping_rule = itd_make_binary(context, ICT_PREFIX_BINARY, left, right);
- else
- itd_unref_comp(left);
-
- }
+ g_itanium_demangling_add_substitution(context, result);
}
- /* <template-param> */
-
- if (looping_rule == NULL)
+ else
{
- g_itanium_dcontext_pop_state(context, &saved);
- looping_rule = itd_template_param(context);
+ itd_unref_comp(result);
+ result = NULL;
}
- /* <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 (result == NULL)
+ goto prefix_exit;
- if (looping_rule != NULL)
- {
- if (result == NULL)
- result = looping_rule;
- else
- result = itd_make_binary(context, ICT_PREFIX_BINARY, result, looping_rule);
- }
+ /**
+ * Toutes les règles <prefix> sont suivie par un <[template] unqualified-name>.
+ *
+ * On vérifie donc que c'est le cas.
+ */
- /**
- * Seconde partie (1/3) : recherche d'un éventuel complément.
- */
+ if (!is_itd_unqualified_name(context))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ goto prefix_exit;
- if (looping_rule == NULL)
- g_itanium_dcontext_pop_state(context, &saved);
+ }
- /* <unqualified-name> */
+ /**
+ * Cette vérification passée, on peut se trouver dans l'un des cas suivants :
+ *
+ * <prefix> ::= <prefix> <unqualified-name>
+ * ::= <prefix> <template unqualified-name> <template-args>
+ *
+ * On tente donc une itération supplémentaire.
+ */
- g_itanium_dcontext_push_state(context, &next_name_saved);
+ g_itanium_demangling_push_state(context, &saved);
- next_name = itd_unqualified_name(context);
+ further = itd_prefix_rec(context, result);
- 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.
- */
+ if (further != NULL)
+ result = further;
- return NULL;
+ else
+ g_itanium_demangling_pop_state(context, &saved);
- break;
+ prefix_exit:
- }
+ return result;
- /* <template-args> */
+}
- g_itanium_dcontext_push_state(context, &next_targs_saved);
- next_targs = itd_template_args(context);
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* loop = consigne pour la poursuite de la boucle. [OUT] *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- g_itanium_dcontext_pop_state(context, &next_targs_saved);
+static itanium_component *itd_prefix_rec(GItaniumDemangling *context, itanium_component *leaf)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ itanium_component *targs; /* Composant 'template-args' */
+ itd_state saved; /* Position d'analyse courante */
+ itanium_component *further; /* Tentative de progression */
- /**
- * Seconde partie (2/3) : validation de la présence d'un jeton
- * <unqualified-name> en réserve pour la règle <nested-name> parente.
- */
+ /**
+ * La règle locale traitée ici est la suivante :
+ *
+ * <prefix> ::= <prefix> <unqualified-name>
+ * ::= <prefix> <unqualified-name> <template-args>
+ *
+ * Le premier <prefix> des règles est contenu dans l'arguement leaf.
+ */
- g_itanium_dcontext_push_state(context, &expected_saved);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
- expected = itd_unqualified_name(context);
+ /**
+ * La présence du <unqualified-name> intial doit être assurée
+ * par l'appelant.
+ *
+ * Mais comme le test ne vaut pas la création, on valide quand même derrière.
+ */
- 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.
- */
+ assert(is_itd_unqualified_name(context));
- itd_unref_comp(next_name);
+ result = itd_unqualified_name(context);
- if (next_targs != NULL)
- itd_unref_comp(next_targs);
+ if (result == NULL)
+ goto prefix_rec_exit;
- g_itanium_dcontext_pop_state(context, &next_name_saved);
+ result = itd_make_binary(ICT_PREFIX_BINARY, leaf, result);
- break;
+ g_itanium_demangling_add_substitution(context, result);
- }
+ /**
+ * Détection et traitement de <template-args>.
+ */
- g_itanium_dcontext_pop_state(context, &expected_saved);
+ peek = peek_input_buffer_char(ibuf);
+ if (peek == 'I')
+ {
/**
- * 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.
+ * Si la détection est avérée, on vient donc de traiter un cas <template-prefix>.
+ * On corrige donc le type au passage.
*/
+ if (itd_get_component_type(result) == ICT_PREFIX_BINARY)
+ itd_set_type(result, ICT_TPREFIX_BINARY);
- if (result != NULL)
- g_itanium_dcontext_add_substitution(context, result);
+ targs = itd_template_args(context);
- printf("result = %p - next_name = %p\n", result, next_name);
+ if (targs != NULL)
+ {
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs);
+ g_itanium_demangling_add_substitution(context, result);
+
+ }
- if (result == NULL)
- result = next_name;
else
- result = itd_make_binary(context, ICT_PREFIX_BINARY, result, next_name);
+ {
+ itd_ref_comp(leaf);
+ itd_unref_comp(result);
+ result = NULL;
+ }
- if (next_targs != NULL)
- result = itd_make_binary(context, ICT_PREFIX_BINARY, result, next_targs);
+ }
+ if (result == NULL)
+ goto prefix_rec_exit;
- printf(" > result = %p\n", result);
+ /**
+ * Toutes les règles <prefix> sont suivie par un <[template] unqualified-name>.
+ *
+ * On vérifie donc que c'est le cas.
+ */
+ if (!is_itd_unqualified_name(context))
+ {
+ itd_ref_comp(leaf);
+ itd_unref_comp(result);
+ result = NULL;
+ goto prefix_rec_exit;
}
- 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);
+ /**
+ * Cette vérification passée, on peut se trouver dans l'un des cas suivants :
+ *
+ * <prefix> ::= <prefix> <unqualified-name>
+ * ::= <prefix> <template unqualified-name> <template-args>
+ *
+ * On tente donc une itération supplémentaire.
+ */
+
+ g_itanium_demangling_push_state(context, &saved);
+
+ further = itd_prefix_rec(context, result);
- printf("### FIN DE PREFIX ### '%s'\n",
- g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
+ if (further != NULL)
+ result = further;
+
+ else
+ g_itanium_demangling_pop_state(context, &saved);
+
+ prefix_rec_exit:
return result;
@@ -928,10 +1013,11 @@ static itanium_component *itd_prefix(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_template_prefix(GItaniumDContext *context)
+static itanium_component *itd_template_prefix(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
- itd_state saved; /* Position d'analyse courante */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
itanium_component *prefix; /* Premier d'un couple de comp.*/
itanium_component *name; /* Second d'un couple de comp. */
@@ -944,36 +1030,98 @@ static itanium_component *itd_template_prefix(GItaniumDContext *context)
*
*/
- result = NULL;
- g_itanium_dcontext_push_state(context, &saved);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
- prefix = itd_prefix(context);
+ if (peek == 'S')
+ result = itd_substitution(context);
+
+ else if (peek == 'T')
+ {
+ result = itd_template_param(context);
+
+ if (result != NULL)
+ g_itanium_demangling_add_substitution(context, result);
+
+ }
- if (prefix != NULL)
+ else
{
+ prefix = itd_prefix(context);
+
+ /**
+ * Quand son traitement est un succès, <prefix> doit toujours
+ * se terminer par <unqualified-name>.
+ */
+
+ assert(prefix == NULL || (prefix != NULL && is_itd_unqualified_name(context)));
+
+ /**
+ * Par ailleurs, la règle <prefix> peut être vide, donc on se doit
+ * de tenter un <unqualified-name> dans tous les cas.
+ */
+
name = itd_unqualified_name(context);
if (name != NULL)
- result = itd_make_binary(context, ICT_TPREFIX_BINARY, prefix, name);
+ {
+ result = itd_make_binary(ICT_TPREFIX_BINARY, prefix, name);
+
+ g_itanium_demangling_add_substitution(context, result);
+
+ }
+
else
- itd_unref_comp(prefix);
+ {
+ result = NULL;
- }
+ if (prefix != NULL)
+ 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 : Détermine si le composant suivant correspond à un type donné.*
+* *
+* Retour : true si le décodage va à priori réussir, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool is_itd_unqualified_name(GItaniumDemangling *context)
+{
+ bool result; /* Bilan à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+
+ /**
+ * La règle anticipée ici est la suivante :
+ *
+ * <unqualified-name> ::= <operator-name>
+ * ::= <ctor-dtor-name>
+ * ::= <source-name>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ result = islower(peek) /* <operator-name> */
+ || (peek == 'C' || peek == 'D') /* <ctor-dtor-name> */
+ || isdigit(peek); /* <source-name> */
return result;
@@ -992,10 +1140,11 @@ static itanium_component *itd_template_prefix(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_unqualified_name(GItaniumDContext *context)
+static itanium_component *itd_unqualified_name(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
- itd_state saved; /* Position d'analyse courante */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
/**
* La règle traitée ici est la suivante :
@@ -1006,21 +1155,21 @@ static itanium_component *itd_unqualified_name(GItaniumDContext *context)
*
*/
- g_itanium_dcontext_push_state(context, &saved);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
- result = itd_operator_name(context);
+ peek = peek_input_buffer_char(ibuf);
- if (result == NULL)
- {
- g_itanium_dcontext_pop_state(context, &saved);
+ if (islower(peek))
+ result = itd_operator_name(context);
+
+ else if (peek == 'C' || peek == 'D')
result = itd_ctor_dtor_name(context);
- }
- if (result == NULL)
- {
- g_itanium_dcontext_pop_state(context, &saved);
+ else if (isdigit(peek))
result = itd_source_name(context);
- }
+
+ else
+ result = NULL;
return result;
@@ -1039,7 +1188,7 @@ static itanium_component *itd_unqualified_name(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_source_name(GItaniumDContext *context)
+static itanium_component *itd_source_name(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
ssize_t number; /* Taille positive */
@@ -1077,10 +1226,11 @@ static itanium_component *itd_source_name(GItaniumDContext *context)
* *
******************************************************************************/
-static bool itd_number(GItaniumDContext *context, ssize_t *size)
+static bool itd_number(GItaniumDemangling *context, ssize_t *size)
{
bool result; /* Validité à renvoyer */
bool negative; /* Taille négative ? */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
char peek; /* Prochain caractère lu */
/**
@@ -1094,13 +1244,15 @@ static bool itd_number(GItaniumDContext *context, ssize_t *size)
negative = false;
- peek = g_itanium_dcontext_peek_char(context);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
if (peek == 'n')
{
negative = true;
- g_itanium_dcontext_advance(context, 1);
- peek = g_itanium_dcontext_peek_char(context);
+ advance_input_buffer(ibuf, 1);
+ peek = peek_input_buffer_char(ibuf);
}
*size = 0;
@@ -1109,8 +1261,8 @@ static bool itd_number(GItaniumDContext *context, ssize_t *size)
{
result = true;
*size = *size * 10 + peek - '0';
- g_itanium_dcontext_advance(context, 1);
- peek = g_itanium_dcontext_peek_char(context);
+ advance_input_buffer(ibuf, 1);
+ peek = peek_input_buffer_char(ibuf);
}
if (negative)
@@ -1134,9 +1286,10 @@ static bool itd_number(GItaniumDContext *context, ssize_t *size)
* *
******************************************************************************/
-static itanium_component *itd_identifier(GItaniumDContext *context, size_t length)
+static itanium_component *itd_identifier(GItaniumDemangling *context, size_t length)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
const char *data; /* Données restantes */
size_t remaining; /* Quantité d'octets */
@@ -1147,15 +1300,17 @@ static itanium_component *itd_identifier(GItaniumDContext *context, size_t lengt
*
*/
- data = g_itanium_dcontext_get_string(context, &remaining);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ data = get_input_buffer_string(ibuf, &remaining);
if (length > remaining)
return NULL;
- result = itd_make_name(context, data, length);
+ result = itd_make_name(data, length);
if (result != NULL)
- g_itanium_dcontext_advance(context, length);
+ advance_input_buffer(ibuf, length);
return result;
@@ -1174,94 +1329,99 @@ static itanium_component *itd_identifier(GItaniumDContext *context, size_t lengt
* *
******************************************************************************/
-static itanium_component *itd_operator_name(GItaniumDContext *context)
+static itanium_component *itd_operator_name(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
char code[2]; /* Code à venir lire */
+ itanium_component *type; /* Type transtypé */
itanium_operator_info info; /* Clef des informations */
itanium_operator_info *found; /* Informations complètes */
/**
* La règle traitée ici est la suivante :
*
- * <operator-name> ::= nw # new
+ * <operator-name> ::= nw # new
* ::= na # new[]
- * ::= dl # delete
- * ::= da # delete[]
+ * ::= 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 # ?
+ * ::= 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)
+ * ::= cv <type> # (cast)
* ::= v <digit> <source-name> # vendor extended operator
*
*/
result = NULL;
- code[0] = g_itanium_dcontext_next_char(context);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!get_input_buffer_next_char_carefully(ibuf, &code[0]))
+ goto itd_operator_name_exit;
if (code[0] == 'v')
{
+ type = itd_type(context);
- result = NULL; /* TODO */
+ if (type != NULL)
+ result = itd_make_cast_operator(type);
+ else
+ result = NULL;
goto itd_operator_name_exit;
-
}
- code[1] = g_itanium_dcontext_next_char(context);
+ if (!get_input_buffer_next_char_carefully(ibuf, &code[1]))
+ goto itd_operator_name_exit;
if (code[0] == 'c' && code[1] == 'v')
{
-
- result = NULL; /* TODO */
-
+ result = NULL;
goto itd_operator_name_exit;
-
-
}
/* Recherche dans la liste des opérateurs reconnus */
@@ -1295,7 +1455,7 @@ static itanium_component *itd_operator_name(GItaniumDContext *context)
sizeof(itanium_operator_info), (__compar_fn_t)comp_itanium_operators);
if (found != NULL)
- result = itd_make_operator(context, found);
+ result = itd_make_operator(found);
itd_operator_name_exit:
@@ -1316,54 +1476,116 @@ static itanium_component *itd_operator_name(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_special_name(GItaniumDContext *context)
+static itanium_component *itd_special_name(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
char next; /* Caractère suivant */
char peek; /* Prochain caractère lu */
itanium_component *offset1; /* Décalage extrait #1 */
+ itanium_component *offset2; /* Décalage extrait #2 */
itanium_component *encoding; /* Encodage suivant */
/**
* La règle traitée ici est la suivante :
*
- * <special-name> ::= T <call-offset> <base encoding>
- * # base is the nominal target function of thunk
+ * <special-name> ::= TV <type> # virtual table
+ * ::= TT <type> # VTT structure (construction vtable index)
+ * ::= TI <type> # typeinfo structure
+ * ::= TS <type> # typeinfo name (null-terminated byte string)
+ * ::= Tc <call-offset> <call-offset> <base encoding>
+ * # base is the nominal target function of thunk
+ * # first call-offset is 'this' adjustment
+ * # second call-offset is result adjustment
+ * ::= T <call-offset> <base encoding>
+ * # base is the nominal target function of thunk
*/
result = NULL;
- next = g_itanium_dcontext_next_char(context);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!get_input_buffer_next_char_carefully(ibuf, &next))
+ goto exit_eof;
if (next == 'T')
{
- peek = g_itanium_dcontext_peek_char(context);
+ peek = peek_input_buffer_char(ibuf);
switch (peek)
{
case 'V':
- result = NULL; /* TODO */
+
+ advance_input_buffer(ibuf, 1);
+
+ result = itd_type(context);
+
+ if (result != NULL)
+ result = itd_make_unary(ICT_SPECIAL_NAME_VTABLE, result);
+
break;
case 'T':
- result = NULL; /* TODO */
+
+ advance_input_buffer(ibuf, 1);
+
+ result = itd_type(context);
+
+ if (result != NULL)
+ result = itd_make_unary(ICT_SPECIAL_NAME_VSTRUCT, result);
+
break;
case 'I':
- result = NULL; /* TODO */
+ advance_input_buffer(ibuf, 1);
+ result = itd_type(context);
break;
case 'S':
- result = NULL; /* TODO */
+ advance_input_buffer(ibuf, 1);
+ result = itd_type(context);
break;
case 'c':
- result = NULL; /* TODO */
+
+ advance_input_buffer(ibuf, 1);
+
+ offset1 = itd_call_offset(context);
+ if (offset1 == NULL) break;
+
+ offset2 = itd_call_offset(context);
+ if (offset2 == NULL)
+ {
+ itd_unref_comp(offset1);
+ break;
+ }
+
+ encoding = itd_encoding(context);
+
+ if (encoding == NULL)
+ {
+ itd_unref_comp(offset1);
+ itd_unref_comp(offset2);
+ }
+
+ else
+ result = itd_make_ternary(ICT_FUNCTION_COVARIANT_THUNK, encoding, offset1, offset2);
+
break;
+ case '\0':
+
+ /**
+ * Si on se trouve à la fin du tampon, on n'avance pas aveuglément !
+ */
+
+ result = NULL;
+ break;
default:
+ advance_input_buffer(ibuf, 1);
+
offset1 = itd_call_offset(context);
if (offset1 == NULL) break;
@@ -1372,7 +1594,7 @@ static itanium_component *itd_special_name(GItaniumDContext *context)
if (encoding == NULL)
itd_unref_comp(offset1);
else
- result = itd_make_binary(context, ICT_FUNCTION_THUNK, offset1, encoding);
+ result = itd_make_binary(ICT_FUNCTION_THUNK, encoding, offset1);
break;
@@ -1380,6 +1602,8 @@ static itanium_component *itd_special_name(GItaniumDContext *context)
}
+ exit_eof:
+
return result;
}
@@ -1397,9 +1621,10 @@ static itanium_component *itd_special_name(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_call_offset(GItaniumDContext *context)
+static itanium_component *itd_call_offset(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
char next; /* Caractère suivant */
/**
@@ -1409,7 +1634,12 @@ static itanium_component *itd_call_offset(GItaniumDContext *context)
* ::= v <v-offset> _
*/
- next = g_itanium_dcontext_next_char(context);
+ result = NULL;
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (get_input_buffer_next_char_carefully(ibuf, &next))
+ goto exit_eof;
switch (next)
{
@@ -1421,18 +1651,16 @@ static itanium_component *itd_call_offset(GItaniumDContext *context)
result = itd_v_offset(context);
break;
- default:
- result = NULL;
- break;
-
}
- if (result != NULL && !g_itanium_dcontext_check_char(context, '_'))
+ if (result != NULL && !check_input_buffer_char(ibuf, '_'))
{
itd_unref_comp(result);
result = NULL;
}
+ exit_eof:
+
return result;
}
@@ -1450,7 +1678,7 @@ static itanium_component *itd_call_offset(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_nv_offset(GItaniumDContext *context)
+static itanium_component *itd_nv_offset(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
ssize_t offset; /* Décalage obtenu */
@@ -1465,7 +1693,7 @@ static itanium_component *itd_nv_offset(GItaniumDContext *context)
if (!itd_number(context, &offset))
return NULL;
- result = itd_make_offset(context, ICT_NON_VIRTUAL_OFFSET, offset);
+ result = itd_make_offset(ICT_NON_VIRTUAL_OFFSET, offset);
return result;
@@ -1484,10 +1712,11 @@ static itanium_component *itd_nv_offset(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_v_offset(GItaniumDContext *context)
+static itanium_component *itd_v_offset(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
ssize_t offset; /* Décalage obtenu #1 */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
ssize_t voffset; /* Décalage obtenu #2 */
/**
@@ -1500,15 +1729,17 @@ static itanium_component *itd_v_offset(GItaniumDContext *context)
if (!itd_number(context, &offset))
return NULL;
- if (!g_itanium_dcontext_check_char(context, '_'))
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, '_'))
return NULL;
if (!itd_number(context, &voffset))
return NULL;
- result = itd_make_binary(context, ICT_VIRTUAL_OFFSET,
- itd_make_offset(context, ICT_NON_VIRTUAL_OFFSET, offset),
- itd_make_offset(context, ICT_VIRTUAL_OFFSET, voffset));
+ result = itd_make_binary(ICT_DOUBLE_OFFSET,
+ itd_make_offset(ICT_NON_VIRTUAL_OFFSET, offset),
+ itd_make_offset(ICT_VIRTUAL_OFFSET, voffset));
return result;
@@ -1527,9 +1758,10 @@ static itanium_component *itd_v_offset(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_ctor_dtor_name(GItaniumDContext *context)
+static itanium_component *itd_ctor_dtor_name(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
char next; /* Caractère suivant */
ItaniumComponentType type; /* Type de composant */
@@ -1544,7 +1776,9 @@ static itanium_component *itd_ctor_dtor_name(GItaniumDContext *context)
* ::= D2 # base object destructor
*/
- next = g_itanium_dcontext_peek_char(context);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ next = peek_input_buffer_char(ibuf);
if (next == 'C')
type = ICT_CONSTRUCTOR;
@@ -1553,17 +1787,16 @@ static itanium_component *itd_ctor_dtor_name(GItaniumDContext *context)
else
return NULL;
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
- next = g_itanium_dcontext_peek_char(context);
+ next = peek_input_buffer_char(ibuf);
if (next != '0' && next != '1' && next != '2')
return NULL;
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
- result = itd_make_empty(context);
- itd_set_type(result, type);
+ result = itd_make_with_type(type);
return result;
@@ -1582,12 +1815,17 @@ static itanium_component *itd_ctor_dtor_name(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_type(GItaniumDContext *context)
+static itanium_component *itd_type(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
TypeQualifier qualifier; /* Propriétés supplémentaires */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ bool handled; /* Prise en compte effectuée ? */
itanium_component *sub; /* Sous-type lié à associer */
+ itanium_component *vendor; /* Extension propriétaire */
+ GDataType *builtin; /* Type construit */
itd_state saved; /* Position d'analyse courante */
+ itanium_component *targs; /* Composant 'template-args' */
/**
* La règle traitée ici est la suivante :
@@ -1614,90 +1852,262 @@ static itanium_component *itd_type(GItaniumDContext *context)
qualifier = itd_cv_qualifiers(context);
- switch (g_itanium_dcontext_peek_char(context))
+ if (qualifier != TQF_NONE)
{
+ result = itd_type(context);
+
+ if (result != NULL)
+ result = itd_make_qualified_type(result, qualifier);
+
+ goto itd_type_end;
+
+ }
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ handled = false;
+
+ switch (peek_input_buffer_char(ibuf))
+ {
+ case 'F':
+ result = itd_function_type(context);
+ handled = true;
+ break;
+
+ case 'A':
+ result = itd_array_type(context);
+ handled = true;
+ break;
+
+ case 'M':
+ result = itd_pointer_to_member_type(context);
+ handled = true;
+ break;
+
case 'P':
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
sub = itd_type(context);
if (sub == NULL) return NULL;
- result = itd_make_unary(context, ICT_POINTER_TO, sub);
+ result = itd_make_unary(ICT_POINTER_TO, sub);
+ handled = true;
break;
case 'R':
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
sub = itd_type(context);
if (sub == NULL) return NULL;
- result = itd_make_unary(context, ICT_REFERENCE_TO, sub);
+ result = itd_make_unary(ICT_REFERENCE_TO, sub);
+ handled = true;
break;
case 'O':
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
sub = itd_type(context);
if (sub == NULL) return NULL;
- result = itd_make_unary(context, ICT_RVALUE_REFERENCE_TO, sub);
+ result = itd_make_unary(ICT_RVALUE_REFERENCE_TO, sub);
+ handled = true;
break;
case 'C':
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
sub = itd_type(context);
if (sub == NULL) return NULL;
- result = itd_make_unary(context, ICT_COMPLEX_PAIR, sub);
+ result = itd_make_unary(ICT_COMPLEX_PAIR, sub);
+ handled = true;
break;
case 'G':
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
sub = itd_type(context);
if (sub == NULL) return NULL;
- result = itd_make_unary(context, ICT_IMAGINARY, sub);
+ result = itd_make_unary(ICT_IMAGINARY, sub);
+ handled = true;
break;
case 'U':
- g_itanium_dcontext_advance(context, 1);
- /* TODO */
- return NULL;
+ advance_input_buffer(ibuf, 1);
+
+ result = NULL;
+
+ vendor = itd_source_name(context);
+
+ if (vendor == NULL)
+ result = NULL;
+
+ else
+ {
+ builtin = g_class_enum_type_new(CET_UNKNOWN, itd_translate_component(vendor, NULL));
+ result = itd_make_type(builtin);
+ itd_unref_comp(vendor);
+
+ sub = itd_type(context);
+
+ if (sub != NULL)
+ itd_unref_comp(sub);
+
+ else
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ handled = true;
break;
- }
+ case 'T':
- if (result != NULL) goto itd_type_end;
+ /**
+ * Comme on a la définition suivante :
+ *
+ * <template-template-param> ::= <template-param>
+ * ::= <substitution>
+ *
+ * On ne sait pas laquelle de ces deux directions prendre :
+ *
+ * <type> ::= <template-param>
+ * ::= <template-template-param> <template-args>
+ *
+ * Comme <template-args> commence toujour par un I, on teste
+ * le caractère courant après <template-param> et on revient
+ * un poil en arrière au besoin.
+ *
+ * Le cas <substitution> est traité de façon similaire après.
+ */
+
+ g_itanium_demangling_push_state(context, &saved);
- g_itanium_dcontext_push_state(context, &saved);
+ result = itd_template_param(context);
+
+ if (result != NULL)
+ {
+ if (peek_input_buffer_char(ibuf) == 'I')
+ {
+ itd_unref_comp(result);
+
+ g_itanium_demangling_pop_state(context, &saved);
+
+ result = itd_template_template_param(context);
+
+ if (result != NULL)
+ {
+ targs = itd_template_args(context);
+
+ if (targs != NULL)
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs);
+
+ else
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ }
+
+ }
+
+ handled = true;
+ break;
+
+ }
+
+ if (handled) goto itd_type_end;
+
+ g_itanium_demangling_push_state(context, &saved);
result = itd_builtin_type(context);
if (result != NULL) goto itd_type_end;
- g_itanium_dcontext_pop_state(context, &saved);
+ g_itanium_demangling_pop_state(context, &saved);
result = itd_class_enum_type(context);
if (result != NULL) goto itd_type_end;
+ g_itanium_demangling_pop_state(context, &saved);
+
+ /**
+ * De façon similaire au cas <template-param> traité au dessus,
+ * on guette un usage de <substitution> via :
+ *
+ * <template-template-param> ::= <template-param>
+ * ::= <substitution>
+ *
+ * La distinction se réalise via une liste d'argument, et on tranche
+ * cette fois entre les deux directions suivantes :
+ *
+ * <type> ::= <template-template-param> <template-args>
+ * ::= <substitution> # See Compression below
+ */
- g_itanium_dcontext_pop_state(context, &saved);
+ g_itanium_demangling_push_state(context, &saved);
result = itd_substitution(context);
- if (result != NULL) goto itd_type_end;
+ if (result != NULL && peek_input_buffer_char(ibuf) == 'I')
+ {
+ itd_unref_comp(result);
+
+ g_itanium_demangling_pop_state(context, &saved);
+ result = itd_template_template_param(context);
+
+ if (result != NULL)
+ {
+ targs = itd_template_args(context);
+
+ if (targs != NULL)
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs);
+
+ else
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+ }
itd_type_end:
+ if (result != NULL)
+ {
+ /**
+ * Les spécifications (§ 5.1.9) précisent:
+ *
+ * There are two exceptions that appear to be substitution candidates
+ * from the grammar, but are explicitly excluded:
+ *
+ * <builtin-type> other than vendor extended types, and
+ * function and operator names other than extern "C" functions.
+ *
+ * On saute donc éventuelleement certains résultats.
+ */
+
+ if (itd_get_component_type(result) != ICT_TYPE)
+ g_itanium_demangling_add_substitution(context, result);
+
+ }
+
return result;
}
@@ -1715,35 +2125,38 @@ static itanium_component *itd_type(GItaniumDContext *context)
* *
******************************************************************************/
-static TypeQualifier itd_cv_qualifiers(GItaniumDContext *context)
+static TypeQualifier itd_cv_qualifiers(GItaniumDemangling *context)
{
TypeQualifier result; /* Valeur à remonter */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
/**
* La règle traitée ici est la suivante :
*
- * <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
+ * <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
*
*/
result = TQF_NONE;
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
while (1)
- switch (g_itanium_dcontext_peek_char(context))
+ switch (peek_input_buffer_char(ibuf))
{
case 'r':
result = TQF_RESTRICT;
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
break;
case 'V':
result = TQF_VOLATILE;
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
break;
case 'K':
result = TQF_CONST;
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
break;
default:
@@ -1771,10 +2184,12 @@ static TypeQualifier itd_cv_qualifiers(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_builtin_type(GItaniumDContext *context)
+static itanium_component *itd_builtin_type(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
BaseType type; /* Type reconnu ou BTP_INVALID */
+ itanium_component *vendor; /* Extension propriétaire */
GDataType *builtin; /* Type construit */
/**
@@ -1805,7 +2220,9 @@ static itanium_component *itd_builtin_type(GItaniumDContext *context)
*
*/
- switch (g_itanium_dcontext_peek_char(context))
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ switch (peek_input_buffer_char(ibuf))
{
case 'v':
type = BTP_VOID;
@@ -1871,10 +2288,21 @@ static itanium_component *itd_builtin_type(GItaniumDContext *context)
type = BTP_ELLIPSIS;
break;
case 'u':
- type = BTP_OTHER;
- /* FIXME */
- /* <source-name> # vendor extended type */
+
+ vendor = itd_source_name(context);
+
+ if (vendor == NULL)
+ result = NULL;
+ else
+ {
+ builtin = g_class_enum_type_new(CET_UNKNOWN, itd_translate_component(vendor, NULL));
+ result = itd_make_type(builtin);
+ itd_unref_comp(vendor);
+ }
+
+ goto done;
break;
+
default:
type = BTP_INVALID;
break;
@@ -1883,12 +2311,14 @@ static itanium_component *itd_builtin_type(GItaniumDContext *context)
if (type != BTP_INVALID)
{
builtin = g_basic_type_new(type);
- result = itd_make_type(context, builtin);
- g_itanium_dcontext_advance(context, 1);
+ result = itd_make_type(builtin);
+ advance_input_buffer(ibuf, 1);
}
else
result = NULL;
+ done:
+
return result;
}
@@ -1906,10 +2336,69 @@ static itanium_component *itd_builtin_type(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_bare_function_type(GItaniumDContext *context)
+static itanium_component *itd_function_type(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère dispo. */
+ itanium_component *args; /* Liste des arguments */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <function-type> ::= F [Y] <bare-function-type> E
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'F'))
+ return NULL;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'Y')
+ advance_input_buffer(ibuf, 1);
+
+ args = itd_bare_function_type(context);
+
+ if (args == NULL)
+ result = NULL;
+
+ else
+ {
+ result = itd_make_function_type(peek == 'Y', args);
+
+ if (!check_input_buffer_char(ibuf, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_bare_function_type(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
itanium_component *type; /* Nouvel élément à intégrer */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
itd_state saved; /* Position d'analyse courante */
/**
@@ -1923,20 +2412,23 @@ static itanium_component *itd_bare_function_type(GItaniumDContext *context)
type = itd_type(context);
if (type == NULL) return NULL;
- result = itd_append_right_to_binary(context, ICT_TYPES_LIST, NULL, type);
+ result = itd_append_right_to_binary(ICT_TYPES_LIST, NULL, type);
- while (1)
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ while (count_input_buffer_remaining(ibuf) > 0)
{
- g_itanium_dcontext_push_state(context, &saved);
+ g_itanium_demangling_push_state(context, &saved);
type = itd_type(context);
+
if (type == NULL)
{
- g_itanium_dcontext_pop_state(context, &saved);
+ g_itanium_demangling_pop_state(context, &saved);
break;
}
- result = itd_append_right_to_binary(context, ICT_TYPES_LIST, result, type);
+ result = itd_append_right_to_binary(ICT_TYPES_LIST, result, type);
}
@@ -1957,7 +2449,7 @@ static itanium_component *itd_bare_function_type(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_class_enum_type(GItaniumDContext *context)
+static itanium_component *itd_class_enum_type(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
@@ -1975,10 +2467,98 @@ static itanium_component *itd_class_enum_type(GItaniumDContext *context)
}
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_array_type(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère dispo. */
+ itanium_component *dim_expr; /* Dimension via expression */
+ ssize_t dim_number; /* Dimension par un nombre */
+ itanium_component *type; /* Type du tableau */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <array-type> ::= A <positive dimension number> _ <element type>
+ * ::= A [<dimension expression>] _ <element type>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'A'))
+ return NULL;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == '[')
+ {
+ advance_input_buffer(ibuf, 1);
+
+ dim_expr = itd_expression(context);
+
+ if (dim_expr == NULL)
+ return NULL;
+
+ if (!check_input_buffer_char(ibuf, ']'))
+ return NULL;
+
+ if (!check_input_buffer_char(ibuf, '_'))
+ return NULL;
+
+ type = itd_type(context);
+
+ if (type == NULL)
+ {
+ itd_unref_comp(dim_expr);
+ return NULL;
+ }
+
+ result = itd_make_array_with_dim_expr(dim_expr, type);
+
+ if (result == NULL)
+ {
+ itd_unref_comp(dim_expr);
+ itd_unref_comp(type);
+ }
+
+ }
+
+ else
+ {
+ if (!itd_number(context, &dim_number))
+ return NULL;
+
+ if (!check_input_buffer_char(ibuf, '_'))
+ return NULL;
+
+ type = itd_type(context);
+
+ if (type == NULL)
+ return NULL;
+ result = itd_make_array_with_dim_number(dim_number, type);
+ if (result == NULL)
+ itd_unref_comp(type);
+ }
+ return result;
+
+}
/******************************************************************************
@@ -1993,14 +2573,154 @@ static itanium_component *itd_class_enum_type(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_template_args(GItaniumDContext *context)
+static itanium_component *itd_pointer_to_member_type(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ itanium_component *class; /* Classe d'appatenance */
+ itanium_component *member; /* Membre représenté */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <pointer-to-member-type> ::= M <class type> <member type>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'M'))
+ return NULL;
+
+ class = itd_type(context);
+
+ if (class != NULL)
+ {
+ member = itd_type(context);
+
+ if (member != NULL)
+ result = itd_make_pointer_to_memeber_type(class, member);
+
+ else
+ {
+ itd_unref_comp(class);
+ result = NULL;
+ }
+
+ }
+
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_template_param(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char cur; /* Caractère analysé */
+ size_t id; /* Identifiant de substitution */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <template-param> ::= T_ # first template parameter
+ * ::= T <parameter-2 non-negative number> _
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'T'))
+ return NULL;
+
+ result = NULL;
+
+ if (get_input_buffer_next_char_carefully(ibuf, &cur))
+ {
+ if (cur == '_' || isdigit(cur) || isupper(cur))
+ {
+ if (!itd_seq_id(context, cur, &id))
+ return NULL;
+
+ result = g_itanium_demangling_get_template_arg(context, id);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_template_template_param(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère dispo. */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'T')
+ result = itd_template_param(context);
+
+ else
+ result = itd_substitution(context);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_template_args(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
itanium_component *arg; /* Nouvel argument extrait */
itd_state saved; /* Position d'analyse courante */
- printf(">>> TA>> '%s'\n", g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
-
/**
* La règle traitée ici est la suivante :
*
@@ -2008,43 +2728,38 @@ static itanium_component *itd_template_args(GItaniumDContext *context)
*
*/
- if (!g_itanium_dcontext_check_char(context, 'I'))
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ if (!check_input_buffer_char(ibuf, 'I'))
return NULL;
arg = itd_template_arg(context);
if (arg == NULL) return NULL;
- result = itd_append_right_to_binary(context, ICT_TYPES_LIST, NULL, arg);
+ result = itd_append_right_to_binary(ICT_TYPES_LIST, NULL, arg);
while (1)
{
- g_itanium_dcontext_push_state(context, &saved);
+ g_itanium_demangling_push_state(context, &saved);
arg = itd_template_arg(context);
if (arg == NULL)
{
- g_itanium_dcontext_pop_state(context, &saved);
+ g_itanium_demangling_pop_state(context, &saved);
break;
}
- result = itd_append_right_to_binary(context, ICT_TYPES_LIST, result, arg);
+ result = itd_append_right_to_binary(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'))
+ if (!check_input_buffer_char(ibuf, 'E'))
{
- //printf("=== TA : BAD E\n\n");
-
- if (result != NULL)
- itd_unref_comp(result);
+ itd_unref_comp(result);
return NULL;
}
- //printf("=== TA >> %p\n\n", result);
-
- result = itd_make_unary(context, ICT_TEMPLATE_ARGS, result);
+ result = itd_make_unary(ICT_TEMPLATE_ARGS, result);
return result;
@@ -2063,10 +2778,11 @@ static itanium_component *itd_template_args(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_template_arg(GItaniumDContext *context)
+static itanium_component *itd_template_arg(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
- itd_state saved; /* Position d'analyse courante */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
/**
* La règle traitée ici est la suivante :
@@ -2077,51 +2793,222 @@ static itanium_component *itd_template_arg(GItaniumDContext *context)
*
*/
- g_itanium_dcontext_push_state(context, &saved);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
- result = itd_type(context);
+ peek = peek_input_buffer_char(ibuf);
- if (result == NULL)
+ if (peek == 'X')
+ {
+ advance_input_buffer(ibuf, 1);
+
+ result = itd_expression(context);
+
+ if (result != NULL && !check_input_buffer_char(ibuf, 'E'))
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ else if (peek == 'L')
+ result = itd_expr_primary(context);
+
+ else
+ result = itd_type(context);
+
+ if (result != NULL)
+ g_itanium_demangling_add_template_arg(context, result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Extrait un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_expression(GItaniumDemangling *context)
+{
+ itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ char peek; /* Prochain caractère lu */
+ char next_peek; /* Caractère après le prochain */
+ itanium_component *targs; /* Composant 'template-args' */
+ ItaniumOperatorType otype; /* Type d'opérateur */
+ const void *odata; /* Données associées */
+ const itanium_operator_info *simple; /* Données d'opérateur simple */
+ int i; /* Boucle de parcours */
+ itanium_component *list; /* Liste de sous-expressions */
+ itanium_component *sub; /* Sous-expression chargée */
+
+ /**
+ * La règle traitée ici est la suivante :
+ *
+ * <expression> ::= <unary operator-name> <expression>
+ * ::= <binary operator-name> <expression> <expression>
+ * ::= <trinary operator-name> <expression> <expression> <expression>
+ * ::= st <type>
+ * ::= <template-param>
+ * ::= sr <type> <unqualified-name> # dependent name
+ * ::= sr <type> <unqualified-name> <template-args> # dependent template-id
+ * ::= <expr-primary>
+ *
+ */
+
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'T')
+ result = itd_template_param(context);
+
+ else if (peek == 'L')
+ result = itd_expr_primary(context);
+
+ else if (islower(peek))
{
- g_itanium_dcontext_pop_state(context, &saved);
+ next_peek = peek_input_buffer_next_char(ibuf);
+
+ if (peek == 's' && next_peek == 't')
+ {
+ advance_input_buffer(ibuf, 2);
+
+ result = itd_type(context);
- if (g_itanium_dcontext_check_char(context, 'X'))
+ }
+
+ else if (peek == 's' && next_peek == 'r')
{
- result = itd_expression(context);
+ advance_input_buffer(ibuf, 2);
- if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
+ result = itd_type(context);
+
+ if (result != NULL)
{
itd_unref_comp(result);
- result = NULL;
+
+ result = itd_unqualified_name(context);
+
+ if (result)
+ {
+ peek = peek_input_buffer_char(ibuf);
+
+ if (peek == 'I')
+ {
+ targs = itd_template_args(context);
+
+ if (targs != NULL)
+ result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs);
+
+ else
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+
+ }
+
+ }
+
}
}
- }
+ else
+ {
+ result = itd_operator_name(context);
- if (result == NULL)
- {
- g_itanium_dcontext_pop_state(context, &saved);
- result = itd_expr_primary(context);
- }
+ if (result != NULL)
+ {
+ odata = itd_get_operator_info(result, &otype);
- return result;
+ switch (otype)
+ {
+ case IOT_SIMPLE:
-}
+ simple = (const itanium_operator_info *)odata;
+
+ list = NULL;
+
+ for (i = 0; i < simple->args; i++)
+ {
+ sub = itd_expression(context);
+
+ if (sub == NULL)
+ {
+ if (list != NULL)
+ {
+ itd_unref_comp(list);
+ list = NULL;
+ }
+
+ break;
+
+ }
+
+ list = itd_append_right_to_binary(ICT_EXPR_LIST, list, sub);
+ }
+ if (list == NULL)
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+ else
+ result = itd_make_binary(ICT_OPERATED_EXPRESSION, result, list);
+ break;
+ case IOT_CAST:
+ sub = itd_expression(context);
+ if (sub == NULL)
+ {
+ itd_unref_comp(result);
+ result = NULL;
+ }
+ else
+ {
+ list = itd_append_right_to_binary(ICT_EXPR_LIST, NULL, sub);
+ result = itd_make_binary(ICT_OPERATED_EXPRESSION, result, list);
+ }
+ break;
+ default:
+ assert(false);
+ itd_unref_comp(result);
+ result = NULL;
+ break;
+ }
+ }
+
+ }
+
+ }
+
+ else
+ result = NULL;
+ return result;
+}
/******************************************************************************
@@ -2137,9 +3024,10 @@ static itanium_component *itd_template_arg(GItaniumDContext *context)
* *
******************************************************************************/
-static itanium_component *itd_value_to_string(GItaniumDContext *context, bool hex)
+static itanium_component *itd_value_to_string(GItaniumDemangling *context, bool hex)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
const char *data; /* Données restantes */
itd_state saved; /* Position d'analyse initiale */
itd_state cur; /* Position d'analyse courante */
@@ -2155,23 +3043,25 @@ static itanium_component *itd_value_to_string(GItaniumDContext *context, bool he
result = NULL;
- data = g_itanium_dcontext_get_string(context, (size_t []) { 0 });
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
+ data = get_input_buffer_text_access(ibuf);
- g_itanium_dcontext_push_state(context, &saved);
+ g_itanium_demangling_push_state(context, &saved);
while (1)
{
- peek = g_itanium_dcontext_peek_char(context);
+ peek = peek_input_buffer_char(ibuf);
switch (peek)
{
case '0' ... '9':
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
break;
case 'a' ... 'f':
if (hex)
- g_itanium_dcontext_advance(context, 1);
+ advance_input_buffer(ibuf, 1);
else
goto exit_iits;
break;
@@ -2189,10 +3079,10 @@ static itanium_component *itd_value_to_string(GItaniumDContext *context, bool he
exit_loop:
- g_itanium_dcontext_push_state(context, &cur);
+ g_itanium_demangling_push_state(context, &cur);
if ((cur.pos - saved.pos) > 0)
- result = itd_make_name(context, data, cur.pos - saved.pos);
+ result = itd_make_name(data, cur.pos - saved.pos);
exit_iits:
@@ -2213,9 +3103,10 @@ static itanium_component *itd_value_to_string(GItaniumDContext *context, bool he
* *
******************************************************************************/
-static itanium_component *itd_expr_primary(GItaniumDContext *context)
+static itanium_component *itd_expr_primary(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
itd_state saved; /* Position d'analyse courante */
itanium_component *type; /* Type de valeur extrait */
itd_state saved_value; /* Position d'analyse courante */
@@ -2229,24 +3120,24 @@ static itanium_component *itd_expr_primary(GItaniumDContext *context)
*
*/
- printf("PRIMARY :: no L\n");
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
- if (!g_itanium_dcontext_check_char(context, 'L'))
+ if (!check_input_buffer_char(ibuf, 'L'))
return NULL;
- g_itanium_dcontext_push_state(context, &saved);
+ g_itanium_demangling_push_state(context, &saved);
type = itd_type(context);
if (type != NULL)
{
- g_itanium_dcontext_push_state(context, &saved_value);
+ g_itanium_demangling_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'))
+ if (result != NULL && !check_input_buffer_char(ibuf, 'E'))
{
itd_unref_comp(result);
result = NULL;
@@ -2256,11 +3147,11 @@ static itanium_component *itd_expr_primary(GItaniumDContext *context)
if (result == NULL)
{
- g_itanium_dcontext_pop_state(context, &saved_value);
+ g_itanium_demangling_pop_state(context, &saved_value);
result = itd_value_to_string(context, true);
- if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
+ if (result != NULL && !check_input_buffer_char(ibuf, 'E'))
{
itd_unref_comp(result);
result = NULL;
@@ -2278,10 +3169,10 @@ static itanium_component *itd_expr_primary(GItaniumDContext *context)
if (result == NULL)
{
- g_itanium_dcontext_pop_state(context, &saved);
+ g_itanium_demangling_pop_state(context, &saved);
result = itd_mangled_name(context);
- if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
+ if (result != NULL && !check_input_buffer_char(ibuf, 'E'))
{
itd_unref_comp(result);
result = NULL;
@@ -2289,8 +3180,6 @@ static itanium_component *itd_expr_primary(GItaniumDContext *context)
}
- printf("PRIMARY :: %p\n", result);
-
return result;
}
@@ -2316,8 +3205,10 @@ static itanium_component *itd_expr_primary(GItaniumDContext *context)
* *
******************************************************************************/
-static bool itd_seq_id(GItaniumDContext *context, char cur, size_t *id)
+static bool itd_seq_id(GItaniumDemangling *context, char cur, size_t *id)
{
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+
/**
* La règle traitée ici est la suivante :
*
@@ -2332,6 +3223,8 @@ static bool itd_seq_id(GItaniumDContext *context, char cur, size_t *id)
* (ie, cur == '_' || isdigit(cur) || isupper(cur)).
*/
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+
if (cur != '_')
{
do
@@ -2343,7 +3236,8 @@ static bool itd_seq_id(GItaniumDContext *context, char cur, size_t *id)
else
return false;
- cur = g_itanium_dcontext_next_char(context);
+ if (!get_input_buffer_next_char_carefully(ibuf, &cur))
+ return false;
}
while (cur != '_');
@@ -2369,14 +3263,16 @@ static bool itd_seq_id(GItaniumDContext *context, char cur, size_t *id)
* *
******************************************************************************/
-static itanium_component *itd_substitution(GItaniumDContext *context)
+static itanium_component *itd_substitution(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
char cur; /* Caractère analysé */
size_t id; /* Identifiant de substitution */
- char peek; /* Prochain caractère lu */
- bool verbose; /* Sélection du rendu idéal */
size_t i; /* Boucle de parcours */
+ const itanium_std_subst_info *stdinfo; /* Raccourci de confort */
+ GDataType *std; /* Espace de noms */
+ GDataType *type; /* Type complet final */
/**
* La règle traitée ici est la suivante :
@@ -2393,52 +3289,56 @@ static itanium_component *itd_substitution(GItaniumDContext *context)
*
*/
- peek = g_itanium_dcontext_peek_char(context);
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
- if (!g_itanium_dcontext_check_char(context, 'S'))
+ if (!check_input_buffer_char(ibuf, 'S'))
return NULL;
- cur = g_itanium_dcontext_next_char(context);
+ result = NULL;
+
+ if (!get_input_buffer_next_char_carefully(ibuf, &cur))
+ goto exit_eof;
if (cur == '_' || isdigit(cur) || isupper(cur))
{
if (!itd_seq_id(context, cur, &id))
return NULL;
- printf("requesting... %zu\n", id);
-
- result = g_itanium_dcontext_get_substitution(context, id);
+ result = g_itanium_demangling_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)
+ {
+ stdinfo = &itanium_standard_substitutions[i];
+
+ if (stdinfo->code == cur)
{
- /* TODO : constructeur... */
+ std = g_class_enum_type_new(CET_NAMESPACE, strdup("std"));
+
+ if (stdinfo->class == NULL)
+ type = std;
- 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);
+ {
+ type = g_class_enum_type_new(CET_CLASS, strdup(stdinfo->class));
+ g_data_type_set_namespace(type, std, "::");
+ }
+ result = itd_make_type(type);
itd_set_type(result, ICT_STD_SUBST);
break;
}
+ }
+
}
+ exit_eof:
+
return result;
}
diff --git a/src/mangling/itanium/abi.h b/plugins/itanium/abi.h
index 469562f..d286b2f 100644
--- a/src/mangling/itanium/abi.h
+++ b/plugins/itanium/abi.h
@@ -21,8 +21,8 @@
*/
-#ifndef _FORMAT_MANGLING_ITANIUM_ABI_H
-#define _FORMAT_MANGLING_ITANIUM_ABI_H
+#ifndef _PLUGINS_ITANIUM_ABI_H
+#define _PLUGINS_ITANIUM_ABI_H
#include "component.h"
@@ -31,8 +31,8 @@
/* Extrait un composant dans un contexte Itanium. */
-itanium_component *itd_mangled_name(GItaniumDContext *);
+itanium_component *itd_mangled_name(GItaniumDemangling *);
-#endif /* _FORMAT_MANGLING_ITANIUM_ABI_H */
+#endif /* _PLUGINS_ITANIUM_ABI_H */
diff --git a/plugins/itanium/component-int.h b/plugins/itanium/component-int.h
new file mode 100644
index 0000000..fb8c423
--- /dev/null
+++ b/plugins/itanium/component-int.h
@@ -0,0 +1,137 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * component-int.h - prototypes internes pour la description des composants Itanium
+ *
+ * Copyright (C) 2013-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_COMPONENT_INT_H
+#define _PLUGINS_ITANIUM_COMPONENT_INT_H
+
+
+#include "component.h"
+
+
+
+/* Composant extrait de l'encodage */
+struct _itanium_component
+{
+ ItaniumComponentType type; /* Type de composant */
+
+ unsigned int refcount; /* Compteur de références */
+
+ fnv64_t hash; /* Empreinte en cache */
+
+ union
+ {
+ /* ICT_NAME */
+ struct
+ {
+ const char *str;
+ size_t len;
+
+ } s_name;
+
+ /* ICT_OPERATOR_NAME */
+ struct
+ {
+ ItaniumOperatorType otype; /* Sélection dans l'union */
+
+ union
+ {
+ itanium_operator_info info; /* Opérateur simple */
+ itanium_component *trans; /* Type transtypé */
+
+ };
+
+ } operator;
+
+ /* ICT_NON_VIRTUAL_OFFSET */
+ /* ICT_VIRTUAL_OFFSET */
+ ssize_t offset; /* Décalage de fonction */
+
+ /* ICT_STD_SUBST */
+ /* ICT_TYPE */
+ GDataType *dtype; /* Type instancié */
+
+ /* ICT_QUALIFIED_TYPE */
+ struct
+ {
+ itanium_component *sub; /* Sous-élément */
+ TypeQualifier qualifier; /* Propriétés supplémentaires */
+
+ } qualified;
+
+ /* ICT_FUNCTION_TYPE */
+ struct
+ {
+ bool extern_c; /* Nature de la fonction */
+ itanium_component *args; /* Liste des arguments */
+
+ } function;
+
+ /* ICT_ARRAY */
+ struct
+ {
+ bool numbered_dim; /* Dimension numérique */
+ union
+ {
+ ssize_t dim_number; /* Taille du tableau */
+ itanium_component *dim_expr;/* La même, en expression */
+ };
+
+ itanium_component *atype; /* Type du tableau */
+
+ } array;
+
+ /* ICT_POINTER_TO_MEMBER */
+ struct
+ {
+ itanium_component *class; /* Classe d'appatenance */
+ itanium_component *member; /* Membre représenté */
+
+ } pmember;
+
+ /* ICT_* */
+ struct
+ {
+ itanium_component *left; /* Elément premier */
+ itanium_component *right; /* Elément second */
+
+ } binary;
+
+ /* ICT_* */
+ struct
+ {
+ itanium_component *first; /* Elément premier */
+ itanium_component *second; /* Elément second */
+ itanium_component *third; /* Elément troisième */
+
+ } ternary;
+
+ /* ICT_* */
+ itanium_component *unary; /* Sous-élément */
+
+ };
+
+};
+
+
+
+#endif /* _PLUGINS_ITANIUM_COMPONENT_INT_H */
diff --git a/plugins/itanium/component.c b/plugins/itanium/component.c
new file mode 100644
index 0000000..6e580f6
--- /dev/null
+++ b/plugins/itanium/component.c
@@ -0,0 +1,1842 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * component.c - représentation des composants extraits de l'ABI C++ Itanium
+ *
+ * Copyright (C) 2013-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "component.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <analysis/types/array.h>
+#include <analysis/types/cse.h>
+#include <analysis/types/expr.h>
+#include <analysis/types/override.h>
+#include <analysis/types/proto.h>
+#include <analysis/types/template.h>
+#include <common/extstr.h>
+#include <common/fnv1a.h>
+
+
+#include "component-int.h"
+
+
+
+
+/* Procédure à appliquer sur un composant visité */
+typedef void (* visit_comp_fc) (itanium_component *);
+
+
+#define reset_comp_hash(c) c->hash = 0
+
+
+/* Crée un composant de contexte Itanium complètement vierge. */
+static itanium_component *itd_alloc(void);
+
+/* Efface de la mémoire un composant de context Itanium. */
+static void itd_free(itanium_component *);
+
+/* Visite les composants en présence. */
+static void visit_comp(itanium_component *, visit_comp_fc);
+
+/* Traduit les composants de contexte Itanium en décalage. */
+static bool itd_translate_component_to_offset(const itanium_component *, call_offset_t *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un composant de contexte Itanium complètement vierge. *
+* *
+* Retour : Composant créé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_alloc(void)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = calloc(1, sizeof(itanium_component));
+
+ result->refcount = 1;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à supprimer. *
+* *
+* Description : Efface de la mémoire un composant de context Itanium. *
+* *
+* Retour : Composant créé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void itd_free(itanium_component *comp)
+{
+ free(comp);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à traiter. *
+* visitor = fonction à appliquer sur les composants présents. *
+* *
+* Description : Visite les composants en présence. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void visit_comp(itanium_component *comp, visit_comp_fc visitor)
+{
+ switch (comp->type)
+ {
+ case ICT_NAME:
+ break;
+
+ case ICT_STD_UNSCOPED_NAME:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_NESTED_NAME:
+ if (comp->binary.left != NULL)
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_TEMPLATE_NAME_ARGS:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_PREFIX_BINARY:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_TPREFIX_BINARY:
+ if (comp->binary.left != NULL)
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_OPERATOR_NAME:
+ if (comp->operator.otype == IOT_CAST)
+ visit_comp(comp->operator.trans, visitor);
+ break;
+
+ case ICT_SPECIAL_NAME_VTABLE:
+ case ICT_SPECIAL_NAME_VSTRUCT:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_NON_VIRTUAL_OFFSET:
+ case ICT_VIRTUAL_OFFSET:
+ break;
+
+ case ICT_DOUBLE_OFFSET:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+
+ case ICT_FUNCTION_THUNK:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_FUNCTION_COVARIANT_THUNK:
+ visit_comp(comp->ternary.first, visitor);
+ visit_comp(comp->ternary.second, visitor);
+ visit_comp(comp->ternary.third, visitor);
+ break;
+
+ case ICT_CONSTRUCTOR:
+ case ICT_DESSTRUCTOR:
+ break;
+
+ case ICT_TYPE:
+ break;
+
+ case ICT_QUALIFIED_TYPE:
+ visit_comp(comp->qualified.sub, visitor);
+ break;
+
+ case ICT_POINTER_TO:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_REFERENCE_TO:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_RVALUE_REFERENCE_TO:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_COMPLEX_PAIR:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_IMAGINARY:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_FUNCTION_TYPE:
+ visit_comp(comp->function.args, visitor);
+ break;
+
+ case ICT_FUNCTION_ENCODING:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_ARRAY:
+ if (!comp->array.numbered_dim)
+ visit_comp(comp->array.dim_expr, visitor);
+ visit_comp(comp->array.atype, visitor);
+ break;
+
+ case ICT_POINTER_TO_MEMBER:
+ visit_comp(comp->pmember.class, visitor);
+ visit_comp(comp->pmember.member, visitor);
+ break;
+
+ case ICT_TEMPLATE_ARGS:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_TYPES_LIST:
+
+ visit_comp(comp->binary.left, visitor);
+
+ if (comp->binary.right != NULL)
+ visit_comp(comp->binary.right, visitor);
+
+ break;
+
+ case ICT_EXPR_LIST:
+
+ visit_comp(comp->binary.left, visitor);
+
+ if (comp->binary.right != NULL)
+ visit_comp(comp->binary.right, visitor);
+
+ break;
+
+ case ICT_OPERATED_EXPRESSION:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_STD_SUBST:
+ break;
+
+ case ICT_COUNT:
+ break;
+
+ }
+
+ visitor(comp);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à mettre à jour. *
+* *
+* Description : Incrémente le nombre d'utilisation du composant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void itd_ref_comp(itanium_component *comp)
+{
+ void visit_for_ref(itanium_component *comp)
+ {
+ comp->refcount++;
+
+ }
+
+ visit_comp(comp, visit_for_ref);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à mettre à jour. *
+* *
+* Description : Décrémente le nombre d'utilisation du composant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void itd_unref_comp(itanium_component *comp)
+{
+ void visit_for_unref(itanium_component *comp)
+ {
+ if (--comp->refcount == 0)
+ {
+ if (comp->type == ICT_TYPE || comp->type == ICT_STD_SUBST)
+ g_object_unref(G_OBJECT(comp->dtype));
+
+ itd_free(comp);
+
+ }
+
+ }
+
+ visit_comp(comp, visit_for_unref);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à manipuler. *
+* *
+* Description : Détermine ou fournit l'empreinte d'un composant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+fnv64_t itd_hash_comp(itanium_component *comp)
+{
+ char *desc; /* Description du composant */
+
+ if (comp->hash == 0)
+ {
+ desc = itd_translate_component(comp, NULL);
+ comp->hash = fnv_64a_hash(desc);
+ free(desc);
+ }
+
+ return comp->hash;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type à définir pour le composant. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_with_type(ItaniumComponentType type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : str = chaîne de caractères à conserver. *
+* len = taille de l'identifiant à retrouver. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_name(const char *str, size_t len)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_NAME;
+ result->s_name.str = str;
+ result->s_name.len = len;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = information de base sur l'opérateur manipulé. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_operator(const itanium_operator_info *info)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_OPERATOR_NAME;
+ result->operator.otype = IOT_SIMPLE;
+ result->operator.info = *info;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = information de base sur l'opérateur manipulé. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_cast_operator(itanium_component *type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_OPERATOR_NAME;
+ result->operator.otype = IOT_CAST;
+ result->operator.trans = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium décodé à consulter. *
+* type = type d'opérateur représenté. *
+* *
+* Description : Donne des indications quant à un opérateur Itanium. *
+* *
+* Retour : Informations à interpréter selon le type transmis. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const void *itd_get_operator_info(const itanium_component *comp, ItaniumOperatorType *type)
+{
+ const void *result; /* Données à retourner */
+
+ assert(comp->type == ICT_OPERATOR_NAME);
+
+ *type = comp->operator.otype;
+
+ switch (*type)
+ {
+ case IOT_SIMPLE:
+ result = &comp->operator.info;
+ break;
+
+ case IOT_CAST:
+ result = comp->operator.trans;
+ break;
+
+ default:
+ assert(false);
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type exacte de décalage. *
+* offset = décalage extrait de l'encodage. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_offset(ItaniumComponentType type, ssize_t offset)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->offset = offset;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dtype = instance de type en place à conserver. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_type(GDataType *dtype)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_TYPE;
+ result->dtype = dtype;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : sub = composant de type en place à référencer. *
+* qualifier = propriétés supplémentaires pour le type. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_qualified_type(itanium_component *sub, TypeQualifier qualifier)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ if (qualifier == TQF_NONE)
+ result = sub;
+
+ else
+ {
+ result = itd_alloc();
+
+ result->type = ICT_QUALIFIED_TYPE;
+ result->qualified.sub = sub;
+ result->qualified.qualifier = qualifier;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : sub = composant de type en place à référencer. *
+* qualifier = propriétés supplémentaires pour le type. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_function_type(bool extern_c, itanium_component *args)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_FUNCTION_TYPE;
+ result->function.extern_c = extern_c;
+ result->function.args = args;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : number = dimension du tableau. *
+* type = type des membres du même tableau. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_array_with_dim_number(ssize_t number, itanium_component *type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_ARRAY;
+ result->array.numbered_dim = true;
+ result->array.dim_number = number;
+ result->array.atype = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = dimension du tableau. *
+* type = type des membres du même tableau. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_array_with_dim_expr(itanium_component *expr, itanium_component *type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_ARRAY;
+ result->array.numbered_dim = false;
+ result->array.dim_expr = expr;
+ result->array.atype = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe d'appatenance. *
+* member = membre représenté. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_pointer_to_memeber_type(itanium_component *class, itanium_component *member)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_POINTER_TO_MEMBER;
+ result->pmember.class = class;
+ result->pmember.member = member;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du composant à mettre en place. *
+* unary = sous-composant à associer. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_unary(ItaniumComponentType type, itanium_component *unary)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->unary = unary;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du composant à mettre en place. *
+* left = premier composant à associer. *
+* right = second composant à associer. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_binary(ItaniumComponentType type, itanium_component *left, itanium_component *right)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->binary.left = left;
+ result->binary.right = right;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du composant à mettre en place. *
+* left = second composant à associer. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_append_right_to_binary(ItaniumComponentType type, itanium_component *parent, itanium_component *left)
+{
+ itanium_component *result; /* Composant à renvoyer */
+ itanium_component *iter; /* Boucle de parcours */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->binary.left = left;
+ result->binary.right = NULL;
+
+ if (parent != NULL)
+ {
+ for (iter = parent; iter->binary.right != NULL; iter = iter->binary.right)
+ reset_comp_hash(iter);
+ iter->binary.right = result;
+ }
+
+ return (parent != NULL ? parent : result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du composant à mettre en place. *
+* c0 = premier composant à associer. *
+* c1 = second composant à associer. *
+* c2 = troisième composant à associer. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_ternary(ItaniumComponentType type, itanium_component *c0, itanium_component *c1, itanium_component *c2)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->ternary.first = c0;
+ result->ternary.second = c1;
+ result->ternary.third = c2;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à mettre à jour. *
+* type = type à redéfinir pour le composant. *
+* *
+* Description : Modifie légèrement le type d'un composant donné. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void itd_set_type(itanium_component *comp, ItaniumComponentType type)
+{
+ comp->type = type;
+
+ reset_comp_hash(comp);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à consulter. *
+* *
+* Description : Fournit le type d'un composant issu d'un contexte Itanium. *
+* *
+* Retour : Type enregistré. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+ItaniumComponentType itd_get_component_type(const itanium_component *comp)
+{
+ return comp->type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = second composant à associer. *
+* base = éventuelle base à compléter ou NULL si aucune. *
+* *
+* Description : Traduit les composants de contexte Itanium. *
+* *
+* Retour : Traduction en format humainement lisible effectuée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *itd_translate_component(const itanium_component *comp, char *base)
+{
+ char *result; /* Chaîne à retourner */
+ char *name; /* Désignation à copier */
+ const itanium_component *sub; /* Sous-partie de composant */
+ ItaniumOperatorType otype; /* Type d'opérateur */
+ const void *odata; /* Données associées */
+ const itanium_operator_info *simple; /* Données d'opérateur simple */
+ char *tmp; /* Transcription temporaire */
+
+ switch (comp->type)
+ {
+ case ICT_NAME:
+ result = strnadd(base, comp->s_name.str, comp->s_name.len);
+ break;
+
+ case ICT_STD_UNSCOPED_NAME:
+ result = stradd(base, "std::");
+ result = itd_translate_component(comp->unary, result);
+ break;
+
+ case ICT_NESTED_NAME:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ result = itd_translate_component(comp->binary.left, base);
+ result = itd_translate_component(comp->binary.right, result);
+ }
+
+ else
+ {
+ if (comp->binary.left != NULL)
+ {
+ result = itd_translate_component(comp->binary.left, base);
+ result = stradd(result, "::");
+ }
+ else
+ result = base;
+
+ result = itd_translate_component(comp->binary.right, result);
+
+ }
+
+ break;
+
+ case ICT_TEMPLATE_NAME_ARGS:
+ result = itd_translate_component(comp->binary.left, base);
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_PREFIX_BINARY:
+ result = itd_translate_component(comp->binary.left, base);
+ if (comp->binary.right->type != ICT_TEMPLATE_ARGS)
+ result = stradd(result, "::");
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_TPREFIX_BINARY:
+ if (comp->binary.left != NULL)
+ {
+ result = itd_translate_component(comp->binary.left, base);
+ if (comp->binary.right->type != ICT_TEMPLATE_ARGS)
+ result = stradd(result, "::");
+ }
+ else
+ result = base;
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_OPERATOR_NAME:
+ switch (comp->operator.otype)
+ {
+ case IOT_SIMPLE:
+ result = stradd(base, "operator");
+ result = stradd(result, comp->operator.info.name);
+ break;
+ case IOT_CAST:
+ result = stradd(base, "(");
+ sub = (const itanium_component *)odata;
+ result = itd_translate_component(comp->operator.trans, result);
+ result = stradd(result, ")");
+ break;
+ default:
+ result = NULL;
+ break;
+ }
+ break;
+
+ case ICT_SPECIAL_NAME_VTABLE:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, "::vtable");
+ break;
+
+ case ICT_SPECIAL_NAME_VSTRUCT:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, "::vstruct");
+ break;
+
+ case ICT_NON_VIRTUAL_OFFSET:
+ case ICT_VIRTUAL_OFFSET:
+ asprintf(&tmp, "%zd", comp->offset);
+ result = stradd(base, tmp);
+ free(tmp);
+ break;
+
+ case ICT_DOUBLE_OFFSET:
+ result = itd_translate_component(comp->binary.left, base);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_FUNCTION_THUNK:
+ result = itd_translate_component(comp->binary.left, base);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_FUNCTION_COVARIANT_THUNK:
+ result = itd_translate_component(comp->ternary.first, base);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->ternary.second, result);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->ternary.third, result);
+ break;
+
+ case ICT_CONSTRUCTOR:
+ result = stradd(base, "<ctor>");
+ break;
+
+ case ICT_DESSTRUCTOR:
+ result = stradd(base, "<dtor>");
+ break;
+
+ case ICT_TYPE:
+ name = g_data_type_to_string(comp->dtype, true);
+ result = stradd(base, name);
+ free(name);
+ break;
+
+ case ICT_QUALIFIED_TYPE:
+
+ switch (comp->qualified.qualifier)
+ {
+ case TQF_RESTRICT:
+ result = stradd(base, "restrict ");
+ break;
+ case TQF_VOLATILE:
+ result = stradd(base, "volatile ");
+ break;
+ case TQF_CONST:
+ result = stradd(base, "const ");
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ result = itd_translate_component(comp->qualified.sub, result);
+
+ break;
+
+ case ICT_POINTER_TO:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, " *");
+ break;
+
+ case ICT_REFERENCE_TO:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, " &");
+ break;
+
+ case ICT_RVALUE_REFERENCE_TO:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, " &");
+ break;
+
+ case ICT_COMPLEX_PAIR:
+ result = stradd(base, "<?>");
+ result = itd_translate_component(comp->unary, result);
+ break;
+
+ case ICT_IMAGINARY:
+ result = stradd(base, "<?>");
+ result = itd_translate_component(comp->unary, result);
+ break;
+
+ case ICT_FUNCTION_TYPE:
+ result = stradd(base, "(*) (");
+ result = itd_translate_component(comp->function.args, result);
+ result = stradd(result, ")");
+ break;
+
+ case ICT_FUNCTION_ENCODING:
+
+ result = stradd(base, "???");
+
+ result = stradd(result, " ");
+
+ result = itd_translate_component(comp->binary.left, result);
+
+ result = stradd(result, "(");
+
+ result = itd_translate_component(comp->binary.right, result);
+
+ result = stradd(result, ")");
+
+ break;
+
+ case ICT_ARRAY:
+
+ result = itd_translate_component(comp->array.atype, base);
+
+ result = stradd(result, "[");
+
+ if (comp->array.numbered_dim)
+ {
+ asprintf(&tmp, "%zd", comp->array.dim_number);
+ result = stradd(result, tmp);
+ free(tmp);
+ }
+
+ else
+ result = itd_translate_component(comp->array.dim_expr, result);
+
+ result = stradd(result, "]");
+
+ break;
+
+ case ICT_POINTER_TO_MEMBER:
+ result = itd_translate_component(comp->pmember.class, base);
+ result = stradd(result, "::");
+ result = itd_translate_component(comp->pmember.member, result);
+ break;
+
+ case ICT_TEMPLATE_ARGS:
+ result = stradd(base, "<");
+ result = itd_translate_component(comp->unary, result);
+ result = stradd(result, ">");
+ break;
+
+ case ICT_TYPES_LIST:
+
+ result = itd_translate_component(comp->binary.left, base);
+
+ if (comp->binary.right != NULL)
+ {
+ result = stradd(result, ", ");
+ result = itd_translate_component(comp->binary.right, result);
+ }
+
+ break;
+
+ case ICT_EXPR_LIST:
+
+ /**
+ * A priori traité en amont.
+ */
+
+ result = itd_translate_component(comp->binary.left, base);
+
+ if (comp->binary.right != NULL)
+ {
+ result = stradd(result, ", ");
+ result = itd_translate_component(comp->binary.right, result);
+ }
+
+ break;
+
+ case ICT_OPERATED_EXPRESSION:
+
+ odata = itd_get_operator_info(comp->binary.left, &otype);
+
+ sub = comp->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+
+ switch (otype)
+ {
+ case IOT_SIMPLE:
+
+ simple = (const itanium_operator_info *)odata;
+
+ switch (simple->args)
+ {
+ case 1:
+ result = stradd(base, simple->name);
+ result = itd_translate_component(sub->binary.left, result);
+ assert(sub->binary.right == NULL);
+ break;
+
+ case 2:
+
+ result = itd_translate_component(sub->binary.left, base);
+
+ result = stradd(result, simple->name);
+
+ sub = sub->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+ result = itd_translate_component(sub->binary.left, result);
+ assert(sub->binary.right == NULL);
+ break;
+
+ case 3:
+
+ result = itd_translate_component(sub->binary.left, base);
+
+ result = stradd(result, simple->name);
+
+ sub = sub->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+ result = itd_translate_component(sub->binary.left, result);
+
+ result = stradd(result, ":");
+
+ sub = sub->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+ result = itd_translate_component(sub->binary.left, result);
+ assert(sub->binary.right == NULL);
+
+ break;
+
+ }
+
+ break;
+
+ case IOT_CAST:
+ result = stradd(base, "(");
+ sub = (const itanium_component *)odata;
+ result = itd_translate_component(sub, result);
+ result = stradd(result, ")");
+ break;
+
+ default:
+ result = NULL;
+ break;
+
+ }
+
+ break;
+
+ case ICT_STD_SUBST:
+ name = g_data_type_to_string(comp->dtype, true);
+ result = stradd(base, name);
+ free(name);
+ break;
+
+ case ICT_COUNT:
+ result = base;
+ break;
+
+ }
+
+
+
+ return result;
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium à traduire en décalage. *
+* off = réceptacle pour les informations traduites. *
+* *
+* Description : Traduit les composants de contexte Itanium en décalage. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool itd_translate_component_to_offset(const itanium_component *comp, call_offset_t *off)
+{
+ bool result; /* Bilan à retourner */
+
+ if (comp->type == ICT_DOUBLE_OFFSET)
+ {
+ result = comp->binary.left->type == ICT_NON_VIRTUAL_OFFSET
+ && comp->binary.right->type == ICT_VIRTUAL_OFFSET;
+
+ assert(result);
+
+ if (result)
+ {
+ off->values[0] = comp->binary.left->offset;
+ off->values[1] = comp->binary.right->offset;
+ off->virtual = true;
+ }
+
+ }
+
+ else if (comp->type == ICT_NON_VIRTUAL_OFFSET)
+ {
+ result = true;
+
+ off->values[0] = comp->offset;
+ off->virtual = false;
+
+ }
+
+ else
+ result = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium à traduire en type. *
+* *
+* Description : Traduit les composants de contexte Itanium en type. *
+* *
+* Retour : Traduction en type décodé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDataType *itd_translate_component_to_type(const itanium_component *comp)
+{
+ GDataType *result; /* Type à retourner */
+ char *name; /* Attribution finale */
+ GDataType *ns; /* Espace de noms d'un type */
+ call_offset_t off0; /* Décalage #0 */
+ call_offset_t off1; /* Décalage #1 */
+ itanium_component *iter; /* Boucle de parcours */
+ GDataType *arg; /* Argument de prototype */
+ GDataType *members; /* Type de membres de tableau */
+ GDataType *param; /* Paramètre de gabarit */
+
+ /* Pour GCC !? */
+ result = NULL;
+
+ switch (comp->type)
+ {
+ case ICT_NAME:
+ name = itd_translate_component(comp, NULL);
+ result = g_class_enum_type_new(CET_STRUCT, name);
+ break;
+
+ case ICT_STD_UNSCOPED_NAME:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ {
+ ns = g_class_enum_type_new(CET_NAMESPACE, strdup("std"));
+ g_data_type_set_namespace(result, ns, "::");
+ }
+ break;
+
+ case ICT_NESTED_NAME:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ name = itd_translate_component(comp->binary.right, name);
+
+ result = g_class_enum_type_new(CET_CLASS, name);
+
+ }
+
+ else
+ {
+ if (comp->binary.left != NULL)
+ {
+ ns = itd_translate_component_to_type(comp->binary.left);
+ if (ns == NULL)
+ {
+ result = NULL;
+ break;
+ }
+ }
+ else
+ ns = NULL;
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL && ns != NULL)
+ g_data_type_set_namespace(result, ns, "::");
+
+ }
+
+ break;
+
+ case ICT_TEMPLATE_NAME_ARGS:
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ g_template_type_set_name(G_TEMPLATE_TYPE(result), name);
+ }
+
+ break;
+
+ case ICT_PREFIX_BINARY:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ name = itd_translate_component(comp->binary.right, name);
+
+ result = g_class_enum_type_new(CET_CLASS, name);
+
+ }
+
+ else
+ {
+ ns = itd_translate_component_to_type(comp->binary.left);
+ if (ns == NULL)
+ {
+ result = NULL;
+ break;
+ }
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL)
+ g_data_type_set_namespace(result, ns, "::");
+
+ }
+
+ break;
+
+ case ICT_TPREFIX_BINARY:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ name = itd_translate_component(comp->binary.right, name);
+
+ result = g_class_enum_type_new(CET_CLASS, name);
+
+ }
+
+ else
+ {
+ if (comp->binary.left != NULL)
+ {
+ ns = itd_translate_component_to_type(comp->binary.left);
+ if (ns == NULL)
+ {
+ result = NULL;
+ break;
+ }
+
+ }
+ else
+ ns = NULL;
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL)
+ {
+ if (ns != NULL)
+ g_data_type_set_namespace(result, ns, "::");
+ }
+ else
+ {
+ if (ns != NULL)
+ g_object_unref(G_OBJECT(ns));
+ }
+
+ }
+
+ break;
+
+ case ICT_OPERATOR_NAME:
+ result = NULL;
+ break;
+
+ case ICT_SPECIAL_NAME_VTABLE:
+
+ ns = itd_translate_component_to_type(comp->unary);
+
+ if (ns == NULL)
+ result = NULL;
+
+ else
+ {
+ result = g_class_enum_type_new(CET_VIRTUAL_TABLE, NULL);
+ g_data_type_set_namespace(result, ns, "::");
+ }
+
+ break;
+
+ case ICT_SPECIAL_NAME_VSTRUCT:
+
+ ns = itd_translate_component_to_type(comp->unary);
+
+ if (ns == NULL)
+ result = NULL;
+
+ else
+ {
+ result = g_class_enum_type_new(CET_VIRTUAL_STRUCT, NULL);
+ g_data_type_set_namespace(result, ns, "::");
+ }
+
+ break;
+
+ case ICT_NON_VIRTUAL_OFFSET:
+ case ICT_VIRTUAL_OFFSET:
+ case ICT_DOUBLE_OFFSET:
+ result = NULL;
+ break;
+
+ case ICT_FUNCTION_THUNK:
+
+ if (!itd_translate_component_to_offset(comp->binary.right, &off0))
+ {
+ result = NULL;
+ break;
+ }
+
+ result = itd_translate_component_to_type(comp->binary.left);
+
+ if (result != NULL)
+ result = g_override_type_new(result, &off0);
+
+ break;
+
+ case ICT_FUNCTION_COVARIANT_THUNK:
+
+ if (!itd_translate_component_to_offset(comp->ternary.second, &off0))
+ {
+ result = NULL;
+ break;
+ }
+
+ if (!itd_translate_component_to_offset(comp->ternary.third, &off1))
+ {
+ result = NULL;
+ break;
+ }
+
+ result = itd_translate_component_to_type(comp->ternary.first);
+
+ if (result != NULL)
+ result = g_override_type_new_with_covariant(result, &off0, &off1);
+
+ break;
+
+ case ICT_CONSTRUCTOR:
+ case ICT_DESSTRUCTOR:
+ result = NULL;
+ break;
+
+ case ICT_TYPE:
+ result = g_data_type_dup(comp->dtype);
+ break;
+
+ case ICT_QUALIFIED_TYPE:
+ result = itd_translate_component_to_type(comp->qualified.sub);
+ if (result != NULL)
+ g_data_type_add_qualifier(result, comp->qualified.qualifier);
+ break;
+
+ case ICT_POINTER_TO:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL && !G_IS_PROTO_TYPE(result))
+ result = g_encapsulated_type_new(ECT_POINTER, result);
+ break;
+
+ case ICT_REFERENCE_TO:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_REFERENCE, result);
+ break;
+
+ case ICT_RVALUE_REFERENCE_TO:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_RVALUE_REF, result);
+ break;
+
+ case ICT_COMPLEX_PAIR:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_COMPLEX, result);
+ break;
+
+ case ICT_IMAGINARY:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_IMAGINARY, result);
+ break;
+
+ case ICT_FUNCTION_TYPE:
+
+ result = g_proto_type_new();
+
+ assert(comp->function.args->type == ICT_TYPES_LIST);
+
+ for (iter = comp->function.args; iter != NULL && result != NULL; iter = iter->binary.right)
+ {
+ assert(iter->type == ICT_TYPES_LIST);
+
+ arg = itd_translate_component_to_type(iter->binary.left);
+
+ if (arg == NULL)
+ {
+ g_object_unref(G_OBJECT(result));
+ result = NULL;
+ }
+
+ else
+ {
+ if (iter == comp->function.args)
+ g_proto_type_set_return_type(G_PROTO_TYPE(result), arg);
+
+ else
+ g_proto_type_add_arg(G_PROTO_TYPE(result), arg);
+ }
+
+ }
+
+ break;
+
+ case ICT_FUNCTION_ENCODING:
+ result = NULL;
+ break;
+
+ case ICT_ARRAY:
+
+ members = itd_translate_component_to_type(comp->array.atype);
+
+ if (members == NULL)
+ result = NULL;
+
+ else
+ {
+ result = g_array_type_new(members);
+
+ if (comp->array.numbered_dim)
+ g_array_type_set_dimension_number(G_ARRAY_TYPE(result), comp->array.dim_number);
+
+ else
+ g_array_type_set_dimension_expression(G_ARRAY_TYPE(result),
+ itd_translate_component(comp, NULL));
+
+ }
+
+ break;
+
+ case ICT_POINTER_TO_MEMBER:
+
+ ns = itd_translate_component_to_type(comp->pmember.class);
+
+ if (ns == NULL)
+ result = NULL;
+
+ else
+ {
+ result = itd_translate_component_to_type(comp->pmember.member);
+
+ if (result == NULL)
+ g_object_unref(G_OBJECT(ns));
+
+ else
+ g_data_type_set_namespace(result, ns, "::");
+
+ }
+
+ break;
+
+ case ICT_TEMPLATE_ARGS:
+
+ assert(comp->unary->type == ICT_TYPES_LIST);
+
+ result = g_template_type_new();
+
+ for (iter = comp->unary; iter != NULL && result != NULL; iter = iter->binary.right)
+ {
+ assert(iter->type == ICT_TYPES_LIST);
+
+ param = itd_translate_component_to_type(iter->binary.left);
+
+ if (param == NULL)
+ {
+ g_object_unref(G_OBJECT(result));
+ result = NULL;
+ }
+ else
+ g_template_type_add_param(G_TEMPLATE_TYPE(result), param);
+
+ }
+
+ break;
+
+ case ICT_TYPES_LIST:
+
+ /**
+ * Les listes doient être rassemblées par l'appelant !
+ */
+
+ assert(false);
+ result = NULL;
+ break;
+
+ case ICT_EXPR_LIST:
+
+ /**
+ * Les listes doient être rassemblées par l'appelant !
+ */
+
+ assert(false);
+ result = NULL;
+ break;
+
+ case ICT_OPERATED_EXPRESSION:
+ result = g_expr_type_new(itd_translate_component(comp, NULL));
+ break;
+
+ case ICT_STD_SUBST:
+ result = g_data_type_dup(comp->dtype);
+ break;
+
+ case ICT_COUNT:
+ assert(false);
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium à traduire en routine. *
+* *
+* Description : Traduit les composants de contexte Itanium en routine. *
+* *
+* Retour : Traduction en routine décodée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinRoutine *itd_translate_component_to_routine(const itanium_component *comp)
+{
+ GBinRoutine *result; /* Routine à retourner */
+ bool has_ret; /* Type de retour présent ? */
+ itanium_component *name; /* Désignation de la routine */
+ char *desc; /* Description humaine */
+ GDataType *ns; /* Espace de noms de la routine*/
+ itanium_component *args; /* Liste de ses arguments */
+ itanium_component *iter; /* Boucle de parcours */
+ GDataType *type; /* Type d'un argument */
+ GBinVariable *arg; /* Argument à ajouter */
+
+ if (comp->type != ICT_FUNCTION_ENCODING)
+ goto bad_encoding;
+
+ result = g_binary_routine_new();
+
+ /* Nom de la routine */
+
+ name = comp->binary.left;
+
+ /**
+ * A la fin de § 5.1.3 ("Operator Encodings") est précisé :
+ *
+ * If the conversion operator is a member template, the result type will
+ * appear before the template parameters.
+ *
+ * On note donc cette particularité.
+ */
+
+ has_ret = (name->type == ICT_TEMPLATE_NAME_ARGS);
+
+ switch (name->type)
+ {
+ case ICT_NAME:
+ g_binary_routine_set_name(result, itd_translate_component(name, NULL));
+ break;
+
+ case ICT_NESTED_NAME:
+ case ICT_TEMPLATE_NAME_ARGS:
+
+ type = itd_translate_component_to_type(name);
+ if (type == NULL) goto unsupported_encoding;
+
+ ns = g_data_type_get_namespace(type);
+
+ g_data_type_set_namespace(type, NULL, NULL);
+
+ desc = g_data_type_to_string(type, true);
+
+ g_object_unref(G_OBJECT(type));
+
+ g_binary_routine_set_name(result, desc);
+
+ g_binary_routine_set_namespace(result, ns, "::");
+
+ break;
+
+ case ICT_OPERATOR_NAME:
+ g_binary_routine_set_name(result, itd_translate_component(name, NULL));
+ break;
+
+ default:
+ goto unsupported_encoding;
+ break;
+
+ }
+
+ /* Liste d'arguments */
+
+ args = comp->binary.right;
+
+ if (args->type != ICT_TYPES_LIST)
+ goto unsupported_encoding;
+
+ for (iter = args; iter != NULL; iter = iter->binary.right)
+ {
+ type = itd_translate_component_to_type(iter->binary.left);
+
+ if (type == NULL)
+ goto unsupported_encoding;
+
+ if (iter == args && has_ret)
+ g_binary_routine_set_return_type(result, type);
+
+ else
+ {
+ arg = g_binary_variable_new(type);
+ g_binary_routine_add_arg(result, arg);
+ }
+
+ }
+
+ return result;
+
+ unsupported_encoding:
+
+ g_object_unref(G_OBJECT(result));
+
+ bad_encoding:
+
+ return NULL;
+
+}
diff --git a/src/mangling/itanium/component.h b/plugins/itanium/component.h
index 4d50d1f..f921ff9 100644
--- a/src/mangling/itanium/component.h
+++ b/plugins/itanium/component.h
@@ -21,8 +21,8 @@
*/
-#ifndef _FORMAT_MANGLING_ITANIUM_COMPONENT_H
-#define _FORMAT_MANGLING_ITANIUM_COMPONENT_H
+#ifndef _PLUGINS_ITANIUM_COMPONENT_H
+#define _PLUGINS_ITANIUM_COMPONENT_H
#include <ctype.h>
@@ -32,9 +32,9 @@
#include <sys/types.h>
-#include "context.h"
-#include "../../analysis/type.h"
-#include "../../common/fnv1a.h"
+#include <analysis/routine.h>
+#include <analysis/type.h>
+#include <common/fnv1a.h>
@@ -42,29 +42,38 @@
typedef enum _ItaniumComponentType
{
/**
- * Représentation d'une règle vide.
+ * Chaîne de caractère, terminée par un octet nul.
*/
- ICT_EMPTY,
+ ICT_NAME,
/**
- * Chaîne de caractère, terminée par un octet nul.
+ * Nom avec préfixe standard.
+ * Le nom en question est placé dans le champ unary.
*/
- ICT_NAME,
- ICT_STD_SUBST,
+ ICT_STD_UNSCOPED_NAME,
/**
* Noms imbriqués, en deux parties : 'binary'.
+ * En cas de préfixe nul, le composant gauche peut être nul.
*/
ICT_NESTED_NAME,
+
+ /**
+ * Noms imbriqués, en deux parties : 'binary'.
+ * C'est normalement le seul réceptacle pour les composants issus
+ * de itd_template_args (sur la branche droite).
+ */
ICT_TEMPLATE_NAME_ARGS,
/**
- * Deux types de préfixes : un ou deux éléments.
- * -> 'unary' ou 'binary'
+ * Type avec préfixes : deux éléments, dans 'binary'
*/
- ICT_PREFIX_UNARY,
ICT_PREFIX_BINARY,
- ICT_TPREFIX_UNARY,
+
+ /**
+ * Préfixes à deux éléments.
+ * En cas de préfixe nul, le composant gauche peut être nul.
+ */
ICT_TPREFIX_BINARY,
/**
@@ -72,15 +81,23 @@ typedef enum _ItaniumComponentType
*/
ICT_OPERATOR_NAME,
+ /**
+ * Particularité des notions d'objets. Les informations utiles
+ * sont rassemblées dans le champ unary.
+ */
+ ICT_SPECIAL_NAME_VTABLE,
+ ICT_SPECIAL_NAME_VSTRUCT,
/**
* Fonctions virtuelles.
* -> décalage : 'offset'.
+ * -> double décalage : 'binary'.
* -> fonctions simples : 'binary'.
* -> fonctions complexes : 'ternary'.
*/
ICT_NON_VIRTUAL_OFFSET,
ICT_VIRTUAL_OFFSET,
+ ICT_DOUBLE_OFFSET,
ICT_FUNCTION_THUNK,
ICT_FUNCTION_COVARIANT_THUNK,
@@ -96,6 +113,12 @@ typedef enum _ItaniumComponentType
ICT_TYPE,
/**
+ * Type qualifié ; les infos utilies sont explicitement
+ * conservées dans le champ qualified.
+ */
+ ICT_QUALIFIED_TYPE,
+
+ /**
* Différentes références vers un sous-type.
* Le champ impacté est 'unary'.
*/
@@ -106,6 +129,12 @@ typedef enum _ItaniumComponentType
ICT_IMAGINARY,
/**
+ * Prototype de fonction.
+ * Le champ impacté est 'function'.
+ */
+ ICT_FUNCTION_TYPE,
+
+ /**
* Fonction (nom + retour/paramètres), sous forme binaire :
* -> left = function name
* -> right = bare-function-type
@@ -113,6 +142,18 @@ typedef enum _ItaniumComponentType
ICT_FUNCTION_ENCODING,
/**
+ * Définition d'un tableau. Les indications de dimensions peuvent
+ * prendre plusieurs formes, et sont rassemblées dans le champ array.
+ */
+ ICT_ARRAY,
+
+ /**
+ * Pointeur vers un membre. Comme l'espace de noms associé est encodé
+ * de façon spéciale, un champ est dédié à ce composant : pmember.
+ */
+ ICT_POINTER_TO_MEMBER,
+
+ /**
* Liste d'arguments pour templates, à encadrer par des chevrons.
* 'unary' pointe vers la liste des éléments.
*/
@@ -125,6 +166,26 @@ typedef enum _ItaniumComponentType
*/
ICT_TYPES_LIST,
+ /**
+ * Liste d'expressions, sous forme binaire comme pour ICT_TYPES_LIST :
+ * -> left = élément de la liste de types.
+ * -> right = reste de la liste de types.
+ */
+ ICT_EXPR_LIST,
+
+ /**
+ * Liste de types, sous forme binaire :
+ * -> left = composant d'opérateur.
+ * -> right = liste d'expressions.
+ */
+ ICT_OPERATED_EXPRESSION,
+
+ /**
+ * Substitution avec préfixe standard. Le résultat est prêt dans le champ
+ * dtype.
+ */
+ ICT_STD_SUBST,
+
ICT_COUNT
} ItaniumComponentType;
@@ -165,39 +226,53 @@ void itd_unref_comp(itanium_component *);
/* Détermine ou fournit l'empreinte d'un composant. */
fnv64_t itd_hash_comp(itanium_component *);
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_with_type(ItaniumComponentType);
-
-/* 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_name(const char *, size_t);
/* Construit un composant dans un contexte Itanium. */
-itanium_component *itd_make_empty(GItaniumDContext *);
+itanium_component *itd_make_operator(const itanium_operator_info *);
/* Construit un composant dans un contexte Itanium. */
-itanium_component *itd_make_name(GItaniumDContext *, const char *, size_t);
+itanium_component *itd_make_cast_operator(itanium_component *);
+
+/* Donne des indications quant à un opérateur Itanium. */
+const void *itd_get_operator_info(const itanium_component *, ItaniumOperatorType *);
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_offset(ItaniumComponentType, ssize_t);
/* Construit un composant dans un contexte Itanium. */
-itanium_component *itd_make_operator(GItaniumDContext *, const itanium_operator_info *);
+itanium_component *itd_make_type(GDataType *);
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_qualified_type(itanium_component *, TypeQualifier);
/* Construit un composant dans un contexte Itanium. */
-itanium_component *itd_make_offset(GItaniumDContext *, ItaniumComponentType, ssize_t);
+itanium_component *itd_make_function_type(bool, itanium_component *);
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_array_with_dim_number(ssize_t, itanium_component *);
/* Construit un composant dans un contexte Itanium. */
-itanium_component *itd_make_type(GItaniumDContext *, GDataType *);
+itanium_component *itd_make_array_with_dim_expr(itanium_component *, itanium_component *);
/* Construit un composant dans un contexte Itanium. */
-itanium_component *itd_make_binary(GItaniumDContext *, ItaniumComponentType, itanium_component *, itanium_component *);
+itanium_component *itd_make_pointer_to_memeber_type(itanium_component *, itanium_component *);
/* Construit un composant dans un contexte Itanium. */
-itanium_component *itd_append_right_to_binary(GItaniumDContext *, ItaniumComponentType, itanium_component *, itanium_component *);
+itanium_component *itd_make_unary(ItaniumComponentType, itanium_component *);
/* Construit un composant dans un contexte Itanium. */
-itanium_component *itd_make_unary(GItaniumDContext *, ItaniumComponentType, itanium_component *);
+itanium_component *itd_make_binary(ItaniumComponentType, itanium_component *, itanium_component *);
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_append_right_to_binary(ItaniumComponentType, itanium_component *, itanium_component *);
+/* Construit un composant dans un contexte Itanium. */
+itanium_component *itd_make_ternary(ItaniumComponentType, itanium_component *, itanium_component *, itanium_component *);
/* Modifie légèrement le type d'un composant donné. */
void itd_set_type(itanium_component *, ItaniumComponentType);
@@ -206,8 +281,14 @@ void itd_set_type(itanium_component *, ItaniumComponentType);
ItaniumComponentType itd_get_component_type(const itanium_component *);
/* Traduit les composants de contexte Itanium. */
-char *itd_translate_component(GItaniumDContext *, const itanium_component *, char *);
+char *itd_translate_component(const itanium_component *, char *);
+
+/* Traduit les composants de contexte Itanium en type. */
+GDataType *itd_translate_component_to_type(const itanium_component *);
+
+/* Traduit les composants de contexte Itanium en routine. */
+GBinRoutine *itd_translate_component_to_routine(const itanium_component *);
-#endif /* _FORMAT_MANGLING_ITANIUM_COMPONENT_H */
+#endif /* _PLUGINS_ITANIUM_COMPONENT_H */
diff --git a/src/mangling/itanium/context.c b/plugins/itanium/context.c
index a0c3614..1d2c365 100644
--- a/src/mangling/itanium/context.c
+++ b/plugins/itanium/context.c
@@ -24,36 +24,26 @@
#include "context.h"
+#include <assert.h>
#include <malloc.h>
#include <string.h>
-#include "abi.h"
-#include "component-int.h"
-#include "../context-int.h"
-
+#include <mangling/context-int.h>
-/* Taille des extensions d'allocation */
-#define ITCOMP_ALLOC_BULK 200
+#include "abi.h"
+#include "component-int.h"
-/* Marqueur de fin pour les disponibilités */
-#define ITCOMP_INVALID ((size_t)-1)
/* Contexte de décodage Itanium (instance) */
-struct _GItaniumDContext
+struct _GItaniumDemangling
{
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 **template_args; /* Paramètres de modèle */
+ size_t targs_count; /* Quantité utilisée */
itanium_component **substitutions; /* Table de substitutions */
size_t subst_count; /* Quantité utilisée */
@@ -61,16 +51,41 @@ struct _GItaniumDContext
};
/* Contexte de décodage Itanium (classe) */
-struct _GItaniumDContextClass
+struct _GItaniumDemanglingClass
{
GDemanglingContextClass parent; /* A laisser en premier */
};
+/* Initialise la classe des contextes de décodage. */
+static void g_itanium_demangling_class_init(GItaniumDemanglingClass *);
+
+/* Initialise une instance de contexte pour décodage. */
+static void g_itanium_demangling_init(GItaniumDemangling *);
+
+/* Supprime toutes les références externes. */
+static void g_itanium_demangling_dispose(GItaniumDemangling *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_itanium_demangling_finalize(GItaniumDemangling *);
+
+/* Prépare l'environnement de contexte pour un décodage Itanium. */
+static void g_itanium_demangling_prepare(GItaniumDemangling *);
+
+/* Valide un composant final issu d'un décodage Itanium. */
+static void g_itanium_demangling_check(GItaniumDemangling *, itanium_component **);
+
+/* Décode une définition de type pour Itanium. */
+static GDataType *g_itanium_demangling_decode_type(GItaniumDemangling *);
+
+/* Décode une définition de routine pour Itanium. */
+static GBinRoutine *g_itanium_demangling_decode_routine(GItaniumDemangling *);
+
+
/* Indique le type défini pour un contexte de décodage. */
-G_DEFINE_TYPE(GItaniumDContext, g_itanium_dcontext, G_TYPE_DEMANGLING_CONTEXT);
+G_DEFINE_TYPE(GItaniumDemangling, g_itanium_demangling, G_TYPE_DEMANGLING_CONTEXT);
/******************************************************************************
@@ -85,8 +100,20 @@ G_DEFINE_TYPE(GItaniumDContext, g_itanium_dcontext, G_TYPE_DEMANGLING_CONTEXT);
* *
******************************************************************************/
-static void g_itanium_dcontext_class_init(GItaniumDContextClass *klass)
+static void g_itanium_demangling_class_init(GItaniumDemanglingClass *klass)
{
+ GObjectClass *object; /* Autre version de la classe */
+ GDemanglingContextClass *context; /* Version de base du contexte */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_itanium_demangling_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_itanium_demangling_finalize;
+
+ context = G_DEMANGLING_CONTEXT_CLASS(klass);
+
+ context->decode_type = (decode_type_fc)g_itanium_demangling_decode_type;
+ context->decode_routine = (decode_routine_fc)g_itanium_demangling_decode_routine;
}
@@ -103,216 +130,170 @@ static void g_itanium_dcontext_class_init(GItaniumDContextClass *klass)
* *
******************************************************************************/
-static void g_itanium_dcontext_init(GItaniumDContext *context)
+static void g_itanium_demangling_init(GItaniumDemangling *context)
{
- context->last_used = ITCOMP_INVALID;
}
/******************************************************************************
* *
-* Paramètres : - *
+* Paramètres : context = instance d'objet GLib à traiter. *
* *
-* Description : Prépare de quoi effectuer un décodage Itanium. *
+* Description : Supprime toutes les références externes. *
* *
-* Retour : Instance du contexte mis en place. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-GDemanglingContext *g_itanium_dcontext_new(void)
+static void g_itanium_demangling_dispose(GItaniumDemangling *context)
{
- GDemanglingContext *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_ITANIUM_DCONTEXT, NULL);
-
- return result;
+ G_OBJECT_CLASS(g_itanium_demangling_parent_class)->dispose(G_OBJECT(context));
}
/******************************************************************************
* *
-* Paramètres : context = contexte de décodage sur lequel s'appuyer. *
-* desc = chaîne de caractères à décoder. *
+* Paramètres : context = instance d'objet GLib à traiter. *
* *
-* Description : Tente de décoder une chaîne de caractères donnée. *
+* Description : Procède à la libération totale de la mémoire. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-void /*GBinRoutine **/g_itanium_dcontext_demangle_routine(GItaniumDContext *context, const char *desc)
+static void g_itanium_demangling_finalize(GItaniumDemangling *context)
{
- 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 *));
-
+ size_t i; /* Boucle de parcours */
- comp = itd_mangled_name(context);
+ for (i = 0; i < context->targs_count; i++)
+ itd_unref_comp(context->template_args[i]);
+ if (context->template_args != NULL)
+ free(context->template_args);
- printf("Got :: %p\n", comp);
+ for (i = 0; i < context->subst_count; i++)
+ itd_unref_comp(context->substitutions[i]);
- str = itd_translate_component(context, comp, NULL);
+ if (context->substitutions != NULL)
+ free(context->substitutions);
- printf("==>> %s\n", str);
+ G_OBJECT_CLASS(g_itanium_demangling_parent_class)->finalize(G_OBJECT(context));
}
/******************************************************************************
* *
-* Paramètres : context = contexte de décodage à manipuler. *
-* state = état courant à sauvegarder. [OUT] *
+* Paramètres : context = environnement de décodage à manipuler. *
* *
-* Description : Fournit l'état courant à une fin de retour en arrière. *
+* Description : Prépare l'environnement de contexte pour un décodage Itanium.*
* *
-* Retour : - *
+* Retour : - . *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_itanium_dcontext_push_state(const GItaniumDContext *context, itd_state *state)
+static void g_itanium_demangling_prepare(GItaniumDemangling *context)
{
- state->pos = context->pos;
- state->subst_count = context->subst_count;
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ size_t len; /* Taille de chaîne à traiter */
-}
+ /**
+ * On part du principe qu'il n'y aura jamais plus de paramètres de modèle
+ * ou de substitutions à enregistrer que de caractères dans la chaîne à traiter.
+ * Du coup, on peut tout allouer d'un coup !
+ */
+ assert(context->template_args == NULL);
-/******************************************************************************
-* *
-* 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 : - *
-* *
-******************************************************************************/
+ assert(context->substitutions == NULL);
-void g_itanium_dcontext_pop_state(GItaniumDContext *context, const itd_state *state)
-{
- size_t i; /* Boucle de parcours */
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
- /*
- printf("--deleting subst-- from %zu to %zu\n",
- state->subst_count, context->subst_count);
- */
+ len = get_input_buffer_size(ibuf);
- for (i = state->subst_count; i < context->subst_count; i++)
- itd_unref_comp(context->substitutions[i]);
+ context->template_args = (itanium_component **)malloc(len * sizeof(itanium_component *));
- context->pos = state->pos;
- context->subst_count = state->subst_count;
+ context->substitutions = (itanium_component **)malloc(len * sizeof(itanium_component *));
}
/******************************************************************************
* *
-* Paramètres : context = contexte de décodage à utiliser. *
+* Paramètres : context = environnement de décodage à manipuler. *
+* comp = composant final à valider. [OUT] *
* *
-* Description : Fournit la valeur du caractère courant. *
+* Description : Valide un composant final issu d'un décodage Itanium. *
* *
-* Retour : Caractère courant. *
+* Retour : - . *
* *
* Remarques : - *
* *
******************************************************************************/
-char g_itanium_dcontext_peek_char(const GItaniumDContext *context)
+static void g_itanium_demangling_check(GItaniumDemangling *context, itanium_component **comp)
{
- return *(context->mangled + context->pos);
+ input_buffer *ibuf; /* Tampon de texte manipulé */
+ size_t remaining; /* Données restant à consommer */
-}
+ if (*comp != NULL)
+ {
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
+ remaining = count_input_buffer_remaining(ibuf);
-/******************************************************************************
-* *
-* 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 : - *
-* *
-******************************************************************************/
+ if (remaining > 0)
+ {
+ itd_unref_comp(*comp);
+ *comp = NULL;
+ }
-void g_itanium_dcontext_advance(GItaniumDContext *context, size_t quantity)
-{
- context->pos += quantity;
+ }
}
/******************************************************************************
* *
-* Paramètres : context = contexte de décodage à utiliser. *
+* Paramètres : context = environnement de décodage à manipuler. *
* *
-* Description : Fournit et avance la tête de lecture courante. *
+* Description : Décode une définition de type pour Itanium. *
* *
-* Retour : Caractère courant. *
+* Retour : Nouvelle instance créée ou NULL en cas d'erreur fatale. *
* *
* Remarques : - *
* *
******************************************************************************/
-char g_itanium_dcontext_next_char(GItaniumDContext *context)
+static GDataType *g_itanium_demangling_decode_type(GItaniumDemangling *context)
{
- return *(context->mangled + context->pos++);
+ GDataType *result; /* Type construit à retourner */
+ itanium_component *comp; /* Composants décodés */
-}
+ g_itanium_demangling_prepare(context);
+ comp = itd_mangled_name(context);
-/******************************************************************************
-* *
-* 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 : - *
-* *
-******************************************************************************/
+ g_itanium_demangling_check(context, &comp);
-bool g_itanium_dcontext_check_char(GItaniumDContext *context, char c)
-{
- bool result; /* Validation à retourner */
+ if (comp == NULL)
+ result = NULL;
- if (g_itanium_dcontext_peek_char(context) == c)
+ else
{
- result = true;
- g_itanium_dcontext_advance(context, 1);
+ result = itd_translate_component_to_type(comp);
+
+ itd_unref_comp(comp);
+
}
- else
- result = false;
return result;
@@ -321,111 +302,121 @@ bool g_itanium_dcontext_check_char(GItaniumDContext *context, char c)
/******************************************************************************
* *
-* Paramètres : context = contexte de décodage à utiliser. *
-* remaining = taille de la chaîne retournée. [OUT] *
+* Paramètres : context = environnement de décodage à manipuler. *
* *
-* Description : Fournit la chaîne de caractère restant à traiter. *
+* Description : Décode une définition de routine pour Itanium. *
* *
-* Retour : Pointeur vers les données courantes. *
+* Retour : Nouvelle instance créée ou NULL en cas d'erreur fatale. *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *g_itanium_dcontext_get_string(const GItaniumDContext *context, size_t *remaining)
+static GBinRoutine *g_itanium_demangling_decode_routine(GItaniumDemangling *context)
{
- const char *result; /* Données à renvoyer */
-
- *remaining = context->len - context->pos;
-
- result = &context->mangled[context->pos];
-
- return result;
-
-}
-
+ GBinRoutine *result; /* Routine en place à retourner*/
+ itanium_component *comp; /* Composants décodés */
+ g_itanium_demangling_prepare(context);
+ comp = itd_mangled_name(context);
+ g_itanium_demangling_check(context, &comp);
-/*
+ if (comp == NULL)
+ result = NULL;
-################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)
+ else
+ {
+ result = itd_translate_component_to_routine(comp);
+ itd_unref_comp(comp);
-*/
+ }
+ return result;
+}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à manipuler. *
+* state = état courant à sauvegarder. [OUT] *
* *
-* Description : Fournit un nouveau composant vierge. *
+* Description : Fournit l'état courant à une fin de retour en arrière. *
* *
-* Retour : Composant prêt à être défini. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-itanium_component *g_itanium_dcontext_get_empty_component(GItaniumDContext *context)
+void g_itanium_demangling_push_state(const GItaniumDemangling *context, itd_state *state)
{
- itanium_component *result; /* Disponibilité à retourner */
- size_t i; /* Boucle de parcours */
- size_t next; /* Indice de disponibilité */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
- 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));
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
- context->next_links = (size_t *)
- realloc(context->next_links, (context->length + ITCOMP_ALLOC_BULK) * sizeof(size_t));
+ save_input_buffer_pos(ibuf, &state->pos);
+ state->targs_count = context->targs_count;
+ state->subst_count = context->subst_count;
- /* 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;
+/******************************************************************************
+* *
+* 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 : - *
+* *
+******************************************************************************/
- if (context->last_used != ITCOMP_INVALID)
- context->next_links[context->last_used] = context->length;
+void g_itanium_demangling_pop_state(GItaniumDemangling *context, const itd_state *state)
+{
+ size_t i; /* Boucle de parcours */
+ input_buffer *ibuf; /* Tampon de texte manipulé */
- /* Mise à jour globale */
+ for (i = state->targs_count; i < context->targs_count; i++)
+ itd_unref_comp(context->template_args[i]);
- context->length += ITCOMP_ALLOC_BULK;
+ for (i = state->subst_count; i < context->subst_count; i++)
+ itd_unref_comp(context->substitutions[i]);
- }
+ ibuf = &G_DEMANGLING_CONTEXT(context)->buffer;
- /* Extraction d'un composant disponible */
+ restore_input_buffer_pos(ibuf, state->pos);
+ context->targs_count = state->targs_count;
+ context->subst_count = state->subst_count;
- 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));
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* comp = composant à conserver en mémoire. *
+* *
+* Description : Indexe un composant représentant un argument de modèle. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- result->context = context;
- g_object_ref(G_OBJECT(result->context));
- result->refcount = 1;
+void g_itanium_demangling_add_template_arg(GItaniumDemangling *context, itanium_component *comp)
+{
+ assert(comp != NULL);
- return result;
+ context->template_args[context->targs_count++] = comp;
+ itd_ref_comp(comp);
}
@@ -433,28 +424,29 @@ itanium_component *g_itanium_dcontext_get_empty_component(GItaniumDContext *cont
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à manipuler. *
-* comp = composant à libérer. *
+* index = indice de l'argument visé. *
* *
-* Description : Marque un composant comme étant disponible pour un usage. *
+* Description : Fournit un composant représentant un argument de modèle. *
* *
-* Retour : - *
+* Retour : Composant déjà extrait et conservé. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_itanium_dcontext_mark_component_as_free(GItaniumDContext *context, itanium_component *comp)
+itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *context, size_t index)
{
- size_t index; /* Indice du composant concerné*/
-
- /*BUG_ON(comp->refcount != 0);*/
-
- g_object_unref(G_OBJECT(comp->context));
+ itanium_component *result; /* Composant à retourner */
- index = comp - context->components;
+ if (index < context->targs_count)
+ {
+ result = context->template_args[index];
+ itd_ref_comp(result);
+ }
+ else
+ result = NULL;
- context->next_links[index] = context->next_links[context->last_used];
- context->next_links[context->last_used] = index;
+ return result;
}
@@ -472,11 +464,13 @@ void g_itanium_dcontext_mark_component_as_free(GItaniumDContext *context, itaniu
* *
******************************************************************************/
-void g_itanium_dcontext_add_substitution(GItaniumDContext *context, itanium_component *comp)
+void g_itanium_demangling_add_substitution(GItaniumDemangling *context, itanium_component *comp)
{
fnv64_t hash; /* Empreinte du candidat */
size_t i; /* Boucle de parcours */
+ assert(comp != NULL);
+
hash = itd_hash_comp(comp);
for (i = 0; i < context->subst_count; i++)
@@ -485,15 +479,8 @@ void g_itanium_dcontext_add_substitution(GItaniumDContext *context, itanium_comp
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);
-
}
}
@@ -512,7 +499,7 @@ void g_itanium_dcontext_add_substitution(GItaniumDContext *context, itanium_comp
* *
******************************************************************************/
-itanium_component *g_itanium_dcontext_get_substitution(GItaniumDContext *context, size_t index)
+itanium_component *g_itanium_demangling_get_substitution(GItaniumDemangling *context, size_t index)
{
itanium_component *result; /* Composant à retourner */
@@ -527,45 +514,3 @@ itanium_component *g_itanium_dcontext_get_substitution(GItaniumDContext *context
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/plugins/itanium/context.h b/plugins/itanium/context.h
new file mode 100644
index 0000000..6ec65ae
--- /dev/null
+++ b/plugins/itanium/context.h
@@ -0,0 +1,83 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.h - prototypes pour le contexte de décodage à la sauce ABI C++ Itanium
+ *
+ * Copyright (C) 2013-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_CONTEXT_H
+#define _PLUGINS_ITANIUM_CONTEXT_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "component.h"
+
+
+
+#define G_TYPE_ITANIUM_DEMANGLING g_itanium_demangling_get_type()
+#define G_ITANIUM_DEMANGLING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ITANIUM_DEMANGLING, GItaniumDemangling))
+#define G_IS_ITANIUM_DEMANGLING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ITANIUM_DEMANGLING))
+#define G_ITANIUM_DEMANGLING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ITANIUM_DEMANGLING, GItaniumDemanglingClass))
+#define G_IS_ITANIUM_DEMANGLING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ITANIUM_DEMANGLING))
+#define G_ITANIUM_DEMANGLING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ITANIUM_DEMANGLING, GItaniumDemanglingClass))
+
+
+/* Contexte de décodage Itanium (instance) */
+typedef struct _GItaniumDemangling GItaniumDemangling;
+
+/* Contexte de décodage Itanium (classe) */
+typedef struct _GItaniumDemanglingClass GItaniumDemanglingClass;
+
+
+/* Indique le type défini pour un contexte de décodage. */
+GType g_itanium_demangling_get_type(void);
+
+/* Sauvegarde d'un état courant */
+typedef struct _itd_state
+{
+ size_t pos; /* Position courante */
+ size_t targs_count; /* Quantité utilisée */
+ size_t subst_count; /* Nombre de substitutions */
+
+} itd_state;
+
+/* Fournit l'état courant à une fin de retour en arrière. */
+void g_itanium_demangling_push_state(const GItaniumDemangling *, itd_state *);
+
+/* Définit l'état courant suite à un retour en arrière. */
+void g_itanium_demangling_pop_state(GItaniumDemangling *, const itd_state *);
+
+/* Indexe un composant représentant un argument de modèle. */
+void g_itanium_demangling_add_template_arg(GItaniumDemangling *, itanium_component *);
+
+/* Fournit un composant représentant un argument de modèle. */
+itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *, size_t);
+
+/* Indexe un composant comme future substitution potentielle. */
+void g_itanium_demangling_add_substitution(GItaniumDemangling *, itanium_component *);
+
+/* Fournit un composant en place pour une substitution. */
+itanium_component *g_itanium_demangling_get_substitution(GItaniumDemangling *, size_t);
+
+
+
+#endif /* _PLUGINS_ITANIUM_CONTEXT_H */
diff --git a/plugins/itanium/core.c b/plugins/itanium/core.c
new file mode 100644
index 0000000..ecfd7f0
--- /dev/null
+++ b/plugins/itanium/core.c
@@ -0,0 +1,64 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - intégration du décodage pour symboles Itanium
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <core/demanglers.h>
+#include <plugins/plugin-def.h>
+
+
+#include "demangler.h"
+#include "python/module.h"
+
+
+
+DEFINE_CHRYSALIDE_PLUGIN("itanium", "Symbol demangler for Itanium", "0.1.0",
+ RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
+
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
+* *
+* Description : Prend acte du chargement du greffon. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
+{
+ bool result; /* Bilan à retourner */
+
+ result = register_demangler_type("itanium", G_TYPE_ITANIUM_DEMANGLER);
+
+ if (result)
+ result = add_mangling_itanium_module_to_python_module();
+
+ return result;
+
+}
diff --git a/plugins/itanium/core.h b/plugins/itanium/core.h
new file mode 100644
index 0000000..f59f4e9
--- /dev/null
+++ b/plugins/itanium/core.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour l'intégration du décodage pour symboles Itanium
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_CORE_H
+#define _PLUGINS_ITANIUM_CORE_H
+
+
+#include <plugins/plugin.h>
+#include <plugins/plugin-int.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
+
+
+
+#endif /* _PLUGINS_ITANIUM_CORE_H */
diff --git a/plugins/itanium/demangler.c b/plugins/itanium/demangler.c
new file mode 100644
index 0000000..690f7c8
--- /dev/null
+++ b/plugins/itanium/demangler.c
@@ -0,0 +1,174 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * demangler.c - décodage des noms d'éléments Itanium
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "demangler.h"
+
+
+#include <mangling/demangler-int.h>
+
+
+#include "context.h"
+
+
+
+/* Décodeur de désignations Itanium (instance) */
+struct _GItaniumDemangler
+{
+ GCompDemangler parent; /* A laisser en premier */
+
+};
+
+/* Décodeur de désignations Itanium (classe) */
+struct _GItaniumDemanglerClass
+{
+ GCompDemanglerClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des décodeurs de désignations. */
+static void g_itanium_demangler_class_init(GItaniumDemanglerClass *);
+
+/* Initialise une instance de décodeur de désignations. */
+static void g_itanium_demangler_init(GItaniumDemangler *);
+
+/* Supprime toutes les références externes. */
+static void g_itanium_demangler_dispose(GItaniumDemangler *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_itanium_demangler_finalize(GItaniumDemangler *);
+
+
+
+/* Indique le type défini pour un décodeur de désignations. */
+G_DEFINE_TYPE(GItaniumDemangler, g_itanium_demangler, G_TYPE_COMP_DEMANGLER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des décodeurs de désignations Itanium. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangler_class_init(GItaniumDemanglerClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GCompDemanglerClass *demangler; /* Version parente basique */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_itanium_demangler_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_itanium_demangler_finalize;
+
+ demangler = G_COMP_DEMANGLER_CLASS(klass);
+
+ demangler->can_demangle = (can_be_demangled_fc)NULL;
+
+ demangler->context_type = G_TYPE_ITANIUM_DEMANGLING;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = instance à initialiser. *
+* *
+* Description : Initialise une instance de décodeur de désignations Itanium. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangler_init(GItaniumDemangler *demangler)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangler_dispose(GItaniumDemangler *demangler)
+{
+ G_OBJECT_CLASS(g_itanium_demangler_parent_class)->dispose(G_OBJECT(demangler));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_demangler_finalize(GItaniumDemangler *demangler)
+{
+ G_OBJECT_CLASS(g_itanium_demangler_parent_class)->finalize(G_OBJECT(demangler));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Met en place un nouveau décodeur de symboles pour Itanium. *
+* *
+* Retour : Instance obtenue ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GCompDemangler *g_itanium_demangler_new(void)
+{
+ GItaniumDemangler *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ITANIUM_DEMANGLER, NULL);
+
+ return G_COMP_DEMANGLER(result);
+
+}
diff --git a/plugins/itanium/demangler.h b/plugins/itanium/demangler.h
new file mode 100644
index 0000000..8b901cc
--- /dev/null
+++ b/plugins/itanium/demangler.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * demangler.h - prototypes pour le décodage des noms d'éléments Itanium
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_DEMANGLER_H
+#define _PLUGINS_ITANIUM_DEMANGLER_H
+
+
+#include <glib-object.h>
+
+
+#include <mangling/demangler.h>
+
+
+
+#define G_TYPE_ITANIUM_DEMANGLER g_itanium_demangler_get_type()
+#define G_ITANIUM_DEMANGLER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ITANIUM_DEMANGLER, GItaniumDemangler))
+#define G_IS_ITANIUM_DEMANGLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ITANIUM_DEMANGLER))
+#define G_ITANIUM_DEMANGLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ITANIUM_DEMANGLER, GItaniumDemanglerClass))
+#define G_IS_ITANIUM_DEMANGLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ITANIUM_DEMANGLER))
+#define G_ITANIUM_DEMANGLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ITANIUM_DEMANGLER, GItaniumDemanglerClass))
+
+
+/* Décodeur de désignations Itanium (instance) */
+typedef struct _GItaniumDemangler GItaniumDemangler;
+
+/* Décodeur de désignations Itanium (classe) */
+typedef struct _GItaniumDemanglerClass GItaniumDemanglerClass;
+
+
+/* Indique le type défini pour un décodeur de désignations Itanium. */
+GType g_itanium_demangler_get_type(void);
+
+/* Met en place un nouveau décodeur de symboles pour Itanium. */
+GCompDemangler *g_itanium_demangler_new(void);
+
+
+
+#endif /* _PLUGINS_ITANIUM_DEMANGLER_H */
diff --git a/plugins/itanium/python/Makefile.am b/plugins/itanium/python/Makefile.am
new file mode 100644
index 0000000..97abc50
--- /dev/null
+++ b/plugins/itanium/python/Makefile.am
@@ -0,0 +1,19 @@
+
+noinst_LTLIBRARIES = libitaniumpython.la
+
+libitaniumpython_la_SOURCES = \
+ demangler.h demangler.c \
+ module.h module.c
+
+libitaniumpython_la_LDFLAGS =
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libitaniumpython_la_SOURCES:%c=)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/itanium/python/demangler.c b/plugins/itanium/python/demangler.c
new file mode 100644
index 0000000..dfade68
--- /dev/null
+++ b/plugins/itanium/python/demangler.c
@@ -0,0 +1,145 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * demangler.c - équivalent Python du fichier "plugins/itanium/demangler.c"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "demangler.h"
+
+
+#include <pygobject.h>
+
+
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/mangling/demangler.h>
+
+
+#include "../demangler.h"
+
+
+
+/* Crée un nouvel objet Python de type 'ItaniumDemangler'. */
+static PyObject *py_itanium_demangler_new(PyTypeObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type de l'objet à instancier. *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Crée un nouvel objet Python de type 'ItaniumDemangler'. *
+* *
+* Retour : Instance Python mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_itanium_demangler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Instance à retourner */
+ GCompDemangler *demangler; /* Instance à transposer */
+
+ demangler = g_itanium_demangler_new();
+
+ result = pygobject_new(G_OBJECT(demangler));
+
+ g_object_unref(G_OBJECT(demangler));
+
+ return (PyObject *)result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_itanium_demangler_type(void)
+{
+ static PyMethodDef py_itanium_demangler_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_itanium_demangler_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_itanium_demangler_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.mangling.ItaniumDemangler",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = "PyChrysalide Itanium demangler",
+
+ .tp_methods = py_itanium_demangler_methods,
+ .tp_getset = py_itanium_demangler_getseters,
+ .tp_new = (newfunc)py_itanium_demangler_new
+
+ };
+
+ return &py_itanium_demangler_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.....ItaniumDemangler'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_python_itanium_demangler(PyObject *module)
+{
+ PyTypeObject *py_itanium_demangler_type;/* Type 'ItaniumDemangler' */
+ PyObject *dict; /* Dictionnaire du module */
+
+ py_itanium_demangler_type = get_python_itanium_demangler_type();
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ITANIUM_DEMANGLER,
+ py_itanium_demangler_type, get_python_compiler_demangler_type()))
+ return false;
+
+ return true;
+
+}
diff --git a/plugins/itanium/python/demangler.h b/plugins/itanium/python/demangler.h
new file mode 100644
index 0000000..e84313a
--- /dev/null
+++ b/plugins/itanium/python/demangler.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * demangler.h - prototypes pour l'équivalent Python du fichier "plugins/itanium/demangler.h"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_PYTHON_DEMANGLER_H
+#define _PLUGINS_ITANIUM_PYTHON_DEMANGLER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_itanium_demangler_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.mangling.ItaniumDemangler'. */
+bool register_python_itanium_demangler(PyObject *);
+
+
+
+#endif /* _PLUGINS_ITANIUM_PYTHON_DEMANGLER_H */
diff --git a/plugins/itanium/python/module.c b/plugins/itanium/python/module.c
new file mode 100644
index 0000000..d42d783
--- /dev/null
+++ b/plugins/itanium/python/module.c
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire itanium en tant que module
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+
+
+#include "demangler.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Etend le module 'mangling' avec des compléments pour Itanium.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_mangling_itanium_module_to_python_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+
+ super = get_access_to_python_module("pychrysalide.mangling");
+
+ result = register_python_itanium_demangler(super);
+
+ return result;
+
+}
diff --git a/plugins/itanium/python/module.h b/plugins/itanium/python/module.h
new file mode 100644
index 0000000..7e35a81
--- /dev/null
+++ b/plugins/itanium/python/module.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire itanium en tant que module
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_ITANIUM_PYTHON_MODULE_H
+#define _PLUGINS_ITANIUM_PYTHON_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Etend le module 'mangling' avec des compléments pour Itanium. */
+bool add_mangling_itanium_module_to_python_module(void);
+
+
+
+#endif /* _PLUGINS_ITANIUM_PYTHON_MODULE_H */
diff --git a/src/common/ibuf.c b/src/common/ibuf.c
index f0ea0ac..5d90eb4 100644
--- a/src/common/ibuf.c
+++ b/src/common/ibuf.c
@@ -50,6 +50,28 @@ void init_text_input_buffer(input_buffer *ibuf, const char *text)
}
+/******************************************************************************
+* *
+* Paramètres : ibuf = tampon de données à consulter. *
+* *
+* Description : Fournit la taille totale du tampon constitué. *
+* *
+* Retour : Valeur positive (ou nulle !). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t get_input_buffer_size(const input_buffer *ibuf)
+{
+ size_t result; /* Quantité à retourner */
+
+ result = ibuf->len;
+
+ return result;
+
+}
+
/******************************************************************************
* *
@@ -65,10 +87,47 @@ void init_text_input_buffer(input_buffer *ibuf, const char *text)
size_t count_input_buffer_remaining(const input_buffer *ibuf)
{
- return ibuf->len - ibuf->pos;
+ size_t result; /* Quantité à renvoyer */
+
+ assert(ibuf->pos <= (ibuf->len + 1));
+
+ if (ibuf->pos > ibuf->len)
+ result = 0;
+
+ else
+ result = ibuf->len - ibuf->pos;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : ibuf = tampon de données à consulter. *
+* *
+* Description : Détermine s'il reste encore des données disponibles. *
+* *
+* Retour : true si des données sont encore présentes, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool input_buffer_contain_data(const input_buffer *ibuf)
+{
+ bool result; /* Bilan à retourner */
+ size_t remaining; /* Quantité restante */
+
+ remaining = count_input_buffer_remaining(ibuf);
+
+ result = (remaining > 0);
+
+ return result;
}
+
/******************************************************************************
* *
* Paramètres : ibuf = tampon de données à modifier. *
@@ -84,7 +143,7 @@ size_t count_input_buffer_remaining(const input_buffer *ibuf)
void advance_input_buffer(input_buffer *ibuf, size_t count)
{
- assert((ibuf->pos + count) <= ibuf->len);
+ assert((ibuf->pos + count) <= (ibuf->len + 1));
ibuf->pos += count;
@@ -112,6 +171,84 @@ const char *get_input_buffer_text_access(const input_buffer *ibuf)
/******************************************************************************
* *
+* Paramètres : ibuf = tampon de données à consulter. *
+* 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 *get_input_buffer_string(const input_buffer *ibuf, size_t *remaining)
+{
+ const char *result; /* Pointeur à retourner */
+
+ assert(ibuf->pos <= ibuf->len);
+
+ result = ibuf->text + ibuf->pos;
+
+ *remaining = ibuf->len - ibuf->pos;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : ibuf = tampon de données à parcourir. *
+* *
+* Description : Fournit le caractère courant à la tête de lecture courante. *
+* *
+* Retour : Caractère courant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char peek_input_buffer_char(const input_buffer *ibuf)
+{
+ assert(ibuf->pos <= ibuf->len);
+
+ return *(ibuf->text + ibuf->pos);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : ibuf = tampon de données à parcourir. *
+* *
+* Description : Fournit le caractère suivant la tête de lecture courante. *
+* *
+* Retour : Caractère courant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char peek_input_buffer_next_char(const input_buffer *ibuf)
+{
+ char result; /* Valeur à retourner */
+
+ assert(ibuf->pos <= ibuf->len);
+
+ if (ibuf->pos == ibuf->len)
+ result = '\0';
+
+ else
+ result = *(ibuf->text + ibuf->pos + 1);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : ibuf = tampon de données à parcourir. *
* *
* Description : Fournit et avance la tête de lecture courante. *
@@ -124,9 +261,79 @@ const char *get_input_buffer_text_access(const input_buffer *ibuf)
char text_input_buffer_next_char(input_buffer *ibuf)
{
+ char result; /* Valeur à retourner */
+
+ assert(ibuf->pos <= ibuf->len);
+
+ result = *(ibuf->text + ibuf->pos);
+
+ advance_input_buffer(ibuf, 1);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : ibuf = tampon de données à parcourir. *
+* out = caractère courant, s'il existe. *
+* *
+* Description : Fournit et avance la tête de lecture courante, si possible. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool get_input_buffer_next_char_carefully(input_buffer *ibuf, char *out)
+{
+ char result; /* Valeur à retourner */
+
assert(ibuf->pos <= ibuf->len);
- return *(ibuf->text + ibuf->pos++);
+ result = input_buffer_contain_data(ibuf);
+
+ if (result)
+ {
+ *out = *(ibuf->text + ibuf->pos);
+
+ advance_input_buffer(ibuf, 1);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : ibuf = tampon de données à parcourir. *
+* c = caractère à retrouver. *
+* *
+* Description : Vérifie la nature du caractère courant. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool check_input_buffer_char(input_buffer *ibuf, char c)
+{
+ bool result; /* Validation à retourner */
+
+ if (peek_input_buffer_char(ibuf) == c)
+ {
+ result = true;
+ advance_input_buffer(ibuf, 1);
+ }
+ else
+ result = false;
+
+ return result;
}
diff --git a/src/common/ibuf.h b/src/common/ibuf.h
index 3d0d5d1..ecd8814 100644
--- a/src/common/ibuf.h
+++ b/src/common/ibuf.h
@@ -25,6 +25,7 @@
#define _COMMON_IBUF_H
+#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
@@ -48,18 +49,39 @@ typedef struct _input_buffer
/* Initialise un contenu textuel pour une lecture ultérieure. */
void init_text_input_buffer(input_buffer *, const char *);
+/* Fournit la taille totale du tampon constitué. */
+size_t get_input_buffer_size(const input_buffer *);
+
/* Compte le nombre d'octets encore non lus. */
size_t count_input_buffer_remaining(const input_buffer *);
+/* Détermine s'il reste encore des données disponibles. */
+bool input_buffer_contain_data(const input_buffer *);
+
/* Avance la tête de lecture dans le tampon de données. */
void advance_input_buffer(input_buffer *, size_t);
/* Fournit un accès brut au niveau de la tête de lecture. */
const char *get_input_buffer_text_access(const input_buffer *);
+/* Fournit la chaîne de caractère restant à traiter. */
+const char *get_input_buffer_string(const input_buffer *, size_t *);
+
+/* Fournit le caractère courant à la tête de lecture courante. */
+char peek_input_buffer_char(const input_buffer *);
+
+/* Fournit le caractère suivant la tête de lecture courante. */
+char peek_input_buffer_next_char(const input_buffer *);
+
/* Fournit et avance la tête de lecture courante. */
char text_input_buffer_next_char(input_buffer *);
+/* Fournit et avance la tête de lecture courante, si possible. */
+bool get_input_buffer_next_char_carefully(input_buffer *, char *);
+
+/* Vérifie la nature du caractère courant. */
+bool check_input_buffer_char(input_buffer *, char);
+
/* Note la position courante de la tête de lecture. */
void save_input_buffer_pos(const input_buffer *, size_t *);
diff --git a/src/mangling/Makefile.am b/src/mangling/Makefile.am
index b78c439..3ed04ef 100644
--- a/src/mangling/Makefile.am
+++ b/src/mangling/Makefile.am
@@ -14,8 +14,7 @@ libmangling_la_SOURCES = \
libmangling_la_LDFLAGS =
libmangling_la_LIBADD = \
- libjavamangling.la \
- itanium/libmanglingitanium.la
+ libjavamangling.la
devdir = $(includedir)/chrysalide/$(subdir:src/%=%)
@@ -45,4 +44,4 @@ AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
# Automake fait les choses à moitié
CLEANFILES = java_gram.h java_gram.c libjavamangling_la-java_tok.c
-SUBDIRS = itanium
+SUBDIRS =
diff --git a/src/mangling/itanium/Makefile.am b/src/mangling/itanium/Makefile.am
deleted file mode 100644
index d393a95..0000000
--- a/src/mangling/itanium/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-
-noinst_LTLIBRARIES = libmanglingitanium.la
-
-libmanglingitanium_la_SOURCES = \
- abi.h abi.c \
- component-int.h \
- component.h component.c \
- context.h context.c
-
-libmanglingitanium_la_LIBADD =
-
-libmanglingitanium_la_LDFLAGS =
-
-
-devdir = $(includedir)/chrysalide/$(subdir:src/%=%)
-
-dev_HEADERS = $(libmanglingitanium_la_SOURCES:%c=)
-
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-
-SUBDIRS =
diff --git a/src/mangling/itanium/component-int.h b/src/mangling/itanium/component-int.h
deleted file mode 100644
index 3d4c1d0..0000000
--- a/src/mangling/itanium/component-int.h
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-#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écalage 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/mangling/itanium/component.c b/src/mangling/itanium/component.c
deleted file mode 100644
index 65c2d7e..0000000
--- a/src/mangling/itanium/component.c
+++ /dev/null
@@ -1,717 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * component.c - représentation des composants extraits de l'ABI C++ Itanium
- *
- * Copyright (C) 2013-2017 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "component.h"
-
-
-#include <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écalage. *
-* offset = décalage extrait de l'encodage. *
-* *
-* Description : Construit un composant dans un contexte Itanium. *
-* *
-* Retour : Composant extrait ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-itanium_component *itd_make_offset(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;
- default:
- result = NULL;
- 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/mangling/itanium/context.h b/src/mangling/itanium/context.h
deleted file mode 100644
index 0ac5a6c..0000000
--- a/src/mangling/itanium/context.h
+++ /dev/null
@@ -1,118 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * context.h - prototypes pour le contexte de décodage à la sauce ABI C++ Itanium
- *
- * Copyright (C) 2013-2017 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _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_TYPE_ITANIUM_DCONTEXT, GItaniumDContext))
-#define G_IS_ITANIUM_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ITANIUM_DCONTEXT))
-#define G_ITANIUM_DCONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ITANIUM_DCONTEXT, GItaniumDContextClass))
-#define G_IS_ITANIUM_DCONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ITANIUM_DCONTEXT))
-#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/tests/mangling/itanium.py b/tests/mangling/itanium.py
new file mode 100644
index 0000000..6bb49d3
--- /dev/null
+++ b/tests/mangling/itanium.py
@@ -0,0 +1,111 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+
+# Tests validant le décodage des types et des routines pour le format Itanium
+
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.mangling import ItaniumDemangler
+
+
+class TestItaniumMangling(ChrysalideTestCase):
+ """TestCase for pychrysalide.mangling.ItaniumDemangler."""
+
+ def check_demangling(self, got, expected):
+ """Check a given demangling result."""
+
+ self.assertEqual(str(got), expected)
+
+
+ def testItaniumTypeMangling(self):
+ """Check Itanium type demangling with specifications samples."""
+
+ # https://itanium-cxx-abi.github.io/cxx-abi/abi-examples.html#mangling
+
+ demangler = ItaniumDemangler()
+
+ demangled = demangler.decode_type('_ZN3FooIA4_iE3barE')
+ self.check_demangling(demangled, 'Foo<int[4]>::bar')
+
+ demangled = demangler.decode_type('_ZN1N1fE')
+ self.check_demangling(demangled, 'N::f')
+
+ demangled = demangler.decode_type('_ZN5Arena5levelE')
+ self.check_demangling(demangled, 'Arena::level')
+
+ demangled = demangler.decode_type('_ZN5StackIiiE5levelE')
+ self.check_demangling(demangled, 'Stack<int, int>::level')
+
+
+ def testItaniumRoutineMangling(self):
+ """Check Itanium routine demangling with specifications samples."""
+
+ # https://itanium-cxx-abi.github.io/cxx-abi/abi-examples.html#mangling
+
+ demangler = ItaniumDemangler()
+
+ demangled = demangler.decode_routine('_Z1fv')
+ self.check_demangling(demangled, '??? f(void)')
+
+ demangled = demangler.decode_routine('_Z1fi')
+ self.check_demangling(demangled, '??? f(int)')
+
+ demangled = demangler.decode_routine('_Z3foo3bar')
+ self.check_demangling(demangled, '??? foo(bar)')
+
+ demangled = demangler.decode_routine('_Zrm1XS_')
+ self.check_demangling(demangled, '??? operator%(X, X)')
+
+ demangled = demangler.decode_routine('_ZplR1XS0_')
+ self.check_demangling(demangled, '??? operator+(X &, X &)')
+
+ demangled = demangler.decode_routine('_ZlsRK1XS1_')
+ self.check_demangling(demangled, '??? operator<<(const X &, const X &)')
+
+ demangled = demangler.decode_routine('_Z1fIiEvi')
+ self.check_demangling(demangled, 'void f<int>(int)')
+
+ demangled = demangler.decode_routine('_Z5firstI3DuoEvS0_')
+ self.check_demangling(demangled, 'void first<Duo>(Duo)')
+
+ demangled = demangler.decode_routine('_Z5firstI3DuoEvT_')
+ self.check_demangling(demangled, 'void first<Duo>(Duo)')
+
+ demangled = demangler.decode_routine('_Z3fooIiPFidEiEvv')
+ self.check_demangling(demangled, 'void foo<int, int (*) (double), int>(void)')
+
+ demangled = demangler.decode_routine('_ZN6System5Sound4beepEv')
+ self.check_demangling(demangled, '??? System::Sound::beep(void)')
+
+ demangled = demangler.decode_routine('_Z1fI1XEvPVN1AIT_E1TE')
+ self.check_demangling(demangled, 'void f<X>(volatile A<X>::T *)')
+
+ demangled = demangler.decode_routine('_ZngILi42EEvN1AIXplT_Li2EEE1TE')
+ self.check_demangling(demangled, 'void operator-<42>(A<42+2>::T)')
+
+ demangled = demangler.decode_routine('_Z4makeI7FactoryiET_IT0_Ev')
+ self.check_demangling(demangled, 'Factory<int> make<Factory, int>(void)')
+
+ demangled = demangler.decode_routine('_Z3foo5Hello5WorldS0_S_')
+ self.check_demangling(demangled, '??? foo(Hello, World, World, Hello)')
+
+ demangled = demangler.decode_routine('_ZlsRSoRKSs')
+ self.check_demangling(demangled, '??? operator<<(std::ostream &, const std::string &)')
+
+
+ def testItaniumRoutineManglingInside(self):
+ """Check Itanium routine demangling examples within the specifications."""
+
+ # http://refspecs.linuxbase.org/cxxabi-1.83.html#linkage
+
+ demangler = ItaniumDemangler()
+
+ demangled = demangler.decode_routine('_Z1fM1AKFvvE')
+ self.check_demangling(demangled, '??? f(const void (A::*) (void))')
+
+ demangled = demangler.decode_routine('_Z1fPFvvEM1SFvvE')
+ self.check_demangling(demangled, '??? f(void (*) (void), void (S::*) (void))')
+
+ demangled = demangler.decode_routine('_ZN1N1TIiiE2mfES0_IddE')
+ self.check_demangling(demangled, '??? N::T<int, int>::mf(N::T<double, double>)')
diff --git a/tools/afl/Makefile b/tools/afl/Makefile
new file mode 100644
index 0000000..4f684aa
--- /dev/null
+++ b/tools/afl/Makefile
@@ -0,0 +1,13 @@
+
+all: itanium
+
+itanium: itanium.c
+ afl-gcc -o $@ \
+ `pkg-config --libs --cflags gtk+-3.0 glib-2.0 libxml-2.0` \
+ -I../.. -I../../src \
+ -Wl,-rpath,$(PWD)/../../src/.libs -L../../src/.libs -lchrysacore \
+ -Wl,-rpath,$(PWD)/../../plugins/itanium/.libs -L../../plugins/itanium/.libs -litanium \
+ $^
+
+clean:
+ rm -f itanium *~
diff --git a/tools/afl/demangler.sh b/tools/afl/demangler.sh
new file mode 100755
index 0000000..e82ccbf
--- /dev/null
+++ b/tools/afl/demangler.sh
@@ -0,0 +1,27 @@
+#§/bin/sh
+
+
+if [ "$#" -ne 1 ]; then
+ echo "Usage: $0 <type>"
+ exit
+fi
+
+rm -rf testcase_dir findings_dir
+
+mkdir testcase_dir findings_dir
+
+n=0
+
+for enc in $( cat ../../tests/mangling/$1.py | grep decode_routine | cut -d\' -f 2 );
+do
+
+ echo -n $enc > testcase_dir/$( printf "%03d" $n )
+
+ n=$(( n + 1 ))
+
+done
+
+
+#echo -n '_Z4makeI7FactoryiET_IT0_Ev' > testcase_dir/00
+
+afl-fuzz -t 100 -m 4096 -i testcase_dir -o findings_dir -- ./$1
diff --git a/tools/afl/itanium.c b/tools/afl/itanium.c
new file mode 100644
index 0000000..9e68078
--- /dev/null
+++ b/tools/afl/itanium.c
@@ -0,0 +1,69 @@
+
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#include <common/io.h>
+#include <plugins/itanium/demangler.h>
+
+
+
+/* Tampon d'entrée */
+static char _input_buffer[4096];
+
+
+
+/******************************************************************************
+* *
+* Paramètres : argc = nombre d'arguments dans la ligne de commande. *
+* argv = arguments de la ligne de commande. *
+* *
+* Description : Point d'entrée du programme. *
+* *
+* Retour : EXIT_SUCCESS si le prgm s'est déroulé sans encombres. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int main(int argc, char **argv)
+{
+ int result; /* Bilan de l'exécution */
+ ssize_t got; /* Quantité de données lues */
+ GCompDemangler *demangler; /* Décodeur à solliciter */
+ GBinRoutine *routine; /* Routine obtenue par décodage*/
+ char *desc; /* Description finale obtenue */
+
+ result = EXIT_FAILURE;
+
+ got = safe_read_partial(STDIN_FILENO, _input_buffer, sizeof(_input_buffer));
+ if (got <= 0) goto exit;
+
+ printf("input: %zd bytes ('%s')\n", got, _input_buffer);
+
+ demangler = g_itanium_demangler_new();
+
+ routine = g_compiler_demangler_decode_routine(demangler, _input_buffer);
+ if (routine == NULL) goto demangling_exit;
+
+ desc = g_binary_routine_to_string(routine, true);
+
+ g_object_unref(G_OBJECT(routine));
+
+ printf("routine: %s\n", desc);
+
+ free(desc);
+
+ result = EXIT_SUCCESS;
+
+ demangling_exit:
+
+ g_object_unref(G_OBJECT(demangler));
+
+ exit:
+
+ return result;
+
+}