From db702d1243e6fec187137d48cecb89de17fefc3b Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 30 Sep 2017 13:22:46 +0200
Subject: Handled dependencies when loading plugins.

---
 ChangeLog                   |  18 +++
 plugins/pychrysa/plugin.c   |   2 +
 plugins/pychrysa/pychrysa.c |   3 +-
 src/common/bits.c           |  23 ++++
 src/common/bits.h           |   3 +
 src/plugins/pglist.c        | 289 ++++++++++++++++++++++++++++++++------------
 src/plugins/pglist.h        |  24 +++-
 src/plugins/plugin-def.h    |   1 -
 src/plugins/plugin-int.h    |  11 +-
 src/plugins/plugin.c        | 206 ++++++++++++++++++++++++++-----
 src/plugins/plugin.h        |  23 ++++
 11 files changed, 488 insertions(+), 115 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1c8b550..201ab6f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+17-08-30  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/pychrysa/plugin.c:
+	* plugins/pychrysa/pychrysa.c:
+	Update code.
+
+	* src/common/bits.c:
+	* src/common/bits.h:
+	Extend the bitfields API.
+
+	* src/plugins/pglist.c:
+	* src/plugins/pglist.h:
+	* src/plugins/plugin-def.h:
+	* src/plugins/plugin-int.h:
+	* src/plugins/plugin.c:
+	* src/plugins/plugin.h:
+	Handle dependencies when loading plugins.
+
 17-08-28  Cyrille Bagard <nocbos@gmail.com>
 
 	* plugins/mobicore/mobicore.c:
diff --git a/plugins/pychrysa/plugin.c b/plugins/pychrysa/plugin.c
index 7d44f10..fad0084 100644
--- a/plugins/pychrysa/plugin.c
+++ b/plugins/pychrysa/plugin.c
@@ -345,8 +345,10 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
 
     /* Conclusion */
 
+    /*
     if (!g_plugin_module_load(G_PLUGIN_MODULE(result)))
         goto gppn_bad_plugin;
+    */
 
     return G_PLUGIN_MODULE(result);
 
diff --git a/plugins/pychrysa/pychrysa.c b/plugins/pychrysa/pychrysa.c
index e9efc54..4d32ee1 100644
--- a/plugins/pychrysa/pychrysa.c
+++ b/plugins/pychrysa/pychrysa.c
@@ -37,6 +37,7 @@
 #include <common/environment.h>
 #include <common/extstr.h>
 #include <core/core.h>
+#include <plugins/pglist.h>
 #include <plugins/plugin-def.h>
 #include <plugins/plugin-int.h>
 
@@ -478,7 +479,7 @@ static bool load_python_plugins(GPluginModule *plugin)
                 g_plugin_module_log_variadic_message(plugin, LMT_PROCESS, 
                                                      _("Loaded the Python plugin found in the '<b>%s</b>' directory"),
                                                      filename);
-                add_plugin_to_main_list(pyplugin);
+                _register_plugin(pyplugin);
             }
 
             free(filename);
