%{ #include #include #include #include "context-int.h" #include "itanium.h" #include "../../common/extstr.h" /** * cf. http://www.codesourcery.com/cxx-abi/abi.html#mangling */ /* --------------------- CONTEXTE POUR LE DECODAGE TYPE ITANIUM --------------------- */ #define G_TYPE_ITANIUM_DCONTEXT g_itanium_dcontext_get_type() #define G_ITANIUM_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_itanium_dcontext_get_type(), GItaniumDContext)) #define G_IS_ITANIUM_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_itanium_dcontext_get_type())) #define G_ITANIUM_DCONTEXT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_itanium_dcontext_get_type(), GItaniumDContextIface)) #define G_ITANIUM_DCONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ITANIUM_DCONTEXT, GItaniumDContextClass)) /* Contexte de décodage Itanium (instance) */ struct _GItaniumDContext { GDemanglingContext parent; /* A laisser en premier */ char *identifier; /* Identifiant en construction */ size_t id_allocated; /* Taille allouée en mémoire */ size_t id_used; /* Longueur de la chaîne */ GSList *routines; /* Routines en cours de maj */ GSList *substitutions; /* Empilement des types créés */ bool start_args; /* Début de définitions d'args */ unsigned int template_level; /* Compteur d'imbrications */ }; /* Contexte de décodage Itanium (classe) */ struct _GItaniumDContextClass { GDemanglingContextClass parent; /* A laisser en premier */ }; /* Taille du bond pour les allocations */ #define ITANIUM_ALLOC_CLUSTER 10 /* Indique le type défini pour un contexte de décodage. */ static GType g_itanium_dcontext_get_type(void); /* Initialise la classe des contextes de décodage. */ static void g_itanium_dcontext_class_init(GItaniumDContextClass *); /* Initialise une instance de contexte pour décodage. */ static void g_itanium_dcontext_init(GItaniumDContext *); /* Supprime toutes les références externes. */ static void g_itanium_dcontext_dispose(GItaniumDContext *); /* Procède à la libération totale de la mémoire. */ static void g_itanium_dcontext_finalize(GItaniumDContext *); /* Réinitialise le constructeur d'identifiants. */ static void g_itanium_dcontext_reset_identifier(GItaniumDContext *); /* Construit à la volée un identifiant. */ static void g_itanium_dcontext_build_identifier(GItaniumDContext *, char); /* Place sous le feu des projecteurs une nouvelle routine. */ static GBinRoutine *g_itanium_dcontext_push_routine(GItaniumDContext *, GBinRoutine *); /* Remet une ancienne routine sous le feu des projecteurs. */ static GBinRoutine *g_itanium_dcontext_pop_routine(GItaniumDContext *); /* Ajoute un élément dans une liste de substitutions. */ static void g_itanium_dcontext_add_item(GItaniumDContext *, GOpenidaType *); /* Fournit le nième élément d'une liste de substitutions. */ static GOpenidaType *g_itanium_dcontext_get_item(GItaniumDContext *, guint); /* Autorise ou non le dépilement des opérateurs. */ static void g_itanium_dcontext_update(GItaniumDContext *); /* ------------------------ TRAITEMENT DE L'ENCODAGE ITANIUM ------------------------ */ /* Fait sauter le premier argument en faveur du type de retour. */ static void compute_routine_itanium_ret_type(GBinRoutine *); /* Recherche et fait sauter les premiers arguments rencontrés. */ static void update_itanium_ret_type(GOpenidaType *); /* Borne la longueur d'une chaîne à lire. */ extern void set_itanium_text_length(unsigned int); /* Autorise la lecture des opérateurs. */ extern void allow_itanium_operators(void); /* Autorise la lecture des opérateurs. */ extern void exclude_itanium_operators(void); char *strmerge(char *str1, const char *sep, char *str2); char *strmerge(char *str1, const char *sep, char *str2) { char *result; if (str1 == NULL) result = str2; else if (str2 == NULL) result = str1; else { result = (char *)calloc(strlen(str1) + strlen(sep) + strlen(str2) + 1, sizeof(char)); strcpy(result, str1); strcat(result, sep); strcat(result, str2); free(str1); free(str2); } return result; } %} %union { struct { union { char *str; void/*GOpenidaType*/ *type; }; int/*bool*/ is_string; } str_or_type; char car; char *text; unsigned int val; short/*s16_t*/ s16_val; void /*GOpenidaType*/ *type; void /*GTemplateType*/ *templtype; void/*simple_variable*/ *simple; void/*complex_variable*/ *complex; void/*variable*/ *var; int/*VariableQualifier*/ qual; void/*GSList*/ *slist; } %parse-param { GItaniumDContext *context } %parse-param { GBinRoutine *routine } %token ITANIUM_SIGNATURE %token EE NN II FF LL %token C1 C2 C3 D1 D2 D3 %token V W B C A H S T I J L M X Y N O F D E G Z DD DE DF DH DI DS U %token TP TR TO TC TG %token QR QV QK %token ST SA SB SS SI SO SD %token OPER_NEW OPER_NEW_ARRAY OPER_DELETE OPER_DELETE_ARRAY OPER_PLUS_UNARY OPER_NEG_UNARY %token OPER_AND_UNARY OPER_DE_UNARY OPER_COMPL OPER_PLUS OPER_MINUS OPER_MUL OPER_DIV OPER_MOD %token OPER_AND OPER_OR OPER_EXCL_OR OPER_AS OPER_PLUS_EQ OPER_MINUS_EQ OPER_MUL_EQ OPER_DIV_EQ %token OPER_MOD_EQ OPER_AND_EQ OPER_OR_EQ OPER_EXCL_OR_EQ OPER_LEFT_SHIFT OPER_RIGHT_SHIFT %token OPER_LEFT_SHIFT_EQ OPER_RIGHT_SHIFT_EQ OPER_EQUAL OPER_NOT_EQ OPER_LESS OPER_GREATER %token OPER_LESS_EQ OPER_GREATER_EQ OPER_NOT OPER_AND_AND OPER_OR_OR OPER_PLUS_PLUS OPER_MINUS_MINUS %token OPER_COMMA OPER_PRIV_MEMB OPER_POINTER_TO OPER_CLASS OPER_INDEX %token SUBSTI_FIRST SUBSTI_N %token TPARAM_FIRST TPARAM_N %token NUMBER CHAR %token LPART MPART RPART %token POSITION POSITION_ABS IMAGE %token RECT %token O_BRACKET C_BRACKET %token PATH %token DEC_16 %token TEXT %type TEXT PATH %type DEC_16 %type name %type unscoped_name %type nested_name %type unscoped_template_name %type unqualified_name operator_name %type registered_prefix %type prefix %type template_prefix source_name %type registered_template_prefix %type template_param template_template_param %type function_type type %type qualifiers %type builtin_type %type class_enum_type %type template_args template_arg_list %type template_arg expr_primary %type substitution %type CHAR %type NUMBER SUBSTI_N TPARAM_N %{ /* De lexi.c... */ /*int yylex(YYSTYPE *, YYLTYPE *);*/ void yyrestart(FILE *); typedef struct yy_buffer_state *YY_BUFFER_STATE; extern YY_BUFFER_STATE yy_scan_string(const char *); extern void yy_delete_buffer(YY_BUFFER_STATE); /* Affiche un message d'erreur concernant l'analyse. */ /*int yyerror(const YYLTYPE *, bool, char **, unsigned char *, char *);*/ %} %% input: ITANIUM_SIGNATURE encoding ; encoding: name { $1.is_string ? g_binary_routine_set_name(routine, $1.str) : g_binary_routine_set_name_from_type(routine, $1.type); } bare_function_type { ; } ; name: nested_name { $$.type = $1; $$.is_string = false; } | unscoped_name { $$.str = $1; $$.is_string = true; } | unscoped_template_name template_args { if (G_IS_TEMPLATE_TYPE($1)) { g_template_type_add_params($1, $2); $$.type = $1; $$.is_string = false; } else { char *tmp; tmp = g_openida_type_to_string($1); $$.type = g_template_type_new(tmp, $2); $$.is_string = false; free(tmp); g_object_unref(G_OBJECT($1)); } //g_template_type_add_params($1, $2); printf(" [name tmp:: %s]\n", g_openida_type_to_string($$.type)); } ; unscoped_name: unqualified_name { $$ = $1; } | ST unqualified_name { $$ = strprep($2, "std::"); } ; unscoped_template_name: unscoped_name { $$ = g_template_type_new($1, NULL); g_itanium_dcontext_add_item(context, $$); } | substitution { $$ = $1; } ; nested_name: NN registered_prefix unqualified_name EE { $$ = ($3 != NULL ? strmerge($2, "::", $3) : $2); printf("passage nested p+uq = '%s'\n", $$); $$ = g_class_enum_type_new(CET_UNKNOWN, $$); g_itanium_dcontext_add_item(context, $$); } | NN qualifiers registered_prefix unqualified_name EE { $$ = ($4 != NULL ? strmerge($3, "::", $4) : $3); printf("passage nested p+uq = '%s'\n", $$); $$ = g_class_enum_type_new(CET_UNKNOWN, $$); g_itanium_dcontext_add_item(context, $$); } | NN registered_template_prefix template_args EE { $$ = $2; g_template_type_add_params($2, $3); printf(" [nested tmp:: %s]\n", g_openida_type_to_string($$)); } | NN qualifiers registered_template_prefix template_args EE { $$ = $3; g_template_type_add_params($3, $4); printf(" [nested tmp:: %s]\n", g_openida_type_to_string($$)); } ; registered_prefix: prefix { if ($1 == NULL) $$ = NULL; else { g_itanium_dcontext_add_item(context, $1); $$ = g_openida_type_to_string($1); } } | substitution { $$ = g_openida_type_to_string($1); printf("prefix substi :: %s\n", g_openida_type_to_string($1)); } ; prefix: /* vide */ { $$ = NULL; } | registered_prefix unqualified_name { $$ = ($2 != NULL ? g_class_enum_type_new(CET_CLASS, strmerge($1, "::", $2)) : $1); printf("passage p+uq = '%s'\n", g_openida_type_to_string($$)); } | registered_template_prefix template_args { $$ = $1; g_template_type_add_params($1, $2); printf("passage p_tmp = '%s'\n", g_openida_type_to_string($$)); } ; registered_template_prefix: template_prefix { $$ = g_template_type_new($1, NULL); /*g_itanium_dcontext_add_item(context, $$);*/ } ; template_prefix: registered_prefix unqualified_name { if ($1 != NULL) printf("$1 == '%s'\n", $1); //if ($1 != NULL) if (strcmp($1, "std") != 0) g_itanium_dcontext_add_item(context, g_class_enum_type_new(CET_CLASS, $1)); $$ = ($2 != NULL ? strmerge($1, "::", $2) : $1); printf("$$ == '%s'\n", $$); g_itanium_dcontext_add_item(context, g_class_enum_type_new(CET_CLASS, $$)); } | template_param { $$ = g_openida_type_to_string($1); printf("[[ tmp param %s ]]\n", $$); g_object_unref(G_OBJECT($1)); } | substitution { $$ = g_openida_type_to_string($1); printf("template_prefix substi :: %s\n", $$); g_object_unref(G_OBJECT($1)); } ; unqualified_name: operator_name { printf("dup :: '%s'\n", $1); fflush(NULL) ;$$ = strdup($1) ; } | ctor_dtor_name { printf("passage C\n"); $$ = NULL; } | source_name { $$ = $1; } ; source_name: NUMBER { set_itanium_text_length($1); g_itanium_dcontext_reset_identifier(context); } identifier { $$ = strdup(context->identifier); printf("==source name== :: %s\n", $$); } ; identifier: identifier CHAR { g_itanium_dcontext_build_identifier(context, $2); } | CHAR { g_itanium_dcontext_build_identifier(context, $1); } ; operator_name: OPER_NEW { $$ = "new"; } | OPER_NEW_ARRAY { $$ = "new[]"; } | OPER_DELETE { $$ = "delete"; } | OPER_DELETE_ARRAY { $$ = "delete[]"; } | OPER_PLUS_UNARY { $$ = "+"; } | OPER_NEG_UNARY { $$ = "-"; } | OPER_AND_UNARY { $$ = "&"; } | OPER_DE_UNARY { $$ = "*"; } | OPER_COMPL { $$ = "~"; } | OPER_PLUS { $$ = "+"; } | OPER_MINUS { $$ = "-"; } | OPER_MUL { $$ = "*"; } | OPER_DIV { $$ = "/"; } | OPER_MOD { $$ = "%"; } | OPER_AND { $$ = "&"; } | OPER_OR { $$ = "|"; } | OPER_EXCL_OR { $$ = "^"; } | OPER_AS { $$ = "="; } | OPER_PLUS_EQ { $$ = "+="; } | OPER_MINUS_EQ { $$ = "-="; } | OPER_MUL_EQ { $$ = "*="; } | OPER_DIV_EQ { $$ = "/="; } | OPER_MOD_EQ { $$ = "%)"; } | OPER_AND_EQ { $$ = "&="; } | OPER_OR_EQ { $$ = "|="; } | OPER_EXCL_OR_EQ { $$ = "^="; } | OPER_LEFT_SHIFT { $$ = "<<"; } | OPER_RIGHT_SHIFT { $$ = ">>"; } | OPER_LEFT_SHIFT_EQ { $$ = "<<="; } | OPER_RIGHT_SHIFT_EQ { $$ = ">>="; } | OPER_EQUAL { $$ = "=="; } | OPER_NOT_EQ { $$ = "!="; } | OPER_LESS { $$ = "<"; } | OPER_GREATER { $$ = ">"; } | OPER_LESS_EQ { $$ = "<="; } | OPER_GREATER_EQ { $$ = ">="; } | OPER_NOT { $$ = "!"; } | OPER_AND_AND { $$ = "&&"; } | OPER_OR_OR { $$ = "||"; } | OPER_PLUS_PLUS { $$ = "++"; } | OPER_MINUS_MINUS { $$ = "--"; } | OPER_COMMA { $$ = ","; } | OPER_PRIV_MEMB { $$ = "->*"; } | OPER_POINTER_TO { $$ = "->"; } | OPER_CLASS { $$ = "()"; } | OPER_INDEX { $$ = "[]"; } ; ctor_dtor_name: C1 { g_binary_routine_set_type(routine, RTT_CONSTRUCTOR); } | C2 { g_binary_routine_set_type(routine, RTT_CONSTRUCTOR); } | C3 { g_binary_routine_set_type(routine, RTT_CONSTRUCTOR); } | D1 { g_binary_routine_set_type(routine, RTT_DESTRUCTOR); } | D2 { g_binary_routine_set_type(routine, RTT_DESTRUCTOR); } | D3 { g_binary_routine_set_type(routine, RTT_DESTRUCTOR); } ; function_type: FF { routine = g_itanium_dcontext_push_routine(context, routine); context->start_args = true; g_itanium_dcontext_update(context); } bare_function_type EE { $$ = g_encapsulated_type_new(ECT_ROUTINE, routine); routine = g_itanium_dcontext_pop_routine(context); if (routine == NULL) YYERROR; } ; type: builtin_type { $$ = $1; printf("builtin '%s'\n", g_openida_type_to_string($1)); } | class_enum_type { $$ = $1; printf("type :: %p\n", $1); fflush(NULL); g_itanium_dcontext_add_item(context, $1); } | substitution { $$ = $1; } | template_param { $$ = $1; } | template_template_param template_args { $$ = g_template_type_new(g_openida_type_to_string($1), NULL); g_object_unref($1); g_template_type_add_params($$, $2); printf(" [type tmp:: %s]\n", g_openida_type_to_string($$)); } | function_type { $$ = $1; } | qualifiers type { $$ = g_openida_type_dup($2); g_openida_type_add_qualifier($$, $1); g_itanium_dcontext_add_item(context, $$); } | TP type { $$ = g_encapsulated_type_new(ECT_POINTER, $2); g_itanium_dcontext_add_item(context, $$); } | TR type { $$ = g_encapsulated_type_new(ECT_REFERENCE, $2); g_itanium_dcontext_add_item(context, $$); } | TO type { $$ = g_encapsulated_type_new(ECT_RVALUE_REF, $2); g_itanium_dcontext_add_item(context, $$); } | TC type { $$ = g_encapsulated_type_new(ECT_COMPLEX, $2); g_itanium_dcontext_add_item(context, $$); } | TG type { $$ = g_encapsulated_type_new(ECT_IMAGINARY, $2); g_itanium_dcontext_add_item(context, $$); } ; qualifiers: QR { $$ = TQF_RESTRICT; } | QV { $$ = TQF_VOLATILE; } | QK { $$ = TQF_CONST; } ; builtin_type: V { $$ = g_basic_type_new(BTP_VOID); } | W { $$ = g_basic_type_new(BTP_WCHAR_T); } | B { $$ = g_basic_type_new(BTP_BOOL); } | C { $$ = g_basic_type_new(BTP_CHAR); } | A { $$ = g_basic_type_new(BTP_SCHAR); } | H { $$ = g_basic_type_new(BTP_UCHAR); } | S { $$ = g_basic_type_new(BTP_SHORT); } | T { $$ = g_basic_type_new(BTP_USHORT); } | I { $$ = g_basic_type_new(BTP_INT); } | J { $$ = g_basic_type_new(BTP_UINT); } | L { $$ = g_basic_type_new(BTP_LONG); } | M { $$ = g_basic_type_new(BTP_ULONG); } | X { $$ = g_basic_type_new(BTP_LONG_LONG); } | Y { $$ = g_basic_type_new(BTP_ULONG_LONG); } | N { $$ = g_basic_type_new(BTP_INT128); } | O { $$ = g_basic_type_new(BTP_UINT128); } | F { $$ = g_basic_type_new(BTP_FLOAT); } | D { $$ = g_basic_type_new(BTP_DOUBLE); } | E { $$ = g_basic_type_new(BTP_LONG_DOUBLE); } | G { $$ = g_basic_type_new(BTP_FLOAT128); } | Z { $$ = g_basic_type_new(BTP_ELLIPSIS); } | DD { $$ = g_basic_type_new(BTP_754R_64); } | DE { $$ = g_basic_type_new(BTP_754R_128); } | DF { $$ = g_basic_type_new(BTP_754R_32); } | DH { $$ = g_basic_type_new(BTP_754R_16); } | DI { $$ = g_basic_type_new(BTP_CHAR32_T); } | DS { $$ = g_basic_type_new(BTP_CHAR16_T); } | U source_name { $$ = g_basic_type_new(BTP_OTHER); /* TODO */ ; free($2); } ; bare_function_type: bare_function_type type { g_binary_routine_add_arg(routine, g_binary_variable_new($2))/*TODO unref*/; } | type { g_binary_routine_add_arg(routine, g_binary_variable_new($1))/*TODO unref*/; } ; class_enum_type: name { printf("is str ?? %d (%p)\n", $1.is_string, $1.type); fflush(NULL); $$ = $1.is_string ? g_class_enum_type_new(CET_UNKNOWN, $1.str) : $1.type; } ; template_param: TPARAM_FIRST { const GOpenidaType *type = g_binary_routine_get_type_from_name(routine); if (G_IS_TEMPLATE_TYPE(type)) $$ = g_template_type_get_param(G_TEMPLATE_TYPE(type), 0); else $$ = NULL; if ($$ == NULL) YYERROR; if (!G_IS_BASIC_TYPE($$)) g_itanium_dcontext_add_item(context, $$); } | TPARAM_N { const GOpenidaType *type = g_binary_routine_get_type_from_name(routine); if (G_IS_TEMPLATE_TYPE(type)) $$ = g_template_type_get_param(G_TEMPLATE_TYPE(type), $1 + 1); else $$ = NULL; if ($$ == NULL) YYERROR; if (!G_IS_BASIC_TYPE($$)) g_itanium_dcontext_add_item(context, $$); } ; template_template_param: template_param { $$ = $1; } | substitution { $$ = $1; } ; template_args: use_templates template_arg_list EE { $$ = $2; context->template_level--; g_itanium_dcontext_update(context); } ; use_templates: II { printf("new template !!!\n"); /* FIXME : régle désormais inutile ! -> remme */ context->template_level++; g_itanium_dcontext_update(context); } ; template_arg_list: template_arg_list template_arg { $$ = g_slist_prepend($1, $2); } | template_arg { $$ = g_slist_prepend(NULL, $1); } | template_args { g_class_enum_type_new(CET_UNKNOWN, "template params"); printf("??? tmp list\n"); } ; template_arg: type { $$ = $1; } | expr_primary { $$ = $1; } ; expr_primary: LL type NUMBER EE { $$ = $2; } ; substitution: ST { $$ = g_class_enum_type_new(CET_CLASS, "std"); } | SA { $$ = g_class_enum_type_new(CET_CLASS, "std::allocator"); } | SB { $$ = g_class_enum_type_new(CET_CLASS, "std::basic_string"); } | SS { $$ = g_class_enum_type_new(CET_CLASS, "std::string"); } | SI { $$ = g_class_enum_type_new(CET_CLASS, "std::istream"); } | SO { $$ = g_class_enum_type_new(CET_CLASS, "std::ostream"); } | SD { $$ = g_class_enum_type_new(CET_CLASS, "std::iostream"); } | SUBSTI_FIRST { $$ = g_itanium_dcontext_get_item(context, 0); if ($$ == NULL) YYERROR; } | SUBSTI_N { $$ = g_itanium_dcontext_get_item(context, $1 + 1); if ($$ == NULL) YYERROR; } ; %% /* ---------------------------------------------------------------------------------- */ /* CONTEXTE POUR LE DECODAGE TYPE ITANIUM */ /* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour un contexte de décodage. */ G_DEFINE_TYPE(GItaniumDContext, g_itanium_dcontext, G_TYPE_DEMANGLING_CONTEXT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des contextes de décodage. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_itanium_dcontext_class_init(GItaniumDContextClass *klass) { GObjectClass *object; /* Autre version de la classe */ object = G_OBJECT_CLASS(klass); object->dispose = g_itanium_dcontext_dispose; object->finalize = g_itanium_dcontext_finalize; } /****************************************************************************** * * * Paramètres : context = instance à initialiser. * * * * Description : Initialise une instance de contexte pour décodage. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_itanium_dcontext_init(GItaniumDContext *context) { context->substitutions = g_slist_alloc(); } /****************************************************************************** * * * Paramètres : context = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_itanium_dcontext_dispose(GItaniumDContext *context) { gpointer data; /* Type à détacher */ GBinRoutine *routine; /* Routine à détacher */ gpointer obj_class; /* Classe parente */ while ((data = g_slist_nth_data(context->substitutions, 0)) != NULL) { g_object_unref(G_OBJECT(data)); context->substitutions = g_slist_remove(context->substitutions, data); } while ((routine = g_itanium_dcontext_pop_routine(context)) != NULL) g_object_unref(G_OBJECT(routine)); obj_class = g_type_class_peek_parent(G_ITANIUM_DCONTEXT_GET_CLASS(context)); G_OBJECT_CLASS(obj_class)->dispose(G_OBJECT(context)); } /****************************************************************************** * * * Paramètres : context = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_itanium_dcontext_finalize(GItaniumDContext *context) { gpointer obj_class; /* Classe parente */ if (context->identifier != NULL) free(context->identifier); obj_class = g_type_class_peek_parent(G_ITANIUM_DCONTEXT_GET_CLASS(context)); G_OBJECT_CLASS(obj_class)->finalize(G_OBJECT(context)); } /****************************************************************************** * * * Paramètres : - * * * * Description : Prépare de quoi effectuer un décodage Itanium. * * * * Retour : Instance du contexte mis en place. * * * * Remarques : - * * * ******************************************************************************/ GDemanglingContext *g_itanium_dcontext_new(void) { GDemanglingContext *result; /* Structure à retourner */ result = g_object_new(G_TYPE_ITANIUM_DCONTEXT, NULL); return result; } /****************************************************************************** * * * Paramètres : context = décodeur à mettre à jour. * * * * Description : Réinitialise le constructeur d'identifiants. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_itanium_dcontext_reset_identifier(GItaniumDContext *context) { context->id_used = 0; } /****************************************************************************** * * * Paramètres : context = décodeur à mettre à jour. * * value = caractère d'identifiant à mémoriser. * * * * Description : Construit à la volée un identifiant. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_itanium_dcontext_build_identifier(GItaniumDContext *context, char value) { if ((context->id_used + 2) > context->id_allocated) { context->id_allocated += ITANIUM_ALLOC_CLUSTER; context->identifier = (char *)realloc(context->identifier, context->id_allocated * sizeof(char)); } context->identifier[context->id_used++] = value; context->identifier[context->id_used] = 0; } /****************************************************************************** * * * Paramètres : context = décodeur à mettre à jour. * * previous = routine à sauvegarder. * * * * Description : Place sous le feu des projecteurs une nouvelle routine. * * * * Retour : Nouvelle routine à compléter. * * * * Remarques : - * * * ******************************************************************************/ static GBinRoutine *g_itanium_dcontext_push_routine(GItaniumDContext *context, GBinRoutine *previous) { GBinRoutine *result; /* Routine nouvelle à renvoyer */ result = g_binary_routine_new(); context->routines = g_slist_append(context->routines, previous); return result; } /****************************************************************************** * * * Paramètres : context = décodeur à mettre à jour. * * * * Description : Remet une ancienne routine sous le feu des projecteurs. * * * * Retour : Routine sauvegardée. * * * * Remarques : - * * * ******************************************************************************/ static GBinRoutine *g_itanium_dcontext_pop_routine(GItaniumDContext *context) { GBinRoutine *result; /* Routine nouvelle à renvoyer */ GSList *last; /* Dernier élément */ last = g_slist_last(context->routines); if (last == NULL) result = NULL; else { result = G_BIN_ROUTINE(last->data); context->routines = g_slist_remove(context->routines, result); } return result; } /****************************************************************************** * * * Paramètres : context = décodeur à mettre à jour. * * type = élément à placer dans la liste des substitutions. * * * * Description : Ajoute un élément dans une liste de substitutions. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_itanium_dcontext_add_item(GItaniumDContext *context, GOpenidaType *type) { g_object_ref(G_OBJECT(type)); printf(" [[ %u ]] PUSH '%s' (%p)\n", g_slist_length(context->substitutions) - 1, g_openida_type_to_string(type), type); context->substitutions = g_slist_append(context->substitutions, type); } /****************************************************************************** * * * Paramètres : context = décodeur à consulter. * * n = indice de l'élément à fournir. * * * * Description : Fournit le nième élément d'une liste de substitutions. * * * * Retour : Type prêt à emploi. * * * * Remarques : - * * * ******************************************************************************/ static GOpenidaType *g_itanium_dcontext_get_item(GItaniumDContext *context, guint n) { printf("get [%u] == %p\n", n, g_slist_nth_data(context->substitutions, n + 1)); return G_OPENIDA_TYPE(g_slist_nth_data(context->substitutions, n + 1)); } /****************************************************************************** * * * Paramètres : context = décodeur à consulter. * * * * Description : Autorise ou non le dépilement des opérateurs. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_itanium_dcontext_update(GItaniumDContext *context) { if (context->start_args || context->template_level > 0) exclude_itanium_operators(); else allow_itanium_operators(); } /* ---------------------------------------------------------------------------------- */ /* TRAITEMENT DE L'ENCODAGE ITANIUM */ /* ---------------------------------------------------------------------------------- */ /** * Affiche un message d'erreur concernant l'analyse. * @param yyloc informations concernant les coordonnées du soucis. * @param hunt indique le type de passe réalisée. * @param ucode code résultant compilé. * @param index indice de commande à mettre à jour. * @param msg indications humaines sur l'événement. * @return 0. */ int yyerror(/*const YYLTYPE *yyloc, bool hunt, char **ucode, unsigned char *index, */char *msg) { fprintf(stderr, "ERREUR !\n"); fprintf(stderr, "%s\n", msg); return -1; } /****************************************************************************** * * * Paramètres : desc = chaîne de caractères à décoder. * * * * Description : Indique si une chaîne peut être traitée par le décodeur. * * * * Retour : Bilan de l'analyse. * * * * Remarques : - * * * ******************************************************************************/ bool can_be_itanium_demangled(const char *desc) { return (strncmp(desc, "_Z", 2) == 0); } /****************************************************************************** * * * Paramètres : context = contexte de décodage à utiliser. * * desc = chaîne de caractères à décoder. * * * * Description : Procède au décodage d'une chaîne de caractères. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool demangle_itanium_routine(GItaniumDContext *context, const char *desc) { GBinRoutine *routine; /* Routine à construire */ YY_BUFFER_STATE buffer; /* Tampon pour bison */ int ret; /* Bilan de l'appel */ GOpenidaType *name_type; /* Nom basé sur un type ? */ routine = g_demangling_context_get_decoded_routine(G_DEMANGLING_CONTEXT(context)); allow_itanium_operators(); buffer = yy_scan_string(desc); ret = yyparse(context, routine); yy_delete_buffer(buffer); if (ret == 0) { name_type = g_binary_routine_get_type_from_name(routine); if (name_type != NULL && G_IS_TEMPLATE_TYPE(name_type)) compute_routine_itanium_ret_type(routine); } return (ret == 0); } /****************************************************************************** * * * Paramètres : routine = routine à traiter si ce n'est pas déjà fait. * * * * Description : Fait sauter le premier argument en faveur du type de retour. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void compute_routine_itanium_ret_type(GBinRoutine *routine) { size_t count; /* Nombre d'arguments présents */ size_t i; /* Boucle de parcours */ GBinVariable *arg; /* Argument de la routine */ GOpenidaType *type; /* Type associé à l'argument */ /* Traitement récursif des arguments */ type = g_binary_routine_get_type_from_name(routine); if (type != NULL) { update_itanium_ret_type(type); /* On force une actualisation au cas où... */ g_binary_routine_set_name(routine, NULL); } count = g_binary_routine_get_args_count(routine); if (count == 0) return; for (i = 0; i < count; i++) { arg = g_binary_routine_get_arg(routine, i); type = g_binary_variable_get_vtype(arg); update_itanium_ret_type(type); } /* Basculement du premier argument */ /** * Avec les références de type partagées, il * se peut que la fonction soit déjà traitée. */ if (g_binary_routine_get_return_type(routine) != NULL) return; arg = g_binary_routine_get_arg(routine, 0); type = g_binary_variable_get_vtype(arg); g_object_ref(G_OBJECT(type)); g_binary_routine_remove_arg(routine, 0); g_binary_routine_set_return_type(routine, type); } /****************************************************************************** * * * Paramètres : type = type à traiter si ce n'est pas déjà fait. * * * * Description : Recherche et fait sauter les premiers arguments rencontrés. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void update_itanium_ret_type(GOpenidaType *type) { GTemplateType *template; /* Gabarit à analyser */ size_t max; /* Nombre d'itérations */ size_t i; /* Boucle de parcours */ GOpenidaType *subtype; /* Type à traiter */ GEncapsulatedType *encaps; /* Encapsulation quelconque */ GBinRoutine *routine; /* Routine à traiter */ /* Gabarits */ if (G_IS_TEMPLATE_TYPE(type)) { template = G_TEMPLATE_TYPE(type); max = g_template_type_count_param(template); for (i = 0; i < max; i++) { subtype = g_template_type_get_param(template, i); update_itanium_ret_type(subtype); } } /* Encapsulations */ else if (G_IS_ENCAPSULATED_TYPE(type)) { encaps = G_ENCAPSULATED_TYPE(type); switch (g_encapsulated_type_get_etype(encaps)) { case ECT_ROUTINE: g_encapsulated_type_get_item(encaps, &routine); compute_routine_itanium_ret_type(routine); break; default: g_encapsulated_type_get_item(encaps, &subtype); update_itanium_ret_type(subtype); break; } } }