From 22d7a5277e2526514b8b01983f502c26aeff5747 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 8 Oct 2023 15:39:00 +0200
Subject: Import external Kaitai definitions when needed.

---
 plugins/kaitai/Makefile.am           |   1 +
 plugins/kaitai/import.c              | 192 +++++++++++++++++++++++++++++++++++
 plugins/kaitai/import.h              |  41 ++++++++
 plugins/kaitai/parsers/meta-int.h    |   3 +
 plugins/kaitai/parsers/meta.c        |  81 ++++++++++++++-
 plugins/kaitai/parsers/meta.h        |   3 +
 plugins/kaitai/parsers/struct-int.h  |   2 +
 plugins/kaitai/parsers/struct.c      |  68 ++++++++++++-
 plugins/kaitai/parsers/type-int.h    |   3 +
 plugins/kaitai/parsers/type.c        |  58 +++++++++++
 plugins/kaitai/parsers/type.h        |   3 +
 plugins/kaitai/python/parsers/meta.c |  52 +++++++++-
 12 files changed, 500 insertions(+), 7 deletions(-)
 create mode 100644 plugins/kaitai/import.c
 create mode 100644 plugins/kaitai/import.h

diff --git a/plugins/kaitai/Makefile.am b/plugins/kaitai/Makefile.am
index 6c612ba..9a4e112 100644
--- a/plugins/kaitai/Makefile.am
+++ b/plugins/kaitai/Makefile.am
@@ -54,6 +54,7 @@ libkaitai_la_SOURCES =						\
 	array.h array.c							\
 	core.h core.c							\
 	expression.h							\
+	import.h import.c						\
 	parser-int.h							\
 	parser.h parser.c						\
 	record-int.h							\
