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);      } | 
