/* OpenIDA - Outil d'analyse de fichiers binaires
* variable.h - prototypes pour la manipulation des variables en tout genre
*
* Copyright (C) 2010 Cyrille Bagard
*
* This file is part of OpenIDA.
*
* OpenIDA is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* OpenIDA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar. If not, see .
*/
#include "type.h"
#include
#include
#include
#include "routine.h"
#include "../common/extstr.h"
/* ------------------------ REPRESENTATION INTERNE DES TYPES ------------------------ */
/* Décrit le type fourni sous forme de caractères. */
typedef GOpenidaType * (* type_dup_fc) (const GOpenidaType *);
/* Décrit le type fourni sous forme de caractères. */
typedef char * (* type_to_string_fc) (const GOpenidaType *);
/* Description de type quelconque (instance) */
struct _GOpenidaType
{
GObject parent; /* A laisser en premier */
type_dup_fc dup; /* Copie d'instance existante */
type_to_string_fc to_string; /* Conversion au format texte */
GOpenidaType *namespace; /* Espace de noms / classe */
TypeQualifier qualifiers; /* Eventuels qualificatifs */
GTypesManager *manager; /* Gestionnaire global */
};
/* Description de type quelconque (classe) */
struct _GOpenidaTypeClass
{
GObjectClass parent; /* A laisser en premier */
};
/* Initialise la classe des types quelconques. */
static void g_openida_type_class_init(GOpenidaTypeClass *);
/* Initialise l'instance d'un type quelconque. */
static void g_openida_type_init(GOpenidaType *);
/* ---------------------------- TYPES DE DONNEES SIMPLES ---------------------------- */
/* Description de type basique (instance) */
struct _GBasicType
{
GOpenidaType parent; /* A laisser en premier */
BaseType type; /* Type représenté si connu */
};
/* Description de type basique (classe) */
struct _GBasicTypeClass
{
GOpenidaTypeClass parent; /* A laisser en premier */
};
/* Initialise la classe des types basiques. */
static void g_basic_type_class_init(GBasicTypeClass *);
/* Initialise l'instance d'un type basique. */
static void g_basic_type_init(GBasicType *);
/* Crée un copie d'un type existant. */
static GOpenidaType *g_basic_type_dup(const GBasicType *);
/* Décrit le type fourni sous forme de caractères. */
static char *g_basic_type_to_string(const GBasicType *);
/* -------------------------- VARIABLES DEPENDANT D'AUTRES -------------------------- */
/* Description de type encapsulé (instance) */
struct _GEncapsulatedType
{
GOpenidaType parent; /* A laisser en premier */
EncapsulationType type; /* Encapsulation utilisée */
GOpenidaType *child; /* Sous-type encadré */
GBinRoutine *routine; /* Routine pointée */
};
/* Description de type encapsulé (classe) */
struct _GEncapsulatedTypeClass
{
GOpenidaTypeClass 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 GOpenidaType *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 *);
/* ---------------------- CLASSES / STRUCTURES ET ENUMERATIONS ---------------------- */
/* Description de type classe/structure et enumeration (instance) */
struct _GClassEnumType
{
GOpenidaType parent; /* A laisser en premier */
ClassEnumType type; /* Type représenté si connu */
char *name; /* Description humaine */
};
/* Description de type classe/structure et enumeration (classe) */
struct _GClassEnumTypeClass
{
GOpenidaTypeClass parent; /* A laisser en premier */
};
/* Initialise la classe des types classe ou assimilés. */
static void g_class_enum_type_class_init(GClassEnumTypeClass *);
/* Initialise l'instance d'un type classe ou assimilé. */
static void g_class_enum_type_init(GClassEnumType *);
/* Crée un copie d'un type existant. */
static GOpenidaType *g_class_enum_type_dup(const GClassEnumType *);
/* Décrit le type fourni sous forme de caractères. */
static char *g_class_enum_type_to_string(const GClassEnumType *);
/* ----------------------- ELEMENTS REPOSANT SUR DES GABARITS ----------------------- */
/* Description de type reposant sur des gabarits (instance) */
struct _GTemplateType
{
GClassEnumType parent; /* A laisser en premier */
GOpenidaType **models; /* Sous-types associés */
size_t models_count; /* Quantité de ces modèles */
};
/* Description de type reposant sur des gabarits (classe) */
struct _GTemplateTypeClass
{
GClassEnumTypeClass parent; /* A laisser en premier */
};
/* Initialise la classe des types reposant sur des gabarits. */
static void g_template_type_class_init(GTemplateTypeClass *);
/* Initialise l'instance d'un type reposant sur des gabarits. */
static void g_template_type_init(GTemplateType *);
/* Crée un copie d'un type existant. */
static GOpenidaType *g_template_type_dup(const GTemplateType *);
/* Décrit le type fourni sous forme de caractères. */
static char *g_template_type_to_string(const GTemplateType *);
/* ---------------------- VALEUR LITERALE DES TYPES INSTANCIES ---------------------- */
/* Description de type instancié avec une valeur litérale (instance) */
struct _GLiteralType
{
GOpenidaType parent; /* A laisser en premier */
GOpenidaType *orig; /* Type instancié */
literal_value value; /* Valeur d'instance */
};
/* Description de type instancié avec une valeur litérale (classe) */
struct _GLiteralTypeClass
{
GOpenidaTypeClass parent; /* A laisser en premier */
};
/* Initialise la classe des types instanciés avec des valeurs. */
static void g_literal_type_class_init(GLiteralTypeClass *);
/* Initialise l'instance d'un type instancié avec une valeur. */
static void g_literal_type_init(GLiteralType *);
/* Crée un copie d'un type existant. */
static GOpenidaType *g_literal_type_dup(const GLiteralType *);
/* Décrit le type fourni sous forme de caractères. */
static char *g_literal_type_to_string(const GLiteralType *);
/* -------------------------- COLLECTE ET GESTION DE TYPES -------------------------- */
/* Description de type quelconque (instance) */
struct _GTypesManager
{
GObject parent; /* A laisser en premier */
MemoryDataSize wdsize; /* Taille d'un mot en octet */
};
/* Description de type quelconque (classe) */
struct _GTypesManagerClass
{
GObjectClass parent; /* A laisser en premier */
};
/* Initialise la classe des gestionnaires de types. */
static void g_types_manager_class_init(GTypesManagerClass *);
/* Initialise l'instance d'un gestionnaire de types. */
static void g_types_manager_init(GTypesManager *manager);
/* ---------------------------------------------------------------------------------- */
/* REPRESENTATION INTERNE DES TYPES */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un type quelconque. */
G_DEFINE_TYPE(GOpenidaType, g_openida_type, G_TYPE_OBJECT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des types quelconques. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_openida_type_class_init(GOpenidaTypeClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : type = instance à initialiser. *
* *
* Description : Initialise l'instance d'un type quelconque. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_openida_type_init(GOpenidaType *type)
{
}
/******************************************************************************
* *
* Paramètres : type = type à dupliquer. *
* *
* Description : Crée un copie d'un type existant. *
* *
* Retour : Nouvelle instance de type identique à celle fournie. *
* *
* Remarques : - *
* *
******************************************************************************/
GOpenidaType *g_openida_type_dup(const GOpenidaType *type)
{
return type->dup(type);
}
/******************************************************************************
* *
* Paramètres : type = type à mettre à jour. *
* namespace = instance d'appartenance. *
* *
* Description : Définit le groupe d'appartenance d'un type donné. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_openida_type_set_namespace(GOpenidaType *type, GOpenidaType *namespace)
{
g_object_ref(G_OBJECT(namespace));
type->namespace = namespace;
}
/******************************************************************************
* *
* Paramètres : type = type à convertir. *
* simple = indique si l'espace de noms doit être exclus ou non.*
* *
* Description : Décrit le type fourni sous forme de caractères. *
* *
* Retour : Chaîne à libérer de la mémoire après usage. *
* *
* Remarques : - *
* *
******************************************************************************/
char *_g_openida_type_to_string(const GOpenidaType *type, bool simple)
{
char *result; /* Chaîne à retourner */
char *namespace; /* Groupe d'appartenance */
result = type->to_string(type);
if (!simple && type->namespace != NULL)
{
namespace = g_openida_type_to_string(type->namespace);
result = strprep(result, "::");
result = strprep(result, namespace);
free(namespace);
}
if (type->qualifiers & TQF_RESTRICT)
result = strprep(result, "restrict ");
if (type->qualifiers & TQF_VOLATILE)
result = strprep(result, "volatile ");
if (type->qualifiers & TQF_CONST)
result = strprep(result, "const ");
return result;
}
/******************************************************************************
* *
* Paramètres : type = instance à mettre à jour. *
* qualifier = nouveau qualificatif pour la variable. *
* *
* Description : Ajoute un qualificatif à une instance de type. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_openida_type_add_qualifier(GOpenidaType *type, TypeQualifier qualifier)
{
type->qualifiers |= qualifier;
}
/******************************************************************************
* *
* Paramètres : type = type à analyser. *
* large = doit-on aussi inclure les types 'référence' ? *
* *
* Description : Indique la terminaison de la représentation du type. *
* *
* Retour : true ou false, selon le type fourni. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_openida_type_is_pointer(const GOpenidaType *type, bool large)
{
bool result; /* Bilan à retourner */
result = G_IS_ENCAPSULATED_TYPE(type);
if (result)
switch (G_ENCAPSULATED_TYPE(type)->type)
{
case ECT_POINTER:
result = true;
break;
case ECT_REFERENCE:
case ECT_RVALUE_REF:
result = large;
break;
default:
result = false;
break;
}
return result;
}
/* ---------------------------------------------------------------------------------- */
/* TYPES DE DONNEES SIMPLES */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un type basique. */
G_DEFINE_TYPE(GBasicType, g_basic_type, G_TYPE_OPENIDA_TYPE);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des types basiques. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_basic_type_class_init(GBasicTypeClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : type = instance à initialiser. *
* *
* Description : Initialise l'instance d'un type basique. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_basic_type_init(GBasicType *type)
{
GOpenidaType *oida_type; /* Version basique */
oida_type = G_OPENIDA_TYPE(type);
oida_type->dup = (type_dup_fc)g_basic_type_dup;
oida_type->to_string = (type_to_string_fc)g_basic_type_to_string;
}
/******************************************************************************
* *
* Paramètres : type = type simple à représenter. *
* *
* Description : Crée une représentation de type basique. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GOpenidaType *g_basic_type_new(BaseType type)
{
GBasicType *result; /* Structure à retourner */
result = g_object_new(G_TYPE_BASIC_TYPE, NULL);
result->type = type;
return G_OPENIDA_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 GOpenidaType *g_basic_type_dup(const GBasicType *type)
{
return g_basic_type_new(type->type);
}
/******************************************************************************
* *
* 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_basic_type_to_string(const GBasicType *type)
{
const char *desc; /* Représentation à copier */
switch (type->type)
{
case BTP_VOID:
desc = "void";
break;
case BTP_WCHAR_T:
desc = "wchar_t";
break;
case BTP_BOOL:
desc = "bool";
break;
case BTP_CHAR:
desc = "char";
break;
case BTP_SCHAR:
desc = "signed char";
break;
case BTP_UCHAR:
desc = "unsigned char";
break;
case BTP_SHORT:
desc = "short";
break;
case BTP_USHORT:
desc = "unsigned short";
break;
case BTP_INT:
desc = "int";
break;
case BTP_UINT:
desc = "unsigned int";
break;
case BTP_LONG:
desc = "long";
break;
case BTP_ULONG:
desc = "unsigned long";
break;
case BTP_LONG_LONG:
desc = "long long";
break;
case BTP_ULONG_LONG:
desc = "unsigned long long";
break;
case BTP_INT128:
desc = "__int128";
break;
case BTP_UINT128:
desc = "unsigned __int128";
break;
case BTP_FLOAT:
desc = "float";
break;
case BTP_DOUBLE:
desc = "double";
break;
case BTP_LONG_DOUBLE:
desc = "long double";
break;
case BTP_FLOAT128:
desc = "__float128";
break;
case BTP_ELLIPSIS:
desc = "...";
break;
case BTP_754R_64:
desc = "__float754r_64";
break;
case BTP_754R_128:
desc = "__float754r_128";
break;
case BTP_754R_32:
desc = "__float754r_32";
break;
case BTP_754R_16:
desc = "__float754r_16";
break;
case BTP_CHAR32_T:
desc = "char32_t";
break;
case BTP_CHAR16_T:
desc = "char16_t";
break;
default:
case BTP_OTHER:
desc = "user";
break;
}
return strdup(desc);
}
/* ---------------------------------------------------------------------------------- */
/* VARIABLES DEPENDANT D'AUTRES */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un type encapsulé. */
G_DEFINE_TYPE(GEncapsulatedType, g_encapsulated_type, G_TYPE_OPENIDA_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)
{
GOpenidaType *oida_type; /* Version basique */
oida_type = G_OPENIDA_TYPE(type);
oida_type->dup = (type_dup_fc)g_encapsulated_type_dup;
oida_type->to_string = (type_to_string_fc)g_encapsulated_type_to_string;
}
/******************************************************************************
* *
* 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 : - *
* *
******************************************************************************/
GOpenidaType *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, GOpenidaType *);
break;
}
va_end(ap);
return G_OPENIDA_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 GOpenidaType *g_encapsulated_type_dup(const GEncapsulatedType *type)
{
GOpenidaType *result; /* Nouvelle instance à renvoyer*/
GOpenidaType *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_openida_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_openida_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_openida_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 à 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 */
GOpenidaType **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, GOpenidaType **);
*child = type->child;
break;
}
va_end(ap);
}
/* ---------------------------------------------------------------------------------- */
/* CLASSES / STRUCTURES ET ENUMERATIONS */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un type classe ou assimilé. */
G_DEFINE_TYPE(GClassEnumType, g_class_enum_type, G_TYPE_OPENIDA_TYPE);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des types classe ou assimilés. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_class_enum_type_class_init(GClassEnumTypeClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : type = instance à initialiser. *
* *
* Description : Initialise l'instance d'un type classe ou assimilé. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_class_enum_type_init(GClassEnumType *type)
{
GOpenidaType *oida_type; /* Version basique */
oida_type = G_OPENIDA_TYPE(type);
oida_type->dup = (type_dup_fc)g_class_enum_type_dup;
oida_type->to_string = (type_to_string_fc)g_class_enum_type_to_string;
}
/******************************************************************************
* *
* Paramètres : type = type de structure à représenter. *
* name = désignation humaine du type. *
* *
* Description : Crée une représentation de classe, structure ou énumération. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GOpenidaType *g_class_enum_type_new(ClassEnumType type, const char *name)
{
GClassEnumType *result; /* Structure à retourner */
result = g_object_new(G_TYPE_CLASS_ENUM_TYPE, NULL);
result->type = type;
result->name = strdup(name);
return G_OPENIDA_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 GOpenidaType *g_class_enum_type_dup(const GClassEnumType *type)
{
return g_class_enum_type_new(type->type, type->name);
}
/******************************************************************************
* *
* 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_class_enum_type_to_string(const GClassEnumType *type)
{
return strdup(type->name);
}
/* ---------------------------------------------------------------------------------- */
/* ELEMENTS REPOSANT SUR DES GABARITS */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un type reposant sur des gabarits. */
G_DEFINE_TYPE(GTemplateType, g_template_type, G_TYPE_CLASS_ENUM_TYPE);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des types reposant sur des gabarits. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_template_type_class_init(GTemplateTypeClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : type = instance à initialiser. *
* *
* Description : Initialise l'instance d'un type reposant sur des gabarits. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_template_type_init(GTemplateType *type)
{
GOpenidaType *oida_type; /* Version basique */
GClassEnumType *ce_type; /* Version basique #2 */
oida_type = G_OPENIDA_TYPE(type);
oida_type->dup = (type_dup_fc)g_template_type_dup;
oida_type->to_string = (type_to_string_fc)g_template_type_to_string;
ce_type = G_CLASS_ENUM_TYPE(type);
ce_type->type = CET_CLASS;
}
/******************************************************************************
* *
* Paramètres : name = désignation humaine du type. *
* list = élements du modèle sur lequel doit reposer le type. *
* *
* Description : Crée une représentation de type reposant sur des gabarits. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GOpenidaType *g_template_type_new(const char *name, GSList *list)
{
GTemplateType *result; /* Structure à retourner */
result = g_object_new(G_TYPE_TEMPLATE_TYPE, NULL);
G_CLASS_ENUM_TYPE(result)->name = strdup(name);
g_template_type_add_params(result, list);
return G_OPENIDA_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 GOpenidaType *g_template_type_dup(const GTemplateType *type)
{
GOpenidaType *result; /* Copie à retourner */
GSList *list; /* Format de liste à fournir */
size_t i; /* Boucle de parcours */
list = NULL;
for (i = 0; i < type->models_count; i++)
list = g_slist_prepend(list, type->models[i]);
result = g_template_type_new(G_CLASS_ENUM_TYPE(type)->name, list);
return G_OPENIDA_TYPE(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_template_type_to_string(const GTemplateType *type)
{
char *result; /* Valeur à renvoyer */
size_t i; /* Boucle de parcours */
char *sub; /* Sous-type à décrire */
result = g_class_enum_type_to_string(G_CLASS_ENUM_TYPE(type));
result = stradd(result, "<");
for (i = 0; i < type->models_count; i++)
{
if (i > 0) result = stradd(result, ", ");
sub = g_openida_type_to_string(type->models[i]);
result = stradd(result, sub);
free(sub);
}
result = stradd(result, ">");
return result;
}
/******************************************************************************
* *
* Paramètres : type = type à mettre à jour. *
* list = élements du modèle sur lequel doit reposer le type. *
* *
* Description : Ajoute une série de paramètres à un gabarit. *
* *
* Retour : - *
* *
* Remarques : La liste doit contenir des éléments dans l'ordre inverse *
* d'apparition. De plus, elle est libérée dans cette fonction. *
* *
******************************************************************************/
void g_template_type_add_params(GTemplateType *type, GSList *list)
{
GSList *iter; /* Boucle de parcours */
list = g_slist_reverse(list);
for (iter = list; iter != NULL; iter = g_slist_next(iter))
{
type->models = (GOpenidaType **)realloc(type->models,
++type->models_count * sizeof(GOpenidaType *));
type->models[type->models_count - 1] = G_OPENIDA_TYPE(iter->data);
}
g_slist_free(list);
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* *
* Description : Indique le nombre de paramètres associés du gabarit. *
* *
* Retour : Nombre de paramètres inclus dans le gabarit. *
* *
* Remarques : - *
* *
******************************************************************************/
size_t g_template_type_count_param(const GTemplateType *type)
{
return type->models_count;
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* index = indice du paramètre à retourner. *
* *
* Description : Fournit un paramètre donné du gabarit. *
* *
* Retour : Type inclus dans le modèle ou NULL si mauvais indice. *
* *
* Remarques : - *
* *
******************************************************************************/
GOpenidaType *g_template_type_get_param(const GTemplateType *type, size_t index)
{
return (index < type->models_count ? type->models[index] : NULL);
}
/* ---------------------------------------------------------------------------------- */
/* VALEUR LITERALE DES TYPES INSTANCIES */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un type reposant sur des gabarits. */
G_DEFINE_TYPE(GLiteralType, g_literal_type, G_TYPE_OPENIDA_TYPE);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des types instanciés avec des valeurs. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_literal_type_class_init(GLiteralTypeClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : type = instance à initialiser. *
* *
* Description : Initialise l'instance d'un type instancié avec une valeur. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_literal_type_init(GLiteralType *type)
{
GOpenidaType *oida_type; /* Version basique */
oida_type = G_OPENIDA_TYPE(type);
oida_type->dup = (type_dup_fc)g_literal_type_dup;
oida_type->to_string = (type_to_string_fc)g_literal_type_to_string;
}
/******************************************************************************
* *
* Paramètres : orig = type d'origine instancié. *
* value = valeur de l'instanciation. *
* *
* Description : Crée une représentation de type instancié avec une valeur. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GOpenidaType *g_literal_type_new(GOpenidaType *orig, literal_value value)
{
GLiteralType *result; /* Structure à retourner */
result = g_object_new(G_TYPE_LITERAL_TYPE, NULL);
result->orig = orig;
result->value = value;
g_object_ref(orig);
return G_OPENIDA_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 GOpenidaType *g_literal_type_dup(const GLiteralType *type)
{
GOpenidaType *orig; /* Copie du type interne */
orig = g_openida_type_dup(type->orig);
return g_literal_type_new(orig, type->value);
}
/******************************************************************************
* *
* 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_literal_type_to_string(const GLiteralType *type)
{
char *result; /* Valeur à renvoyer */
size_t max; /* Longueur totale du texte */
if (G_IS_BASIC_TYPE(type->orig))
switch (G_BASIC_TYPE(type->orig)->type)
{
case BTP_BOOL:
result = strdup(type->value.int_val ? "true" : "false");
break;
case BTP_INT:
max = strlen("2147483647" /* INT_MAX */) + 1;
result = (char *)calloc(max, sizeof(char));
snprintf(result, max, "%d", type->value.int_val);
break;
default:
result = strdup("TODO");
break;
}
else result = strdup("???");
return result;
}
/* ---------------------------------------------------------------------------------- */
/* COLLECTE ET GESTION DE TYPES */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un gestionnaire de types. */
G_DEFINE_TYPE(GTypesManager, g_types_manager, G_TYPE_OBJECT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des gestionnaires de types. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_types_manager_class_init(GTypesManagerClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : manager = instance à initialiser. *
* *
* Description : Initialise l'instance d'un gestionnaire de types. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_types_manager_init(GTypesManager *manager)
{
}