diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analysis/type-int.h | 50 | ||||
-rw-r--r-- | src/analysis/type.c | 302 | ||||
-rw-r--r-- | src/analysis/type.h | 29 | ||||
-rw-r--r-- | src/analysis/types/proto.c | 23 |
4 files changed, 337 insertions, 67 deletions
diff --git a/src/analysis/type-int.h b/src/analysis/type-int.h index e14d209..d6c2588 100644 --- a/src/analysis/type-int.h +++ b/src/analysis/type-int.h @@ -29,6 +29,7 @@ #include "storage/serialize-int.h" +#include "../glibext/objhole.h" @@ -58,18 +59,61 @@ typedef bool (* type_is_reference_fc) (const GDataType *); +/* Informations glissées dans la structure GObject de GBinSymbol */ +typedef union _type_obj_extra +{ + struct + { + TypeQualifier qualifiers; /* Eventuels qualificatifs */ + char ns_sep[2]; /* Séparateur d'éléments */ + TypeFlag flags; /* Propriétés du type */ + + }; + + gint lock; /* Gestion d'accès aux fanions */ + +} type_obj_extra; + /* Description de type quelconque (instance) */ struct _GDataType { GObject parent; /* A laisser en premier */ - TypeQualifier qualifiers; /* Eventuels qualificatifs */ - GDataType *namespace; /* Espace de noms / classe */ - char *ns_sep; /* Séparateur d'éléments */ + +#if __SIZEOF_INT__ == __SIZEOF_LONG__ + + /** + * L'inclusion des informations suivantes dépend de l'architecture. + * + * Si la structure GObject possède un trou, on remplit de préférence + * ce dernier. + */ + + type_obj_extra extra; /* Externalisation embarquée */ + +#endif }; +/** + * Accès aux informations éventuellement déportées. + */ + +#if __SIZEOF_INT__ == __SIZEOF_LONG__ + +# define INIT_DATA_TYPE_EXTRA(tp) tp->extra.lock = 0 + +# define GET_DATA_TYPE_EXTRA(tp) &tp->extra + +#else + +# define INIT_DATA_TYPE_EXTRA(tp) INIT_GOBJECT_EXTRA(G_OBJECT(tp)) + +# define GET_DATA_TYPE_EXTRA(tp) GET_GOBJECT_EXTRA(G_OBJECT(tp), type_obj_extra) + +#endif + /* Description de type quelconque (classe) */ struct _GDataTypeClass { diff --git a/src/analysis/type.c b/src/analysis/type.c index a5cc46c..4a0b7d8 100644 --- a/src/analysis/type.c +++ b/src/analysis/type.c @@ -24,6 +24,7 @@ #include "type.h" +#include <assert.h> #include <malloc.h> #include <string.h> @@ -109,10 +110,11 @@ static void g_data_type_class_init(GDataTypeClass *klass) static void g_data_type_init(GDataType *type) { + INIT_DATA_TYPE_EXTRA(type); + g_data_type_set_qualifiers(type, TQF_NONE); type->namespace = NULL; - type->ns_sep = NULL; } @@ -172,9 +174,6 @@ static void g_data_type_dispose(GDataType *type) static void g_data_type_finalize(GDataType *type) { - if (type->ns_sep != NULL) - free(type->ns_sep); - G_OBJECT_CLASS(g_data_type_parent_class)->finalize(G_OBJECT(type)); } @@ -197,27 +196,35 @@ static void g_data_type_finalize(GDataType *type) static bool _g_data_type_load(GDataType *type, GObjectStorage *storage, packed_buffer *pbuf) { bool result; /* Bilan à retourner */ - uint8_t has_ns; /* Association d'un espace ? */ uleb128_t value; /* Valeur ULEB128 à charger */ + char ns_sep[2]; /* Séparateur d'éléments */ + GDataType *namespace; /* Espace de noms / classe */ result = unpack_uleb128(&value, pbuf); if (!result) goto exit; g_data_type_set_qualifiers(type, value); - result = extract_packed_buffer(pbuf, &has_ns, sizeof(uint8_t), false); + result = unpack_uleb128(&value, pbuf); + if (!result) goto exit; + + g_data_type_set_flags(type, value); + + result = extract_packed_buffer(pbuf, ns_sep, 2 * sizeof(char), false); if (!result) goto exit; - if (has_ns == 0x01) + if (ns_sep[0] != '\0') { - result = g_data_type_load(type->namespace, storage, pbuf); - if (!result) goto exit; + //result = g_data_type_load(type->namespace, storage, pbuf); // TODO + namespace = NULL; - result = unpack_uleb128(&value, pbuf); + result = (namespace != NULL); if (!result) goto exit; - type->ns_sep = calloc(value, sizeof(char)); - result = extract_packed_buffer(pbuf, type->ns_sep, value, false); + result = g_data_type_set_namespace(type, namespace, ns_sep); + assert(result); + + g_object_unref(G_OBJECT(namespace)); } @@ -273,31 +280,34 @@ static bool g_data_type_load(GDataType *type, GObjectStorage *storage, packed_bu static bool _g_data_type_store(const GDataType *type, GObjectStorage *storage, packed_buffer *pbuf) { bool result; /* Bilan à retourner */ - uint8_t has_ns; /* Association d'un espace ? */ - size_t ns_sep_len; /* Taille du séparateur */ + type_obj_extra *extra; /* Données insérées à modifier */ result = pack_uleb128((uleb128_t []){ g_data_type_get_qualifiers(type) }, pbuf); if (!result) goto exit; - has_ns = (type->namespace != NULL ? 0x01 : 0x00); - - result = extend_packed_buffer(pbuf, &has_ns, sizeof(uint8_t), false); + result = pack_uleb128((uleb128_t []){ g_data_type_get_flags(type) }, pbuf); if (!result) goto exit; - if (type->namespace != NULL) - { - result = g_data_type_store(type->namespace, storage, pbuf); - if (!result) goto exit; + extra = GET_DATA_TYPE_EXTRA(type); - ns_sep_len = strlen(type->ns_sep); + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); - result = pack_uleb128((uleb128_t []){ ns_sep_len }, pbuf); - if (!result) goto exit; + result = extend_packed_buffer(pbuf, extra->ns_sep, 2 * sizeof(char), false); + if (!result) goto unlocking_exit; + + if (extra->ns_sep[0] != '\0') + { + assert(type->namespace != NULL); - result = extend_packed_buffer(pbuf, type->ns_sep, ns_sep_len, false); + result = g_data_type_store(type->namespace, storage, pbuf); + if (!result) goto unlocking_exit; } + unlocking_exit: + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); + exit: return result; @@ -380,23 +390,39 @@ GDataType *g_data_type_dup(const GDataType *type) { GDataType *result; /* Copie à retourner */ GDataTypeClass *class; /* Classe du type */ + type_obj_extra *extra; /* Données insérées à modifier */ GDataType *ns; /* Eventuel espace de noms */ - char *ns_sep; /* Séparation des espaces */ + bool status; /* Bilan d'un rattachement */ class = G_DATA_TYPE_GET_CLASS(type); result = class->dup(type); - if (type->namespace != NULL) + g_data_type_set_qualifiers(result, g_data_type_get_qualifiers(type)); + + g_data_type_set_flags(result, g_data_type_get_flags(type)); + + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); + + if (extra->ns_sep[0] != '\0') { + assert(type->namespace != NULL); + ns = g_data_type_dup(type->namespace); - ns_sep = type->ns_sep != NULL ? strdup(type->ns_sep) : NULL; - g_data_type_set_namespace(result, ns, ns_sep); + status = g_data_type_set_namespace(result, ns, extra->ns_sep); + assert(status); + + g_object_unref(G_OBJECT(ns)); + + if (!status) + g_clear_object(&result); } - result->qualifiers = type->qualifiers; + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); return result; @@ -420,7 +446,9 @@ char *g_data_type_to_string(const GDataType *type, bool include) { char *result; /* Chaîne à retourner */ GDataTypeClass *class; /* Classe du type */ + type_obj_extra *extra; /* Données insérées à modifier */ char *namespace; /* Groupe d'appartenance */ + TypeQualifier qualifiers; /* Qualificatifs du type */ class = G_DATA_TYPE_GET_CLASS(type); @@ -429,24 +457,36 @@ char *g_data_type_to_string(const GDataType *type, bool include) if (result == NULL) result = strdup(""); - if (include && type->namespace != NULL && g_data_type_handle_namespaces(type)) + if (include) { - namespace = g_data_type_to_string(type->namespace, true); + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); - result = strprep(result, type->ns_sep); - result = strprep(result, namespace); + if (type->namespace != NULL && g_data_type_handle_namespaces(type)) + { + namespace = g_data_type_to_string(type->namespace, true); - free(namespace); + result = strprep(result, extra->ns_sep); + result = strprep(result, namespace); + + free(namespace); + + } + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); } - if (type->qualifiers & TQF_RESTRICT) + qualifiers = g_data_type_get_qualifiers(type); + + if (qualifiers & TQF_RESTRICT) result = strprep(result, "restrict "); - if (type->qualifiers & TQF_VOLATILE) + if (qualifiers & TQF_VOLATILE) result = strprep(result, "volatile "); - if (type->qualifiers & TQF_CONST) + if (qualifiers & TQF_CONST) result = strprep(result, "const "); return result; @@ -457,7 +497,7 @@ char *g_data_type_to_string(const GDataType *type, bool include) /****************************************************************************** * * * Paramètres : type = instance à mettre à jour. * -* qualifiers = nouveaux qualificatifs pour la variable. * +* qualifiers = nouveaux qualificatifs pour le type. * * * * Description : Définit l'ensemble des qualificatifs d'une instance de type. * * * @@ -469,7 +509,15 @@ char *g_data_type_to_string(const GDataType *type, bool include) void g_data_type_set_qualifiers(GDataType *type, TypeQualifier qualifiers) { - type->qualifiers = qualifiers; + type_obj_extra *extra; /* Données insérées à modifier */ + + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); + + extra->qualifiers = qualifiers; + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); } @@ -477,7 +525,7 @@ void g_data_type_set_qualifiers(GDataType *type, TypeQualifier qualifiers) /****************************************************************************** * * * Paramètres : type = instance à mettre à jour. * -* qualifier = nouveau qualificatif pour la variable. * +* qualifier = nouveau qualificatif pour le type. * * * * Description : Ajoute un qualificatif à une instance de type. * * * @@ -489,7 +537,15 @@ void g_data_type_set_qualifiers(GDataType *type, TypeQualifier qualifiers) void g_data_type_add_qualifier(GDataType *type, TypeQualifier qualifier) { - type->qualifiers |= qualifier; + type_obj_extra *extra; /* Données insérées à modifier */ + + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); + + extra->qualifiers |= qualifier; + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); } @@ -509,8 +565,15 @@ void g_data_type_add_qualifier(GDataType *type, TypeQualifier qualifier) TypeQualifier g_data_type_get_qualifiers(const GDataType *type) { TypeQualifier result; /* Qualificatifs à renvoyer */ + type_obj_extra *extra; /* Données insérées à modifier */ - result = type->qualifiers; + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); + + result = extra->qualifiers; + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); return result; @@ -525,22 +588,48 @@ TypeQualifier g_data_type_get_qualifiers(const GDataType *type) * * * Description : Définit le groupe d'appartenance d'un type donné. * * * -* Retour : - * +* Retour : true si la définition est effective, false en cas de rejet. * * * * Remarques : - * * * ******************************************************************************/ -void g_data_type_set_namespace(GDataType *type, GDataType *namespace, char *sep) +bool g_data_type_set_namespace(GDataType *type, GDataType *namespace, const char *sep) { - if (type->namespace != NULL) - g_object_unref(G_OBJECT(type->namespace)); + bool result; /* Bilan à retourner */ + type_obj_extra *extra; /* Données insérées à modifier */ + + result = ((namespace == NULL && sep == NULL) || (namespace != NULL && sep != NULL && sep[0] != '\0')); + + if (result) + { + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); + + if (sep == NULL) + { + extra->ns_sep[0] = '\0'; + extra->ns_sep[1] = '\0'; + } + else + { + extra->ns_sep[0] = sep[0]; + extra->ns_sep[1] = sep[1]; + } + + if (type->namespace != NULL) + g_object_unref(G_OBJECT(type->namespace)); - if (type->ns_sep != NULL) - free(type->ns_sep); + type->namespace = namespace; + + g_object_ref(G_OBJECT(namespace)); + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); + + } - type->namespace = namespace; - type->ns_sep = sep; + return result; } @@ -560,12 +649,19 @@ void g_data_type_set_namespace(GDataType *type, GDataType *namespace, char *sep) GDataType *g_data_type_get_namespace(const GDataType *type) { GDataType *result; /* Espace à renvoyer */ + type_obj_extra *extra; /* Données insérées à modifier */ + + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); result = type->namespace; if (result != NULL) g_object_ref(G_OBJECT(result)); + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); + return result; } @@ -583,11 +679,25 @@ GDataType *g_data_type_get_namespace(const GDataType *type) * * ******************************************************************************/ -const char *g_data_type_get_namespace_separator(const GDataType *type) +char *g_data_type_get_namespace_separator(const GDataType *type) { char *result; /* Séparateur à retourner */ + type_obj_extra *extra; /* Données insérées à modifier */ + + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); + + if (extra->ns_sep[0] == '\0') + result = NULL; + + else if (extra->ns_sep[1] == '\0') + result = strndup(extra->ns_sep, 1); - result = type->ns_sep; + else + result = strndup(extra->ns_sep, 2); + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); return result; @@ -625,6 +735,92 @@ bool g_data_type_handle_namespaces(const GDataType *type) /****************************************************************************** * * +* Paramètres : type = instance à mettre à jour. * +* flags = nouvelles propriétés pour le type. * +* * +* Description : Définit l'ensemble des fanions d'une instance de type. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_data_type_set_flags(GDataType *type, TypeFlag flags) +{ + type_obj_extra *extra; /* Données insérées à modifier */ + + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); + + extra->flags = flags; + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); + +} + + +/****************************************************************************** +* * +* Paramètres : type = instance à mettre à jour. * +* flag = nouvelle propriété pour le type. * +* * +* Description : Ajoute un fanion à une instance de type. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_data_type_add_flag(GDataType *type, TypeFlag flag) +{ + type_obj_extra *extra; /* Données insérées à modifier */ + + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); + + extra->flags |= flag; + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); + +} + + +/****************************************************************************** +* * +* Paramètres : type = instance à consulter. * +* * +* Description : Fournit les fanions associés à une instance de type. * +* * +* Retour : Qualificatifs éventuels. * +* * +* Remarques : - * +* * +******************************************************************************/ + +TypeFlag g_data_type_get_flags(const GDataType *type) +{ + TypeFlag result; /* Propriétés à renvoyer */ + type_obj_extra *extra; /* Données insérées à modifier */ + + extra = GET_DATA_TYPE_EXTRA(type); + + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); + + result = extra->flags; + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : type = type à consulter. * * * * Description : Indique si le type est un pointeur. * diff --git a/src/analysis/type.h b/src/analysis/type.h index f21c008..819af38 100644 --- a/src/analysis/type.h +++ b/src/analysis/type.h @@ -51,13 +51,23 @@ typedef enum _TypeQualifier TQF_NONE = (0 << 0), /* Néant */ TQF_RESTRICT = (1 << 0), /* restrict (C99) */ TQF_VOLATILE = (1 << 1), /* volatile */ - TQF_CONST = (1 << 2) /* const */ + TQF_CONST = (1 << 2), /* const */ + + TQF_ALL = ((1 << 3) - 1) /* Masque de qualificatifs */ } TypeQualifier; +/* Propriétés particulières d'un type */ +typedef enum _TypeFlag +{ + TFL_NONE = (0 << 0), /* Aucune propriété */ + TFL_SINGLETON_SOON = (1 << 0), /* Singleton en devenir */ + TFL_SINGLETON = (1 << 1), /* Singleton effectif */ + + TFL_USER_LOW_BIT = (1 << 2), /* Premier bit libre */ + TFL_USER_HIGH_BIT = (1 << 6) /* Dernier bit libre */ -/* Masque de tous les qualificatifs */ -#define TQF_ALL ((1 << 3) - 1) +} TypeFlag; /* Indique le type défini pour un type quelconque. */ @@ -82,17 +92,26 @@ void g_data_type_add_qualifier(GDataType *, TypeQualifier); TypeQualifier g_data_type_get_qualifiers(const GDataType *); /* Définit le groupe d'appartenance d'un type donné. */ -void g_data_type_set_namespace(GDataType *, GDataType *, char *); +bool g_data_type_set_namespace(GDataType *, GDataType *, const char *); /* Fournit le groupe d'appartenance d'un type donné. */ GDataType *g_data_type_get_namespace(const GDataType *); /* Fournit la chaîne de séparation entre deux entités. */ -const char *g_data_type_get_namespace_separator(const GDataType *); +char *g_data_type_get_namespace_separator(const GDataType *); /* Indique si le type assure une gestion des espaces de noms. */ bool g_data_type_handle_namespaces(const GDataType *); +/* Définit l'ensemble des fanions d'une instance de type. */ +void g_data_type_set_flags(GDataType *, TypeFlag); + +/* Ajoute un fanion à une instance de type. */ +void g_data_type_add_flag(GDataType *, TypeFlag); + +/* Fournit les fanions associés à une instance de type. */ +TypeFlag g_data_type_get_flags(const GDataType *); + /* Indique si le type est un pointeur. */ bool g_data_type_is_pointer(const GDataType *); diff --git a/src/analysis/types/proto.c b/src/analysis/types/proto.c index aa096d8..4df0552 100644 --- a/src/analysis/types/proto.c +++ b/src/analysis/types/proto.c @@ -396,6 +396,7 @@ static char *g_proto_type_to_string(const GProtoType *type, bool include) { char *result; /* Valeur à renvoyer */ GDataType *base; /* Version d'instance parente */ + type_obj_extra *extra; /* Données insérées à modifier */ char *namespace; /* Groupe d'appartenance */ size_t i; /* Boucle de parcours */ char *arg; /* Argument à décrire */ @@ -415,15 +416,25 @@ static char *g_proto_type_to_string(const GProtoType *type, bool include) base = G_DATA_TYPE(type); - if (include && base->namespace != NULL) + if (include) { - namespace = g_data_type_to_string(base->namespace, true); - if (namespace == NULL) goto error; + extra = GET_DATA_TYPE_EXTRA(base); - result = stradd(result, namespace); - result = stradd(result, base->ns_sep); + g_bit_lock(&extra->lock, HOLE_LOCK_BIT); - free(namespace); + if (base->namespace != NULL) + { + namespace = g_data_type_to_string(base->namespace, true); + if (namespace == NULL) goto error; + + result = strprep(result, extra->ns_sep); + result = strprep(result, namespace); + + free(namespace); + + } + + g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); } |