diff --git a/plugins/kaitai/import.c b/plugins/kaitai/import.c
new file mode 100644
index 0000000..f645eae
--- /dev/null
+++ b/plugins/kaitai/import.c
@@ -0,0 +1,192 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * import.c - localisation de fichiers de définitions externes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "import.h"
+
+
+#include <libgen.h>
+#include <malloc.h>
+#include <string.h>
+
+
+
+/* Charge un type Kaitai à partir d'une définition voisine. */
+static GKaitaiType *import_relative_kaitai_definition(const char *, const char *);
+
+/* Charge un interpréteur pour une définition voisine. */
+static GKaitaiStruct *load_relative_kaitai_definition(const char *, const char *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : target    = désignation de la définition à retrouver.        *
+*                reference = éventuel fichier pour les positions relatives.   *
+*                                                                             *
+*  Description : Charge un type Kaitai à partir d'une définition voisine.     *
+*                                                                             *
+*  Retour      : Type valide en place ou NULL en cas d'échec.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GKaitaiType *import_relative_kaitai_definition(const char *target, const char *reference)
+{
+    GKaitaiType *result;                    /* Structure chargée à renvoyer*/
+    char *tmp;                              /* Zone de travail temporaire  */
+    char *base;                             /* Base de recherche           */
+    char *filename;                         /* Nom de fichier à tester     */
+    int ret;                                /* Bilan d'une construction    */
+
+    result = NULL;
+
+    tmp = strdup(reference);
+    base = dirname(tmp);
+
+    ret = asprintf(&filename, "%s%c%s.ksy", base, G_DIR_SEPARATOR, target);
+    if (ret == -1) goto build_error;
+
+    result = g_kaitai_type_new_as_import(target, filename);
+
+    free(filename);
+
+ build_error:
+
+    free(tmp);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : target    = désignation de la définition à retrouver.        *
+*                reference = éventuel fichier pour les positions relatives.   *
+*                                                                             *
+*  Description : Met en place un type Kaitai pour une définition désignée.    *
+*                                                                             *
+*  Retour      : Type valide en place ou NULL en cas d'échec.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiType *import_kaitai_definition(const char *target, const char *reference)
+{
+    GKaitaiType *result;                    /* Structure chargée à renvoyer*/
+
+    result = NULL;
+
+    if (reference != NULL)
+    {
+        result = import_relative_kaitai_definition(target, reference);
+
+        if (result != NULL)
+            goto done;
+
+    }
+
+ done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : target    = désignation de la définition à retrouver.        *
+*                reference = éventuel fichier pour les positions relatives.   *
+*                                                                             *
+*  Description : Charge un interpréteur pour une définition voisine.          *
+*                                                                             *
+*  Retour      : Interprétateur valide en place ou NULL en cas d'échec.       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GKaitaiStruct *load_relative_kaitai_definition(const char *target, const char *reference)
+{
+    GKaitaiStruct *result;                  /* Structure chargée à renvoyer*/
+    char *tmp;                              /* Zone de travail temporaire  */
+    char *base;                             /* Base de recherche           */
+    char *filename;                         /* Nom de fichier à tester     */
+    int ret;                                /* Bilan d'une construction    */
+
+    result = NULL;
+
+    tmp = strdup(reference);
+    base = dirname(tmp);
+
+    ret = asprintf(&filename, "%s%c%s.ksy", base, G_DIR_SEPARATOR, target);
+    if (ret == -1) goto build_error;
+
+    result = g_kaitai_structure_new_from_file(filename);
+
+    free(filename);
+
+ build_error:
+
+    free(tmp);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : target    = désignation de la définition à retrouver.        *
+*                reference = éventuel fichier pour les positions relatives.   *
+*                                                                             *
+*  Description : Met en place un interpréteur pour une définition désignée.   *
+*                                                                             *
+*  Retour      : Interprétateur valide en place ou NULL en cas d'échec.       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiStruct *load_relative_kaitai_definition(const char *target, const char *reference)
+{
+    GKaitaiStruct *result;                  /* Structure chargée à renvoyer*/
+
+    result = NULL;
+
+    if (reference != NULL)
+    {
+        result = load_relative_kaitai_definition(target, reference);
+
+        if (result != NULL)
+            goto done;
+
+    }
+
+ done:
+
+    return result;
+
+}
diff --git a/plugins/kaitai/import.h b/plugins/kaitai/import.h
new file mode 100644
index 0000000..12fde07
--- /dev/null
+++ b/plugins/kaitai/import.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * import.h - prototypes pour la localisation de fichiers de définitions externes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_IMPORT_H
+#define _PLUGINS_KAITAI_IMPORT_H
+
+
+#include "parsers/struct.h"
+#include "parsers/type.h"
+
+
+
+/* Met en place un type Kaitai pour une définition désignée. */
+GKaitaiType *import_kaitai_definition(const char *, const char *);
+
+/* Met en place un interpréteur pour une définition désignée. */
+GKaitaiStruct *load_relative_kaitai_definition(const char *, const char *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_IMPORT_H */
diff --git a/plugins/kaitai/parsers/meta-int.h b/plugins/kaitai/parsers/meta-int.h
index 7d847ef..5fe9174 100644
--- a/plugins/kaitai/parsers/meta-int.h
+++ b/plugins/kaitai/parsers/meta-int.h
@@ -39,6 +39,9 @@ struct _GKaitaiMeta
 
     SourceEndian endian;                    /* Boutisme par défaut         */
 
+    char **dependencies;                    /* Définitions à importer      */
+    size_t dep_count;                       /* Nombre de ces définitions   */
+
 };
 
 /* Description globale d'une définition Kaitai (classe) */
diff --git a/plugins/kaitai/parsers/meta.c b/plugins/kaitai/parsers/meta.c
index dc30c73..132eefd 100644
--- a/plugins/kaitai/parsers/meta.c
+++ b/plugins/kaitai/parsers/meta.c
@@ -97,6 +97,9 @@ static void g_kaitai_meta_init(GKaitaiMeta *meta)
 
     meta->endian = SRE_LITTLE;
 
+    meta->dependencies = NULL;
+    meta->dep_count = 0;
+
 }
 
 
@@ -133,12 +136,20 @@ static void g_kaitai_meta_dispose(GKaitaiMeta *meta)
 
 static void g_kaitai_meta_finalize(GKaitaiMeta *meta)
 {
+    size_t i;                               /* Boucle de parcours          */
+
     if (meta->id != NULL)
         free(meta->id);
 
     if (meta->title != NULL)
         free(meta->title);
 
+    for (i = 0; i < meta->dep_count; i++)
+        free(meta->dependencies[i]);
+
+    if (meta->dependencies != NULL)
+        free(meta->dependencies);
+
     G_OBJECT_CLASS(g_kaitai_meta_parent_class)->finalize(G_OBJECT(meta));
 
 }
@@ -188,6 +199,9 @@ bool g_kaitai_meta_create(GKaitaiMeta *meta, GYamlNode *parent)
     bool result;                            /* Bilan à retourner           */
     GYamlNode *node;                        /* Noeud particulier présent   */
     const char *value;                      /* Valeur Yaml particulière    */
+    GYamlNode **nodes;                      /* Eventuels noeuds trouvés    */
+    size_t count;                           /* Quantité de ces noeuds      */
+    size_t i;                               /* Boucle de parcours          */
 
     result = true;
 
@@ -245,6 +259,45 @@ bool g_kaitai_meta_create(GKaitaiMeta *meta, GYamlNode *parent)
 
     }
 
+    /* Imports */
+
+    node = g_yaml_node_find_first_by_path(parent, "/meta/imports/");
+
+    if (node != NULL)
+    {
+        result = G_IS_YAML_COLLEC(node);
+
+        if (result)
+        {
+            nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(node), &count);
+
+            for (i = 0; i < count; i++)
+            {
+                if (!G_IS_YAML_PAIR(nodes[i]))
+                    break;
+
+                value = g_yaml_pair_get_key(G_YAML_PAIR(nodes[i]));
+
+                meta->dependencies = realloc(meta->dependencies, ++meta->dep_count * sizeof(char *));
+
+                meta->dependencies[meta->dep_count - 1] = strdup(value);
+
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            }
+
+            result = (i == count);
+
+            for (; i < count; i++)
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            if (nodes != NULL)
+                free(nodes);
+
+        }
+
+    }
+
     return result;
 
 }
