/* Chrysalide - Outil d'analyse de fichiers binaires
* encaps.c - manipulation des types de données encapsulés
*
* Copyright (C) 2012-2017 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* Chrysalide is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Chrysalide is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Chrysalide. If not, see .
*/
#include "encaps.h"
#include
#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 */
size_t dimension; /* Dimension quand applicable */
};
/* 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 *);
assert(result->routine != NULL);
g_binary_routine_set_name(result->routine, "(*)");
break;
default:
result->child = va_arg(ap, GDataType *);
assert(result->child != NULL);
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 */
size_t i; /* Boucle de parcours */
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_ARRAY:
result = stradd(result, " ");
for (i = 0; i < type->dimension; i++)
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 : - *
* *
******************************************************************************/
#if 0
static void g_encapsulated_type_output(const GEncapsulatedType *type, GLangOutput *lang, GBufferLine *line, bool info, bool full)
{
g_buffer_line_append_text(line, BLC_LAST_USED, "!TODO!", 6, info ? RTT_COMMENT : RTT_RAW, NULL);
}
#endif
/******************************************************************************
* *
* 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);
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* *
* Description : Fournit la dimension éventuellement associée au type. *
* *
* Retour : Dimension positive ou nulle. *
* *
* Remarques : - *
* *
******************************************************************************/
size_t g_encapsulated_type_get_dimension(const GEncapsulatedType *type)
{
return type->dimension;
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* dim = dimension positive ou nulle. *
* *
* Description : Définit la dimension éventuellement associée au type. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_encapsulated_type_set_dimension(GEncapsulatedType *type, size_t dim)
{
type->dimension = dim;
}