From a857e1e9db9d298b7aa91e8f618e6c0ea4db84ac Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 7 Jul 2018 12:49:20 +0200
Subject: Extended the types API.

---
 plugins/itanium/component.c              |  77 ++++++-
 plugins/pychrysalide/analysis/module.c   |   2 +
 plugins/pychrysalide/analysis/routine.c  | 347 +++++++++++++++++++++++++++++++
 plugins/pychrysalide/analysis/type.c     | 304 +++++++++++++++++++++++++++
 plugins/pychrysalide/analysis/variable.c |   2 +-
 src/analysis/routine.c                   |  24 ++-
 src/analysis/routine.h                   |   4 +-
 src/analysis/type.c                      |  43 ++++
 src/analysis/type.h                      |  10 +
 9 files changed, 797 insertions(+), 16 deletions(-)

diff --git a/plugins/itanium/component.c b/plugins/itanium/component.c
index b8aa9c5..c2bf78a 100644
--- a/plugins/itanium/component.c
+++ b/plugins/itanium/component.c
@@ -60,6 +60,9 @@ static void visit_comp(itanium_component *, visit_comp_fc);
 /* Traduit les composants de contexte Itanium en décalage. */
 static bool itd_translate_component_to_offset(const itanium_component *, call_offset_t *);
 
+/* Ajoute un espace de noms à un type déjà préparé. */
+static void itd_prepend_namespace_to_type(GDataType *, GDataType *);
+
 
 
 /******************************************************************************
@@ -1279,6 +1282,39 @@ static bool itd_translate_component_to_offset(const itanium_component *comp, cal
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : type = type à traiter.                                       *
+*                ns   = espace à intégrer.                                    *
+*                                                                             *
+*  Description : Ajoute un espace de noms à un type déjà préparé.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void itd_prepend_namespace_to_type(GDataType *type, GDataType *ns)
+{
+    GDataType *existing;                    /* Espace en place ?           */
+
+    existing = g_data_type_get_namespace(type);
+
+    if (existing == NULL)
+        g_data_type_set_namespace(type, ns, "::");
+
+    else
+    {
+        itd_prepend_namespace_to_type(existing, ns);
+
+        g_object_unref(G_OBJECT(existing));
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : comp = composant Itanium à traduire en type.                 *
 *                                                                             *
 *  Description : Traduit les composants de contexte Itanium en type.          *
@@ -1294,6 +1330,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
     GDataType *result;                      /* Type à retourner            */
     char *name;                             /* Attribution finale          */
     GDataType *ns;                          /* Espace de noms d'un type    */
+    GDataType *sub;                         /* Sous-titre à traiter        */
     call_offset_t off0;                     /* Décalage #0                 */
     call_offset_t off1;                     /* Décalage #1                 */
     itanium_component *iter;                /* Boucle de parcours          */
@@ -1316,7 +1353,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
             if (result != NULL)
             {
                 ns = g_class_enum_type_new(CET_NAMESPACE, strdup("std"));
-                g_data_type_set_namespace(result, ns, "::");
+                itd_prepend_namespace_to_type(result, ns);
             }
             break;
 
@@ -1348,7 +1385,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
                 result = itd_translate_component_to_type(comp->binary.right);
 
                 if (result != NULL && ns != NULL)
-                    g_data_type_set_namespace(result, ns, "::");
+                    itd_prepend_namespace_to_type(result, ns);
 
             }
 
@@ -1360,8 +1397,30 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
 
             if (result != NULL)
             {
-                name = itd_translate_component(comp->binary.left, NULL);
+                sub = itd_translate_component_to_type(comp->binary.left);
+
+                if (sub == NULL)
+                {
+                    name = itd_translate_component(comp->binary.left, NULL);
+                    ns = NULL;
+                }
+
+                else
+                {
+                    ns = g_data_type_get_namespace(sub);
+                    g_data_type_set_namespace(sub, NULL, NULL);
+
+                    name = g_data_type_to_string(sub, true);
+
+                    g_object_unref(G_OBJECT(sub));
+
+                }
+
                 g_template_type_set_name(G_TEMPLATE_TYPE(result), name);
+
+                if (ns != NULL)
+                    itd_prepend_namespace_to_type(result, ns);
+
             }
 
             break;