@@ -279,7 +332,7 @@ const char *g_kaitai_meta_get_id(const GKaitaiMeta *meta)
 *                                                                             *
 *  Description : Fournit la désignation humaine d'une définiton Kaitai.       *
 *                                                                             *
-*  Retour      : Intitulé de définition OU NULL.                              *
+*  Retour      : Intitulé de définition ou NULL.                              *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
@@ -317,3 +370,29 @@ SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *meta)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : meta  = description globale à consulter.                     *
+*                count = quantité de définitions à importer. [OUT]            *
+*                                                                             *
+*  Description : Indique la liste des définitions à importer.                 *
+*                                                                             *
+*  Retour      : Liste de désignations de définitions ou NULL.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *meta, size_t *count)
+{
+    const char * const *result;             /* Liste à retourner           */
+
+    result = (const char * const *)meta->dependencies;
+
+    *count = meta->dep_count;
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parsers/meta.h b/plugins/kaitai/parsers/meta.h
index 3797823..b8b685d 100644
--- a/plugins/kaitai/parsers/meta.h
+++ b/plugins/kaitai/parsers/meta.h
@@ -63,6 +63,9 @@ const char *g_kaitai_meta_get_title(const GKaitaiMeta *);
 /* Indique le boustime observé par défaut par une définiton. */
 SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *);
 
+/* Indique la liste des définitions à importer. */
+const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *, size_t *);
+
 
 
 #endif  /* _PLUGINS_KAITAI_PARSERS_META_H */
diff --git a/plugins/kaitai/parsers/struct-int.h b/plugins/kaitai/parsers/struct-int.h
index f34be32..6eb6e53 100644
--- a/plugins/kaitai/parsers/struct-int.h
+++ b/plugins/kaitai/parsers/struct-int.h
@@ -37,6 +37,8 @@ struct _GKaitaiStruct
 {
     GKaitaiParser parent;                   /* A laisser en premier        */
 
+    char *filename;                         /* Eventuelle source de données*/
+
     GKaitaiMeta *meta;                      /* Description globale         */
 
     GKaitaiAttribute **seq_items;           /* Sous-attributs présents     */
diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c
index 128a788..07126c6 100644
--- a/plugins/kaitai/parsers/struct.c
+++ b/plugins/kaitai/parsers/struct.c
@@ -33,6 +33,7 @@
 
 
 #include "struct-int.h"
+#include "../import.h"
 #include "../parser.h"
 #include "../records/empty.h"
 #include "../records/group.h"
@@ -54,6 +55,9 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *);
 /* Procède à la libération totale de la mémoire. */
 static void g_kaitai_structure_finalize(GKaitaiStruct *);
 
+/* Charge les éventuelles dépendances de la définition. */
+static bool g_kaitai_structure_load_imports(GKaitaiStruct *);
+
 
 
 /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
