summaryrefslogtreecommitdiff
path: root/src/analysis
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2021-03-07 17:52:38 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2021-03-07 17:52:38 (GMT)
commit7a60504691ebd8b914592e60990cc3526cf26e29 (patch)
tree8093ae850e6dc720296c71deee3c3eb0a5763ed1 /src/analysis
parenta79d209385fca4e74a6a85b2386be71ec23057bb (diff)
Compact data type definitions.
Diffstat (limited to 'src/analysis')
-rw-r--r--src/analysis/type-int.h50
-rw-r--r--src/analysis/type.c302
-rw-r--r--src/analysis/type.h29
-rw-r--r--src/analysis/types/proto.c23
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);
}