From 944461f7af1995b08783dc761772908ec7c204a6 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 29 Dec 2013 14:07:38 +0000 Subject: Handled Itanium demangling with C code (first part). git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@361 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- src/common/cpp.h | 6 + src/common/extstr.c | 41 +- src/common/extstr.h | 3 + src/format/mangling/Makefile.am | 14 +- src/format/mangling/itanium.h | 62 - src/format/mangling/itanium/Makefile.am | 18 + src/format/mangling/itanium/abi.c | 2442 +++++++++++++++++++++++++++ src/format/mangling/itanium/abi.h | 38 + src/format/mangling/itanium/component-int.h | 79 + src/format/mangling/itanium/component.c | 714 ++++++++ src/format/mangling/itanium/component.h | 213 +++ src/format/mangling/itanium/context.c | 571 +++++++ src/format/mangling/itanium/context.h | 117 ++ src/format/mangling/itanium_gram.y | 1222 -------------- src/format/mangling/itanium_tok.l | 232 --- src/main.c | 4 +- 16 files changed, 4248 insertions(+), 1528 deletions(-) delete mode 100644 src/format/mangling/itanium.h create mode 100755 src/format/mangling/itanium/Makefile.am create mode 100644 src/format/mangling/itanium/abi.c create mode 100644 src/format/mangling/itanium/abi.h create mode 100644 src/format/mangling/itanium/component-int.h create mode 100644 src/format/mangling/itanium/component.c create mode 100644 src/format/mangling/itanium/component.h create mode 100644 src/format/mangling/itanium/context.c create mode 100644 src/format/mangling/itanium/context.h delete mode 100644 src/format/mangling/itanium_gram.y delete mode 100644 src/format/mangling/itanium_tok.l diff --git a/src/common/cpp.h b/src/common/cpp.h index b5e09c0..a658559 100644 --- a/src/common/cpp.h +++ b/src/common/cpp.h @@ -31,6 +31,12 @@ /** + * Fournit la taille d'un tableau statique. + */ +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + + +/** * Détermine la taille de la plus longue chaîne de caractères * correspondant à un type donné. */ diff --git a/src/common/extstr.c b/src/common/extstr.c index 8249515..309f487 100644 --- a/src/common/extstr.c +++ b/src/common/extstr.c @@ -47,9 +47,46 @@ char *stradd(char *str1, const char *str2) { char *result; /* Chaîne à renvoyer */ - result = (char *)realloc(str1, (strlen(str1) + strlen(str2) + 1) * sizeof(char)); + if (str1 == NULL) + result = strdup(str2); + + else + { + result = (char *)realloc(str1, (strlen(str1) + strlen(str2) + 1) * sizeof(char)); + strcat(result, str2); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : str1 = chaîne de caractères à compléter. * +* str2 = chaîne de caractères à ajouter. * +* n = taille de la seconde chaîne. * +* * +* Description : Complète une chaîne de caractères avec une autre. * +* * +* Retour : Chaîne de caractères complétée, à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *strnadd(char *str1, const char *str2, size_t n) +{ + char *result; /* Chaîne à renvoyer */ - strcat(result, str2); + if (str1 == NULL) + result = strndup(str2, n); + + else + { + result = (char *)realloc(str1, (strlen(str1) + n + 1) * sizeof(char)); + strncat(result, str2, n); + } return result; diff --git a/src/common/extstr.h b/src/common/extstr.h index 592719e..830e1fa 100644 --- a/src/common/extstr.h +++ b/src/common/extstr.h @@ -32,6 +32,9 @@ /* Complète une chaîne de caractères avec une autre. */ char *stradd(char *str1, const char *str2); +/* Complète une chaîne de caractères avec une autre. */ +char *strnadd(char *, const char *, size_t); + /* Fait précéder une chaîne de caractères par une autre. */ char *strprep(char *, const char *); diff --git a/src/format/mangling/Makefile.am b/src/format/mangling/Makefile.am index 9774b73..53f4b70 100644 --- a/src/format/mangling/Makefile.am +++ b/src/format/mangling/Makefile.am @@ -1,5 +1,4 @@ -#BUILT_SOURCES = itanium_gram.h libjavamangling_la-java_gram.h BUILT_SOURCES = libjavamangling_la-java_gram.h AM_YFLAGS = -d @@ -10,14 +9,12 @@ libformatmangling_la_SOURCES = \ context-int.h \ context.h context.c \ demangler.h demangler.c -#itanium.h \ -#itanium_gram.y \ -#itanium_tok.l libformatmangling_la_LDFLAGS = libformatmangling_la_LIBADD = \ - libjavamangling.la + libjavamangling.la \ + itanium/libformatmanglingitanium.la # Partie Java @@ -27,7 +24,7 @@ libjavamangling_la_SOURCES = \ java_gram.y \ java_tok.l -libjavamangling_la_YFLAGS = -d -p java_ -o y.tab.c +libjavamangling_la_YFLAGS = -d -p java_ -o y.tab.c3 libjavamangling_la_LFLAGS = -P java_ -o lex.yy.c @@ -42,5 +39,6 @@ AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) # Automake fait les choses à moitié -CLEANFILES = itanium_gram.h itanium_gram.c itanium_tok.c \ - java_gram.h java_gram.c libjavamangling_la-java_tok.c +CLEANFILES = java_gram.h java_gram.c libjavamangling_la-java_tok.c + +SUBDIRS = itanium diff --git a/src/format/mangling/itanium.h b/src/format/mangling/itanium.h deleted file mode 100644 index 2d2fd59..0000000 --- a/src/format/mangling/itanium.h +++ /dev/null @@ -1,62 +0,0 @@ - -/* OpenIDA - Outil d'analyse de fichiers binaires - * itanium.h - prototypes pour le décodage des noms d'éléments selon Intel - * - * Copyright (C) 2009-2010 Cyrille Bagard - * - * This file is part of OpenIDA. - * - * OpenIDA is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * OpenIDA is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see . - */ - - -#ifndef _FORMAT_MANGLING_ITANIUM_H -#define _FORMAT_MANGLING_ITANIUM_H - - -#include - - -#include "context.h" -#include "demangler.h" - - - -/* --------------------- CONTEXTE POUR LE DECODAGE TYPE ITANIUM --------------------- */ - - -/* Contexte de décodage Itanium (instance) */ -typedef struct _GItaniumDContext GItaniumDContext; - -/* Contexte de décodage Itanium (classe) */ -typedef struct _GItaniumDContextClass GItaniumDContextClass; - - -/* Prépare de quoi effectuer un décodage Itanium. */ -GDemanglingContext *g_itanium_dcontext_new(void); - - - -/* ------------------------ TRAITEMENT DE L'ENCODAGE ITANIUM ------------------------ */ - - -/* Indique si une chaîne peut être traitée par le décodeur. */ -bool can_be_itanium_demangled(const char *); - -/* Procède au décodage d'une chaîne de caractères. */ -bool demangle_itanium_routine(GItaniumDContext *, const char *); - - - -#endif /* _FORMAT_MANGLING_ITANIUM_H */ diff --git a/src/format/mangling/itanium/Makefile.am b/src/format/mangling/itanium/Makefile.am new file mode 100755 index 0000000..6265691 --- /dev/null +++ b/src/format/mangling/itanium/Makefile.am @@ -0,0 +1,18 @@ + +noinst_LTLIBRARIES = libformatmanglingitanium.la + +libformatmanglingitanium_la_SOURCES = \ + abi.h abi.c \ + component.h component.c \ + context.h context.c + +libformatmanglingitanium_la_LIBADD = + +libformatmanglingitanium_la_LDFLAGS = + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = diff --git a/src/format/mangling/itanium/abi.c b/src/format/mangling/itanium/abi.c new file mode 100644 index 0000000..75585df --- /dev/null +++ b/src/format/mangling/itanium/abi.c @@ -0,0 +1,2442 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * abi.c - décodage des noms d'éléments selon l'ABI C++ Itanium + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include "abi.h" + + +#include +#include + + + +#include "../../../analysis/types/basic.h" +#include "../../../common/cpp.h" + + + +/* Liste des opérateurs reconnus */ + +#define IDT_NL(s) s, sizeof(s) - 1 + +const itanium_operator_info itanium_demangle_operators[] = { + + { "aN", IDT_NL("&="), 2 }, + { "aS", IDT_NL("="), 2 }, + { "aa", IDT_NL("&&"), 2 }, + { "ad", IDT_NL("&"), 1 }, + { "an", IDT_NL("&"), 2 }, + { "at", IDT_NL("alignof "), 1 }, + { "az", IDT_NL("alignof "), 1 }, + { "cc", IDT_NL("const_cast"), 2 }, + { "cl", IDT_NL("()"), 2 }, + { "cm", IDT_NL(","), 2 }, + { "co", IDT_NL("~"), 1 }, + { "dV", IDT_NL("/="), 2 }, + { "da", IDT_NL("delete[] "), 1 }, + { "dc", IDT_NL("dynamic_cast"), 2 }, + { "de", IDT_NL("*"), 1 }, + { "dl", IDT_NL("delete "), 1 }, + { "ds", IDT_NL(".*"), 2 }, + { "dt", IDT_NL("."), 2 }, + { "dv", IDT_NL("/"), 2 }, + { "eO", IDT_NL("^="), 2 }, + { "eo", IDT_NL("^"), 2 }, + { "eq", IDT_NL("=="), 2 }, + { "ge", IDT_NL(">="), 2 }, + { "gs", IDT_NL("::"), 1 }, + { "gt", IDT_NL(">"), 2 }, + { "ix", IDT_NL("[]"), 2 }, + { "lS", IDT_NL("<<="), 2 }, + { "le", IDT_NL("<="), 2 }, + { "li", IDT_NL("operator\"\" "), 1 }, + { "ls", IDT_NL("<<"), 2 }, + { "lt", IDT_NL("<"), 2 }, + { "mI", IDT_NL("-="), 2 }, + { "mL", IDT_NL("*="), 2 }, + { "mi", IDT_NL("-"), 2 }, + { "ml", IDT_NL("*"), 2 }, + { "mm", IDT_NL("--"), 1 }, + { "na", IDT_NL("new[]"), 3 }, + { "ne", IDT_NL("!="), 2 }, + { "ng", IDT_NL("-"), 1 }, + { "nt", IDT_NL("!"), 1 }, + { "nw", IDT_NL("new"), 3 }, + { "oR", IDT_NL("|="), 2 }, + { "oo", IDT_NL("||"), 2 }, + { "or", IDT_NL("|"), 2 }, + { "pL", IDT_NL("+="), 2 }, + { "pl", IDT_NL("+"), 2 }, + { "pm", IDT_NL("->*"), 2 }, + { "pp", IDT_NL("++"), 1 }, + { "ps", IDT_NL("+"), 1 }, + { "pt", IDT_NL("->"), 2 }, + { "qu", IDT_NL("?"), 3 }, + { "rM", IDT_NL("%="), 2 }, + { "rS", IDT_NL(">>="), 2 }, + { "rc", IDT_NL("reinterpret_cast"), 2 }, + { "rm", IDT_NL("%"), 2 }, + { "rs", IDT_NL(">>"), 2 }, + { "sc", IDT_NL("static_cast"), 2 }, + { "st", IDT_NL("sizeof "), 1 }, + { "sz", IDT_NL("sizeof "), 1 }, + { "tr", IDT_NL("throw"), 0 }, + { "tw", IDT_NL("throw "), 1 } +}; + +/* Substitutions standards */ + +typedef struct _itanium_std_subst_info +{ + char code; /* Identifiant associé */ + + const char *simple; /* Représentation simple */ + size_t simple_len; /* Taille de cette représentat°*/ + + const char *full; /* Représentation complète */ + size_t full_len; /* Taille de cette représentat°*/ + + const char *last_name; /* Pour les (con|de)structeurs */ + size_t last_name_len; /* Taille de cette indication */ + +} itanium_std_subst_info; + +const itanium_std_subst_info itanium_standard_substitutions[] = { + + { + 't', + IDT_NL("std"), + IDT_NL("std"), + NULL, + 0 + }, + { + 'a', + IDT_NL("std::allocator"), + IDT_NL("std::allocator"), + IDT_NL("allocator") + }, + { + 'b', + IDT_NL("std::basic_string"), + IDT_NL("std::basic_string"), + IDT_NL("basic_string") + }, + { + 's', + IDT_NL("std::string"), + IDT_NL("std::basic_string, std::allocator>"), + IDT_NL("basic_string") + }, + { + 'i', + IDT_NL("std::istream"), + IDT_NL("std::basic_istream>"), + IDT_NL("basic_istream") + }, + { + 'o', + IDT_NL("std::ostream"), + IDT_NL("std::basic_ostream>"), + IDT_NL("basic_ostream") + }, + { + 'd', + IDT_NL("std::iostream"), + IDT_NL("std::basic_iostream>"), + IDT_NL("basic_iostream") + } + +}; + + + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_encoding(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_unscoped_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_unscoped_template_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_nested_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_prefix(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_prefix(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_unqualified_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_source_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static bool itd_number(GItaniumDContext *, ssize_t *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_identifier(GItaniumDContext *, size_t); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_operator_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_special_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_call_offset(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_nv_offset(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_v_offset(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_ctor_dtor_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_type(GItaniumDContext *); + +/* Extrait une propriété de composant pour un contexte Itanium. */ +static TypeQualifier itd_cv_qualifiers(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_builtin_type(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_bare_function_type(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_class_enum_type(GItaniumDContext *); + + + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_args(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_arg(GItaniumDContext *); + + + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_value_to_string(GItaniumDContext *, bool); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_expr_primary(GItaniumDContext *); + + + + +/* Extrait un composant dans un contexte Itanium. */ +static bool itd_seq_id(GItaniumDContext *, char, size_t *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_substitution(GItaniumDContext *); + + + + + + +#define itd_template_param(ctx) NULL + + +#define itd_local_name(ctx) NULL + + + + +#define itd_expression(ctx) NULL + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_mangled_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + + /** + * La règle traitée ici est la suivante : + * + * ::= _Z + * + */ + + if (!g_itanium_dcontext_check_char(context, '_')) + return NULL; + + if (!g_itanium_dcontext_check_char(context, 'Z')) + return NULL; + + result = itd_encoding(context); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_encoding(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *func; /* Composant 'function name' */ + itanium_component *types; /* Composant 'bare-function...'*/ + + /** + * La règle traitée ici est la suivante : + * + * ::= + * ::= + * ::= + * + */ + + result = NULL; + g_itanium_dcontext_push_state(context, &saved); + + func = itd_name(context); + + if (func != NULL) + { + types = itd_bare_function_type(context); + + if (types != NULL) + result = itd_make_binary(context, ICT_FUNCTION_ENCODING, func, types); + else + itd_unref_comp(func); + + } + /* + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_name(context); + } + */ + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_special_name(context); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *tname; /* Composant '...template-name'*/ + itanium_component *targs; /* Composant 'template-args' */ + + /** + * La règle traitée ici est la suivante : + * + * ::= + * ::= + * ::= + * ::= + * + */ + + g_itanium_dcontext_push_state(context, &saved); + + result = itd_nested_name(context); + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + + tname = itd_unscoped_template_name(context); + + if (tname != NULL) + { + targs = itd_template_args(context); + + if (targs != NULL) + { + g_itanium_dcontext_add_substitution(context, tname); + result = itd_make_binary(context, ICT_TEMPLATE_NAME_ARGS, tname, targs); + } + + else + itd_unref_comp(tname); + + } + + } + + /** + * La règle doit être traitée après , + * car ces deux dernières ont une base commune et la seconde peut avoir besoin + * d'aller plus loin avec la règle . + * + * On termine donc par moins gourmand si la règle la plus complexe n'a pas abouti. + */ + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_unscoped_name(context); + } + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_local_name(context); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_unscoped_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + + /** + * La règle traitée ici est la suivante : + * + * ::= + * ::= St # ::std:: + * + */ + + + /* TODO : 'St' */ + + + result = itd_unqualified_name(context); + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_unscoped_template_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + + /** + * La règle traitée ici est la suivante : + * + * ::= + * ::= + * + */ + + g_itanium_dcontext_push_state(context, &saved); + + result = itd_unscoped_name(context); + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_substitution(context); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_nested_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + TypeQualifier qualifier; /* Propriétés supplémentaires */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *left; /* Première partie */ + itanium_component *right; /* Seconde partie */ + + static int inner = 0; + + int val = inner++; + + printf("\n ### (%d) NESTED>> '%s'\n", val, + g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + /** + * La règle traitée ici est la suivante : + * + * ::= N [] E + * ::= N [] E + * + */ + + if (!g_itanium_dcontext_check_char(context, 'N')) + return NULL; + + qualifier = itd_cv_qualifiers(context); + + result = NULL; + + g_itanium_dcontext_push_state(context, &saved); + + + printf("\n ----- (%d) nested prefix '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + + + left = itd_prefix(context); + + if (left != NULL) + { + if (itd_get_component_type(left) != ICT_EMPTY) + g_itanium_dcontext_add_substitution(context, left); + + right = itd_unqualified_name(context); + + if (right != NULL) + { + if (g_itanium_dcontext_check_char(context, 'E')) + result = itd_make_binary(context, ICT_NESTED_NAME, left, right); + else + printf("=== (%d) nested/prefix : BAD E\n\n", val); + + //result = itd_make_binary(context, ICT_NESTED_NAME, left, right); + + } + else + itd_unref_comp(left); + + printf(" ---- (%d) nested prefix --> %p\n\n", val, result); + + } + + + if (result == NULL) + { + printf("\n ----- (%d) nested template_arg '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + g_itanium_dcontext_pop_state(context, &saved); + + left = itd_template_prefix(context); + + if (left != NULL) + { + g_itanium_dcontext_add_substitution(context, left); + + right = itd_template_args(context); + + if (right != NULL) + { + if (g_itanium_dcontext_check_char(context, 'E')) + result = itd_make_binary(context, ICT_NESTED_NAME, left, right); + else + printf("=== (%d) nested/prefix : BAD E\n\n", val); + } + else + itd_unref_comp(left); + + } + + printf(" ---- (%d) nested template_arg --> %p\n\n", val, result); + + } + + + + printf("(%d) nested/E >> '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + /* + if (!g_itanium_dcontext_check_char(context, 'E')) + { + printf("=== (%d) NESTED : BAD E\n\n", val); + + if (result != NULL) + itd_unref_comp(result); + return NULL; + } + */ + + if (result != NULL) + printf("=== (%d) NESTED OK (%p)\n\n", val, result); + + inner--; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_prefix(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itanium_component *looping_rule; /* Extraction d'une boucle */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *left; /* Première partie */ + itanium_component *right; /* Seconde partie */ + + itd_state next_name_saved; /* Position d'analyse courante */ + itanium_component *next_name; /* Eventuel complément #1 */ + itd_state next_targs_saved; /* Position d'analyse courante */ + itanium_component *next_targs; /* Eventuel complément #2 */ + + + + itd_state expected_saved; /* Position d'analyse suivante */ + itanium_component *expected; /* Nom non-qualifié en réserve */ + + + + /** + * Les deux règles traitées ici sont les suivantes : + * + * ::= + * ::= + * ::= + * ::= # empty + * ::= + * + * ::=