@@ -116,6 +120,8 @@ static void g_kaitai_structure_class_init(GKaitaiStructClass *klass)
 
 static void g_kaitai_structure_init(GKaitaiStruct *kstruct)
 {
+    kstruct->filename = NULL;
+
     kstruct->meta = NULL;
 
     kstruct->seq_items = NULL;
@@ -182,6 +188,9 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *kstruct)
 
 static void g_kaitai_structure_finalize(GKaitaiStruct *kstruct)
 {
+    if (kstruct->filename != NULL)
+        free(kstruct->filename);
+
     if (kstruct->seq_items != NULL)
         free(kstruct->seq_items);
 
@@ -305,6 +314,8 @@ bool g_kaitai_structure_create_from_file(GKaitaiStruct *kstruct, const char *fil
     bool result;                            /* Bilan à retourner           */
     GYamlNode *root;                        /* Noeud racine YAML           */
 
+    kstruct->filename = strdup(filename);
+
     root = parse_yaml_from_file(filename);
 
     if (root != NULL)
@@ -343,6 +354,7 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
     GYamlNode **nodes;                      /* Eventuels noeuds trouvés    */
     size_t count;                           /* Quantité de ces noeuds      */
     size_t i;                               /* Boucle de parcours          */
+    size_t first;                           /* Premier emplacement dispo.  */
     bool failed;                            /* Détection d'un échec        */
 
     result = false;
@@ -352,6 +364,9 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
     kstruct->meta = g_kaitai_meta_new(parent);
     assert(kstruct->meta != NULL);
 
+    result = g_kaitai_structure_load_imports(kstruct);
+    if (!result) goto bad_loading;
+
     /* Séquence */
 
     collec = g_yaml_node_find_first_by_path(parent, "/seq/");
@@ -406,13 +421,15 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
 
         if (count > 0)
         {
-            kstruct->types = calloc(count, sizeof(GKaitaiType *));
-            kstruct->types_count = count;
+            first = kstruct->types_count;
+
+            kstruct->types_count += count;
+            kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *));
 
             for (i = 0; i < count; i++)
             {
-                kstruct->types[i] = g_kaitai_type_new(nodes[i]);
-                if (kstruct->types[i] == NULL) break;
+                kstruct->types[first + i] = g_kaitai_type_new(nodes[i]);
+                if (kstruct->types[first + i] == NULL) break;
 
                 g_object_unref(G_OBJECT(nodes[i]));
 
@@ -529,6 +546,49 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : kstruct = lecteur de définition à initialiser pleinement.    *
+*                                                                             *
+*  Description : Charge les éventuelles dépendances de la définition.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_structure_load_imports(GKaitaiStruct *kstruct)
+{
+    bool result;                            /* Bilan d'opération à renvoyer*/
+    const char * const *dependencies;       /* Liste d'imports requis      */
+    size_t count;                           /* Quantité de ces imports     */
+    size_t i;                               /* Boucle de parcours          */
+    GKaitaiType *imported;                  /* Structure importée          */
+
+    result = true;
+
+    dependencies = g_kaitai_meta_get_dependencies(kstruct->meta, &count);
+
+    for (i = 0; i < count; i++)
+    {
+        imported = import_kaitai_definition(dependencies[i], kstruct->filename);
+        if (imported == NULL) break;
+
+        kstruct->types_count++;
+        kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *));
+
+        kstruct->types[kstruct->types_count - 1] = imported;
+
+    }
+
+    result = (i == count);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : kstruct = structure Kaitai à consulter.                      *
 *                                                                             *
 *  Description : Fournit la description globale d'une définition Kaitai.      *
diff --git a/plugins/kaitai/parsers/type-int.h b/plugins/kaitai/parsers/type-int.h
index 4a4d939..535ce57 100644
--- a/plugins/kaitai/parsers/type-int.h
+++ b/plugins/kaitai/parsers/type-int.h
@@ -50,6 +50,9 @@ struct _GKaitaiTypeClass
 /* Met en place un lecteur de type pour Kaitai. */
 bool g_kaitai_type_create(GKaitaiType *, GYamlNode *);
 
+/* Met en place un lecteur de type externe pour Kaitai. */
+bool g_kaitai_type_create_as_import(GKaitaiType *, const char *, const char *);
+
 
 
 #endif  /* PLUGINS_KAITAI_PARSERS_TYPE_INT_H */
diff --git a/plugins/kaitai/parsers/type.c b/plugins/kaitai/parsers/type.c
index 30d0373..81efbeb 100644
--- a/plugins/kaitai/parsers/type.c
+++ b/plugins/kaitai/parsers/type.c
@@ -215,6 +215,64 @@ bool g_kaitai_type_create(GKaitaiType *type, GYamlNode *parent)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : name     = nom à attribuer au futur type.                    *
+*                filename = chemin vers une définition Kaitai à charger.      *
+*                                                                             *
+*  Description : Construit un lecteur de type externe pour Kaitai.            *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiType *g_kaitai_type_new_as_import(const char *name, const char *filename)
+{
+    GKaitaiType *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_KAITAI_TYPE, NULL);
+
+    if (!g_kaitai_type_create_as_import(result, name, filename))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type     = lecteur de type Kaitai à initialiser pleinement.  *
+*                name     = nom à attribuer au futur type.                    *
+*                filename = chemin vers une définition Kaitai à charger.      *
+*                                                                             *
+*  Description : Met en place un lecteur de type externe pour Kaitai.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_type_create_as_import(GKaitaiType *type, const char *name, const char *filename)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    /* Extraction du nom */
+
+    type->name = strdup(name);
+
+    /* Extraction des bases du type */
+
+    result = g_kaitai_structure_create_from_file(G_KAITAI_STRUCT(type), filename);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : type = définition de type particulier à consulter.           *
 *                                                                             *
 *  Description : Indique le nom de scène du type représenté.                  *
diff --git a/plugins/kaitai/parsers/type.h b/plugins/kaitai/parsers/type.h
index 0656c64..d19ab90 100644
--- a/plugins/kaitai/parsers/type.h
+++ b/plugins/kaitai/parsers/type.h
@@ -54,6 +54,9 @@ GType g_kaitai_type_get_type(void);
 /* Construit un lecteur de type pour Kaitai. */
 GKaitaiType *g_kaitai_type_new(GYamlNode *);
 
+/* Construit un lecteur de type externe pour Kaitai. */
+GKaitaiType *g_kaitai_type_new_as_import(const char *, const char *);
+
 /* Indique le nom de scène du type représenté. */
 const char *g_kaitai_type_get_name(const GKaitaiType *);
 
diff --git a/plugins/kaitai/python/parsers/meta.c b/plugins/kaitai/python/parsers/meta.c
index 3432640..0bd7bf9 100644
--- a/plugins/kaitai/python/parsers/meta.c
+++ b/plugins/kaitai/python/parsers/meta.c
@@ -50,6 +50,9 @@ static PyObject *py_kaitai_meta_get_id(PyObject *, void *);
 /* Fournit la désignation humaine d'une définiton Kaitai. */
 static PyObject *py_kaitai_meta_get_title(PyObject *, void *);
 
+/* Indique la liste des définitions à importer. */
+static PyObject *py_kaitai_meta_get_dependencies(PyObject *, void *);
+
 
 
 /******************************************************************************
@@ -162,7 +165,7 @@ static PyObject *py_kaitai_meta_get_id(PyObject *self, void *closure)
 *                                                                             *
 *  Description : Fournit la désignation humaine d'une définiton Kaitai.       *
 *                                                                             *
-*  Retour      : Intitulé de définition OU None.                              *
+*  Retour      : Intitulé de définition ou None.                              *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
@@ -206,7 +209,7 @@ static PyObject *py_kaitai_meta_get_title(PyObject *self, void *closure)
 *                                                                             *
 *  Description : Fournit la désignation humaine d'une définiton Kaitai.       *
 *                                                                             *
-*  Retour      : Intitulé de définition OU None.                              *
+*  Retour      : Intitulé de définition ou None.                              *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
@@ -238,6 +241,50 @@ static PyObject *py_kaitai_meta_get_endian(PyObject *self, void *closure)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique la liste des définitions à importer.                 *
+*                                                                             *
+*  Retour      : Liste de désignations de définitions, vide ou non.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_meta_get_dependencies(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiMeta *meta;                      /* Version native de l'objet   */
+    const char * const *dependencies;       /* Liste d'imports requis      */
+    size_t count;                           /* Quantité de ces imports     */
+    size_t i;                               /* Boucle de parcours          */
+
+#define KAITAI_META_DEPENDENCIES_ATTRIB PYTHON_GET_DEF_FULL \
+(                                                           \
+    dependencies, py_kaitai_meta,                           \
+    "Tuple of all definitions to import for the current"    \
+    " definition.\n"                                        \
+    "\n"                                                    \
+    "The result may be an empty string list."               \
+)
+
+    meta = G_KAITAI_META(pygobject_get(self));
+
+    dependencies = g_kaitai_meta_get_dependencies(meta, &count);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+        PyTuple_SetItem(result, i, PyUnicode_FromString(dependencies[i]));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -258,6 +305,7 @@ PyTypeObject *get_python_kaitai_meta_type(void)
         KAITAI_META_ID_ATTRIB,
         KAITAI_META_TITLE_ATTRIB,
         KAITAI_META_ENDIAN_ATTRIB,
+        KAITAI_META_DEPENDENCIES_ATTRIB,
         { NULL }
     };
 
-- 
cgit v0.11.2-87-g4458