/* Chrysalide - Outil d'analyse de fichiers binaires * encaps.c - manipulation des types de données encapsulés * * Copyright (C) 2012 Cyrille Bagard * * This file is part of Chrysalide. * * 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 "encaps.h" #include "../routine.h" #include "../type-int.h" #include "../../common/extstr.h" /* Description de type encapsulé (instance) */ struct _GEncapsulatedType { GDataType parent; /* A laisser en premier */ EncapsulationType type; /* Encapsulation utilisée */ GDataType *child; /* Sous-type encadré */ GBinRoutine *routine; /* Routine pointée */ }; /* Description de type encapsulé (classe) */ struct _GEncapsulatedTypeClass { GDataTypeClass parent; /* A laisser en premier */ }; /* Initialise la classe des types encapsulés. */ static void g_encapsulated_type_class_init(GEncapsulatedTypeClass *); /* Initialise l'instance d'un type encapsulé. */ static void g_encapsulated_type_init(GEncapsulatedType *); /* Crée un copie d'un type existant. */ static GDataType *g_encapsulated_type_dup(const GEncapsulatedType *); /* Décrit le type fourni sous forme de caractères. */ static char *g_encapsulated_type_to_string(const GEncapsulatedType *); /* Procède à l'impression de la description d'un type. */ static void g_encapsulated_type_output(const GEncapsulatedType *, GLangOutput *, GBufferLine *, bool, bool); /* Indique le type défini pour un type encapsulé. */ G_DEFINE_TYPE(GEncapsulatedType, g_encapsulated_type, G_TYPE_DATA_TYPE); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des types encapsulés. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_encapsulated_type_class_init(GEncapsulatedTypeClass *klass) { } /****************************************************************************** * * * Paramètres : type = instance à initialiser. * * * * Description : Initialise l'instance d'un type encapsulé. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_encapsulated_type_init(GEncapsulatedType *type) { GDataType *data_type; /* Version basique */ data_type = G_DATA_TYPE(type); data_type->dup = (type_dup_fc)g_encapsulated_type_dup; data_type->to_string = (type_to_string_fc)g_encapsulated_type_to_string; data_type->output = (output_type_fc)g_encapsulated_type_output; } /****************************************************************************** * * * Paramètres : type = type d'extension à représenter. * * child = variable dont on doit dériver. * * * * Description : Crée une représentation de variable dérivée. * * * * Retour : Adresse de la structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ GDataType *g_encapsulated_type_new(EncapsulationType type, ...) { GEncapsulatedType *result; /* Structure à retourner */ va_list ap; /* Liste variable d'arguments */ result = g_object_new(G_TYPE_ENCAPSULATED_TYPE, NULL); result->type = type; va_start(ap, type); switch (type) { case ECT_ROUTINE: result->routine = va_arg(ap, GBinRoutine *); g_binary_routine_set_name(result->routine, "(*)"); break; default: result->child = va_arg(ap, GDataType *); break; } va_end(ap); return G_DATA_TYPE(result); } /****************************************************************************** * * * Paramètres : type = type à dupliquer. * * * * Description : Crée un copie d'un type existant. * * * * Retour : Nouvelle instance de type identique à celle fournie. * * * * Remarques : - * * * ******************************************************************************/ static GDataType *g_encapsulated_type_dup(const GEncapsulatedType *type) { GDataType *result; /* Nouvelle instance à renvoyer*/ GDataType *child; /* Copie du type interne */ switch (type->type) { case ECT_ROUTINE: g_object_ref(G_OBJECT(type->routine)); result = g_encapsulated_type_new(type->type, type->routine); break; default: child = g_data_type_dup(type->child); result = g_encapsulated_type_new(type->type, child); break; } return result; } /****************************************************************************** * * * Paramètres : type = type à convertir. * * * * Description : Décrit le type fourni sous forme de caractères. * * * * Retour : Chaîne à libérer de la mémoire après usage. * * * * Remarques : - * * * ******************************************************************************/ static char *g_encapsulated_type_to_string(const GEncapsulatedType *type) { char *result; /* Chaîne finale à renvoyer */ switch (type->type) { case ECT_ROUTINE: result = g_binary_routine_to_string(type->routine); break; default: result = g_data_type_to_string(type->child); break; } switch (type->type) { case ECT_POINTER: if (G_IS_ENCAPSULATED_TYPE(type->child) && G_ENCAPSULATED_TYPE(type->child)->type == ECT_ROUTINE) break; if (!g_data_type_is_pointer(type->child, false)) result = stradd(result, " "); result = stradd(result, "*"); break; case ECT_REFERENCE: result = stradd(result, " &"); break; case ECT_RVALUE_REF: result = stradd(result, " &&"); break; case ECT_COMPLEX: result = stradd(result, " complex"); break; case ECT_IMAGINARY: result = stradd(result, " imaginary"); break; case ECT_ROUTINE: /* Pour GCC */ default: break; } return result; } /****************************************************************************** * * * Paramètres : type = type à afficher. * * lang = langage à utiliser pour la sortie humaine. * * buffer = tampon mis à disposition pour la sortie. * * info = nature du cadre de destination. * * full = besoin de descriptions étendues ? * * * * Description : Procède à l'impression de la description d'un type. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_encapsulated_type_output(const GEncapsulatedType *type, GLangOutput *lang, GBufferLine *line, bool info, bool full) { g_buffer_line_insert_text(line, BLC_LAST_USED, "!TODO!", 6, info ? RTT_COMMENT : RTT_RAW); } /****************************************************************************** * * * Paramètres : type = type à consulter. * * * * Description : Fournit le type d'encapsulation gérée par le type. * * * * Retour : Type d'encapsulation gérée. * * * * Remarques : - * * * ******************************************************************************/ EncapsulationType g_encapsulated_type_get_etype(const GEncapsulatedType *type) { return type->type; } /****************************************************************************** * * * Paramètres : type = type à consulter. * * ... = sous-type ou routine encapsulée dans le type. [OUT] * * * * Description : Fournit la routine encapsulée dans le type. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_encapsulated_type_get_item(const GEncapsulatedType *type, ...) { va_list ap; /* Liste variable d'arguments */ GDataType **child; /* Adresse pour sous-type */ GBinRoutine **routine; /* Adresse pour routine */ va_start(ap, type); switch (type->type) { case ECT_ROUTINE: routine = va_arg(ap, GBinRoutine **); *routine = type->routine; break; default: child = va_arg(ap, GDataType **); *child = type->child; break; } va_end(ap); }