@@ -1389,7 +1448,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
                 result = itd_translate_component_to_type(comp->binary.right);
 
                 if (result != NULL)
-                    g_data_type_set_namespace(result, ns, "::");
+                    itd_prepend_namespace_to_type(result, ns);
 
             }
 
@@ -1426,7 +1485,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
                 if (result != NULL)
                 {
                     if (ns != NULL)
-                        g_data_type_set_namespace(result, ns, "::");
+                        itd_prepend_namespace_to_type(result, ns);
                 }
                 else
                 {
@@ -1452,7 +1511,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
             else
             {
                 result = g_class_enum_type_new(CET_VIRTUAL_TABLE, NULL);
-                g_data_type_set_namespace(result, ns, "::");
+                itd_prepend_namespace_to_type(result, ns);
             }
 
             break;
@@ -1467,7 +1526,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
             else
             {
                 result = g_class_enum_type_new(CET_VIRTUAL_STRUCT, NULL);
-                g_data_type_set_namespace(result, ns, "::");
+                itd_prepend_namespace_to_type(result, ns);
             }
 
             break;
@@ -1635,7 +1694,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
                     g_object_unref(G_OBJECT(ns));
 
                 else
-                    g_data_type_set_namespace(result, ns, "::");
+                    itd_prepend_namespace_to_type(result, ns);
 
             }
 
@@ -1773,7 +1832,7 @@ GBinRoutine *itd_translate_component_to_routine(const itanium_component *comp)
             g_data_type_set_namespace(type, NULL, NULL);
 
             if (G_IS_TEMPLATE_TYPE(type))
