/* Chrysalide - Outil d'analyse de fichiers binaires
* abi.c - décodage des noms d'éléments selon l'ABI C++ Itanium
*
* Copyright (C) 2013-2017 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* Chrysalide is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Chrysalide is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 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
* ::=
*
* ::=
* ::=
* ::=
*
* Pour éviter une récursivité qui ferait exploser la pile, on les fusionne
* en une nouvelle règle étendue :
*
* ::=
* ::=
* ::=
* ::=
* ::=
* ::= # empty
* ::=
*
* On découpe ainsi les traitements en deux parties :
* - extraction du socle non récursif.
* - extraction éventuelle d'un complément []
*/
result = NULL;
while (1)
{
printf("loop....\n");
looping_rule = NULL;
/**
* Première partie.
*/
g_itanium_dcontext_push_state(context, &saved);
/* */
left = itd_template_param(context);
if (left != NULL)
{
g_itanium_dcontext_add_substitution(context, left);
right = itd_template_args(context);
if (right != NULL)
looping_rule = itd_make_binary(context, ICT_PREFIX_BINARY, left, right);
else
itd_unref_comp(left);
}
/* */
if (looping_rule != NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
left = itd_substitution(context);
if (left != NULL)
{
right = itd_template_args(context);
if (right != NULL)
looping_rule = itd_make_binary(context, ICT_PREFIX_BINARY, left, right);
else
itd_unref_comp(left);
}
}
/* */
if (looping_rule == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
looping_rule = itd_template_param(context);
}
/* */
if (looping_rule == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
looping_rule = itd_substitution(context);
}
printf("looping_rule = %p\n", looping_rule);
if (looping_rule != NULL)
{
if (result == NULL)
result = looping_rule;
else
result = itd_make_binary(context, ICT_PREFIX_BINARY, result, looping_rule);
}
/**
* Seconde partie (1/3) : recherche d'un éventuel complément.
*/
if (looping_rule == NULL)
g_itanium_dcontext_pop_state(context, &saved);
/* */
g_itanium_dcontext_push_state(context, &next_name_saved);
next_name = itd_unqualified_name(context);
if (next_name == NULL)
{
/**
* Si on n'obtient pas de ici, rien ne sert de
* continuer. On se dirige donc vers la sortie avec ce que l'on a.
*/
return NULL;
break;
}
/* */
g_itanium_dcontext_push_state(context, &next_targs_saved);
next_targs = itd_template_args(context);
g_itanium_dcontext_pop_state(context, &next_targs_saved);
/**
* Seconde partie (2/3) : validation de la présence d'un jeton
* en réserve pour la règle parente.
*/
g_itanium_dcontext_push_state(context, &expected_saved);
expected = itd_unqualified_name(context);
if (expected == NULL)
{
/**
* La lecture a été trop loin ici.
*
* Le dernier valide pour la règle parente est
* donc celui lu à une fin de recherche de complément.
*
* On revient donc à ce stade avant de se diriger vers la sortie.
*/
itd_unref_comp(next_name);
if (next_targs != NULL)
itd_unref_comp(next_targs);
g_itanium_dcontext_pop_state(context, &next_name_saved);
break;
}
g_itanium_dcontext_pop_state(context, &expected_saved);
/**
* Seconde partie (3/3) : pleine inscription des composants extraits.
*
* On s'est manifestement retrouvé dans un des deux cas suivants :
* - ::=
* - ::=
*
* Or est un candidat pour des substitutions futures, donc on
* procède à son enregistrement, s'il n'est pas nul.
*/
if (result != NULL)
g_itanium_dcontext_add_substitution(context, result);
printf("result = %p - next_name = %p\n", result, next_name);
if (result == NULL)
result = next_name;
else
result = itd_make_binary(context, ICT_PREFIX_BINARY, result, next_name);
if (next_targs != NULL)
result = itd_make_binary(context, ICT_PREFIX_BINARY, result, next_targs);
printf(" > result = %p\n", result);
}
if (result == NULL)
result = itd_make_empty(context);
/*
if (itd_get_component_type(result) != ICT_PREFIX_BINARY)
result = itd_make_unary(context, ICT_PREFIX_UNARY, result);
*/
//printf(" : %p\n", result);
printf("### FIN DE PREFIX ### '%s'\n",
g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_template_prefix(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
itd_state saved; /* Position d'analyse courante */
itanium_component *prefix; /* Premier d'un couple de comp.*/
itanium_component *name; /* Second d'un couple de comp. */
/**
* La règle traitée ici est la suivante :
*
* ::=
* ::=
* ::=
*
*/
result = NULL;
g_itanium_dcontext_push_state(context, &saved);
prefix = itd_prefix(context);
if (prefix != NULL)
{
name = itd_unqualified_name(context);
if (name != NULL)
result = itd_make_binary(context, ICT_TPREFIX_BINARY, prefix, name);
else
itd_unref_comp(prefix);
}
if (result == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
result = itd_template_param(context);
}
if (result == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
result = itd_substitution(context);
}
if (result != NULL && itd_get_component_type(result) != ICT_TPREFIX_BINARY)
result = itd_make_unary(context, ICT_TPREFIX_UNARY, result);
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_unqualified_name(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
itd_state saved; /* Position d'analyse courante */
/**
* La règle traitée ici est la suivante :
*
* ::=
* ::=
* ::=
*
*/
g_itanium_dcontext_push_state(context, &saved);
result = itd_operator_name(context);
if (result == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
result = itd_ctor_dtor_name(context);
}
if (result == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
result = itd_source_name(context);
}
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_source_name(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
ssize_t number; /* Taille positive */
/**
* La règle traitée ici est la suivante :
*
* ::=
*
*/
if (!itd_number(context, &number))
return NULL;
if (number <= 0)
return NULL;
result = itd_identifier(context, number);
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* size = taille positive ou non lue. [OUT] *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Bilan de l'opération (un chifre lu au moins). *
* *
* Remarques : - *
* *
******************************************************************************/
static bool itd_number(GItaniumDContext *context, ssize_t *size)
{
bool result; /* Validité à renvoyer */
bool negative; /* Taille négative ? */
char peek; /* Prochain caractère lu */
/**
* La règle traitée ici est la suivante :
*
* ::= [n]
*
*/
result = false;
negative = false;
peek = g_itanium_dcontext_peek_char(context);
if (peek == 'n')
{
negative = true;
g_itanium_dcontext_advance(context, 1);
peek = g_itanium_dcontext_peek_char(context);
}
*size = 0;
while (isdigit(peek))
{
result = true;
*size = *size * 10 + peek - '0';
g_itanium_dcontext_advance(context, 1);
peek = g_itanium_dcontext_peek_char(context);
}
if (negative)
*size *= -1;
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* length = taille de l'identifiant à retrouver. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_identifier(GItaniumDContext *context, size_t length)
{
itanium_component *result; /* Construction à retourner */
const char *data; /* Données restantes */
size_t remaining; /* Quantité d'octets */
/**
* La règle traitée ici est la suivante :
*
* ::=
*
*/
data = g_itanium_dcontext_get_string(context, &remaining);
if (length > remaining)
return NULL;
result = itd_make_name(context, data, length);
if (result != NULL)
g_itanium_dcontext_advance(context, length);
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_operator_name(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
char code[2]; /* Code à venir lire */
itanium_operator_info info; /* Clef des informations */
itanium_operator_info *found; /* Informations complètes */
/**
* La règle traitée ici est la suivante :
*
* ::= nw # new
* ::= na # new[]
* ::= dl # delete
* ::= da # delete[]
* ::= ps # + (unary)
* ::= ng # - (unary)
* ::= ad # & (unary)
* ::= de # * (unary)
* ::= co # ~
* ::= pl # +
* ::= mi # -
* ::= ml # *
* ::= dv # /
* ::= rm # %
* ::= an # &
* ::= or # |
* ::= eo # ^
* ::= aS # =
* ::= pL # +=
* ::= mI # -=
* ::= mL # *=
* ::= dV # /=
* ::= rM # %=
* ::= aN # &=
* ::= oR # |=
* ::= eO # ^=
* ::= ls # <<
* ::= rs # >>
* ::= lS # <<=
* ::= rS # >>=
* ::= eq # ==
* ::= ne # !=
* ::= lt # <
* ::= gt # >
* ::= le # <=
* ::= ge # >=
* ::= nt # !
* ::= aa # &&
* ::= oo # ||
* ::= pp # ++
* ::= mm # --
* ::= cm # ,
* ::= pm # ->*
* ::= pt # ->
* ::= cl # ()
* ::= ix # []
* ::= qu # ?
* ::= st # sizeof (a type)
* ::= sz # sizeof (an expression)
* ::= cv # (cast)
* ::= v # vendor extended operator
*
*/
result = NULL;
code[0] = g_itanium_dcontext_next_char(context);
if (code[0] == 'v')
{
result = NULL; /* TODO */
goto itd_operator_name_exit;
}
code[1] = g_itanium_dcontext_next_char(context);
if (code[0] == 'c' && code[1] == 'v')
{
result = NULL; /* TODO */
goto itd_operator_name_exit;
}
/* Recherche dans la liste des opérateurs reconnus */
info.code = code;
int comp_itanium_operators(const itanium_operator_info *a, const itanium_operator_info *b)
{
int result; /* Bilan à renvoyer */
if (a->code[0] < b->code[0])
result = -1;
else if (a->code[0] > b->code[0])
result = 1;
else
{
if (a->code[1] < b->code[1])
result = -1;
else if (a->code[1] > b->code[1])
result = 1;
else
result = 0;
}
return result;
}
found = bsearch(&info, itanium_demangle_operators,
ARRAY_SIZE(itanium_demangle_operators),
sizeof(itanium_operator_info), (__compar_fn_t)comp_itanium_operators);
if (found != NULL)
result = itd_make_operator(context, found);
itd_operator_name_exit:
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_special_name(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
char next; /* Caractère suivant */
char peek; /* Prochain caractère lu */
itanium_component *offset1; /* Décalage extrait #1 */
itanium_component *encoding; /* Encodage suivant */
/**
* La règle traitée ici est la suivante :
*
* ::= T
* # base is the nominal target function of thunk
*/
result = NULL;
next = g_itanium_dcontext_next_char(context);
if (next == 'T')
{
peek = g_itanium_dcontext_peek_char(context);
switch (peek)
{
case 'V':
result = NULL; /* TODO */
break;
case 'T':
result = NULL; /* TODO */
break;
case 'I':
result = NULL; /* TODO */
break;
case 'S':
result = NULL; /* TODO */
break;
case 'c':
result = NULL; /* TODO */
break;
default:
offset1 = itd_call_offset(context);
if (offset1 == NULL) break;
encoding = itd_encoding(context);
if (encoding == NULL)
itd_unref_comp(offset1);
else
result = itd_make_binary(context, ICT_FUNCTION_THUNK, offset1, encoding);
break;
}
}
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_call_offset(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
char next; /* Caractère suivant */
/**
* La règle traitée ici est la suivante :
*
* ::= h _
* ::= v _
*/
next = g_itanium_dcontext_next_char(context);
switch (next)
{
case 'h':
result = itd_nv_offset(context);
break;
case 'v':
result = itd_v_offset(context);
break;
default:
result = NULL;
break;
}
if (result != NULL && !g_itanium_dcontext_check_char(context, '_'))
{
itd_unref_comp(result);
result = NULL;
}
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_nv_offset(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
ssize_t offset; /* Décalage obtenu */
/**
* La règle traitée ici est la suivante :
*
* ::=
* # non-virtual base override
*/
if (!itd_number(context, &offset))
return NULL;
result = itd_make_offset(context, ICT_NON_VIRTUAL_OFFSET, offset);
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_v_offset(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
ssize_t offset; /* Décalage obtenu #1 */
ssize_t voffset; /* Décalage obtenu #2 */
/**
* La règle traitée ici est la suivante :
*
* ::= _
* # virtual base override, with vcall offset
*/
if (!itd_number(context, &offset))
return NULL;
if (!g_itanium_dcontext_check_char(context, '_'))
return NULL;
if (!itd_number(context, &voffset))
return NULL;
result = itd_make_binary(context, ICT_VIRTUAL_OFFSET,
itd_make_offset(context, ICT_NON_VIRTUAL_OFFSET, offset),
itd_make_offset(context, ICT_VIRTUAL_OFFSET, voffset));
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_ctor_dtor_name(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
char next; /* Caractère suivant */
ItaniumComponentType type; /* Type de composant */
/**
* La règle traitée ici est la suivante :
*
* ::= C1 # complete object constructor
* ::= C2 # base object constructor
* ::= C3 # complete object allocating constructor
* ::= D0 # deleting destructor
* ::= D1 # complete object destructor
* ::= D2 # base object destructor
*/
next = g_itanium_dcontext_peek_char(context);
if (next == 'C')
type = ICT_CONSTRUCTOR;
else if (next == 'D')
type = ICT_DESSTRUCTOR;
else
return NULL;
g_itanium_dcontext_advance(context, 1);
next = g_itanium_dcontext_peek_char(context);
if (next != '0' && next != '1' && next != '2')
return NULL;
g_itanium_dcontext_advance(context, 1);
result = itd_make_empty(context);
itd_set_type(result, type);
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_type(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
TypeQualifier qualifier; /* Propriétés supplémentaires */
itanium_component *sub; /* Sous-type lié à associer */
itd_state saved; /* Position d'analyse courante */
/**
* La règle traitée ici est la suivante :
*
* ::=
* ::=
* ::=
* ::=
* ::=
* ::=
* ::=
* ::= # See Compression below
* ::=
* ::= P # pointer-to
* ::= R # reference-to
* ::= O # rvalue reference-to (C++0x)
* ::= C # complex pair (C 2000)
* ::= G # imaginary (C 2000)
* ::= U # vendor extended type qualifier
*
*/
result = NULL;
qualifier = itd_cv_qualifiers(context);
switch (g_itanium_dcontext_peek_char(context))
{
case 'P':
g_itanium_dcontext_advance(context, 1);
sub = itd_type(context);
if (sub == NULL) return NULL;
result = itd_make_unary(context, ICT_POINTER_TO, sub);
break;
case 'R':
g_itanium_dcontext_advance(context, 1);
sub = itd_type(context);
if (sub == NULL) return NULL;
result = itd_make_unary(context, ICT_REFERENCE_TO, sub);
break;
case 'O':
g_itanium_dcontext_advance(context, 1);
sub = itd_type(context);
if (sub == NULL) return NULL;
result = itd_make_unary(context, ICT_RVALUE_REFERENCE_TO, sub);
break;
case 'C':
g_itanium_dcontext_advance(context, 1);
sub = itd_type(context);
if (sub == NULL) return NULL;
result = itd_make_unary(context, ICT_COMPLEX_PAIR, sub);
break;
case 'G':
g_itanium_dcontext_advance(context, 1);
sub = itd_type(context);
if (sub == NULL) return NULL;
result = itd_make_unary(context, ICT_IMAGINARY, sub);
break;
case 'U':
g_itanium_dcontext_advance(context, 1);
/* TODO */
return NULL;
break;
}
if (result != NULL) goto itd_type_end;
g_itanium_dcontext_push_state(context, &saved);
result = itd_builtin_type(context);
if (result != NULL) goto itd_type_end;
g_itanium_dcontext_pop_state(context, &saved);
result = itd_class_enum_type(context);
if (result != NULL) goto itd_type_end;
g_itanium_dcontext_pop_state(context, &saved);
result = itd_substitution(context);
if (result != NULL) goto itd_type_end;
itd_type_end:
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait une propriété de composant pour un contexte Itanium. *
* *
* Retour : Indication extraite. *
* *
* Remarques : - *
* *
******************************************************************************/
static TypeQualifier itd_cv_qualifiers(GItaniumDContext *context)
{
TypeQualifier result; /* Valeur à remonter */
/**
* La règle traitée ici est la suivante :
*
* ::= [r] [V] [K] # restrict (C99), volatile, const
*
*/
result = TQF_NONE;
while (1)
switch (g_itanium_dcontext_peek_char(context))
{
case 'r':
result = TQF_RESTRICT;
g_itanium_dcontext_advance(context, 1);
break;
case 'V':
result = TQF_VOLATILE;
g_itanium_dcontext_advance(context, 1);
break;
case 'K':
result = TQF_CONST;
g_itanium_dcontext_advance(context, 1);
break;
default:
goto itd_cv_qualifiers_exit;
break;
}
itd_cv_qualifiers_exit:
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_builtin_type(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
BaseType type; /* Type reconnu ou BTP_INVALID */
GDataType *builtin; /* Type construit */
/**
* La règle traitée ici est la suivante :
*
* ::= v # void
* ::= w # wchar_t
* ::= b # bool
* ::= c # char
* ::= a # signed char
* ::= h # unsigned char
* ::= s # short
* ::= t # unsigned short
* ::= i # int
* ::= j # unsigned int
* ::= l # long
* ::= m # unsigned long
* ::= x # long long, __int64
* ::= y # unsigned long long, __int64
* ::= n # __int128
* ::= o # unsigned __int128
* ::= f # float
* ::= d # double
* ::= e # long double, __float80
* ::= g # __float128
* ::= z # ellipsis
* ::= u # vendor extended type
*
*/
switch (g_itanium_dcontext_peek_char(context))
{
case 'v':
type = BTP_VOID;
break;
case 'w':
type = BTP_WCHAR_T;
break;
case 'b':
type = BTP_BOOL;
break;
case 'c':
type = BTP_CHAR;
break;
case 'a':
type = BTP_SCHAR;
break;
case 'h':
type = BTP_UCHAR;
break;
case 's':
type = BTP_SHORT;
break;
case 't':
type = BTP_USHORT;
break;
case 'i':
type = BTP_INT;
break;
case 'j':
type = BTP_UINT;
break;
case 'l':
type = BTP_LONG;
break;
case 'm':
type = BTP_ULONG;
break;
case 'x':
type = BTP_LONG_LONG;
break;
case 'y':
type = BTP_ULONG_LONG;
break;
case 'n':
type = BTP_INT128;
break;
case 'o':
type = BTP_UINT128;
break;
case 'f':
type = BTP_FLOAT;
break;
case 'd':
type = BTP_DOUBLE;
break;
case 'e':
type = BTP_LONG_DOUBLE;
break;
case 'g':
type = BTP_FLOAT128;
break;
case 'z':
type = BTP_ELLIPSIS;
break;
case 'u':
type = BTP_OTHER;
/* FIXME */
/* # vendor extended type */
break;
default:
type = BTP_INVALID;
break;
}
if (type != BTP_INVALID)
{
builtin = g_basic_type_new(type);
result = itd_make_type(context, builtin);
g_itanium_dcontext_advance(context, 1);
}
else
result = NULL;
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_bare_function_type(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
itanium_component *type; /* Nouvel élément à intégrer */
itd_state saved; /* Position d'analyse courante */
/**
* La règle traitée ici est la suivante :
*
* ::= +
* # types are possible return type, then parameter types
*
*/
type = itd_type(context);
if (type == NULL) return NULL;
result = itd_append_right_to_binary(context, ICT_TYPES_LIST, NULL, type);
while (1)
{
g_itanium_dcontext_push_state(context, &saved);
type = itd_type(context);
if (type == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
break;
}
result = itd_append_right_to_binary(context, ICT_TYPES_LIST, result, type);
}
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_class_enum_type(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
/**
* La règle traitée ici est la suivante :
*
* ::=
*
*/
result = itd_name(context);
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_template_args(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
itanium_component *arg; /* Nouvel argument extrait */
itd_state saved; /* Position d'analyse courante */
printf(">>> TA>> '%s'\n", g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
/**
* La règle traitée ici est la suivante :
*
* ::= I + E
*
*/
if (!g_itanium_dcontext_check_char(context, 'I'))
return NULL;
arg = itd_template_arg(context);
if (arg == NULL) return NULL;
result = itd_append_right_to_binary(context, ICT_TYPES_LIST, NULL, arg);
while (1)
{
g_itanium_dcontext_push_state(context, &saved);
arg = itd_template_arg(context);
if (arg == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
break;
}
result = itd_append_right_to_binary(context, ICT_TYPES_LIST, result, arg);
}
//printf(" ta/E >> '%s'\n", g_itanium_dcontext_get_string(context, (size_t []){ 0 }));
if (!g_itanium_dcontext_check_char(context, 'E'))
{
//printf("=== TA : BAD E\n\n");
if (result != NULL)
itd_unref_comp(result);
return NULL;
}
//printf("=== TA >> %p\n\n", result);
result = itd_make_unary(context, ICT_TEMPLATE_ARGS, result);
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_template_arg(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
itd_state saved; /* Position d'analyse courante */
/**
* La règle traitée ici est la suivante :
*
* ::= # type or template
* ::= X E # expression
* ::= # simple expressions
*
*/
g_itanium_dcontext_push_state(context, &saved);
result = itd_type(context);
if (result == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
if (g_itanium_dcontext_check_char(context, 'X'))
{
result = itd_expression(context);
if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
{
itd_unref_comp(result);
result = NULL;
}
}
}
if (result == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
result = itd_expr_primary(context);
}
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* hex = prise en compte des caractères hexadécimaux ? *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_value_to_string(GItaniumDContext *context, bool hex)
{
itanium_component *result; /* Construction à retourner */
const char *data; /* Données restantes */
itd_state saved; /* Position d'analyse initiale */
itd_state cur; /* Position d'analyse courante */
char peek; /* Prochain caractère lu */
/**
* Les règles traitées ici sont les suivantes :
*
* # integer literal
* # floating literal
*
*/
result = NULL;
data = g_itanium_dcontext_get_string(context, (size_t []) { 0 });
g_itanium_dcontext_push_state(context, &saved);
while (1)
{
peek = g_itanium_dcontext_peek_char(context);
switch (peek)
{
case '0' ... '9':
g_itanium_dcontext_advance(context, 1);
break;
case 'a' ... 'f':
if (hex)
g_itanium_dcontext_advance(context, 1);
else
goto exit_iits;
break;
case 'E':
goto exit_loop;
break;
default:
goto exit_iits;
}
}
exit_loop:
g_itanium_dcontext_push_state(context, &cur);
if ((cur.pos - saved.pos) > 0)
result = itd_make_name(context, data, cur.pos - saved.pos);
exit_iits:
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_expr_primary(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
itd_state saved; /* Position d'analyse courante */
itanium_component *type; /* Type de valeur extrait */
itd_state saved_value; /* Position d'analyse courante */
/**
* La règle traitée ici est la suivante :
*
* ::= L E # integer literal
* ::= L E # floating literal
* ::= L E # external name
*
*/
printf("PRIMARY :: no L\n");
if (!g_itanium_dcontext_check_char(context, 'L'))
return NULL;
g_itanium_dcontext_push_state(context, &saved);
type = itd_type(context);
if (type != NULL)
{
g_itanium_dcontext_push_state(context, &saved_value);
/* Règle */
result = itd_value_to_string(context, false);
if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
{
itd_unref_comp(result);
result = NULL;
}
/* Règle */
if (result == NULL)
{
g_itanium_dcontext_pop_state(context, &saved_value);
result = itd_value_to_string(context, true);
if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
{
itd_unref_comp(result);
result = NULL;
}
}
itd_unref_comp(type);
}
else
result = NULL;
/* Règle */
if (result == NULL)
{
g_itanium_dcontext_pop_state(context, &saved);
result = itd_mangled_name(context);
if (result != NULL && !g_itanium_dcontext_check_char(context, 'E'))
{
itd_unref_comp(result);
result = NULL;
}
}
printf("PRIMARY :: %p\n", result);
return result;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* cur = caractère courant. *
* id = identifiant lu en cas de succès. [OUT] *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
static bool itd_seq_id(GItaniumDContext *context, char cur, size_t *id)
{
/**
* La règle traitée ici est la suivante :
*
*
*
*/
*id = 0;
/**
* La fonction n'est appelée que si un début de séquence est détecté.
* (ie, cur == '_' || isdigit(cur) || isupper(cur)).
*/
if (cur != '_')
{
do
{
if (isdigit(cur))
*id = *id * 36 + cur - '0';
else if (isupper(cur))
*id = *id * 36 + cur - 'A' + 10;
else
return false;
cur = g_itanium_dcontext_next_char(context);
}
while (cur != '_');
(*id)++;
}
return true;
}
/******************************************************************************
* *
* Paramètres : context = contexte de décodage à utiliser. *
* *
* Description : Extrait un composant dans un contexte Itanium. *
* *
* Retour : Composant extrait ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
static itanium_component *itd_substitution(GItaniumDContext *context)
{
itanium_component *result; /* Construction à retourner */
char cur; /* Caractère analysé */
size_t id; /* Identifiant de substitution */
char peek; /* Prochain caractère lu */
bool verbose; /* Sélection du rendu idéal */
size_t i; /* Boucle de parcours */
/**
* La règle traitée ici est la suivante :
*
* ::= S _
* ::= S_
* ::= St # ::std::
* ::= Sa # ::std::allocator
* ::= Sb # ::std::basic_string
* ::= Ss # ::std::basic_string, ::std::allocator>
* ::= Si # ::std::basic_istream>
* ::= So # ::std::basic_ostream>
* ::= Sd # ::std::basic_iostream>
*
*/
peek = g_itanium_dcontext_peek_char(context);
if (!g_itanium_dcontext_check_char(context, 'S'))
return NULL;
cur = g_itanium_dcontext_next_char(context);
if (cur == '_' || isdigit(cur) || isupper(cur))
{
if (!itd_seq_id(context, cur, &id))
return NULL;
printf("requesting... %zu\n", id);
result = g_itanium_dcontext_get_substitution(context, id);
}
else
{
result = NULL;
peek = g_itanium_dcontext_peek_char(context);
verbose = (peek == 'C' || peek == 'D'); /* TODO : prefixe ? */
for (i = 0; i < ARRAY_SIZE(itanium_standard_substitutions); i++)
if (itanium_standard_substitutions[i].code == cur)
{
/* TODO : constructeur... */
if (verbose)
result = itd_make_name(context,
itanium_standard_substitutions[i].full,
itanium_standard_substitutions[i].full_len);
else
result = itd_make_name(context,
itanium_standard_substitutions[i].simple,
itanium_standard_substitutions[i].simple_len);
itd_set_type(result, ICT_STD_SUBST);
break;
}
}
return result;
}