diff --git a/src/common/bits.c b/src/common/bits.c
index 4d4731a..837e31e 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -180,6 +180,29 @@ void copy_bit_field(bitfield_t *dest, const bitfield_t *src)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : field = champ de bits à consulter.                           *
+*                                                                             *
+*  Description : Indique la taille d'un champ de bits donné.                  *
+*                                                                             *
+*  Retour      : Taille du champ de bits.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t get_bit_field_size(const bitfield_t *field)
+{
+    size_t result;                          /* Dimension à retourner       */
+
+    result = field->length;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : a = premier champ à analyser.                                *
 *                b = second champ à analyser.                                 *
 *                                                                             *
diff --git a/src/common/bits.h b/src/common/bits.h
index b9fc0e6..72b431e 100644
--- a/src/common/bits.h
+++ b/src/common/bits.h
@@ -45,6 +45,9 @@ void delete_bit_field(bitfield_t *);
 /* Copie un champ de bits dans un autre. */
 void copy_bit_field(bitfield_t *, const bitfield_t *);
 
+/* Indique la taille d'un champ de bits donné. */
+size_t get_bit_field_size(const bitfield_t *);
+
 /* Compare deux champs de bits entre eux. */
 int compare_bit_fields(const bitfield_t *, const bitfield_t *);
 
diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c
index 112a560..54c8784 100644
--- a/src/plugins/pglist.c
+++ b/src/plugins/pglist.c
@@ -32,40 +32,27 @@
 
 
 #include <config.h>
+#include <i18n.h>
 
 
 #include "plugin-int.h"
 #include "../common/extstr.h"
 
 
-/* Représentation dédiée aux listes de greffons */
-typedef struct _pg_array
-{
-    PluginAction action;                    /* Action commune ou PGA_ALL   */
-
-    GPluginModule **plugins;                /* Liste de greffons           */
-    size_t plugins_count;                   /* Taille de cette liste       */
-
-} pg_array;
-
-/* Propriétés de l'ensemble des greffons */
-typedef struct _plugins_list
-{
-    pg_array *all;                          /* Liste de tous les greffons  */
-    pg_array sorted[PGA_COUNT];             /* Tri par catégories          */
-
-} plugins_list;
-
 
 /* Liste de l'ensemble des greffons */
-static plugins_list _list;
+static GPluginModule **_pg_list = NULL;
+static size_t _pg_count = 0;
+
+/* Accès à cette liste */
+static GRWLock _pg_lock;
 
 
 /* Filtre les répertoire et les modules de greffons pootentels. */
-int filter_dirs_or_mods(const struct dirent *);
+static int filter_dirs_or_mods(const struct dirent *);
 
 /* Part à la recherche de greffons sous forme de modules. */
-void browse_directory_for_plugins(plugins_list *, const char *);
+static void browse_directory_for_plugins(const char *);
 
 
 
@@ -83,15 +70,11 @@ void browse_directory_for_plugins(plugins_list *, const char *);
 
 bool init_all_plugins(void)
 {
-    size_t i;                               /* Boucle de parcours          */
+    g_rw_lock_init(&_pg_lock);
 
-    for (i = 0; i < PGA_COUNT; i++)
-        _list.sorted[i].action = PGA_EMPTY;
+    browse_directory_for_plugins(PACKAGE_SOURCE_DIR "/plugins");
 
-    _list.sorted[0].action = PGA_ALL;
-    _list.all = &_list.sorted[0];
-
-    browse_directory_for_plugins(&_list, PACKAGE_SOURCE_DIR "/plugins");
+    load_remaning_plugins();
 
     return true;
 
@@ -114,11 +97,16 @@ void exit_all_plugins(void)
 {
     size_t i;                               /* Boucle de parcours          */
 
-    for (i = 0; i < _list.all->plugins_count; i++)
-        g_object_unref(_list.all->plugins[i]);
+    if (_pg_list != NULL)
+    {
+        for (i = 0; i < _pg_count; i++)
+            g_object_unref(_pg_list[i]);
+
+        free(_pg_list);
+
+    }
 
-    for (i = 0; i < PGA_COUNT; i++)
-        free(_list.sorted[i].plugins);
+    g_rw_lock_clear(&_pg_lock);
 
 }
 
@@ -135,7 +123,7 @@ void exit_all_plugins(void)
 *                                                                             *
 ******************************************************************************/
 
-int filter_dirs_or_mods(const struct dirent *entry)
+static int filter_dirs_or_mods(const struct dirent *entry)
 {
     int result;                             /* Conclusion à remonter       */
 
@@ -152,8 +140,7 @@ int filter_dirs_or_mods(const struct dirent *entry)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : list = liste de greffons à compléter si possible.            *
-*                dir  = répertoire à parcourir en quête de greffons (sans /). *
+*  Paramètres  : dir = répertoire à parcourir en quête de greffons (sans /).  *
 *                                                                             *
 *  Description : Part à la recherche de greffons sous forme de modules.       *
 *                                                                             *
@@ -163,7 +150,7 @@ int filter_dirs_or_mods(const struct dirent *entry)
 *                                                                             *
 ******************************************************************************/
 
-void browse_directory_for_plugins(plugins_list *list, const char *dir)
+static void browse_directory_for_plugins(const char *dir)
 {
     struct dirent **namelist;               /* Eléments trouvés            */
     int ret;                                /* Bilan du parcours           */
@@ -186,14 +173,14 @@ void browse_directory_for_plugins(plugins_list *list, const char *dir)
         strcat(filename, namelist[ret]->d_name);
 
         if (namelist[ret]->d_type == DT_DIR)
-            browse_directory_for_plugins(list, filename);
+            browse_directory_for_plugins(filename);
 
         else
         {
             plugin = g_plugin_module_new(filename);
 
             if (plugin != NULL)
-                add_plugin_to_main_list(plugin);
+                register_plugin(plugin);
 
         }
 
@@ -209,34 +196,57 @@ void browse_directory_for_plugins(plugins_list *list, const char *dir)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : action = fonctionnalité recherchée.                          *
-*                count  = nombre de greffons trouvés. [OUT]                   *
+*  Paramètres  : plugin = greffon à ajouter aux autres disponibles.           *
 *                                                                             *
-*  Description : Founit les greffons offrant le service demandé.              *
+*  Description : Ajoute un greffon à la liste principale de greffons.         *
 *                                                                             *
-*  Retour      : Liste de greffons correspondants issue d'un tri interne.     *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *count)
+void _register_plugin(GPluginModule *plugin)
 {
-    const GPluginModule **result;           /* Greffon à retourner         */
     size_t i;                               /* Boucle de parcours          */
+    const plugin_interface *pg_iface;       /* Informations à consulter    */
+    const char *name;                       /* Désignation du greffon      */
 
-    result = NULL;
-    *count = 0;
+    /**
+     * L'appel sans verrou n'est fourni que pour les greffons
+     * mettant en place des greffons en interne !
+     */
 
-    for (i = 0; i < PGA_COUNT; i++)
-        if (_list.sorted[i].action == action)
+    /* Recherche d'un éventuel doublon */
+
+    pg_iface = g_plugin_module_get_interface(plugin);
+
+    name = pg_iface->name;
+
+    for (i = 0; i < _pg_count; i++)
+    {
+        pg_iface = g_plugin_module_get_interface(_pg_list[i]);
+
+        if (strcmp(name, pg_iface->name) == 0)
         {
-            result = (const GPluginModule **)_list.sorted[i].plugins;
-            *count = _list.sorted[i].plugins_count;
+            log_variadic_message(LMT_ERROR,
+                                 _("Plugin '%s' already registered!"), name);
+
             break;
+
         }
 
-    return result;
+    }
+
+    /* Ajout du greffon à la liste */
+
+    if (i == _pg_count)
+    {
+        _pg_list = (GPluginModule **)realloc(_pg_list, ++_pg_count * sizeof(GPluginModule));
+
+        _pg_list[_pg_count - 1] = plugin;
+
+    }
 
 }
 
@@ -253,52 +263,179 @@ const GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *co
 *                                                                             *
 ******************************************************************************/
 
-void add_plugin_to_main_list(GPluginModule *plugin)
+void register_plugin(GPluginModule *plugin)
 {
-    const plugin_interface *interface;      /* Informations à consulter    */
-    size_t i;                               /* Boucle de parcours #1       */
-    size_t j;                               /* Boucle de parcours #2       */
+    g_rw_lock_writer_lock(&_pg_lock);
+
+    _register_plugin(plugin);
+
+    g_rw_lock_writer_unlock(&_pg_lock);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Charge tous les greffons restant à charger.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    interface = g_plugin_module_get_interface(plugin);
+void load_remaning_plugins(void)
+{
+    bool changed;                           /* Variation de dépendances    */
+    size_t i;                               /* Boucle de parcours          */
+    PluginStatusFlags flags;                /* Fanions de greffon          */
+
+    g_rw_lock_reader_lock(&_pg_lock);
 
-    void add_plugin_into_array(pg_array *array, GPluginModule *pg)
+    /* Etablit la liste de toutes les dépendances */
+
+    do
     {
-        array->plugins = (GPluginModule **)realloc(array->plugins,
-                                                   ++array->plugins_count * sizeof(GPluginModule));
+        changed = false;
 
-        array->plugins[array->plugins_count - 1] = pg;
+        for (i = 0; i < _pg_count; i++)
+            changed |= g_plugin_module_resolve_dependencies(_pg_list[i], _pg_list, _pg_count);
 
     }
+    while (changed);
 
-    /* FIXME : lock */
+    /* Effectue les chargements possibles */
 
-    add_plugin_into_array(_list.all, plugin);
+    for (i = 0; i < _pg_count; i++)
+    {
+        flags = g_plugin_module_get_flags(_pg_list[i]);
 
-    for (i = 0; i < interface->actions_count; i++)
+        if ((flags & (BROKEN_PLUGIN_STATUS | PSF_LOADED)) == 0)
+            g_plugin_module_load(_pg_list[i], _pg_list, _pg_count);
+
+    }
+
+    /* Supprime les greffons non chargés */
+
+    for (i = 0; i < _pg_count; i++)
     {
-        if (interface->actions[i] == PGA_ALL) continue;
+        flags = g_plugin_module_get_flags(_pg_list[i]);
 
-        for (j = 1; j < PGA_COUNT; j++)
+        if ((flags & PSF_LOADED) == 0)
         {
-            if (_list.sorted[j].action == interface->actions[i])
-            {
-                add_plugin_into_array(&_list.sorted[j], plugin);
-                break;
-            }
+            g_object_unref(G_OBJECT(_pg_list[i]));
+
+            memmove(&_pg_list[i], &_pg_list[i + 1], (_pg_count - i - 1) * sizeof(GPluginModule *));
+            _pg_count--;
 
-            else if (_list.sorted[j].action == PGA_EMPTY)
+        }
+
+    }
+
+    g_rw_lock_reader_unlock(&_pg_lock);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : name  = désignation du greffon recherché.                    *
+*                index = indice du greffon trouvé. [OUT]                      *
+*                                                                             *
+*  Description : Founit le greffon répondant à un nom donné.                  *
+*                                                                             *
+*  Retour      : Instance du greffon trouvé ou NULL si aucun.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GPluginModule *get_plugin_by_name(const char *name, size_t *index)
+{
+    GPluginModule *result;                  /* Greffon trouvé à renvoyer   */
+    size_t i;                               /* Boucle de parcours          */
+    const plugin_interface *pg_iface;       /* Vitrine d'un greffon        */
+
+    result = NULL;
+
+    /**
+     * L'accès à la liste doit être encadré.
+     */
+    assert(g_rw_lock_writer_trylock(&_pg_lock) == FALSE);
+
+    for (i = 0; i < _pg_count && result == NULL; i++)
+    {
+        pg_iface = g_plugin_module_get_interface(_pg_list[i]);
+
+        if (strcmp(pg_iface->name, name) == 0)
+        {
+            result = _pg_list[i];
+
+            if (index != NULL)
+                *index = i;
+
+        }
+
+    }
+
+    if (result != NULL)
+        g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : action = fonctionnalité recherchée.                          *
+*                count  = nombre de greffons trouvés. [OUT]                   *
+*                                                                             *
+*  Description : Founit les greffons offrant le service demandé.              *
+*                                                                             *
+*  Retour      : Liste de greffons correspondants issue d'un tri interne.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *count)
+{
+    GPluginModule **result;                 /* Liste à retourner           */
+    const plugin_interface *pg_iface;       /* Informations à consulter    */
+    size_t i;                               /* Boucle de parcours #1       */
+    size_t j;                               /* Boucle de parcours #2       */
+
+    result = NULL;
+    *count = 0;
+
+    g_rw_lock_reader_lock(&_pg_lock);
+
+    for (i = 0; i < _pg_count; i++)
+    {
+        pg_iface = g_plugin_module_get_interface(_pg_list[i]);
+
+        for (j = 0; j < pg_iface->actions_count; j++)
+        {
+            if (pg_iface->actions[j] == action)
             {
-                add_plugin_into_array(&_list.sorted[j], plugin);
-                _list.sorted[j].action = interface->actions[i];
+                result = (GPluginModule **)realloc(result, ++(*count) * sizeof(GPluginModule *));
+
+                result[*count - 1] = _pg_list[i];
+                g_object_ref(G_OBJECT(_pg_list[i]));
+
                 break;
+
             }
 
         }
 
-        assert(j < PGA_COUNT);
-
     }
 
-    /* FIXME : lock */
+    g_rw_lock_reader_unlock(&_pg_lock);
+
+    return result;
 
 }
diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h
index 5dfd6c3..d2f2243 100644
--- a/src/plugins/pglist.h
+++ b/src/plugins/pglist.h
@@ -41,8 +41,21 @@ bool init_all_plugins(void);
 /* Procède au déchargement des différents greffons présents. */
 void exit_all_plugins(void);
 
+/* Ajoute un greffon à la liste principale de greffons. */
+void _register_plugin(GPluginModule *);
+
+/* Ajoute un greffon à la liste principale de greffons. */
+void register_plugin(GPluginModule *);
+
+/* Charge tous les greffons restant à charger. */
+void load_remaning_plugins(void);
+
+/* Founit le greffon répondant à un nom donné. */
+GPluginModule *get_plugin_by_name(const char *, size_t *);
+
 /* Founit less greffons offrant le service demandé. */
-const GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
+GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
+
 
 
 /**
@@ -52,18 +65,23 @@ const GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
 #define process_all_plugins_for(a, f, ...)                  \
     {                                                       \
         size_t __count;                                     \
-        const GPluginModule **__list;                       \
+        GPluginModule **__list;                             \
         size_t __i;                                         \
         __list = get_all_plugins_for_action(a, &__count);   \
         for (__i = 0; __i < __count; __i++)                 \
+        {                                                   \
             f(__list[__i], a, __VA_ARGS__);                 \
+            g_object_ref(G_OBJECT(__list[__i]));            \
+        }                                                   \
+        if (__list != NULL)                                 \
+            free(__list);                                   \
     }                                                       \
     while (0)
 
 
 /* DPS_FORMAT */
 
-#define find_matching_format()
+//#define find_matching_format()
 
 #define handle_binary_format(a, f, s)                                     \
     process_all_plugins_for(a, g_plugin_module_handle_binary_format, f, s)
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 7344a06..83b2c9a 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -285,7 +285,6 @@ typedef struct _plugin_interface
 
     const char **required;                  /* Pré-chargements requis      */
     size_t required_count;                  /* Quantité de ces dépendances */
-    /* status */
 
     plugin_action_t *actions;               /* Liste des actions gérées    */
     size_t actions_count;                   /* Quantité de ces actions     */
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index ac6ade6..821653c 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -32,6 +32,7 @@
 #include "plugin.h"
 #include "plugin-def.h"
 #include "../analysis/content.h"
+#include "../common/bits.h"
 #include "../gui/panels/log.h"
 
 
@@ -91,6 +92,10 @@ struct _GPluginModule
 
     const plugin_interface *interface;      /* Déclaration d'interfaçage   */
 
+    PluginStatusFlags flags;                /* Fanion pour l'état courant  */
+
+    bitfield_t *dependencies;               /* Cartographie des dépendances*/
+
     pg_management_fc init;                  /* Procédure d'initialisation  */
     pg_management_fc exit;                  /* Procédure d'extinction      */
 
@@ -126,9 +131,6 @@ struct _GPluginModuleClass
 
 
 
-/* Termine le chargement du greffon préparé. */
-bool g_plugin_module_load(GPluginModule *);
-
 /* Présente dans le journal un message simple. */
 void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, const char *);
 
@@ -137,8 +139,7 @@ void g_plugin_module_log_variadic_message(const GPluginModule *, LogMessageType,
 
 
 
-/* Ajoute un greffon à la liste principale de greffons. */
-void add_plugin_to_main_list(GPluginModule *);
+
 
 
 
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 03c3b21..cd59ee1 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -25,6 +25,7 @@
 #include "plugin.h"
 
 
+#include <assert.h>
 #include <gmodule.h>
 #include <libgen.h>
 #include <malloc.h>
@@ -34,6 +35,7 @@
 #include <string.h>
 
 
+#include "pglist.h"
 #include "plugin-int.h"
 
 
@@ -142,6 +144,9 @@ static void g_plugin_module_finalize(GPluginModule *plugin)
 {
     free(plugin->filename);
 
+    if (plugin->dependencies != NULL)
+        delete_bit_field(plugin->dependencies);
+
     G_OBJECT_CLASS(g_plugin_module_parent_class)->finalize(G_OBJECT(plugin));
 
 }
@@ -318,11 +323,6 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
 
     }
 
-    /* Conclusion */
-
-    if (!g_plugin_module_load(result))
-        goto bad_plugin;
-
     return result;
 
  bad_plugin:
@@ -336,42 +336,122 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin = greffon à valider.                                  *
+*  Paramètres  : plugin = greffon à consulter.                                *
 *                                                                             *
-*  Description : Termine le chargement du greffon préparé.                    *
+*  Description : Fournit la description du greffon dans son intégralité.      *
 *                                                                             *
-*  Retour      : Bilan du chargement effectif.                                *
+*  Retour      : Interfaçage renseigné.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const plugin_interface *g_plugin_module_get_interface(const GPluginModule *plugin)
+{
+    return plugin->interface;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à consulter.                                *
+*                                                                             *
+*  Description : Fournit des indications sur l'état du greffon.               *
+*                                                                             *
+*  Retour      : Fanions portant des indications.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PluginStatusFlags g_plugin_module_get_flags(const GPluginModule *plugin)
+{
+    return plugin->flags;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à mettre à jour.                            *
+*                list   = ensemble des greffons disponibles.                  *
+*                count  = taille de cet ensemble.                             *
+*                                                                             *
+*  Description : Met à jour l'ensemble des dépendances du greffon.            *
+*                                                                             *
+*  Retour      : true si la liste des dépendances a évolué.                   *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool g_plugin_module_load(GPluginModule *plugin)
+bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule **list, size_t count)
 {
     bool result;                            /* Bilan à faire remonter      */
-    char *dir;                              /* Répertoire modifiable       */
+    const plugin_interface *pg_iface;       /* Définition du greffon       */
+    bitfield_t *new;                        /* Nouvelle définition         */
+    size_t i;                               /* Boucle de parcours          */
+    GPluginModule *dependency;              /* Module nécessaire           */
+    size_t index;                           /* Indice de greffon visé      */
 
-    result = true;
+    result = false;
 
-    dir = strdup(plugin->filename);
-    dir = dirname(dir);
+    if (plugin->dependencies == NULL)
+        plugin->dependencies = create_bit_field(count, false);
 
-    if (plugin->init != NULL)
+#ifndef NDEBUG
+    else
+        assert(count == get_bit_field_size(plugin->dependencies));
+#endif
+
+    if ((plugin->flags & (PSF_UNKNOW_DEP | PSF_DEP_LOOP)) != 0)
     {
-        if (!plugin->init(plugin))
+        pg_iface = g_plugin_module_get_interface(plugin);
+
+        /* Collecte des dépendances */
+
+        new = dup_bit_field(plugin->dependencies);
+
+        for (i = 0; i < pg_iface->required_count; i++)
         {
-            log_variadic_message(LMT_ERROR,
-                                 _("Plugin '%s' failed to load itself..."), plugin->filename);
-            result = false;
+            dependency = get_plugin_by_name(pg_iface->required[i], &index);
+
+            if (dependency == NULL)
+                plugin->flags |= PSF_UNKNOW_DEP;
+
+            else
+            {
+                or_bit_field(new, dependency->dependencies);
+
+                g_object_ref(G_OBJECT(dependency));
+
+            }
+
         }
-    }
 
-    if (result)
-        log_variadic_message(LMT_PROCESS,
-                             _("Loaded the '<b>%s</b>' file as plugin from the '<b>%s</b>' directory"),
-                             strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir);
+        /* Mise à jour du suivi */
+
+        if (compare_bit_fields(plugin->dependencies, new) != 0)
+        {
+            copy_bit_field(plugin->dependencies, new);
+            result = true;
+        }
+
+        delete_bit_field(new);
+
+        /* Vérification sanitaire */
+
+        dependency = get_plugin_by_name(pg_iface->name, &index);
+        assert(dependency != NULL);
 
-    free(dir);
+        if (test_in_bit_field(plugin->dependencies, index))
+            plugin->flags |= PSF_DEP_LOOP;
+
+        g_object_ref(G_OBJECT(dependency));
+
+
+    }
 
     return result;
 
@@ -380,19 +460,87 @@ bool g_plugin_module_load(GPluginModule *plugin)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin = greffon à consulter.                                *
+*  Paramètres  : plugin = greffon à valider.                                  *
+*                list   = ensemble des greffons disponibles.                  *
+*                count  = taille de cet ensemble.                             *
 *                                                                             *
-*  Description : Fournit la description du greffon dans son intégralité.      *
+*  Description : Termine le chargement du greffon préparé.                    *
 *                                                                             *
-*  Retour      : Interfaçage renseigné.                                       *
+*  Retour      : Bilan du chargement effectif.                                *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const plugin_interface *g_plugin_module_get_interface(const GPluginModule *plugin)
+bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t count)
 {
-    return plugin->interface;
+    bool result;                            /* Bilan à retourner           */
+    PluginStatusFlags flags;                /* Fanions de greffon          */
+    const plugin_interface *pg_iface;       /* Définition du greffon       */
+    size_t i;                               /* Boucle de parcours          */
+    GPluginModule *dependency;              /* Module nécessaire           */
+    char *dir;                              /* Répertoire modifiable       */
+
+    /* Si un essai précédent a déjà échoué ou réussi... */
+
+    flags = g_plugin_module_get_flags(plugin);
+
+    assert((flags & BROKEN_PLUGIN_STATUS) == 0);
+
+    if (flags & PSF_FAILURE) return false;
+
+    if (flags & PSF_LOADED) return true;
+
+    /* Chargement des dépendances */
+
+    pg_iface = g_plugin_module_get_interface(plugin);
+
+    result = true;
+
+    for (i = 0; i < pg_iface->required_count && result; i++)
+    {
+        dependency = get_plugin_by_name(pg_iface->required[i], NULL);
+
+        result = g_plugin_module_load(dependency, list, count);
+
+    }
+
+    if (!result)
+        log_variadic_message(LMT_ERROR,
+                             _("Some dependencies failed to load for Plugin '%s'"), plugin->filename);
+
+    /* Chargement du greffon courant */
+
+    if (result)
+    {
+        if (plugin->init != NULL)
+        {
+            result = plugin->init(plugin);
+
+            if (!result)
+                log_variadic_message(LMT_ERROR,
+                                     _("Plugin '%s' failed to load itself..."), plugin->filename);
+
+        }
+
+        if (result)
+        {
+            dir = strdup(plugin->filename);
+            dir = dirname(dir);
+
+            log_variadic_message(LMT_PROCESS,
+                                 _("Loaded the '<b>%s</b>' file as plugin from the '<b>%s</b>' directory"),
+                                 strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir);
+
+            free(dir);
+
+            plugin->flags |= PSF_LOADED;
+
+        }
+
+    }
+
+    return result;
 
 }
 
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index bc6189f..6d783b7 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -44,6 +44,21 @@ typedef struct _GPluginModule GPluginModule;
 typedef struct _GPluginModuleClass GPluginModuleClass;
 
 
+/* Fanions indiquant le statut du greffon */
+typedef enum _PluginStatusFlags
+{
+    PSF_NONE        = (0 << 0),             /* Aucune indication           */
+    PSF_UNKNOW_DEP  = (1 << 0),             /* Dépendance non trouvée      */
+    PSF_DEP_LOOP    = (1 << 1),             /* Dépendances circulaires     */
+    PSF_FAILURE     = (1 << 2),             /* Erreur au chargement        */
+    PSF_LOADED      = (1 << 2)              /* Greffon intégré au système  */
+
+} PluginStatusFlags;
+
+
+#define BROKEN_PLUGIN_STATUS (PSF_UNKNOW_DEP | PSF_DEP_LOOP | PSF_FAILURE)
+
+
 #define G_TYPE_PLUGIN_MODULE                (g_plugin_module_get_type())
 #define G_PLUGIN_MODULE(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLUGIN_MODULE, GPluginModule))
 #define G_IS_PLUGIN_MODULE(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLUGIN_MODULE))
@@ -61,6 +76,14 @@ GPluginModule *g_plugin_module_new(const gchar *);
 /* Fournit la description du greffon dans son intégralité. */
 const plugin_interface *g_plugin_module_get_interface(const GPluginModule *);
 
+/* Fournit des indications sur l'état du greffon. */
+PluginStatusFlags g_plugin_module_get_flags(const GPluginModule *);
+
+/* Met à jour l'ensemble des dépendances du greffon. */
+bool g_plugin_module_resolve_dependencies(GPluginModule *, GPluginModule **, size_t);
+
+/* Termine le chargement du greffon préparé. */
+bool g_plugin_module_load(GPluginModule *, GPluginModule **, size_t);
 
 
 
-- 
cgit v0.11.2-87-g4458