-                g_binary_routine_set_name_from_type(result, type);
+                g_binary_routine_set_typed_name(result, type);
 
             else
             {
diff --git a/plugins/pychrysalide/analysis/module.c b/plugins/pychrysalide/analysis/module.c
index 614adf0..60f08ce 100644
--- a/plugins/pychrysalide/analysis/module.c
+++ b/plugins/pychrysalide/analysis/module.c
@@ -39,6 +39,7 @@
 #include "variable.h"
 #include "contents/module.h"
 #include "db/module.h"
+#include "types/module.h"
 #include "../access.h"
 
 
@@ -103,6 +104,7 @@ bool add_analysis_module_to_python_module(PyObject *super)
 
     result &= add_analysis_contents_module_to_python_module(module);
     result &= add_analysis_db_module_to_python_module(module);
+    result &= add_analysis_types_module_to_python_module(module);
 
     if (result)
         register_access_to_python_module("pychrysalide.analysis", module);
diff --git a/plugins/pychrysalide/analysis/routine.c b/plugins/pychrysalide/analysis/routine.c
index a95131d..fddc026 100644
--- a/plugins/pychrysalide/analysis/routine.c
+++ b/plugins/pychrysalide/analysis/routine.c
@@ -37,6 +37,7 @@
 
 
 #include "block.h"
+#include "type.h"
 #include "../helpers.h"
 #include "../format/symbol.h"
 
@@ -48,15 +49,39 @@ static PyObject *py_binary_routine_to_str(PyObject *);
 /* Crée un nouvel objet Python de type 'BinRoutine'. */
 static PyObject *py_binary_routine_new(PyTypeObject *, PyObject *, PyObject *);
 
+/* Fournit le groupe d'appartenance d'une routine donnée. */
+static PyObject *py_binary_routine_get_namespace(PyObject *, void *);
+
+/* Définit le groupe d'appartenance d'une routine donnée. */
+static int py_binary_routine_set_namespace(PyObject *, PyObject *, void *);
+
 /* Fournit le nom humain d'une routine. */
 static PyObject *py_binary_routine_get_name(PyObject *, void *);
 
 /* Définit le nom humain d'une routine. */
 static int py_binary_routine_set_name(PyObject *, PyObject *, void *);
 
+/* Fournit le type construisant le nom humain d'une routine. */
+static PyObject *py_binary_routine_get_typed_name(PyObject *, void *);
+
+/* Définit de façon indirecte le nom humain d'une routine. */
+static int py_binary_routine_set_typed_name(PyObject *, PyObject *, void *);
+
+/* Fournit le type de retour d'une routine. */
+static PyObject *py_binary_routine_get_return_type(PyObject *, void *);
+
+/* Définit le type de retour d'une routine. */
+static int py_binary_routine_set_return_type(PyObject *, PyObject *, void *);
+
+/* Fournit la liste des arguments associés à la routine. */
+static PyObject *py_binary_routine_get_args(PyObject *, void *);
+
 /* Fournit les blocs basiques de la routine. */
 static PyObject *py_binary_routine_get_basic_blocks(PyObject *, void *);
 
+/* Définit les blocs basiques de la routine. */
+static int py_binary_routine_set_basic_blocks(PyObject *, PyObject *, void *);
+
 
 
 /******************************************************************************
@@ -120,6 +145,104 @@ static PyObject *py_binary_routine_new(PyTypeObject *type, PyObject *args, PyObj
 *  Paramètres  : self    = objet Python concerné par l'appel.                 *
 *                closure = non utilisé ici.                                   *
 *                                                                             *
+*  Description : Fournit le groupe d'appartenance d'une routine donnée.       *
+*                                                                             *
+*  Retour      : Eventuelle instance d'appartenance ou None.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_binary_routine_get_namespace(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GBinRoutine *routine;                   /* Elément à consulter         */
+    GDataType *ns;                          /* Espace de noms              */
+
+    routine = G_BIN_ROUTINE(pygobject_get(self));
+    ns = g_binary_routine_get_namespace(routine);
+
+    if (ns != NULL)
+    {
+        result = pygobject_new(G_OBJECT(ns));
+        g_object_unref(G_OBJECT(ns));
+    }
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Définit le groupe d'appartenance d'une routine donnée.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération pour Python.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_binary_routine_set_namespace(PyObject *self, PyObject *value, void *closure)
+{
+    GBinRoutine *routine;                   /* Elément à traiter           */
+    GDataType *ns;                          /* Espace de noms              */
+    char *sep;                              /* Séparateur des espaces      */
+
+    if ((!PyTuple_Check(value) || (PyTuple_Check(value) && PyTuple_Size(value) != 2)) && value != Py_None)
+    {
+        PyErr_SetString(PyExc_TypeError,
+                        _("The attribute value must be a tuple with GDataType and a separator or None."));
+        return -1;
+    }
+
+    routine = G_BIN_ROUTINE(pygobject_get(self));
+
+    if (value == Py_None)
+        g_binary_routine_set_namespace(routine, NULL, NULL);
+
+    else
+    {
+        if (!PyObject_IsInstance(PyTuple_GetItem(value, 0), (PyObject *)get_python_data_type_type()))
+        {
+            PyErr_SetString(PyExc_TypeError, _("The first tuple item must be a GDataType."));
+            return -1;
+        }
+
+        if (!PyUnicode_Check(PyTuple_GetItem(value, 1)))
+        {
+            PyErr_SetString(PyExc_TypeError, _("The second tuple item must be a string."));
+            return -1;
+        }
+
+        ns = G_DATA_TYPE(pygobject_get(PyTuple_GetItem(value, 0)));
+        sep = strdup(PyUnicode_DATA(pygobject_get(PyTuple_GetItem(value, 1))));
+
+        g_object_ref(G_OBJECT(ns));
+        g_binary_routine_set_namespace(routine, ns, sep);
+
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
 *  Description : Fournit le nom humain d'une routine.                         *
 *                                                                             *
 *  Retour      : Désignation humainement lisible ou None si non définie.      *
@@ -189,6 +312,214 @@ static int py_binary_routine_set_name(PyObject *self, PyObject *value, void *clo
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit le type construisant le nom humain d'une routine.    *
+*                                                                             *
+*  Retour      : Eventuel type à l'origine du nom ou None.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_binary_routine_get_typed_name(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GBinRoutine *routine;                   /* Elément à consulter         */
+    GDataType *name;                        /* Type de nom                 */
+
+    routine = G_BIN_ROUTINE(pygobject_get(self));
+    name = g_binary_routine_get_typed_name(routine);
+
+    if (name != NULL)
+    {
+        result = pygobject_new(G_OBJECT(name));
+        g_object_unref(G_OBJECT(name));
+    }
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Définit de façon indirecte le nom humain d'une routine.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération pour Python.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_binary_routine_set_typed_name(PyObject *self, PyObject *value, void *closure)
+{
+    GBinRoutine *routine;                   /* Elément à traiter           */
+    GDataType *name;                        /* Type de nom                 */
+
+    if (!PyObject_IsInstance(value, (PyObject *)get_python_data_type_type()) && value != Py_None)
+    {
+        PyErr_SetString(PyExc_TypeError, _("The attribute value must be a GDataType or None."));
+        return -1;
+    }
+
+    routine = G_BIN_ROUTINE(pygobject_get(self));
+
+    if (value == Py_None)
+        g_binary_routine_set_return_type(routine, NULL);
+
+    else
+    {
+        name = G_DATA_TYPE(pygobject_get(value));
+
+        g_object_ref(G_OBJECT(name));
+        g_binary_routine_set_typed_name(routine, name);
+
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit le type de retour d'une routine.                     *
+*                                                                             *
+*  Retour      : Indication sur le type de retour en place.                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_binary_routine_get_return_type(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GBinRoutine *routine;                   /* Elément à consulter         */
+    GDataType *ret;                         /* Type de retour              */
+
+    routine = G_BIN_ROUTINE(pygobject_get(self));
+    ret = g_binary_routine_get_return_type(routine);
+
+    if (ret != NULL)
+    {
+        result = pygobject_new(G_OBJECT(ret));
+        g_object_unref(G_OBJECT(ret));
+    }
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Définit le type de retour d'une routine.                     *
+*                                                                             *
+*  Retour      : Bilan de l'opération pour Python.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_binary_routine_set_return_type(PyObject *self, PyObject *value, void *closure)
+{
+    GBinRoutine *routine;                   /* Elément à traiter           */
+    GDataType *ret;                         /* Type de retour              */
+
+    if (!PyObject_IsInstance(value, (PyObject *)get_python_data_type_type()) && value != Py_None)
+    {
+        PyErr_SetString(PyExc_TypeError, _("The attribute value must be a GDataType or None."));
+        return -1;
+    }
+
+    routine = G_BIN_ROUTINE(pygobject_get(self));
+
+    if (value == Py_None)
+        g_binary_routine_set_return_type(routine, NULL);
+
+    else
+    {
+        ret = G_DATA_TYPE(pygobject_get(value));
+
+        g_object_ref(G_OBJECT(ret));
+        g_binary_routine_set_return_type(routine, ret);
+
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = classe représentant une routine binaire.           *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Fournit la liste des arguments associés à la routine.        *
+*                                                                             *
+*  Retour      : Ensemble de blocs déterminés via les instructions.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_binary_routine_get_args(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Résultat à retourner        */
+    GBinRoutine *routine;                   /* Version native              */
+    size_t count;                           /* Nombre de paramètres        */
+    size_t i;                               /* Boucle de parcours          */
+    GBinVariable *arg;                      /* Argument à transcrire       */
+
+    routine = G_BIN_ROUTINE(pygobject_get(self));
+
+    count = g_binary_routine_get_args_count(routine);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+    {
+        arg = g_binary_routine_get_arg(routine, i);
+
+        PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(arg)));
+
+        g_object_unref(arg);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : self    = classe représentant une routine binaire.           *
 *                closure = adresse non utilisée ici.                          *
 *                                                                             *
@@ -269,10 +600,26 @@ PyTypeObject *get_python_binary_routine_type(void)
 
     static PyGetSetDef py_binary_routine_getseters[] = {
         {
+            "namespace", py_binary_routine_get_namespace, py_binary_routine_set_namespace,
+            "Namespace for the routine, None if any.", NULL
+        },
+        {
             "name", py_binary_routine_get_name, py_binary_routine_set_name,
             "Name of the current routine.", NULL
         },
         {
+            "typed_name", py_binary_routine_get_typed_name, py_binary_routine_set_typed_name,
+            "Name of the current routine provided by a type.", NULL
+        },
+        {
+            "ret", py_binary_routine_get_return_type, py_binary_routine_set_return_type,
+            "Return type of the routine, None if any.", NULL
+        },
+        {
+            "args", py_binary_routine_get_args, NULL,
+            "Arguments for the routine.", NULL
+        },
+        {
             "basic_blocks", py_binary_routine_get_basic_blocks, py_binary_routine_set_basic_blocks,
             "Basic blocks of the binary routine.", NULL
         },
diff --git a/plugins/pychrysalide/analysis/type.c b/plugins/pychrysalide/analysis/type.c
index 146e490..3694877 100644
--- a/plugins/pychrysalide/analysis/type.c
+++ b/plugins/pychrysalide/analysis/type.c
@@ -29,6 +29,9 @@
 #include <pygobject.h>
 
 
+#include <i18n.h>
+
+
 #include <analysis/type.h>
 
 
@@ -39,6 +42,27 @@
 /* Décrit le type fourni sous forme de caractères. */
 static PyObject *py_data_type_to_str(PyObject *);
 
+/* Fournit le groupe d'appartenance d'un type donné. */
+static PyObject *py_data_type_get_namespace(PyObject *, void *);
+
+/* Définit le groupe d'appartenance d'un type donné. */
+static int py_data_type_set_namespace(PyObject *, PyObject *, void *);
+
+/* Fournit les qualificatifs associés à une instance de type. */
+static PyObject *py_data_type_get_qualifiers(PyObject *, void *);
+
+/* Définit l'ensemble des qualificatifs d'une instance de type. */
+static int py_data_type_set_qualifiers(PyObject *, PyObject *, void *);
+
+/* Indique si le type est un pointeur. */
+static PyObject *py_data_type_is_pointer(PyObject *, void *);
+
+/* Indique si le type est une référence. */
+static PyObject *py_data_type_is_reference(PyObject *, void *);
+
+/* Définit les constantes pour les types de données. */
+static bool py_data_type_define_constants(PyTypeObject *);
+
 
 
 /******************************************************************************
@@ -74,6 +98,237 @@ static PyObject *py_data_type_to_str(PyObject *self)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit le groupe d'appartenance d'un type donné.            *
+*                                                                             *
+*  Retour      : Eventuelle instance d'appartenance ou None.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_data_type_get_namespace(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GDataType *type;                        /* Elément à consulter         */
+    GDataType *ns;                          /* Espace de noms              */
+
+    type = G_DATA_TYPE(pygobject_get(self));
+    ns = g_data_type_get_namespace(type);
+
+    if (ns != NULL)
+    {
+        result = pygobject_new(G_OBJECT(ns));
+        g_object_unref(G_OBJECT(ns));
+    }
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Définit le groupe d'appartenance d'un type donné.            *
+*                                                                             *
+*  Retour      : Bilan de l'opération pour Python.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_data_type_set_namespace(PyObject *self, PyObject *value, void *closure)
+{
+    GDataType *type;                        /* Elément à traiter           */
+    GDataType *ns;                          /* Espace de noms              */
+    char *sep;                              /* Séparateur des espaces      */
+
+    if ((!PyTuple_Check(value) || (PyTuple_Check(value) && PyTuple_Size(value) != 2)) && value != Py_None)
+    {
+        PyErr_SetString(PyExc_TypeError,
+                        _("The attribute value must be a tuple with GDataType and a separator or None."));
+        return -1;
+    }
+
+    type = G_DATA_TYPE(pygobject_get(self));
+
+    if (value == Py_None)
+        g_data_type_set_namespace(type, NULL, NULL);
+
+    else
+    {
+        if (!PyObject_IsInstance(PyTuple_GetItem(value, 0), (PyObject *)get_python_data_type_type()))
+        {
+            PyErr_SetString(PyExc_TypeError, _("The first tuple item must be a GDataType."));
+            return -1;
+        }
+
+        if (!PyUnicode_Check(PyTuple_GetItem(value, 1)))
+        {
+            PyErr_SetString(PyExc_TypeError, _("The second tuple item must be a string."));
+            return -1;
+        }
+
+        ns = G_DATA_TYPE(pygobject_get(PyTuple_GetItem(value, 0)));
+        sep = strdup(PyUnicode_DATA(pygobject_get(PyTuple_GetItem(value, 1))));
+
+        g_object_ref(G_OBJECT(ns));
+        g_data_type_set_namespace(type, ns, sep);
+
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit les qualificatifs associés à une instance de type.   *
+*                                                                             *
+*  Retour      : Qualificatifs éventuels.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_data_type_get_qualifiers(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GDataType *type;                        /* Elément à consulter         */
+    TypeQualifier qualifiers;               /* Qualificatifs en place      */
+
+    type = G_DATA_TYPE(pygobject_get(self));
+    qualifiers = g_data_type_get_qualifiers(type);
+
+    result = PyLong_FromUnsignedLong(qualifiers);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Définit l'ensemble des qualificatifs d'une instance de type. *
+*                                                                             *
+*  Retour      : Bilan de l'opération pour Python.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_data_type_set_qualifiers(PyObject *self, PyObject *value, void *closure)
+{
+    GDataType *type;                        /* Elément à traiter           */
+    unsigned long qualifiers;               /* Qualificatifs à intégrer    */
+
+    if (!PyLong_Check(value))
+    {
+        PyErr_SetString(PyExc_TypeError, _("The attribute value must be a integer mask."));
+        return -1;
+    }
+
+    qualifiers = PyLong_AsUnsignedLong(value);
+
+    if (qualifiers > TQF_ALL)
+    {
+        PyErr_SetString(PyExc_TypeError, _("Invalid value for type qualifiers."));
+        return -1;
+    }
+
+    type = G_DATA_TYPE(pygobject_get(self));
+
+    g_data_type_set_qualifiers(type, qualifiers);
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique si le type est un pointeur.                          *
+*                                                                             *
+*  Retour      : Bilan de la consultation.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_data_type_is_pointer(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GDataType *type;                        /* Elément à consulter         */
+    bool status;                            /* Etat à faire suivre         */
+
+    type = G_DATA_TYPE(pygobject_get(self));
+
+    status = g_data_type_is_pointer(type);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique si le type est une référence.                        *
+*                                                                             *
+*  Retour      : Bilan de la consultation.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_data_type_is_reference(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GDataType *type;                        /* Elément à consulter         */
+    bool status;                            /* Etat à faire suivre         */
+
+    type = G_DATA_TYPE(pygobject_get(self));
+
+    status = g_data_type_is_reference(type);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -91,6 +346,22 @@ PyTypeObject *get_python_data_type_type(void)
     };
 
     static PyGetSetDef py_data_type_getseters[] = {
+        {
+            "namespace", py_data_type_get_namespace, py_data_type_set_namespace,
+            "Namespace for the type, None if any.", NULL
+        },
+        {
+            "qualifiers", py_data_type_get_qualifiers, py_data_type_set_qualifiers,
+            "Qualifiers linked to the type, TQF_NONE if any.", NULL
+        },
+        {
+            "is_pointer", py_data_type_is_pointer, NULL,
+            "True if the type is a pointer.", NULL
+        },
+        {
+            "is_reference", py_data_type_is_reference, NULL,
+            "True if the type is a reference.", NULL
+        },
         { NULL }
     };
 
@@ -118,6 +389,36 @@ PyTypeObject *get_python_data_type_type(void)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : obj_type = type dont le dictionnaire est à compléter.        *
+*                                                                             *
+*  Description : Définit les constantes pour les types de données.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool py_data_type_define_constants(PyTypeObject *obj_type)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    result &= PyDict_AddIntMacro(obj_type, TQF_NONE);
+    result &= PyDict_AddIntMacro(obj_type, TQF_RESTRICT);
+    result &= PyDict_AddIntMacro(obj_type, TQF_VOLATILE);
+    result &= PyDict_AddIntMacro(obj_type, TQF_CONST);
+
+    result &= PyDict_AddIntMacro(obj_type, TQF_ALL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : module = module dont la définition est à compléter.          *
 *                                                                             *
 *  Description : Prend en charge l'objet 'pychrysalide.analysis.DataType'.    *
@@ -140,6 +441,9 @@ bool register_python_data_type(PyObject *module)
     if (!register_class_for_pygobject(dict, G_TYPE_DATA_TYPE, py_data_type_type, &PyGObject_Type))
         return false;
 
+    if (!py_data_type_define_constants(py_data_type_type))
+        return false;
+
     return true;
 
 }
diff --git a/plugins/pychrysalide/analysis/variable.c b/plugins/pychrysalide/analysis/variable.c
index 7437e54..268e3c9 100644
--- a/plugins/pychrysalide/analysis/variable.c
+++ b/plugins/pychrysalide/analysis/variable.c
@@ -167,7 +167,7 @@ static PyObject *py_binary_variable_get_name(PyObject *self, void *closure)
 
 static int py_binary_variable_set_name(PyObject *self, PyObject *value, void *closure)
 {
-    GBinVariable *variable;                 /* Elément à consulter         */
+    GBinVariable *variable;                 /* Elément à traiter           */
 
     if (!PyUnicode_Check(value) && value != Py_None)
     {
diff --git a/src/analysis/routine.c b/src/analysis/routine.c
index 43097cc..d223165 100644
--- a/src/analysis/routine.c
+++ b/src/analysis/routine.c
@@ -24,6 +24,7 @@
 #include "routine.h"
 
 
+#include <assert.h>
 #include <malloc.h>
 #include <string.h>
 #include <stdio.h>
@@ -341,7 +342,7 @@ const char *g_binary_routine_get_name(const GBinRoutine *routine)
 *                                                                             *
 ******************************************************************************/
 
-void g_binary_routine_set_name_from_type(GBinRoutine *routine, GDataType *type)
+void g_binary_routine_set_typed_name(GBinRoutine *routine, GDataType *type)
 {
     if (routine->full_name != NULL)
          g_object_unref(G_OBJECT(routine->full_name));
@@ -363,7 +364,7 @@ void g_binary_routine_set_name_from_type(GBinRoutine *routine, GDataType *type)
 *                                                                             *
 ******************************************************************************/
 
-GDataType *g_binary_routine_get_type_from_name(const GBinRoutine *routine)
+GDataType *g_binary_routine_get_typed_name(const GBinRoutine *routine)
 {
     GDataType *result;                      /* Type à retourner            */
 
@@ -486,7 +487,22 @@ size_t g_binary_routine_get_args_count(const GBinRoutine *routine)
 
 GBinVariable *g_binary_routine_get_arg(GBinRoutine *routine, size_t index)
 {
-    return routine->args[index];
+    GBinVariable *result;                   /* Argument à retourner        */
+
+    assert(index < routine->args_count);
+
+    if (index >= routine->args_count)
+        result = NULL;
+
+    else
+    {
+        result = routine->args[index];
+
+        g_object_ref(G_OBJECT(result));
+
+    }
+
+    return result;
 
 }
 
@@ -537,7 +553,7 @@ static char *g_binary_routine_get_label(const GBinRoutine *routine)
     char *result;                           /* Etiquette à renvoyer        */
 
     if (routine->full_name != NULL)
-        result = g_data_type_to_string(routine->full_name, false);
+        result = g_data_type_to_string(routine->full_name, true);
 
     else
         result = strdup(routine->name != NULL ? routine->name : "");
diff --git a/src/analysis/routine.h b/src/analysis/routine.h
index 0a4917f..9671c92 100644
--- a/src/analysis/routine.h
+++ b/src/analysis/routine.h
@@ -87,10 +87,10 @@ void g_binary_routine_set_name(GBinRoutine *, char *);
 const char *g_binary_routine_get_name(const GBinRoutine *);
 
 /* Définit de façon indirecte le nom humain d'une routine. */
-void g_binary_routine_set_name_from_type(GBinRoutine *, GDataType *);
+void g_binary_routine_set_typed_name(GBinRoutine *, GDataType *);
 
 /* Fournit le type construisant le nom humain d'une routine. */
-GDataType *g_binary_routine_get_type_from_name(const GBinRoutine *);
+GDataType *g_binary_routine_get_typed_name(const GBinRoutine *);
 
 /* Définit le type de retour d'une routine. */
 void g_binary_routine_set_return_type(GBinRoutine *, GDataType *);
diff --git a/src/analysis/type.c b/src/analysis/type.c
index cc446cb..5c1878f 100644
--- a/src/analysis/type.c
+++ b/src/analysis/type.c
@@ -271,6 +271,26 @@ GDataType *g_data_type_get_namespace(const GDataType *type)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : type       = instance à mettre à jour.                       *
+*                qualifiers = nouveaux qualificatifs pour la variable.        *
+*                                                                             *
+*  Description : Définit l'ensemble des qualificatifs d'une instance de type. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_data_type_set_qualifiers(GDataType *type, TypeQualifier qualifiers)
+{
+    type->qualifiers = qualifiers;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : type      = instance à mettre à jour.                        *
 *                qualifier = nouveau qualificatif pour la variable.           *
 *                                                                             *
@@ -291,6 +311,29 @@ void g_data_type_add_qualifier(GDataType *type, TypeQualifier qualifier)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : type = instance à consulter.                                 *
+*                                                                             *
+*  Description : Fournit les qualificatifs associés à une instance de type.   *
+*                                                                             *
+*  Retour      : Qualificatifs éventuels.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+TypeQualifier g_data_type_get_qualifiers(const GDataType *type)
+{
+    TypeQualifier result;                   /* Qualificatifs à renvoyer    */
+
+    result = type->qualifiers;
+
+    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 bd80f18..a8a9d5f 100644
--- a/src/analysis/type.h
+++ b/src/analysis/type.h
@@ -56,6 +56,10 @@ typedef enum _TypeQualifier
 } TypeQualifier;
 
 
+/* Masque de tous les qualificatifs */
+#define TQF_ALL ((1 << 3) - 1)
+
+
 /* Indique le type défini pour un type quelconque. */
 GType g_data_type_get_type(void);
 
@@ -71,9 +75,15 @@ void 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 *);
 
+/* Définit l'ensemble des qualificatifs d'une instance de type. */
+void g_data_type_set_qualifiers(GDataType *, TypeQualifier);
+
 /* Ajoute un qualificatif à une instance de type. */
 void g_data_type_add_qualifier(GDataType *, TypeQualifier);
 
+/* Fournit les qualificatifs associés à une instance de type. */
+TypeQualifier g_data_type_get_qualifiers(const GDataType *);
+
 /* Indique si le type est un pointeur. */
 bool g_data_type_is_pointer(const GDataType *);
 
-- 
cgit v0.11.2-87-g4458