/* OpenIDA - Outil d'analyse de fichiers binaires * variable.h - prototypes pour la manipulation des variables en tout genre * * Copyright (C) 2009 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) { }