From 5eab5f1bf3665e948e2054817fb688963dc86935 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 24 May 2023 02:38:15 +0200
Subject: Define a first implementation of Kaitai parsing.

---
 configure.ac                              |    6 +
 plugins/Makefile.am                       |    1 +
 plugins/kaitai/Makefile.am                |   92 ++
 plugins/kaitai/array-int.h                |   51 +
 plugins/kaitai/array.c                    |  376 +++++
 plugins/kaitai/array.h                    |   76 +
 plugins/kaitai/core.c                     |   79 +
 plugins/kaitai/core.h                     |   38 +
 plugins/kaitai/expression.h               |  134 ++
 plugins/kaitai/grammar.y                  | 1854 +++++++++++++++++++++
 plugins/kaitai/parser-int.h               |   55 +
 plugins/kaitai/parser.c                   |  159 ++
 plugins/kaitai/parser.h                   |   63 +
 plugins/kaitai/parsers/Makefile.am        |   25 +
 plugins/kaitai/parsers/attribute-int.h    |  104 ++
 plugins/kaitai/parsers/attribute.c        | 2074 ++++++++++++++++++++++++
 plugins/kaitai/parsers/attribute.h        |  154 ++
 plugins/kaitai/parsers/enum-int.h         |   79 +
 plugins/kaitai/parsers/enum.c             |  765 +++++++++
 plugins/kaitai/parsers/enum.h             |   76 +
 plugins/kaitai/parsers/instance-int.h     |   59 +
 plugins/kaitai/parsers/instance.c         |  478 ++++++
 plugins/kaitai/parsers/instance.h         |   68 +
 plugins/kaitai/parsers/meta-int.h         |   57 +
 plugins/kaitai/parsers/meta.c             |  319 ++++
 plugins/kaitai/parsers/meta.h             |   68 +
 plugins/kaitai/parsers/struct-int.h       |   75 +
 plugins/kaitai/parsers/struct.c           |  782 +++++++++
 plugins/kaitai/parsers/struct.h           |   80 +
 plugins/kaitai/parsers/switch-int.h       |   78 +
 plugins/kaitai/parsers/switch.c           |  706 ++++++++
 plugins/kaitai/parsers/switch.h           |   61 +
 plugins/kaitai/parsers/type-int.h         |   55 +
 plugins/kaitai/parsers/type.c             |  236 +++
 plugins/kaitai/parsers/type.h             |   62 +
 plugins/kaitai/python/Makefile.am         |   25 +
 plugins/kaitai/python/array.c             |  265 +++
 plugins/kaitai/python/array.h             |   45 +
 plugins/kaitai/python/module.c            |  132 ++
 plugins/kaitai/python/module.h            |   41 +
 plugins/kaitai/python/parser.c            |  205 +++
 plugins/kaitai/python/parser.h            |   45 +
 plugins/kaitai/python/parsers/Makefile.am |   19 +
 plugins/kaitai/python/parsers/attribute.c |  420 +++++
 plugins/kaitai/python/parsers/attribute.h |   45 +
 plugins/kaitai/python/parsers/enum.c      |  468 ++++++
 plugins/kaitai/python/parsers/enum.h      |   45 +
 plugins/kaitai/python/parsers/instance.c  |  280 ++++
 plugins/kaitai/python/parsers/instance.h  |   45 +
 plugins/kaitai/python/parsers/meta.c      |  366 +++++
 plugins/kaitai/python/parsers/meta.h      |   45 +
 plugins/kaitai/python/parsers/module.c    |  124 ++
 plugins/kaitai/python/parsers/module.h    |   41 +
 plugins/kaitai/python/parsers/struct.c    |  376 +++++
 plugins/kaitai/python/parsers/struct.h    |   45 +
 plugins/kaitai/python/parsers/type.c      |  278 ++++
 plugins/kaitai/python/parsers/type.h      |   45 +
 plugins/kaitai/python/record.c            |  420 +++++
 plugins/kaitai/python/record.h            |   45 +
 plugins/kaitai/python/records/Makefile.am |   18 +
 plugins/kaitai/python/records/empty.c     |  286 ++++
 plugins/kaitai/python/records/empty.h     |   45 +
 plugins/kaitai/python/records/group.c     |  305 ++++
 plugins/kaitai/python/records/group.h     |   45 +
 plugins/kaitai/python/records/item.c      |  394 +++++
 plugins/kaitai/python/records/item.h      |   45 +
 plugins/kaitai/python/records/list.c      |  336 ++++
 plugins/kaitai/python/records/list.h      |   45 +
 plugins/kaitai/python/records/module.c    |  122 ++
 plugins/kaitai/python/records/module.h    |   41 +
 plugins/kaitai/python/records/value.c     |  335 ++++
 plugins/kaitai/python/records/value.h     |   45 +
 plugins/kaitai/python/scope.c             |  542 +++++++
 plugins/kaitai/python/scope.h             |   51 +
 plugins/kaitai/python/stream.c            |  278 ++++
 plugins/kaitai/python/stream.h            |   45 +
 plugins/kaitai/record-int.h               |   73 +
 plugins/kaitai/record.c                   |  408 +++++
 plugins/kaitai/record.h                   |   88 +
 plugins/kaitai/records/Makefile.am        |   21 +
 plugins/kaitai/records/empty-int.h        |   57 +
 plugins/kaitai/records/empty.c            |  236 +++
 plugins/kaitai/records/empty.h            |   58 +
 plugins/kaitai/records/group-int.h        |   58 +
 plugins/kaitai/records/group.c            |  382 +++++
 plugins/kaitai/records/group.h            |   65 +
 plugins/kaitai/records/item-int.h         |   58 +
 plugins/kaitai/records/item.c             |  309 ++++
 plugins/kaitai/records/item.h             |   65 +
 plugins/kaitai/records/list-int.h         |   60 +
 plugins/kaitai/records/list.c             |  424 +++++
 plugins/kaitai/records/list.h             |   71 +
 plugins/kaitai/records/value-int.h        |   57 +
 plugins/kaitai/records/value.c            |  336 ++++
 plugins/kaitai/records/value.h            |   65 +
 plugins/kaitai/scope.c                    |  257 +++
 plugins/kaitai/scope.h                    |   72 +
 plugins/kaitai/stream-int.h               |   55 +
 plugins/kaitai/stream.c                   |  237 +++
 plugins/kaitai/stream.h                   |   65 +
 plugins/kaitai/tokens.l                   |  327 ++++
 tests/plugins/kaitai.py                   | 2474 +++++++++++++++++++++++++++++
 102 files changed, 22666 insertions(+)
 create mode 100644 plugins/kaitai/Makefile.am
 create mode 100644 plugins/kaitai/array-int.h
 create mode 100644 plugins/kaitai/array.c
 create mode 100644 plugins/kaitai/array.h
 create mode 100644 plugins/kaitai/core.c
 create mode 100644 plugins/kaitai/core.h
 create mode 100644 plugins/kaitai/expression.h
 create mode 100644 plugins/kaitai/grammar.y
 create mode 100644 plugins/kaitai/parser-int.h
 create mode 100644 plugins/kaitai/parser.c
 create mode 100644 plugins/kaitai/parser.h
 create mode 100644 plugins/kaitai/parsers/Makefile.am
 create mode 100644 plugins/kaitai/parsers/attribute-int.h
 create mode 100644 plugins/kaitai/parsers/attribute.c
 create mode 100644 plugins/kaitai/parsers/attribute.h
 create mode 100644 plugins/kaitai/parsers/enum-int.h
 create mode 100644 plugins/kaitai/parsers/enum.c
 create mode 100644 plugins/kaitai/parsers/enum.h
 create mode 100644 plugins/kaitai/parsers/instance-int.h
 create mode 100644 plugins/kaitai/parsers/instance.c
 create mode 100644 plugins/kaitai/parsers/instance.h
 create mode 100644 plugins/kaitai/parsers/meta-int.h
 create mode 100644 plugins/kaitai/parsers/meta.c
 create mode 100644 plugins/kaitai/parsers/meta.h
 create mode 100644 plugins/kaitai/parsers/struct-int.h
 create mode 100644 plugins/kaitai/parsers/struct.c
 create mode 100644 plugins/kaitai/parsers/struct.h
 create mode 100644 plugins/kaitai/parsers/switch-int.h
 create mode 100644 plugins/kaitai/parsers/switch.c
 create mode 100644 plugins/kaitai/parsers/switch.h
 create mode 100644 plugins/kaitai/parsers/type-int.h
 create mode 100644 plugins/kaitai/parsers/type.c
 create mode 100644 plugins/kaitai/parsers/type.h
 create mode 100644 plugins/kaitai/python/Makefile.am
 create mode 100644 plugins/kaitai/python/array.c
 create mode 100644 plugins/kaitai/python/array.h
 create mode 100644 plugins/kaitai/python/module.c
 create mode 100644 plugins/kaitai/python/module.h
 create mode 100644 plugins/kaitai/python/parser.c
 create mode 100644 plugins/kaitai/python/parser.h
 create mode 100644 plugins/kaitai/python/parsers/Makefile.am
 create mode 100644 plugins/kaitai/python/parsers/attribute.c
 create mode 100644 plugins/kaitai/python/parsers/attribute.h
 create mode 100644 plugins/kaitai/python/parsers/enum.c
 create mode 100644 plugins/kaitai/python/parsers/enum.h
 create mode 100644 plugins/kaitai/python/parsers/instance.c
 create mode 100644 plugins/kaitai/python/parsers/instance.h
 create mode 100644 plugins/kaitai/python/parsers/meta.c
 create mode 100644 plugins/kaitai/python/parsers/meta.h
 create mode 100644 plugins/kaitai/python/parsers/module.c
 create mode 100644 plugins/kaitai/python/parsers/module.h
 create mode 100644 plugins/kaitai/python/parsers/struct.c
 create mode 100644 plugins/kaitai/python/parsers/struct.h
 create mode 100644 plugins/kaitai/python/parsers/type.c
 create mode 100644 plugins/kaitai/python/parsers/type.h
 create mode 100644 plugins/kaitai/python/record.c
 create mode 100644 plugins/kaitai/python/record.h
 create mode 100644 plugins/kaitai/python/records/Makefile.am
 create mode 100644 plugins/kaitai/python/records/empty.c
 create mode 100644 plugins/kaitai/python/records/empty.h
 create mode 100644 plugins/kaitai/python/records/group.c
 create mode 100644 plugins/kaitai/python/records/group.h
 create mode 100644 plugins/kaitai/python/records/item.c
 create mode 100644 plugins/kaitai/python/records/item.h
 create mode 100644 plugins/kaitai/python/records/list.c
 create mode 100644 plugins/kaitai/python/records/list.h
 create mode 100644 plugins/kaitai/python/records/module.c
 create mode 100644 plugins/kaitai/python/records/module.h
 create mode 100644 plugins/kaitai/python/records/value.c
 create mode 100644 plugins/kaitai/python/records/value.h
 create mode 100644 plugins/kaitai/python/scope.c
 create mode 100644 plugins/kaitai/python/scope.h
 create mode 100644 plugins/kaitai/python/stream.c
 create mode 100644 plugins/kaitai/python/stream.h
 create mode 100644 plugins/kaitai/record-int.h
 create mode 100644 plugins/kaitai/record.c
 create mode 100644 plugins/kaitai/record.h
 create mode 100644 plugins/kaitai/records/Makefile.am
 create mode 100644 plugins/kaitai/records/empty-int.h
 create mode 100644 plugins/kaitai/records/empty.c
 create mode 100644 plugins/kaitai/records/empty.h
 create mode 100644 plugins/kaitai/records/group-int.h
 create mode 100644 plugins/kaitai/records/group.c
 create mode 100644 plugins/kaitai/records/group.h
 create mode 100644 plugins/kaitai/records/item-int.h
 create mode 100644 plugins/kaitai/records/item.c
 create mode 100644 plugins/kaitai/records/item.h
 create mode 100644 plugins/kaitai/records/list-int.h
 create mode 100644 plugins/kaitai/records/list.c
 create mode 100644 plugins/kaitai/records/list.h
 create mode 100644 plugins/kaitai/records/value-int.h
 create mode 100644 plugins/kaitai/records/value.c
 create mode 100644 plugins/kaitai/records/value.h
 create mode 100644 plugins/kaitai/scope.c
 create mode 100644 plugins/kaitai/scope.h
 create mode 100644 plugins/kaitai/stream-int.h
 create mode 100644 plugins/kaitai/stream.c
 create mode 100644 plugins/kaitai/stream.h
 create mode 100644 plugins/kaitai/tokens.l
 create mode 100644 tests/plugins/kaitai.py

diff --git a/configure.ac b/configure.ac
index f4fe90b..eb4693b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -631,6 +631,12 @@ AC_CONFIG_FILES([Makefile
                  plugins/java/Makefile
                  plugins/javadesc/Makefile
                  plugins/javadesc/python/Makefile
+                 plugins/kaitai/Makefile
+                 plugins/kaitai/parsers/Makefile
+                 plugins/kaitai/records/Makefile
+                 plugins/kaitai/python/Makefile
+                 plugins/kaitai/python/parsers/Makefile
+                 plugins/kaitai/python/records/Makefile
                  plugins/libcsem/Makefile
                  plugins/lnxsyscalls/Makefile
                  plugins/mobicore/Makefile
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index be0bd88..7ce4229 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -24,6 +24,7 @@ SUBDIRS = \
 	fmtp \
 	itanium \
 	javadesc \
+	kaitai \
 	mobicore \
 	pe \
 	yaml \
diff --git a/plugins/kaitai/Makefile.am b/plugins/kaitai/Makefile.am
new file mode 100644
index 0000000..cbc0f25
--- /dev/null
+++ b/plugins/kaitai/Makefile.am
@@ -0,0 +1,92 @@
+
+BUILT_SOURCES = grammar.h
+
+
+# On évite d'utiliser les variables personnalisées de type *_la_[YL]FLAGS
+# afin de conserver des noms de fichiers simples, ie sans le nom de la
+# bibliothèque de sortie en préfixe.
+
+AM_YFLAGS = -v -d -p kaitai_ -Wno-yacc -Wcounterexamples
+
+AM_LFLAGS = -P kaitai_ -o lex.yy.c --header-file=tokens.h    		\
+                        -Dyyget_lineno=kaitai_get_lineno			\
+                        -Dyy_scan_bytes=kaitai__scan_bytes			\
+                        -Dyy_delete_buffer=kaitai__delete_buffer
+
+lib_LTLIBRARIES = libkaitai.la
+
+libdir = $(pluginslibdir)
+
+
+if BUILD_PYTHON_PACKAGE
+
+RUN_PATH = -Wl,-rpath,'$$ORIGIN/../chrysalide-libs'
+
+endif
+
+if BUILD_PYTHON3_BINDINGS
+
+PYTHON3_LIBADD = python/libkaitaipython.la
+
+if BUILD_DISCARD_LOCAL
+
+if BUILD_PYTHON_PACKAGE
+PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN/..'
+else
+PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN'
+endif
+
+else
+
+PYTHON3_RUN_PATH = -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs
+
+endif
+
+PYTHON3_LDFLAGS = $(PYTHON3_RUN_PATH) -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+PYTHON3_SUBDIRS = python
+
+endif
+
+
+libkaitai_la_SOURCES =						\
+	array-int.h								\
+	array.h array.c							\
+	core.h core.c							\
+	expression.h							\
+	parser-int.h							\
+	parser.h parser.c						\
+	record-int.h							\
+	record.h record.c						\
+	scope.h scope.c							\
+	stream-int.h							\
+	stream.h stream.c						\
+	tokens.l								\
+	grammar.y
+
+libkaitai_la_LIBADD =						\
+	parsers/libkaitaiparsers.la				\
+	records/libkaitairecords.la				\
+	$(PYTHON3_LIBADD)
+
+libkaitai_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+libkaitai_la_LDFLAGS =						\
+	-L$(top_srcdir)/src/.libs -lchrysacore	\
+	$(PYTHON3_LDFLAGS)
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitai_la_SOURCES:%c=)
+
+
+# Automake fait les choses à moitié
+CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h
+
+# Pareil : de tous les fichiers générés, seule la sortie de Flex saute pour les distributions !
+EXTRA_DIST = tokens.h
+
+
+# misc
+SUBDIRS = parsers records $(PYTHON3_SUBDIRS)
diff --git a/plugins/kaitai/array-int.h b/plugins/kaitai/array-int.h
new file mode 100644
index 0000000..123b16d
--- /dev/null
+++ b/plugins/kaitai/array-int.h
@@ -0,0 +1,51 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * array-int.h - prototypes pour les données associées à un flux de données Kaitai
+ *
+ * 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_ARRAY_INT_H
+#define PLUGINS_KAITAI_ARRAY_INT_H
+
+
+#include "array.h"
+
+
+
+/* Tableau rassemblant des éléments divers (instance) */
+struct _GKaitaiArray
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    resolved_value_t *items;                /* Eléments du tableau         */
+    size_t count;                           /* Quantité de ces éléments    */
+
+};
+
+/* Tableau rassemblant des éléments divers (classe) */
+struct _GKaitaiArrayClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+};
+
+
+
+#endif  /* PLUGINS_KAITAI_ARRAY_INT_H */
diff --git a/plugins/kaitai/array.c b/plugins/kaitai/array.c
new file mode 100644
index 0000000..86f0856
--- /dev/null
+++ b/plugins/kaitai/array.c
@@ -0,0 +1,376 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * array.c - données associées à un flux de données Kaitai
+ *
+ * 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 "array.h"
+
+
+#include <assert.h>
+#include <limits.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "array-int.h"
+#include "expression.h"
+
+
+
+/* Initialise la classe des flux de données pour Kaitai. */
+static void g_kaitai_array_class_init(GKaitaiArrayClass *);
+
+/* Initialise un flux de données accessibles à Kaitai. */
+static void g_kaitai_array_init(GKaitaiArray *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_array_dispose(GKaitaiArray *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_array_finalize(GKaitaiArray *);
+
+/* Détermine la taille de la séquence d'octets du tableau. */
+static bool g_kaitai_array_compute_bytes_length(const GKaitaiArray *, size_t *);
+
+
+
+/* Indique le type défini pour un tableau rassemblant des éléments Kaitai. */
+G_DEFINE_TYPE(GKaitaiArray, g_kaitai_array, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des tableau d'éléments Kaitai.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_array_class_init(GKaitaiArrayClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_array_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_kaitai_array_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : array = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise un tableau rassemblant des éléments divers.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_array_init(GKaitaiArray *array)
+{
+    array->items = NULL;
+    array->count = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : array = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_array_dispose(GKaitaiArray *array)
+{
+    G_OBJECT_CLASS(g_kaitai_array_parent_class)->dispose(G_OBJECT(array));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : array = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_array_finalize(GKaitaiArray *array)
+{
+    G_OBJECT_CLASS(g_kaitai_array_parent_class)->finalize(G_OBJECT(array));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Constitue une amorce de tableau pour rassembler des éléments.*
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiArray *g_kaitai_array_new(void)
+{
+    GKaitaiArray *result;                  /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_KAITAI_ARRAY, NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : array = tableau Kaitai à consulter.                          *
+*                                                                             *
+*  Description : Dénombre le nombre d'éléments enregistrés.                   *
+*                                                                             *
+*  Retour      : Taille du tableau manipulé.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t g_kaitai_array_count_items(const GKaitaiArray *array)
+{
+    size_t result;                          /* Quantité à retourner        */
+
+    result = array->count;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : array = tableau Kaitai à compléter.                          *
+*                item  = élément Kaitai à archiver.                           *
+*                                                                             *
+*  Description : Intègre un élément supplémentaire dans un tableau Kaitai.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_kaitai_array_append_item(GKaitaiArray *array, const resolved_value_t *item)
+{
+    array->items = realloc(array->items, ++array->count * sizeof(resolved_value_t));
+
+    COPY_RESOLVED_VALUE(array->items[array->count - 1], *item);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list  = ensemble de correspondances attribut/binaire.        *
+*                index = indice de la correspondance visée.                   *
+*                item  = élément archivé dans le talbeau à fournir. [OUT]     *
+*                                                                             *
+*  Description : Fournit un élément ciblé dans un tableau Kaitai.             *
+*                                                                             *
+*  Retour      : Validité de l'emplacmeent pour élément à renseigner.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_array_get_item(const GKaitaiArray *array, size_t index, resolved_value_t *item)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = (index < array->count);
+
+    if (result)
+        COPY_RESOLVED_VALUE(*item, array->items[index]);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : array  = tableau Kaitai à consulter.                         *
+*                length = nombre d'octets représentés. [OUT]                  *
+*                                                                             *
+*  Description : Détermine la taille de la séquence d'octets du tableau.      *
+*                                                                             *
+*  Retour      : true si le tableau peut être converti en octets, ou false.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_array_compute_bytes_length(const GKaitaiArray *array, size_t *length)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+    const resolved_value_t *item;           /* Elément en cours d'analyse  */
+    size_t extra;                           /* Taille d'un sous-tableau    */
+
+    result = true;
+
+    *length = 0;
+
+    for (i = 0; i < array->count && result; i++)
+    {
+        item = &array->items[i];
+
+        switch (item->type)
+        {
+            case GVT_UNSIGNED_INTEGER:
+                result = (item->unsigned_integer <= UCHAR_MAX);
+                if (result) (*length)++;
+                break;
+
+            case GVT_SIGNED_INTEGER:
+                result = (0 <= item->signed_integer && item->signed_integer <= SCHAR_MAX);
+                if (result) (*length)++;
+                break;
+
+            case GVT_BYTES:
+                *length += item->bytes.len;
+                break;
+
+            case GVT_ARRAY:
+                result = g_kaitai_array_compute_bytes_length(item->array, &extra);
+                if (result) *length += extra;
+                break;
+
+            default:
+                result = false;
+                break;
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : array = tableau Kaitai à consulter.                          *
+*                bytes = conversion en série d'octets équivalent. [OUT]       *
+*                                                                             *
+*  Description : Convertit un tableau d'éléments en séquence d'octets.        *
+*                                                                             *
+*  Retour      : true si une série d'octets a pu être constituée, ou false.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_array_convert_to_bytes(const GKaitaiArray *array, sized_string_t *bytes)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t length;                          /* Taille de la chaîne finale  */
+    size_t i;                               /* Boucle de parcours          */
+    const resolved_value_t *item;           /* Elément en cours d'analyse  */
+    char *iter;                             /* Tête d'écriture             */
+    sized_string_t extra;                   /* Données d'un sous-tableau   */
+
+    /* Détermination de la taille finale */
+
+    result = g_kaitai_array_compute_bytes_length(array, &length);
+
+    /* Construction d'une chaîne d'octets si possible */
+
+    if (result)
+    {
+        bytes->data = malloc(length * sizeof(char));
+        bytes->len = length;
+
+        iter = bytes->data;
+
+        for (i = 0; i < array->count; i++)
+        {
+            item = &array->items[i];
+
+            switch (item->type)
+            {
+                case GVT_UNSIGNED_INTEGER:
+                    *iter = item->unsigned_integer;
+                    iter++;
+                    break;
+
+                case GVT_SIGNED_INTEGER:
+                    *iter = item->signed_integer;
+                    iter++;
+                    break;
+
+                case GVT_BYTES:
+                    memcpy(iter, item->bytes.data, item->bytes.len);
+                    iter += item->bytes.len;
+                    break;
+
+                case GVT_ARRAY:
+                    result = g_kaitai_array_convert_to_bytes(item->array, &extra);
+                    assert(result);
+
+                    memcpy(iter, extra.data, extra.len);
+                    iter += extra.len;
+
+                    exit_szstr(&extra);
+                    break;
+
+                default:
+                    break;
+
+            }
+
+        }
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/array.h b/plugins/kaitai/array.h
new file mode 100644
index 0000000..e93c7c0
--- /dev/null
+++ b/plugins/kaitai/array.h
@@ -0,0 +1,76 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * array.h - prototypes pour les données associées à un flux de données Kaitai
+ *
+ * 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_ARRAY_H
+#define PLUGINS_KAITAI_ARRAY_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <common/szstr.h>
+
+
+
+/* expression.h : informations transportées par une expression */
+typedef struct _resolved_value_t resolved_value_t;
+
+
+
+#define G_TYPE_KAITAI_ARRAY            g_kaitai_array_get_type()
+#define G_KAITAI_ARRAY(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_ARRAY, GKaitaiArray))
+#define G_IS_KAITAI_ARRAY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_ARRAY))
+#define G_KAITAI_ARRAY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_ARRAY, GKaitaiArrayClass))
+#define G_IS_KAITAI_ARRAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_ARRAY))
+#define G_KAITAI_ARRAY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_ARRAY, GKaitaiArrayClass))
+
+
+/* Tableau rassemblant des éléments divers (instance) */
+typedef struct _GKaitaiArray GKaitaiArray;
+
+/* Tableau rassemblant des éléments divers (classe) */
+typedef struct _GKaitaiArrayClass GKaitaiArrayClass;
+
+
+/* Indique le type défini pour un tableau rassemblant des éléments Kaitai. */
+GType g_kaitai_array_get_type(void);
+
+/* Constitue une amorce de tableau pour rassembler des éléments. */
+GKaitaiArray *g_kaitai_array_new(void);
+
+/* Dénombre le nombre d'éléments enregistrés. */
+size_t g_kaitai_array_count_items(const GKaitaiArray *);
+
+/* Intègre un élément supplémentaire dans un tableau Kaitai. */
+void g_kaitai_array_append_item(GKaitaiArray *, const resolved_value_t *);
+
+/* Fournit un élément ciblé dans un tableau Kaitai. */
+bool g_kaitai_array_get_item(const GKaitaiArray *, size_t, resolved_value_t *);
+
+/* Convertit un tableau d'éléments en séquence d'octets. */
+bool g_kaitai_array_convert_to_bytes(const GKaitaiArray *, sized_string_t *);
+
+
+
+#endif  /* PLUGINS_KAITAI_ARRAY_H */
diff --git a/plugins/kaitai/core.c b/plugins/kaitai/core.c
new file mode 100644
index 0000000..65424a5
--- /dev/null
+++ b/plugins/kaitai/core.c
@@ -0,0 +1,79 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - prise en charge des descriptions de binaires au format Kaitai
+ *
+ * Copyright (C) 2019 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 "core.h"
+
+
+#include <plugins/self.h>
+
+
+#ifdef HAVE_PYTHON3_BINDINGS
+#   include "python/module.h"
+#endif
+
+
+#ifdef HAVE_PYTHON3_BINDINGS
+#   define PG_REQ RL("PyChrysalide")
+#else
+#   define PG_REQ NO_REQ
+#endif
+
+
+
+DEFINE_CHRYSALIDE_PLUGIN("Kaitai", "Content parser using Kaitai structure definitions",
+                         PACKAGE_VERSION, CHRYSALIDE_WEBSITE("doc/kaitai"),
+                         PG_REQ, AL(PGA_PLUGIN_INIT));
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                                                                             *
+*  Description : Prend acte du chargement du greffon.                         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+#ifdef HAVE_PYTHON3_BINDINGS
+
+    if (result)
+        result = add_kaitai_module_to_python_module();
+
+    if (result)
+        result = populate_kaitai_module();
+
+#endif
+
+    return result;
+
+}
diff --git a/plugins/kaitai/core.h b/plugins/kaitai/core.h
new file mode 100644
index 0000000..61241f4
--- /dev/null
+++ b/plugins/kaitai/core.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour la prise en charge des descriptions de binaires au format Kaitai
+ *
+ * Copyright (C) 2019 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_CORE_H
+#define _PLUGINS_KAITAI_CORE_H
+
+
+#include <plugins/plugin.h>
+#include <plugins/plugin-int.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_CORE_H */
diff --git a/plugins/kaitai/expression.h b/plugins/kaitai/expression.h
new file mode 100644
index 0000000..06cf9cf
--- /dev/null
+++ b/plugins/kaitai/expression.h
@@ -0,0 +1,134 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expression.h - déclarations de prototypes utiles aux résolutions d'expressions
+ *
+ * Copyright (C) 2022 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_EXPRESSION_H
+#define _PLUGINS_KAITAI_EXPRESSION_H
+
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+
+#include <common/szstr.h>
+
+
+#include "array.h"
+#include "scope.h"
+#include "stream.h"
+
+
+
+/* Type de valeur résolue */
+typedef enum _GrammarValueType
+{
+    GVT_ERROR,                              /* Erreur remontée             */
+    GVT_UNSIGNED_INTEGER,                   /* Valeur entière #1           */
+    GVT_SIGNED_INTEGER,                     /* Valeur entière #2           */
+    GVT_FLOAT,                              /* Valeur fractionnée          */
+    GVT_BOOLEAN,                            /* Valeur booléenne            */
+    GVT_BYTES,                              /* Série d'octets dynamique    */
+    GVT_ARRAY,                              /* Tableau d'éléments divers   */
+    GVT_RECORD,                             /* Correspondance en place     */
+    GVT_STREAM,                             /* Flux de données             */
+
+} GrammarValueType;
+
+/* Informations transportées par une expression */
+typedef struct _resolved_value_t
+{
+    GrammarValueType type;                  /* Type de valeur portée       */
+
+    union
+    {
+        unsigned long long unsigned_integer;/* Valeur entière #1           */
+        signed long long signed_integer;    /* Valeur entière #2           */
+        double floating_number;             /* Valeur à virgule flottante  */
+        bool status;                        /* Valeur à deux états         */
+        sized_string_t bytes;               /* Série d'octets              */
+
+        GKaitaiArray *array;                /* Tableau d'éléments divers   */
+        GMatchRecord *record;               /* Correspondance désignée     */
+        GKaitaiStream *stream;              /* Flux de données pour Kaitai */
+
+    };
+
+} resolved_value_t;
+
+
+#define COPY_RESOLVED_VALUE(dst, src)                   \
+    do                                                  \
+    {                                                   \
+        (dst) = (src);                                  \
+        switch ((dst).type)                             \
+        {                                               \
+            case GVT_ARRAY:                             \
+                g_object_ref(G_OBJECT((dst).array));    \
+                break;                                  \
+            case GVT_RECORD:                            \
+                g_object_ref(G_OBJECT((dst).record));   \
+                break;                                  \
+            case GVT_STREAM:                            \
+                g_object_ref(G_OBJECT((dst).stream));   \
+                break;                                  \
+            default:                                    \
+                break;                                  \
+        }                                               \
+    }                                                   \
+    while (0)
+
+
+#define EXIT_RESOLVED_VALUE(v)                          \
+    switch ((v).type)                                   \
+    {                                                   \
+        case GVT_ARRAY:                                 \
+            g_clear_object(&(v).array);                 \
+            break;                                      \
+        case GVT_RECORD:                                \
+            g_clear_object(&(v).record);                \
+            break;                                      \
+        case GVT_STREAM:                                \
+            g_clear_object(&(v).stream);                \
+            break;                                      \
+        default:                                        \
+            break;                                      \
+    }
+
+
+/* Interprète une expression en une valeur quelconque. */
+bool resolve_kaitai_expression_as_any(const kaitai_scope_t *, const char *, size_t, resolved_value_t *);
+
+/* Interprète une expression en valeur ciblée entière. */
+bool resolve_kaitai_expression_as_integer(const kaitai_scope_t *, const char *, size_t, resolved_value_t *);
+
+/* Interprète une expression en valeur ciblée booléenne. */
+bool resolve_kaitai_expression_as_boolean(const kaitai_scope_t *, const char *, size_t, resolved_value_t *);
+
+/* Interprète une expression en série d'octets. */
+bool resolve_kaitai_expression_as_bytes(const kaitai_scope_t *, const char *, size_t, resolved_value_t *);
+
+/* Interprète une expression en flux de données pour Kaitai. */
+bool resolve_kaitai_expression_as_stream(const kaitai_scope_t *, const char *, size_t, GKaitaiStream **);
+
+
+
+#endif  /* _PLUGINS_KAITAI_EXPRESSION_H */
diff --git a/plugins/kaitai/grammar.y b/plugins/kaitai/grammar.y
new file mode 100644
index 0000000..9e31113
--- /dev/null
+++ b/plugins/kaitai/grammar.y
@@ -0,0 +1,1854 @@
+
+%{
+
+#include "expression.h"
+#include "tokens.h"
+
+
+/* Affiche un message d'erreur suite à l'analyse en échec. */
+static int yyerror(yyscan_t, const kaitai_scope_t *, resolved_value_t *, const char *);
+
+/* Interprète une expression en une valeur quelconque. */
+static bool _resolve_kaitai_expression_as_any(const kaitai_scope_t *, const char *, size_t, resolved_value_t *);
+
+/* Traduit les éventuels champs impliqués dans une expression. */
+static bool reduce_resolved_kaitai_expression(resolved_value_t *);
+
+
+%}
+
+
+%code requires {
+
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void *yyscan_t;
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib.h>
+
+#include "expression.h"
+#include "record.h"
+#include "records/item.h"
+#include "records/list.h"
+#include "records/value.h"
+
+}
+
+%union {
+
+    resolved_value_t value;                 /* Valeur portée               */
+
+    unsigned long long unsigned_integer;    /* Valeur entière #1           */
+    signed long long signed_integer;        /* Valeur entière #2           */
+    double floating_number;                 /* Valeur à virgule flottante  */
+    sized_string_t sized_cstring;           /* Chaîne de caractères        */
+    char byte;                              /* Octet unique                */
+
+}
+
+
+/**
+ * Cf.
+ * http://stackoverflow.com/questions/34418381/how-to-reference-lex-or-parse-parameters-in-flex-rules/34420950
+ */
+
+%define api.pure full
+
+%parse-param { yyscan_t yyscanner } { const kaitai_scope_t *locals } { resolved_value_t *resolved }
+%lex-param { yyscan_t yyscanner }
+
+%code provides {
+
+#define YY_DECL \
+    int kaitai_lex(YYSTYPE *yylval_param, yyscan_t yyscanner)
+
+YY_DECL;
+
+
+
+#define SET_ERR(out)    \
+    out.type = GVT_ERROR
+
+#define EXIT_WITH_ERR(out, lbl)                 \
+    do                                          \
+    {                                           \
+        SET_ERR(out);                           \
+        goto exit_ ## lbl;                      \
+    }                                           \
+    while (0)
+
+#define CHECK_TYPE(arg, tp, out, lbl)               \
+    if (arg.type != tp) EXIT_WITH_ERR(out, lbl)
+
+#define CHECK_TYPES(arg, tp1, tp2, out, lbl)        \
+    if (arg.type != tp1 && arg.type != tp2) EXIT_WITH_ERR(out, lbl)
+
+#define REDUCE_EXPR(arg, out, lbl)                  \
+    if (!reduce_resolved_kaitai_expression(&arg))   \
+        EXIT_WITH_ERR(out, lbl)
+
+#define REDUCE_NUMERIC_EXPR(arg, out, lbl)                          \
+    if (!reduce_resolved_kaitai_expression(&arg))                   \
+        EXIT_WITH_ERR(out, lbl);                                    \
+    if (arg.type == GVT_SIGNED_INTEGER && arg.signed_integer >= 0)  \
+    {                                                               \
+        arg.unsigned_integer = arg.signed_integer;                  \
+        arg.type = GVT_UNSIGNED_INTEGER;                            \
+    }
+
+
+#define ARITHMETIC_ADD_CODE(op1, op2, out, lbl)                                         \
+    switch (op1.type)                                                                   \
+    {                                                                                   \
+        case GVT_UNSIGNED_INTEGER:                                                      \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                       \
+            {                                                                           \
+                out.unsigned_integer = op1.unsigned_integer + op2.unsigned_integer;     \
+                out.type = GVT_UNSIGNED_INTEGER;                                        \
+            }                                                                           \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                    \
+            {                                                                           \
+                if (op1.unsigned_integer < -op2.signed_integer)                         \
+                {                                                                       \
+                    out.signed_integer = op1.unsigned_integer + op2.signed_integer;     \
+                    out.type = GVT_SIGNED_INTEGER;                                      \
+                }                                                                       \
+                else                                                                    \
+                {                                                                       \
+                    out.unsigned_integer = op1.unsigned_integer + op2.signed_integer;   \
+                    out.type = GVT_UNSIGNED_INTEGER;                                    \
+                }                                                                       \
+            }                                                                           \
+            else if (op2.type == GVT_FLOAT)                                             \
+            {                                                                           \
+                out.floating_number = op1.unsigned_integer + op2.floating_number;       \
+                out.type = GVT_FLOAT;                                                   \
+            }                                                                           \
+            else EXIT_WITH_ERR(out, lbl);                                               \
+            break;                                                                      \
+                                                                                        \
+        case GVT_SIGNED_INTEGER:                                                        \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                       \
+            {                                                                           \
+                if (-op1.signed_integer > op2.unsigned_integer)                         \
+                {                                                                       \
+                    out.signed_integer = op1.signed_integer + op2.unsigned_integer;     \
+                    out.type = GVT_SIGNED_INTEGER;                                      \
+                }                                                                       \
+                else                                                                    \
+                {                                                                       \
+                    out.unsigned_integer = op1.signed_integer + op2.unsigned_integer;   \
+                    out.type = GVT_UNSIGNED_INTEGER;                                    \
+                }                                                                       \
+            }                                                                           \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                    \
+            {                                                                           \
+                out.signed_integer = op1.signed_integer + op2.signed_integer;           \
+                out.type = GVT_SIGNED_INTEGER;                                          \
+            }                                                                           \
+            else if (op2.type == GVT_FLOAT)                                             \
+            {                                                                           \
+                out.floating_number = op1.signed_integer + op2.floating_number;         \
+                out.type = GVT_FLOAT;                                                   \
+            }                                                                           \
+            else EXIT_WITH_ERR(out, lbl);                                               \
+            break;                                                                      \
+                                                                                        \
+        case GVT_FLOAT:                                                                 \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                       \
+            {                                                                           \
+                out.floating_number = op1.floating_number + op2.unsigned_integer;       \
+                out.type = GVT_FLOAT;                                                   \
+            }                                                                           \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                    \
+            {                                                                           \
+                out.floating_number = op1.floating_number + op2.signed_integer;         \
+                out.type = GVT_FLOAT;                                                   \
+            }                                                                           \
+            else if (op2.type == GVT_FLOAT)                                             \
+            {                                                                           \
+                out.floating_number = op1.floating_number + op2.floating_number;        \
+                out.type = GVT_FLOAT;                                                   \
+            }                                                                           \
+            else EXIT_WITH_ERR(out, lbl);                                               \
+            break;                                                                      \
+                                                                                        \
+        default:                                                                        \
+            EXIT_WITH_ERR(out, lbl);                                                    \
+            break;                                                                      \
+                                                                                        \
+    }
+
+
+#define ARITHMETIC_SUB_CODE(op1, op2, out, lbl)                                         \
+    switch (op1.type)                                                                   \
+    {                                                                                   \
+        case GVT_UNSIGNED_INTEGER:                                                      \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                       \
+            {                                                                           \
+                if (op1.unsigned_integer < op2.unsigned_integer)                        \
+                {                                                                       \
+                    out.signed_integer = op1.unsigned_integer - op2.unsigned_integer;   \
+                    out.type = GVT_SIGNED_INTEGER;                                      \
+                }                                                                       \
+                else                                                                    \
+                {                                                                       \
+                    out.unsigned_integer = op1.unsigned_integer - op2.unsigned_integer; \
+                    out.type = GVT_UNSIGNED_INTEGER;                                    \
+                }                                                                       \
+            }                                                                           \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                    \
+            {                                                                           \
+                out.unsigned_integer = op1.unsigned_integer - op2.signed_integer;       \
+                out.type = GVT_UNSIGNED_INTEGER;                                        \
+            }                                                                           \
+            else if (op2.type == GVT_FLOAT)                                             \
+            {                                                                           \
+                out.floating_number = op1.unsigned_integer - op2.floating_number;       \
+                out.type = GVT_FLOAT;                                                   \
+            }                                                                           \
+            else EXIT_WITH_ERR(out, lbl);                                               \
+            break;                                                                      \
+                                                                                        \
+        case GVT_SIGNED_INTEGER:                                                        \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                       \
+            {                                                                           \
+                out.signed_integer = op1.signed_integer - op2.unsigned_integer;         \
+                out.type = GVT_SIGNED_INTEGER;                                          \
+            }                                                                           \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                    \
+            {                                                                           \
+                if (op1.signed_integer < op2.signed_integer)                            \
+                {                                                                       \
+                    out.signed_integer = op1.signed_integer - op2.signed_integer;       \
+                    out.type = GVT_SIGNED_INTEGER;                                      \
+                }                                                                       \
+                else                                                                    \
+                {                                                                       \
+                    out.unsigned_integer = op1.signed_integer - op2.signed_integer;     \
+                    out.type = GVT_UNSIGNED_INTEGER;                                    \
+                }                                                                       \
+            }                                                                           \
+            else if (op2.type == GVT_FLOAT)                                             \
+            {                                                                           \
+                out.floating_number = op1.signed_integer - op2.floating_number;         \
+                out.type = GVT_FLOAT;                                                   \
+            }                                                                           \
+            else EXIT_WITH_ERR(out, lbl);                                               \
+            break;                                                                      \
+                                                                                        \
+        case GVT_FLOAT:                                                                 \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                       \
+            {                                                                           \
+                out.floating_number = op1.floating_number - op2.unsigned_integer;       \
+                out.type = GVT_FLOAT;                                                   \
+            }                                                                           \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                    \
+            {                                                                           \
+                out.floating_number = op1.floating_number - op2.signed_integer;         \
+                out.type = GVT_FLOAT;                                                   \
+            }                                                                           \
+            else if (op2.type == GVT_FLOAT)                                             \
+            {                                                                           \
+                out.floating_number = op1.floating_number - op2.floating_number;        \
+                out.type = GVT_FLOAT;                                                   \
+            }                                                                           \
+            else EXIT_WITH_ERR(out, lbl);                                               \
+            break;                                                                      \
+                                                                                        \
+        default:                                                                        \
+            EXIT_WITH_ERR(out, lbl);                                                    \
+            break;                                                                      \
+                                                                                        \
+    }
+
+
+#define ARITHMETIC_GENOP_CODE(op1, op2, _meth_, out, lbl)                                   \
+    switch (op1.type)                                                                       \
+    {                                                                                       \
+        case GVT_UNSIGNED_INTEGER:                                                          \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                           \
+            {                                                                               \
+                out.unsigned_integer = op1.unsigned_integer _meth_ op2.unsigned_integer;    \
+                out.type = GVT_UNSIGNED_INTEGER;                                            \
+            }                                                                               \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                        \
+            {                                                                               \
+                out.signed_integer = op1.unsigned_integer _meth_ op2.signed_integer;        \
+                out.type = GVT_SIGNED_INTEGER;                                              \
+            }                                                                               \
+            else if (op2.type == GVT_FLOAT)                                                 \
+            {                                                                               \
+                out.floating_number = op1.unsigned_integer _meth_ op2.floating_number;      \
+                out.type = GVT_FLOAT;                                                       \
+            }                                                                               \
+            else EXIT_WITH_ERR(out, lbl);                                                   \
+            break;                                                                          \
+                                                                                            \
+        case GVT_SIGNED_INTEGER:                                                            \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                           \
+            {                                                                               \
+                out.unsigned_integer = op1.signed_integer _meth_ op2.unsigned_integer;      \
+                out.type = GVT_SIGNED_INTEGER;                                              \
+            }                                                                               \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                        \
+            {                                                                               \
+                out.unsigned_integer = op1.signed_integer _meth_ op2.signed_integer;        \
+                out.type = GVT_UNSIGNED_INTEGER;                                            \
+            }                                                                               \
+            else if (op2.type == GVT_FLOAT)                                                 \
+            {                                                                               \
+                out.floating_number = op1.signed_integer _meth_ op2.floating_number;        \
+                out.type = GVT_FLOAT;                                                       \
+            }                                                                               \
+            else EXIT_WITH_ERR(out, lbl);                                                   \
+            break;                                                                          \
+                                                                                            \
+        case GVT_FLOAT:                                                                     \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                           \
+            {                                                                               \
+                out.unsigned_integer = op1.floating_number _meth_ op2.unsigned_integer;     \
+                out.type = GVT_FLOAT;                                                       \
+            }                                                                               \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                        \
+            {                                                                               \
+                out.signed_integer = op1.floating_number _meth_ op2.signed_integer;         \
+                out.type = GVT_FLOAT;                                                       \
+            }                                                                               \
+            else if (op2.type == GVT_FLOAT)                                                 \
+            {                                                                               \
+                out.floating_number = op1.floating_number _meth_ op2.floating_number;       \
+                out.type = GVT_FLOAT;                                                       \
+            }                                                                               \
+            else EXIT_WITH_ERR(out, lbl);                                                   \
+            break;                                                                          \
+                                                                                            \
+        default:                                                                            \
+            EXIT_WITH_ERR(out, lbl);                                                        \
+            break;                                                                          \
+                                                                                            \
+    }
+
+
+/**
+ * Cf. https://stackoverflow.com/questions/11720656/modulo-operation-with-negative-numbers/52529440#52529440
+ */
+#define EUCLIDEAN_MODULO(a, b, r)       \
+    r = a % (signed long long)b;        \
+    if (r < 0)                          \
+        r = (b < 0) ? r - b : r + b;    \
+
+
+#define ARITHMETIC_MOD_CODE(op1, op2, out, lbl)                                                     \
+    switch (op1.type)                                                                               \
+    {                                                                                               \
+        case GVT_UNSIGNED_INTEGER:                                                                  \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                                   \
+            {                                                                                       \
+                EUCLIDEAN_MODULO(op1.unsigned_integer, op2.unsigned_integer, out.unsigned_integer); \
+                out.type = GVT_UNSIGNED_INTEGER;                                                    \
+            }                                                                                       \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                                \
+            {                                                                                       \
+                EUCLIDEAN_MODULO(op1.unsigned_integer, op2.signed_integer, out.signed_integer);     \
+                out.type = GVT_SIGNED_INTEGER;                                                      \
+            }                                                                                       \
+            else EXIT_WITH_ERR(out, lbl);                                                           \
+            break;                                                                                  \
+                                                                                                    \
+        case GVT_SIGNED_INTEGER:                                                                    \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                                   \
+            {                                                                                       \
+                EUCLIDEAN_MODULO(op1.signed_integer, op2.unsigned_integer, out.signed_integer);     \
+                out.type = GVT_SIGNED_INTEGER;                                                      \
+            }                                                                                       \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                                \
+            {                                                                                       \
+                EUCLIDEAN_MODULO(op1.signed_integer, op2.signed_integer, out.signed_integer);       \
+                out.type = GVT_SIGNED_INTEGER;                                                      \
+            }                                                                                       \
+            else EXIT_WITH_ERR(out, lbl);                                                           \
+            break;                                                                                  \
+                                                                                                    \
+        default:                                                                                    \
+            EXIT_WITH_ERR(out, lbl);                                                                \
+            break;                                                                                  \
+                                                                                                    \
+    }
+
+
+#define RELATIONAL_CODE(op1, op2, _meth_, out, lbl)                                 \
+    switch (op1.type)                                                               \
+    {                                                                               \
+        case GVT_UNSIGNED_INTEGER:                                                  \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                   \
+            {                                                                       \
+                out.status = (op1.unsigned_integer _meth_ op2.unsigned_integer);    \
+                out.type = GVT_BOOLEAN;                                             \
+            }                                                                       \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                \
+            {                                                                       \
+                out.status = (op1.unsigned_integer _meth_ op2.signed_integer);      \
+                out.type = GVT_BOOLEAN;                                             \
+            }                                                                       \
+            else EXIT_WITH_ERR(out, lbl);                                           \
+            break;                                                                  \
+                                                                                    \
+        case GVT_SIGNED_INTEGER:                                                    \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                   \
+            {                                                                       \
+                out.status = (op1.signed_integer _meth_ op2.unsigned_integer);      \
+                out.type = GVT_BOOLEAN;                                             \
+            }                                                                       \
+            else if (op2.type == GVT_SIGNED_INTEGER)                                \
+            {                                                                       \
+                out.status = (op1.signed_integer _meth_ op2.signed_integer);        \
+                out.type = GVT_BOOLEAN;                                             \
+            }                                                                       \
+            else EXIT_WITH_ERR(out, lbl);                                           \
+            break;                                                                  \
+                                                                                    \
+        case GVT_BYTES:                                                             \
+            if (op2.type == GVT_BYTES)                                              \
+            {                                                                       \
+                int __ret;                                                          \
+                __ret = szmemcmp(&op1.bytes, &op2.bytes);                           \
+                out.status = (__ret _meth_ 0);                                      \
+                out.type = GVT_BOOLEAN;                                             \
+            }                                                                       \
+            else if (op2.type == GVT_ARRAY)                                         \
+            {                                                                       \
+                sized_string_t __abytes_2;                                          \
+                int __ret;                                                          \
+                if (!g_kaitai_array_convert_to_bytes(op2.array, &__abytes_2))       \
+                    EXIT_WITH_ERR(out, lbl);                                        \
+                __ret = szmemcmp(&op1.bytes, &__abytes_2);                          \
+                exit_szstr(&__abytes_2);                                            \
+                out.status = (__ret _meth_ 0);                                      \
+                out.type = GVT_BOOLEAN;                                             \
+            }                                                                       \
+            else EXIT_WITH_ERR(out, lbl);                                           \
+            break;                                                                  \
+                                                                                    \
+        case GVT_ARRAY:                                                             \
+            if (op2.type == GVT_BYTES)                                              \
+            {                                                                       \
+                sized_string_t __abytes_1;                                          \
+                int __ret;                                                          \
+                if (!g_kaitai_array_convert_to_bytes(op1.array, &__abytes_1))       \
+                    EXIT_WITH_ERR(out, lbl);                                        \
+                __ret = szmemcmp(&__abytes_1, &op2.bytes);                          \
+                exit_szstr(&__abytes_1);                                            \
+                out.status = (__ret _meth_ 0);                                      \
+                out.type = GVT_BOOLEAN;                                             \
+            }                                                                       \
+            else if (op2.type == GVT_ARRAY)                                         \
+            {                                                                       \
+                sized_string_t __abytes_1;                                          \
+                sized_string_t __abytes_2;                                          \
+                int __ret;                                                          \
+                if (!g_kaitai_array_convert_to_bytes(op1.array, &__abytes_1))       \
+                    EXIT_WITH_ERR(out, lbl);                                        \
+                if (!g_kaitai_array_convert_to_bytes(op2.array, &__abytes_2))       \
+                {                                                                   \
+                    exit_szstr(&__abytes_1);                                        \
+                    EXIT_WITH_ERR(out, lbl);                                        \
+                }                                                                   \
+                __ret = szmemcmp(&__abytes_1, &__abytes_2);                         \
+                exit_szstr(&__abytes_1);                                            \
+                exit_szstr(&__abytes_2);                                            \
+                out.status = (__ret _meth_ 0);                                      \
+                out.type = GVT_BOOLEAN;                                             \
+            }                                                                       \
+            else EXIT_WITH_ERR(out, lbl);                                           \
+            break;                                                                  \
+                                                                                    \
+        case GVT_STREAM:                                                            \
+            if (op2.type == GVT_STREAM)                                             \
+            {                                                                       \
+                GBinContent *__cnt_1;                                               \
+                GBinContent *__cnt_2;                                               \
+                __cnt_1 = g_kaitai_stream_get_content(op1.stream);                  \
+                __cnt_2 = g_kaitai_stream_get_content(op2.stream);                  \
+                out.status = (__cnt_1 _meth_ __cnt_2);                              \
+                out.type = GVT_BOOLEAN;                                             \
+                g_object_unref(G_OBJECT(__cnt_1));                                  \
+                g_object_unref(G_OBJECT(__cnt_2));                                  \
+            }                                                                       \
+            else EXIT_WITH_ERR(out, lbl);                                           \
+            break;                                                                  \
+                                                                                    \
+        default:                                                                    \
+            EXIT_WITH_ERR(out, lbl);                                                \
+            break;                                                                  \
+                                                                                    \
+    }
+
+
+#define BITWISE_CODE(op1, op2, _meth_, out, lbl)                                            \
+    switch (op1.type)                                                                       \
+    {                                                                                       \
+        case GVT_UNSIGNED_INTEGER:                                                          \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                           \
+            {                                                                               \
+                out.unsigned_integer = (op1.unsigned_integer _meth_ op2.unsigned_integer);  \
+                out.type = GVT_UNSIGNED_INTEGER;                                            \
+            }                                                                               \
+            else EXIT_WITH_ERR(out, lbl);                                                   \
+            break;                                                                          \
+                                                                                            \
+        case GVT_SIGNED_INTEGER:                                                            \
+            if (op2.type == GVT_UNSIGNED_INTEGER)                                           \
+            {                                                                               \
+                out.signed_integer = (op1.signed_integer _meth_ op2.unsigned_integer);      \
+                out.type = GVT_SIGNED_INTEGER;                                              \
+            }                                                                               \
+            else EXIT_WITH_ERR(out, lbl);                                                   \
+            break;                                                                          \
+                                                                                            \
+        default:                                                                            \
+            EXIT_WITH_ERR(out, lbl);                                                        \
+            break;                                                                          \
+                                                                                            \
+    }
+
+
+
+
+}
+
+
+%token <unsigned_integer> UNSIGNED_INTEGER
+%token <signed_integer> SIGNED_INTEGER
+%token <floating_number> FLOAT
+
+%token <sized_cstring> IDENTIFIER
+%token <sized_cstring> RAW_BYTES
+%token <byte> RAW_BYTE
+%token <sized_cstring> RAW_BYTES_WITH_ENDING_DOT
+%token <sized_cstring> PLAIN_BYTES
+
+%token <sized_cstring> ENCODING_NAME
+
+
+%token PLUS             "+"
+%token MINUS            "-"
+%token MUL              "*"
+%token DIV              "/"
+%token MOD              "%"
+
+%token LT               "<"
+%token LE               "<="
+%token EQ               "=="
+%token NE               "!="
+%token GT               ">"
+%token GE               ">="
+
+%token SHIFT_LEFT       "<<"
+%token SHIFT_RIGHT      ">>"
+%token BIT_AND          "&"
+%token BIT_OR           "|"
+%token BIT_XOR          "^"
+
+%token NOT              "not"
+%token AND              "and"
+%token OR               "or"
+
+%token PAREN_O          "("
+%token PAREN_C          ")"
+%token HOOK_O           "["
+%token HOOK_C           "]"
+%token COMMA            ","
+%token DOT              "."
+
+%token QMARK            "?"
+%token COLON            ":"
+%token DOUBLE_COLON     "::"
+
+%token METH_SIZE        ".size"
+%token METH_LENGTH      ".length"
+%token METH_REVERSE     ".reverse"
+%token METH_SUBSTRING   ".substring"
+%token METH_TO_I        ".to_i"
+%token METH_TO_I_RAD    ".to_i("
+%token METH_TO_S        ".to_s"
+%token METH_TO_S_ENC    ".to_s("
+
+%token ROOT             "_root"
+%token PARENT           "_parent"
+%token LAST             "_"
+%token METH_IO          "._io"
+
+%token TRUE_CONST       "true"
+%token FALSE_CONST      "false"
+
+
+                                  //%type <value> operand
+%type <value> any_expr
+                                  //%type <value> arithm_expr
+                                  //%type <value> arithm_op
+
+%type <value> boolean
+
+
+
+%type <value> arithmetic_expr
+%type <value> relational_expr
+%type <value> logical_expr
+%type <value> bitwise_expr
+%type <value> ternary_expr
+
+%type <value> convert_2_bytes
+%type <value> convert_2_integer
+
+
+%type <value> integer
+
+%type <value> float
+
+%type <value> bytes
+
+%type <value> bytes_concat
+%type <value> raw_bytes
+
+
+%type <value> array
+%type <value> array_items
+
+
+%type <value> field
+%type <value> enumeration
+%type <value> stream
+
+
+
+%destructor { printf("----------------------freeing %p...\n", &$$), fflush(NULL); } <*>
+
+
+                                  //%type <integer> INTEGER
+                                  //
+
+                                  //%type <integer> arithm_expr
+                                  //%type <integer> arithm_op
+
+                                  //%type <boolean> bool_expr
+                                  //%type <boolean> relational_op logical_op ternary_op
+
+
+                                  //%type <integer> constant
+
+
+
+
+
+/**
+ * Cf. https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
+ */
+
+
+
+
+
+%left "?" ":"
+
+%left OR
+%left "and"
+
+/* 13 */
+%left "|"
+
+/* 12 */
+%left "^"
+
+/* 11 */
+%left "&"
+
+%left LT LE EQ NE GT GE
+
+/* 7 */
+%left "<<" ">>"
+
+
+%right NOT
+
+%left PLUS MINUS
+%left "*"
+%left DIV MOD
+
+
+%left "["
+
+
+
+
+%left ".size"
+%left ".length"
+%left ".reverse"
+%left ".substring"
+%left ".to_i"
+%left ".to_i("
+%left ".to_s"
+%left ".to_s("
+
+%left "._io"
+
+%left "."
+
+/* 1 */
+%right "::"
+
+
+%%
+
+        expressions : any_expr { *resolved = $1; }
+                    ;
+
+           any_expr : boolean           { $$ = $1; }
+                    | bytes             { $$ = $1; }
+                    | integer           { $$ = $1; }
+                    | float             { $$ = $1; }
+                    | array             { $$ = $1; }
+                    | field             { $$ = $1; }
+                    | enumeration       { $$ = $1; }
+                    | stream            { $$ = $1; }
+                    | arithmetic_expr   { $$ = $1; }
+                    | relational_expr   { $$ = $1; }
+                    | logical_expr      { $$ = $1; }
+                    | bitwise_expr      { $$ = $1; }
+                    | ternary_expr      { $$ = $1; }
+                    | convert_2_bytes   { $$ = $1; }
+                    | convert_2_integer { $$ = $1; }
+                    | "(" any_expr ")"  { $$ = $2; }
+                    ;
+
+
+/* Expressions impliquants formules et opérandes */
+
+    arithmetic_expr : any_expr "+" any_expr
+                    {
+                        REDUCE_NUMERIC_EXPR($1, $$, arithmetic_expr_plus);
+                        REDUCE_NUMERIC_EXPR($3, $$, arithmetic_expr_plus);
+
+                        if ($1.type == GVT_BYTES && $3.type == GVT_BYTES)
+                        {
+                            $$.bytes.len = $1.bytes.len + $3.bytes.len;
+                            $$.bytes.data = malloc($$.bytes.len);
+
+                            memcpy($$.bytes.data, $1.bytes.data, $1.bytes.len);
+                            memcpy($$.bytes.data + $1.bytes.len, $3.bytes.data, $3.bytes.len);
+
+                            $$.type = GVT_BYTES;
+
+                        }
+
+                        else if ($1.type == GVT_BYTES && $3.type == GVT_ARRAY)
+                        {
+                            sized_string_t __abytes_2;
+
+                            if (!g_kaitai_array_convert_to_bytes($3.array, &__abytes_2))
+                                EXIT_WITH_ERR($$, arithmetic_expr_plus);
+
+                            $$.bytes.len = $1.bytes.len + __abytes_2.len;
+                            $$.bytes.data = malloc($$.bytes.len);
+
+                            memcpy($$.bytes.data, $1.bytes.data, $1.bytes.len);
+                            memcpy($$.bytes.data + $1.bytes.len, __abytes_2.data, __abytes_2.len);
+
+                            $$.type = GVT_BYTES;
+
+                            exit_szstr(&__abytes_2);
+
+                        }
+
+                        else
+                        {
+                            ARITHMETIC_ADD_CODE($1, $3, $$, arithmetic_expr_plus);
+                        }
+
+                    exit_arithmetic_expr_plus:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "-" any_expr
+                    {
+                        REDUCE_NUMERIC_EXPR($1, $$, arithmetic_expr_minus);
+                        REDUCE_NUMERIC_EXPR($3, $$, arithmetic_expr_minus);
+                        ARITHMETIC_SUB_CODE($1, $3, $$, arithmetic_expr_minus);
+                    exit_arithmetic_expr_minus:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "*" any_expr
+                    {
+                        REDUCE_NUMERIC_EXPR($1, $$, arithmetic_expr_mul);
+                        REDUCE_NUMERIC_EXPR($3, $$, arithmetic_expr_mul);
+                        ARITHMETIC_GENOP_CODE($1, $3, *, $$, arithmetic_expr_mul);
+                    exit_arithmetic_expr_mul:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "/" any_expr
+                    {
+                        REDUCE_NUMERIC_EXPR($1, $$, arithmetic_expr_div);
+                        REDUCE_NUMERIC_EXPR($3, $$, arithmetic_expr_div);
+                        ARITHMETIC_GENOP_CODE($1, $3, /, $$, arithmetic_expr_div);
+                    exit_arithmetic_expr_div:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "%" any_expr
+                    {
+                        REDUCE_NUMERIC_EXPR($1, $$, arithmetic_expr_mod);
+                        REDUCE_NUMERIC_EXPR($3, $$, arithmetic_expr_mod);
+                        ARITHMETIC_MOD_CODE($1, $3, $$, arithmetic_expr_mod);
+                    exit_arithmetic_expr_mod:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    ;
+
+
+    relational_expr : any_expr "<" any_expr
+                    {
+                        REDUCE_EXPR($1, $$, relational_expr_lt);
+                        REDUCE_EXPR($3, $$, relational_expr_lt);
+                        RELATIONAL_CODE($1, $3, <, $$, relational_expr_lt);
+                    exit_relational_expr_lt:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "<=" any_expr
+                    {
+                        REDUCE_EXPR($1, $$, relational_expr_le);
+                        REDUCE_EXPR($3, $$, relational_expr_le);
+                        RELATIONAL_CODE($1, $3, <=, $$, relational_expr_le);
+                    exit_relational_expr_le:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "==" any_expr
+                    {
+                        REDUCE_EXPR($1, $$, relational_expr_eq);
+                        REDUCE_EXPR($3, $$, relational_expr_eq);
+                        RELATIONAL_CODE($1, $3, ==, $$, relational_expr_eq);
+                    exit_relational_expr_eq:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "!=" any_expr
+                    {
+                        REDUCE_EXPR($1, $$, relational_expr_ne);
+                        REDUCE_EXPR($3, $$, relational_expr_ne);
+                        RELATIONAL_CODE($1, $3, !=, $$, relational_expr_ne);
+                    exit_relational_expr_ne:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr ">" any_expr
+                    {
+                        REDUCE_EXPR($1, $$, relational_expr_gt);
+                        REDUCE_EXPR($3, $$, relational_expr_gt);
+                        RELATIONAL_CODE($1, $3, >, $$, relational_expr_gt);
+                    exit_relational_expr_gt:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr ">=" any_expr
+                    {
+                        REDUCE_EXPR($1, $$, relational_expr_ge);
+                        REDUCE_EXPR($3, $$, relational_expr_ge);
+                        RELATIONAL_CODE($1, $3, >=, $$, relational_expr_ge);
+                    exit_relational_expr_ge:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    ;
+
+
+       bitwise_expr : any_expr "<<" any_expr
+                    {
+                        REDUCE_NUMERIC_EXPR($1, $$, bitwise_expr_shift_left);
+                        REDUCE_NUMERIC_EXPR($3, $$, bitwise_expr_shift_left);
+                        BITWISE_CODE($1, $3, <<, $$, bitwise_expr_shift_left);
+                    exit_bitwise_expr_shift_left:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr ">>" any_expr
+                    {
+                        REDUCE_NUMERIC_EXPR($1, $$, bitwise_expr_shift_right);
+                        REDUCE_NUMERIC_EXPR($3, $$, bitwise_expr_shift_right);
+                        BITWISE_CODE($1, $3, >>, $$, bitwise_expr_shift_right);
+                    exit_bitwise_expr_shift_right:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "&" any_expr
+                    {
+                        REDUCE_NUMERIC_EXPR($1, $$, bitwise_expr_and);
+                        REDUCE_NUMERIC_EXPR($3, $$, bitwise_expr_and);
+                        BITWISE_CODE($1, $3, &, $$, bitwise_expr_and);
+                    exit_bitwise_expr_and:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "|" any_expr
+                    {
+                        REDUCE_NUMERIC_EXPR($1, $$, bitwise_expr_or);
+                        REDUCE_NUMERIC_EXPR($3, $$, bitwise_expr_or);
+                        BITWISE_CODE($1, $3, |, $$, bitwise_expr_or);
+                    exit_bitwise_expr_or:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "^" any_expr
+                    {
+                        REDUCE_NUMERIC_EXPR($1, $$, bitwise_expr_xor);
+                        REDUCE_NUMERIC_EXPR($3, $$, bitwise_expr_xor);
+                        BITWISE_CODE($1, $3, ^, $$, bitwise_expr_xor);
+                    exit_bitwise_expr_xor:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    ;
+
+
+       logical_expr : "not" any_expr
+                    {
+                        REDUCE_EXPR($2, $$, logical_expr_not);
+                        CHECK_TYPE($2, GVT_BOOLEAN, $$, logical_expr_not);
+                        $$.status = !$2.status;
+                        $$.type = GVT_BOOLEAN;
+                    exit_logical_expr_not:
+                        EXIT_RESOLVED_VALUE($2);
+                    }
+                    | any_expr "and" any_expr
+                    {
+                        REDUCE_EXPR($1, $$, logical_expr_and);
+                        CHECK_TYPE($1, GVT_BOOLEAN, $$, logical_expr_and);
+                        REDUCE_EXPR($3, $$, logical_expr_and);
+                        CHECK_TYPE($3, GVT_BOOLEAN, $$, logical_expr_and);
+                        $$.status = $1.status && $3.status;
+                        $$.type = GVT_BOOLEAN;
+                    exit_logical_expr_and:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    | any_expr "or" any_expr
+                    {
+                        REDUCE_EXPR($1, $$, logical_expr_or);
+                        CHECK_TYPE($1, GVT_BOOLEAN, $$, logical_expr_or);
+                        REDUCE_EXPR($3, $$, logical_expr_or);
+                        CHECK_TYPE($3, GVT_BOOLEAN, $$, logical_expr_or);
+                        $$.status = $1.status || $3.status;
+                        $$.type = GVT_BOOLEAN;
+                    exit_logical_expr_or:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    ;
+
+
+       ternary_expr : any_expr "?" any_expr ":" any_expr
+                    {
+                        REDUCE_EXPR($1, $$, ternary_expr);
+                        CHECK_TYPE($1, GVT_BOOLEAN, $$, ternary_expr);
+                        if ($1.status)
+                            COPY_RESOLVED_VALUE($$, $3);
+                        else
+                            COPY_RESOLVED_VALUE($$, $5);
+                    exit_ternary_expr:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                        EXIT_RESOLVED_VALUE($5);
+                    }
+                    ;
+
+
+/* Conversions et méthodes particulières de types */
+
+    convert_2_bytes : any_expr ".to_s"
+                    {
+                        int __ret;
+
+                        if ($1.type == GVT_UNSIGNED_INTEGER)
+                        {
+                            __ret = asprintf(&$$.bytes.data, "%llu", $1.unsigned_integer);
+                            if (__ret == -1) EXIT_WITH_ERR($$, convert_2_bytes_to_s);
+
+                            $$.bytes.len = __ret;
+                            $$.type = GVT_BYTES;
+
+                        }
+                        else if ($1.type == GVT_SIGNED_INTEGER)
+                        {
+                            __ret = asprintf(&$$.bytes.data, "%lld", $1.signed_integer);
+                            if (__ret == -1) EXIT_WITH_ERR($$, convert_2_bytes_to_s);
+
+                            $$.bytes.len = __ret;
+                            $$.type = GVT_BYTES;
+
+                        }
+                        else
+                            EXIT_WITH_ERR($$, convert_2_bytes_to_s);
+
+                    exit_convert_2_bytes_to_s:
+                        EXIT_RESOLVED_VALUE($1);
+                    }
+                    | any_expr ".to_s(" ENCODING_NAME ")"
+                    {
+                        /**
+                         * Cf. https://fossies.org/linux/libiconv/man/iconv_open.3.html
+                         */
+
+                        char *__fromcode;
+                        gsize __bytes_read;
+                        gsize __bytes_written;
+
+                        if ($1.type != GVT_BYTES)
+                            EXIT_WITH_ERR($$, convert_2_bytes_to_s_encoding);
+
+                        __fromcode = strndup($3.data, $3.len);
+
+                        $$.bytes.data = g_convert($1.bytes.data, $1.bytes.len,
+                                                  __fromcode, "", &__bytes_read, &__bytes_written, NULL);
+
+                        free(__fromcode);
+
+                        if (__bytes_read != $1.bytes.len)
+                            EXIT_WITH_ERR($$, convert_2_bytes_to_s_encoding);
+
+                        $$.bytes.len = __bytes_written;
+                        $$.type = GVT_BYTES;
+
+                    exit_convert_2_bytes_to_s_encoding:
+                        EXIT_RESOLVED_VALUE($1);
+                    }
+                    ;
+
+
+  convert_2_integer : any_expr ".length"
+                    {
+                        if ($1.type != GVT_BYTES)
+                            EXIT_WITH_ERR($$, convert_2_integer_to_s);
+
+                        $$.unsigned_integer = $1.bytes.len;
+                        $$.type = GVT_UNSIGNED_INTEGER;
+
+                    exit_convert_2_integer_to_s:
+                        EXIT_RESOLVED_VALUE($1);
+                    }
+                    | any_expr ".to_i"
+                    {
+                        char *__n;
+                        char *__end;
+
+                        if ($1.type == GVT_FLOAT)
+                        {
+                            if ($1.floating_number < 0)
+                            {
+                                $$.signed_integer = $1.floating_number;
+                                $$.type = GVT_SIGNED_INTEGER;
+                            }
+                            else
+                            {
+                                $$.unsigned_integer = $1.floating_number;
+                                $$.type = GVT_UNSIGNED_INTEGER;
+                            }
+
+                        }
+
+                        else if ($1.type == GVT_BOOLEAN)
+                        {
+                            $$.unsigned_integer = $1.status ? 1 : 0;
+                            $$.type = GVT_UNSIGNED_INTEGER;
+                        }
+
+                        else if ($1.type == GVT_BYTES)
+                        {
+                            if ($1.bytes.len == 0)
+                                EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+                            __n = malloc($1.bytes.len + 1);
+                            memcpy(__n, $1.bytes.data, $1.bytes.len);
+                            __n[$1.bytes.len] = '\0';
+
+                            if ($1.bytes.data[0] == '-')
+                            {
+                                if ($1.bytes.len == 1)
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+                                $$.signed_integer = strtoll(__n, &__end, 10);
+                                $$.type = GVT_SIGNED_INTEGER;
+
+                                if (errno == EINVAL || errno == ERANGE)
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+                                if (__end != &__n[$1.bytes.len])
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+                            }
+                            else
+                            {
+                                if ($1.bytes.len == 1)
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+                                $$.unsigned_integer = strtoull(__n, &__end, 10);
+                                $$.type = GVT_UNSIGNED_INTEGER;
+
+                                if (errno == EINVAL || errno == ERANGE)
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+                                if (__end != &__n[$1.bytes.len])
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+                            }
+
+                            free(__n);
+
+                        }
+
+                        else EXIT_WITH_ERR($$, convert_2_integer_to_i);
+
+                    exit_convert_2_integer_to_i:
+                        EXIT_RESOLVED_VALUE($1);
+                    }
+                    | any_expr ".to_i(" any_expr ")"
+                    {
+                        int __base;
+                        char *__n;
+                        char *__end;
+
+                        if ($1.type == GVT_BYTES)
+                        {
+                            if ($1.bytes.len == 0)
+                                EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+                            if ($3.type == GVT_UNSIGNED_INTEGER)
+                            {
+                                __base = $3.unsigned_integer;
+                                if (__base < 2)
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+                            }
+                            else if ($3.type == GVT_SIGNED_INTEGER)
+                            {
+                                __base = $3.signed_integer;
+                                if (__base < 2)
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+                            }
+                            else EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+                            __n = malloc($1.bytes.len + 1);
+                            memcpy(__n, $1.bytes.data, $1.bytes.len);
+                            __n[$1.bytes.len] = '\0';
+
+                            if ($1.bytes.data[0] == '-')
+                            {
+                                if ($1.bytes.len == 1)
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+                                $$.signed_integer = strtoll(__n, &__end, __base);
+                                $$.type = GVT_SIGNED_INTEGER;
+
+                                if (errno == EINVAL || errno == ERANGE)
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+                                if (__end != &__n[$1.bytes.len])
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+                            }
+                            else
+                            {
+                                if ($1.bytes.len == 1)
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+                                $$.unsigned_integer = strtoull(__n, &__end, __base);
+                                $$.type = GVT_UNSIGNED_INTEGER;
+
+                                if (errno == EINVAL || errno == ERANGE)
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+                                if (__end != &__n[$1.bytes.len])
+                                    EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+                            }
+
+                            free(__n);
+
+                        }
+
+                        else EXIT_WITH_ERR($$, convert_2_integer_to_i_base);
+
+                    exit_convert_2_integer_to_i_base:
+                        EXIT_RESOLVED_VALUE($1);
+                    }
+                    | any_expr ".size"
+                    {
+                        GRecordList *__list;
+
+                        if ($1.type != GVT_RECORD) EXIT_WITH_ERR($$, convert_2_integer_size);
+                        if (!G_IS_RECORD_LIST($1.record)) EXIT_WITH_ERR($$, convert_2_integer_size);
+
+                        __list = G_RECORD_LIST($1.record);
+
+                        $$.unsigned_integer = g_record_list_count_records(__list);
+                        $$.type = GVT_UNSIGNED_INTEGER;
+
+                    exit_convert_2_integer_size:
+                        EXIT_RESOLVED_VALUE($1);
+                    }
+                    ;
+
+
+/* Types de base */
+
+            boolean : "true"
+                    {
+                        $$.status = true;
+                        $$.type = GVT_BOOLEAN;
+                    }
+                    | "false"
+                    {
+                        $$.status = false;
+                        $$.type = GVT_BOOLEAN;
+                    }
+                    ;
+
+
+            integer : UNSIGNED_INTEGER
+                    {
+                        $$.unsigned_integer = $1;
+                        $$.type = GVT_UNSIGNED_INTEGER;
+                    }
+                    | SIGNED_INTEGER
+                    {
+                        $$.signed_integer = $1;
+                        $$.type = GVT_SIGNED_INTEGER;
+                    }
+                    ;
+
+
+              float : FLOAT
+                    {
+                        $$.floating_number = $1;
+                        $$.type = GVT_FLOAT;
+                    }
+                    ;
+
+
+              bytes : bytes_concat { $$ = $1; }
+                    | PLAIN_BYTES
+                    {
+                        $$.bytes.len = $1.len;
+                        $$.bytes.data = malloc($1.len);
+                        memcpy($$.bytes.data, $1.data, $1.len);
+                        $$.type = GVT_BYTES;
+                    }
+                    | any_expr ".reverse"
+                    {
+                        size_t __i;
+
+                        CHECK_TYPE($1, GVT_BYTES, $$, bytes_reverse);
+
+                        $$.bytes.data = malloc($1.bytes.len);
+                        $$.bytes.len = $1.bytes.len;
+
+                        for (__i = 0; __i < $1.bytes.len; __i++)
+                            $$.bytes.data[__i] = $1.bytes.data[$1.bytes.len - __i - 1];
+
+                        $$.type = GVT_BYTES;
+
+                    exit_bytes_reverse:
+                        EXIT_RESOLVED_VALUE($1);
+                    }
+                    | any_expr ".substring" "(" any_expr "," any_expr ")"
+                    {
+                        unsigned long long __from;
+                        unsigned long long __to;
+
+                        REDUCE_NUMERIC_EXPR($4, $$, bytes_reverse);
+                        CHECK_TYPES($4, GVT_UNSIGNED_INTEGER, GVT_SIGNED_INTEGER, $$, bytes_substring);
+                        REDUCE_NUMERIC_EXPR($6, $$, bytes_reverse);
+                        CHECK_TYPES($6, GVT_UNSIGNED_INTEGER, GVT_SIGNED_INTEGER, $$, bytes_substring);
+
+                        __from = ($4.type == GVT_UNSIGNED_INTEGER ? $4.unsigned_integer : $4.signed_integer);
+                        __to = ($6.type == GVT_UNSIGNED_INTEGER ? $6.unsigned_integer : $6.signed_integer);
+
+                        if (__from > __to) EXIT_WITH_ERR($$, bytes_substring);
+                        if (__to >= $1.bytes.len) EXIT_WITH_ERR($$, bytes_substring);
+
+                        $$.bytes.len = __to - __from + 1;
+                        $$.bytes.data = malloc($$.bytes.len);
+
+                        memcpy($$.bytes.data, &$1.bytes.data[__from], $$.bytes.len);
+
+                        $$.type = GVT_BYTES;
+
+                    exit_bytes_substring:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($4);
+                        EXIT_RESOLVED_VALUE($6);
+                    }
+                    ;
+
+       bytes_concat : raw_bytes { $$ = $1; };
+                    | bytes_concat raw_bytes
+                    {
+                        $$.bytes.len = $1.bytes.len + $2.bytes.len;
+                        $$.bytes.data = malloc($$.bytes.len);
+                        memcpy($$.bytes.data, $1.bytes.data, $1.bytes.len);
+                        memcpy($$.bytes.data + $1.bytes.len, $2.bytes.data, $2.bytes.len);
+                        $$.type = GVT_BYTES;
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($2);
+                    }
+                    ;
+
+          raw_bytes : RAW_BYTES
+                    {
+                        $$.bytes.len = $1.len;
+                        $$.bytes.data = malloc($1.len);
+                        memcpy($$.bytes.data, $1.data, $1.len);
+                        $$.type = GVT_BYTES;
+                    }
+                    | RAW_BYTE
+                    {
+                        $$.bytes.len = 1;
+                        $$.bytes.data = malloc(1);
+                        $$.bytes.data[0] = $1;
+                        $$.type = GVT_BYTES;
+                    }
+                    | RAW_BYTES_WITH_ENDING_DOT
+                    {
+                        $$.bytes.len = $1.len;
+                        $$.bytes.data = malloc($1.len);
+                        memcpy($$.bytes.data, $1.data, $1.len);
+                        $$.type = GVT_BYTES;
+                    }
+                    ;
+
+
+/* Tableau d'éléments variés */
+
+              array : "[" "]"
+                    {
+                        $$.array = g_kaitai_array_new();
+                        $$.type = GVT_ARRAY;
+                    }
+                    | "[" array_items "]"
+                    {
+                        $$ = $2;
+                    }
+                    ;
+
+
+        array_items : any_expr
+                    {
+                        $$.array = g_kaitai_array_new();
+                        $$.type = GVT_ARRAY;
+
+                        g_kaitai_array_append_item($$.array, &$1);
+
+                        EXIT_RESOLVED_VALUE($1);
+
+                    }
+                    | array_items "," any_expr
+                    {
+                        $$ = $1;
+                        g_kaitai_array_append_item($$.array, &$3);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    ;
+
+
+/* Accès aux objets Kaitai manipulés */
+
+              field : IDENTIFIER
+                    {
+                        $$.record = g_match_record_find_by_name(locals->parent,
+                                                                $1.data, $1.len,
+                                                                DIRECT_SEARCH_DEEP_LEVEL);
+
+                        if ($$.record != NULL)
+                            $$.type = GVT_RECORD;
+
+                        /* Si aucune correspondance, le contenu brut est utilisé */
+                        else
+                        {
+                            $$.bytes.len = $1.len;
+                            $$.bytes.data = malloc($1.len);
+                            memcpy($$.bytes.data, $1.data, $1.len);
+                            $$.type = GVT_BYTES;
+                        }
+
+                    }
+                    | "_root"
+                    {
+                        $$.record = get_root_record(locals);
+                        if ($$.record == NULL) SET_ERR($$);
+                        else $$.type = GVT_RECORD;
+                    }
+                    | "_parent"
+                    {
+                        $$.record = get_parent_record(locals);
+                        if ($$.record == NULL) SET_ERR($$);
+                        else $$.type = GVT_RECORD;
+                    }
+                    | "_"
+                    {
+                        $$.record = get_last_record(locals);
+                        if ($$.record == NULL) SET_ERR($$);
+                        else $$.type = GVT_RECORD;
+                    }
+                    | any_expr "." IDENTIFIER
+                    {
+                        if ($1.type != GVT_RECORD)
+                            EXIT_WITH_ERR($$, field_dot);
+
+                        $$.record = g_match_record_find_by_name($1.record,
+                                                                $3.data, $3.len,
+                                                                DIRECT_SEARCH_DEEP_LEVEL);
+
+                        if ($$.record == NULL)
+                            EXIT_WITH_ERR($$, field_dot);
+
+                        $$.type = GVT_RECORD;
+
+                    exit_field_dot:
+                        EXIT_RESOLVED_VALUE($1);
+                    }
+                    | any_expr "[" any_expr "]"
+                    {
+                        size_t __index;
+                        GRecordList *__list;
+                        size_t __count;
+                        GKaitaiArray *__array;
+
+                        /* Indice de l'élément auquel accéder */
+
+                        REDUCE_NUMERIC_EXPR($3, $$, field_indexed);
+
+                        if ($3.type == GVT_UNSIGNED_INTEGER)
+                            __index = $3.unsigned_integer;
+                        else
+                            EXIT_WITH_ERR($$, field_indexed);
+
+                        /* Série à consulter */
+
+                        REDUCE_EXPR($1, $$, field_indexed);
+
+                        if ($1.type == GVT_RECORD && G_IS_RECORD_LIST($1.record))
+                        {
+                            __list = G_RECORD_LIST($1.record);
+                            __count = g_record_list_count_records(__list);
+
+                            if (__index >= __count)
+                                EXIT_WITH_ERR($$, field_indexed);
+
+                            $$.record = g_record_list_get_record(__list, __index);
+
+                            if ($$.record == NULL)
+                                EXIT_WITH_ERR($$, field_indexed);
+
+                            $$.type = GVT_RECORD;
+
+                        }
+
+                        else if ($1.type == GVT_ARRAY)
+                        {
+                            __array = G_KAITAI_ARRAY($1.array);
+                            __count = g_kaitai_array_count_items(__array);
+
+                            if (__index >= __count)
+                                EXIT_WITH_ERR($$, field_indexed);
+
+                            if (!g_kaitai_array_get_item(__array, __index, &$$))
+                                EXIT_WITH_ERR($$, field_indexed);
+
+                        }
+
+                        else
+                            EXIT_WITH_ERR($$, field_indexed);
+
+                    exit_field_indexed:
+                        EXIT_RESOLVED_VALUE($1);
+                        EXIT_RESOLVED_VALUE($3);
+                    }
+                    ;
+
+
+        enumeration : IDENTIFIER "::" IDENTIFIER
+                    {
+                        if (!g_match_record_resolve_enum(locals->parent, &$1, &$3, &$$))
+                            SET_ERR($$);
+                    }
+
+
+             stream : any_expr "._io"
+                    {
+                        GBinContent *__content;
+                        mrange_t __range;
+
+                        if ($1.type != GVT_RECORD)
+                            EXIT_WITH_ERR($$, stream_io);
+
+                        __content = g_match_record_get_content($1.record);
+                        g_match_record_get_range($1.record, &__range);
+
+                        $$.stream = g_kaitai_stream_new(__content, get_mrange_addr(&__range));
+                        $$.type = GVT_STREAM;
+
+                        g_object_unref(G_OBJECT(__content));
+
+                    exit_stream_io:
+                        EXIT_RESOLVED_VALUE($1);
+                    }
+                    ;
+
+
+%%
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : yyscanner = décodeur impliqué dans le processus.             *
+*                locals    = variables locales pour les résolutions de types. *
+*                out       = valeur entière résultante. [OUT]                 *
+*                msg       = message d'erreur.                                *
+*                                                                             *
+*  Description : Affiche un message d'erreur suite à l'analyse en échec.      *
+*                                                                             *
+*  Retour      : 0                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int yyerror(yyscan_t yyscanner, const kaitai_scope_t *locals, resolved_value_t *resolved, const char *msg)
+{
+	printf("YYERROR line %d: %s\n", yyget_lineno(yyscanner), msg);
+
+	return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                text   = définitions des règles à charger.                   *
+*                length = longueur de ces définitions.                        *
+*                out    = valeur générique résultante. [OUT]                  *
+*                                                                             *
+*  Description : Interprète une expression en une valeur quelconque.          *
+*                                                                             *
+*  Retour      : Bilan à retourner.                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool _resolve_kaitai_expression_as_any(const kaitai_scope_t *locals, const char *text, size_t length, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à renvoyer            */
+    yyscan_t lexstate;                      /* Gestion d'analyse lexicale  */
+    char *real_text;                        /* Zone de travail effective   */
+    size_t real_length;                     /* Taille associée             */
+    YY_BUFFER_STATE state;                  /* Contexte d'analyse          */
+    int status;                             /* Bilan d'une analyse         */
+
+    result = false;
+
+    kaitai_lex_init(&lexstate);
+
+    assert(length > 0);
+
+    if (text[length - 1] == '.')
+    {
+        /**
+         * Si le contenu à analyser se termine par un point, la position finale
+         * de ce point est prise en compte. Pour ce faire, le marqueur "$" des
+         * expressions régulières est sollicité. Hors, ce dernier n'est reconnu
+         * que pour le caractère "\n" terminant une ligne.
+         *
+         * On l'ajoute donc artificiellement.
+         */
+
+        real_length = length + 1;
+
+        real_text = malloc(real_length);
+        memcpy(real_text, text, length);
+        real_text[length] = '\n';
+
+    }
+    else
+    {
+        real_text = (char *)text;
+        real_length = length;
+    }
+
+    state = kaitai__scan_bytes(real_text, real_length, lexstate);
+
+    if (text[length - 1] == '.')
+        free(real_text);
+
+    status = yyparse(lexstate, locals, out);
+
+    result = (status == EXIT_SUCCESS);
+
+    yy_delete_buffer(state, lexstate);
+
+    kaitai_lex_destroy(lexstate);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                text   = définitions des règles à charger.                   *
+*                length = longueur de ces définitions.                        *
+*                out    = valeur générique résultante. [OUT]                  *
+*                                                                             *
+*  Description : Interprète une expression en une valeur quelconque.          *
+*                                                                             *
+*  Retour      : Bilan à retourner.                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool resolve_kaitai_expression_as_any(const kaitai_scope_t *locals, const char *text, size_t length, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à renvoyer            */
+
+    result = _resolve_kaitai_expression_as_any(locals, text, length, out);
+
+    return result;
+
+}
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : in_out = expression résolue traitée. [OUT]                   *
+*                                                                             *
+*  Description : Traduit les éventuels champs impliqués dans une expression.  *
+*                                                                             *
+*  Retour      : Bilan à retourner.                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool reduce_resolved_kaitai_expression(resolved_value_t *in_out)
+{
+    bool result;                            /* Bilan à renvoyer            */
+    resolved_value_t deeper;                /* Précision supplémentaire    */
+
+    result = true;
+
+    while (result && in_out->type == GVT_RECORD)
+    {
+        if (G_IS_RECORD_VALUE(in_out->record))
+            result = g_record_value_compute_value(G_RECORD_VALUE(in_out->record), &deeper);
+
+        else if (G_IS_RECORD_ITEM(in_out->record))
+            result = g_record_item_get_value(G_RECORD_ITEM(in_out->record), &deeper);
+
+        else
+            break;
+
+        if (result)
+        {
+            EXIT_RESOLVED_VALUE(*in_out);
+            *in_out = deeper;
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                text   = définitions des règles à charger.                   *
+*                length = longueur de ces définitions.                        *
+*                out    = valeur entière résultante. [OUT]                    *
+*                                                                             *
+*  Description : Interprète une expression en valeur ciblée entière.          *
+*                                                                             *
+*  Retour      : Bilan à retourner.                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool resolve_kaitai_expression_as_integer(const kaitai_scope_t *locals, const char *text, size_t length, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à renvoyer            */
+
+    result = _resolve_kaitai_expression_as_any(locals, text, length, out);
+
+    if (result)
+        result = reduce_resolved_kaitai_expression(out);
+
+    if (result)
+        result = (out->type == GVT_UNSIGNED_INTEGER || out->type == GVT_SIGNED_INTEGER);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                text   = définitions des règles à charger.                   *
+*                length = longueur de ces définitions.                        *
+*                out    = valeur booléenne résultante. [OUT]                  *
+*                                                                             *
+*  Description : Interprète une expression en valeur ciblée booléenne.        *
+*                                                                             *
+*  Retour      : Bilan à retourner.                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool resolve_kaitai_expression_as_boolean(const kaitai_scope_t *locals, const char *text, size_t length, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à renvoyer            */
+
+    result = _resolve_kaitai_expression_as_any(locals, text, length, out);
+
+    if (result)
+        result = reduce_resolved_kaitai_expression(out);
+
+    if (result && out->type != GVT_BOOLEAN)
+    {
+        EXIT_RESOLVED_VALUE(*out);
+        result = false;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                text   = définitions des règles à charger.                   *
+*                length = longueur de ces définitions.                        *
+*                out    = valeur booléenne résultante. [OUT]                  *
+*                                                                             *
+*  Description : Interprète une expression en série d'octets.                 *
+*                                                                             *
+*  Retour      : Bilan à retourner.                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool resolve_kaitai_expression_as_bytes(const kaitai_scope_t *locals, const char *text, size_t length, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à renvoyer            */
+    char ch;                                /* Caractère unique spécifié   */
+    sized_string_t converted;               /* Conversion finale ?         */
+
+    result = _resolve_kaitai_expression_as_any(locals, text, length, out);
+
+    if (result)
+        result = reduce_resolved_kaitai_expression(out);
+
+    if (result)
+    {
+        if (out->type == GVT_UNSIGNED_INTEGER)
+        {
+            ch = out->unsigned_integer;
+            result = (ch <= 0xff);
+
+            if (result)
+            {
+                EXIT_RESOLVED_VALUE(*out);
+
+                out->bytes.data = malloc(sizeof(char));
+                out->bytes.data[0] = ch;
+                out->bytes.len = 1;
+                out->type = GVT_BYTES;
+
+            }
+
+        }
+
+        else if (out->type == GVT_ARRAY)
+        {
+            result = g_kaitai_array_convert_to_bytes(out->array, &converted);
+
+            if (result)
+            {
+                EXIT_RESOLVED_VALUE(*out);
+
+                out->bytes = converted;
+                out->type = GVT_BYTES;
+
+            }
+
+        }
+
+    }
+
+    if (result && out->type != GVT_BYTES)
+    {
+        EXIT_RESOLVED_VALUE(*out);
+        result = false;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                text   = définitions des règles à charger.                   *
+*                length = longueur de ces définitions.                        *
+*                stream = flux de données pour Kaitai résultant. [OUT]        *
+*                                                                             *
+*  Description : Interprète une expression en flux de données pour Kaitai.    *
+*                                                                             *
+*  Retour      : Bilan à retourner.                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool resolve_kaitai_expression_as_stream(const kaitai_scope_t *locals, const char *text, size_t length, GKaitaiStream **stream)
+{
+    bool result;                            /* Bilan à renvoyer            */
+    resolved_value_t out;                   /* Elément générique obtenu    */
+
+    result = _resolve_kaitai_expression_as_any(locals, text, length, &out);
+
+    if (result) 
+    {
+        assert(out.type == GVT_STREAM);
+        *stream = out.stream;
+    }
+    else
+        *stream = NULL;
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parser-int.h b/plugins/kaitai/parser-int.h
new file mode 100644
index 0000000..4ddb0f9
--- /dev/null
+++ b/plugins/kaitai/parser-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser-int.h - prototypes pour les spécifications internes d'un lecteur Kaitai
+ *
+ * Copyright (C) 2019 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_PARSER_INT_H
+#define PLUGINS_KAITAI_PARSER_INT_H
+
+
+#include "parser.h"
+
+
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+typedef bool (* parse_kaitai_fc) (GKaitaiParser *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+
+
+
+/* Spécification d'un lecteur Kaitai (instance) */
+struct _GKaitaiParser
+{
+    GObject parent;                         /* A laisser en premier        */
+
+};
+
+/* Spécification d'un lecteur Kaitai (classe) */
+struct _GKaitaiParserClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+    parse_kaitai_fc parse;                  /* Phase d'analyse de contenu  */
+
+};
+
+
+
+#endif  /* PLUGINS_KAITAI_PARSER_INT_H */
diff --git a/plugins/kaitai/parser.c b/plugins/kaitai/parser.c
new file mode 100644
index 0000000..77c15b3
--- /dev/null
+++ b/plugins/kaitai/parser.c
@@ -0,0 +1,159 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.c - spécification d'un lecteur Kaitai
+ *
+ * Copyright (C) 2019 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 "parser.h"
+
+
+#include "parser-int.h"
+
+
+
+/* Initialise la classe des lecteurs de spécification Kaitai. */
+static void g_kaitai_parser_class_init(GKaitaiParserClass *);
+
+/* Initialise un lecteur de spécification Kaitai. */
+static void g_kaitai_parser_init(GKaitaiParser *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_parser_dispose(GKaitaiParser *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_parser_finalize(GKaitaiParser *);
+
+
+
+/* Indique le type défini pour un lecteur de spécification Kaitai. */
+G_DEFINE_TYPE(GKaitaiParser, g_kaitai_parser, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des lecteurs de spécification Kaitai.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_parser_class_init(GKaitaiParserClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_parser_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_kaitai_parser_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parser = instance à initialiser.                             *
+*                                                                             *
+*  Description : Initialise un lecteur de spécification Kaitai.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_parser_init(GKaitaiParser *parser)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parser = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_parser_dispose(GKaitaiParser *parser)
+{
+    G_OBJECT_CLASS(g_kaitai_parser_parent_class)->dispose(G_OBJECT(parser));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parser = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_parser_finalize(GKaitaiParser *parser)
+{
+    G_OBJECT_CLASS(g_kaitai_parser_parent_class)->finalize(G_OBJECT(parser));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parser  = structure Kaitai en cours de parcours.             *
+*                locals  = variables locales pour les résolutions de types.   *
+*                content = données binaires à analyser et traduire.           *
+*                pos     = tête de lecture courante. [OUT]                    *
+*                record  = noeud d'arborescence d'éléments rencontrés. [OUT]  *
+*                                                                             *
+*  Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
+*                                                                             *
+*  Retour      : Bilan de l'opératon : true pour continuer, false sinon.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_parser_parse_content(GKaitaiParser *parser, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+{
+    bool result;                            /* Bilan à retourner           */
+    GKaitaiParserClass *class;              /* Classe de l'instance        */
+
+    class = G_KAITAI_PARSER_GET_CLASS(parser);
+
+    result = class->parse(parser, locals, content, pos, record);
+
+    if (result)
+        remember_last_record(locals, *record);
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parser.h b/plugins/kaitai/parser.h
new file mode 100644
index 0000000..4c17087
--- /dev/null
+++ b/plugins/kaitai/parser.h
@@ -0,0 +1,63 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.h - prototypes pour la spécification d'un lecteur Kaitai
+ *
+ * Copyright (C) 2019 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_PARSER_H
+#define PLUGINS_KAITAI_PARSER_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/content.h>
+
+
+#include "record.h"
+#include "scope.h"
+
+
+
+#define G_TYPE_KAITAI_PARSER            g_kaitai_parser_get_type()
+#define G_KAITAI_PARSER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_PARSER, GKaitaiParser))
+#define G_IS_KAITAI_PARSER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_PARSER))
+#define G_KAITAI_PARSER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_PARSER, GKaitaiParserClass))
+#define G_IS_KAITAI_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_PARSER))
+#define G_KAITAI_PARSER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_PARSER, GKaitaiParserClass))
+
+
+/* Spécification d'un lecteur Kaitai (instance) */
+typedef struct _GKaitaiParser GKaitaiParser;
+
+/* Spécification d'un lecteur Kaitai (classe) */
+typedef struct _GKaitaiParserClass GKaitaiParserClass;
+
+
+/* Indique le type défini pour un lecteur de spécification Kaitai. */
+GType g_kaitai_parser_get_type(void);
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+bool g_kaitai_parser_parse_content(GKaitaiParser *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+
+
+
+#endif  /* PLUGINS_KAITAI_PARSER_H */
diff --git a/plugins/kaitai/parsers/Makefile.am b/plugins/kaitai/parsers/Makefile.am
new file mode 100644
index 0000000..c7e313b
--- /dev/null
+++ b/plugins/kaitai/parsers/Makefile.am
@@ -0,0 +1,25 @@
+
+noinst_LTLIBRARIES = libkaitaiparsers.la
+
+libkaitaiparsers_la_SOURCES =				\
+	attribute-int.h							\
+	attribute.h attribute.c					\
+	enum-int.h								\
+	enum.h enum.c							\
+	instance-int.h							\
+	instance.h instance.c					\
+	meta-int.h								\
+	meta.h meta.c							\
+	struct-int.h							\
+	struct.h struct.c						\
+	switch-int.h							\
+	switch.h switch.c						\
+	type-int.h								\
+	type.h type.c
+
+libkaitaiparsers_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaiparsers_la_SOURCES:%c=)
diff --git a/plugins/kaitai/parsers/attribute-int.h b/plugins/kaitai/parsers/attribute-int.h
new file mode 100644
index 0000000..ef64089
--- /dev/null
+++ b/plugins/kaitai/parsers/attribute-int.h
@@ -0,0 +1,104 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * attribute-int.h - prototypes pour les spécifications internes d'un attribut Kaitai
+ *
+ * Copyright (C) 2019 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_PARSERS_ATTRIBUTE_INT_H
+#define _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_INT_H
+
+
+#include "attribute.h"
+#include "switch.h"
+#include "../parser-int.h"
+
+
+
+/* Indique l'étiquette à utiliser pour identifier un attribut. */
+typedef const char * (* get_attribute_label_fc) (const GKaitaiAttribute *);
+
+/* Spécification d'un attribut Kaitai (instance) */
+struct _GKaitaiAttribute
+{
+    GKaitaiParser parent;                   /* A laisser en premier        */
+
+    char *raw_id;                           /* Identifiant Kaitai          */
+    char *orig_id;                          /* Identifiant humain          */
+
+    char *doc;                              /* Eventuelle documentation    */
+
+    KaitaiAttributePayload payload;         /* Forme de la spécialisation  */
+
+    struct
+    {
+        /* KAP_FIXED_CONTENT */
+        sized_string_t fixed_content;       /* Données brutes attendues    */
+
+        /* KAP_BASIC_TYPE */
+        struct
+        {
+            BaseType basic;                 /* Type de base                */
+
+            bool is_string;                 /* Renvoi vers une chaîne      */
+
+            SourceEndian endian;            /* Boutisme forcé ?            */
+            bool has_endian;                /* Présence de cette force     */
+
+        };
+
+        /* KAP_USER_TYPE */
+        char *named_type;                   /* Type particulier            */
+
+        /* KAP_DYNAMIC_TYPE */
+        GKaitaiSwitch *switchon;            /* Détermination dynamique     */
+
+    };
+
+    /* KAP_SIZED */
+    char *fixed_size;                       /* Taille déterminée           */
+
+    KaitaiAttributeRepetition repetition;   /* Forme de répétition         */
+    char *repeat_controller;                /* Indication sur la répétition*/
+
+    char *condition;                        /* Condition de chargement     */
+
+    sized_string_t terminator;              /* Marqueur de fin éventuel    */
+    bool consume;                           /* Consommation dans le flux   */
+    bool include;                           /* Intégration de ce marqueur  */
+    bool eos_error;                         /* Gestion des erreurs en bout */
+
+};
+
+/* Spécification d'un attribut Kaitai (classe) */
+struct _GKaitaiAttributeClass
+{
+    GKaitaiParserClass parent;              /* A laisser en premier        */
+
+    get_attribute_label_fc get_label;       /* Désignation d'une étiquette */
+
+};
+
+
+/* Met en place un lecteur d'attribut Kaitai. */
+bool g_kaitai_attribute_create(GKaitaiAttribute *, GYamlNode *, bool);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_INT_H */
diff --git a/plugins/kaitai/parsers/attribute.c b/plugins/kaitai/parsers/attribute.c
new file mode 100644
index 0000000..c61fe99
--- /dev/null
+++ b/plugins/kaitai/parsers/attribute.c
@@ -0,0 +1,2074 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * attribute.c - spécification d'un attribut Kaitai
+ *
+ * Copyright (C) 2019 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 "attribute.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include <analysis/contents/restricted.h>
+#include <plugins/yaml/pair.h>
+
+
+#include "attribute-int.h"
+#include "../expression.h"
+#include "../scope.h"
+#include "../records/empty.h"
+#include "../records/item.h"
+#include "../records/list.h"
+
+
+
+/* -------------------- CORRESPONDANCE ENTRE ATTRIBUT ET BINAIRE -------------------- */
+
+
+/* Initialise la classe des attributs de spécification Kaitai. */
+static void g_kaitai_attribute_class_init(GKaitaiAttributeClass *);
+
+/* Initialise un attribut de spécification Kaitai. */
+static void g_kaitai_attribute_init(GKaitaiAttribute *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_attribute_dispose(GKaitaiAttribute *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_attribute_finalize(GKaitaiAttribute *);
+
+/* Traduit en type concret une chaîne de caractères. */
+static bool g_kaitai_attribute_resolve_type(GKaitaiAttribute *, const char *);
+
+/* Valide la cohérence des informations portées par l'attribut. */
+static bool g_kaitai_attribute_check(const GKaitaiAttribute *);
+
+/* Copie le coeur de la définition d'un lecteur d'attribut. */
+static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+
+/* Extrait d'un contenu une série d'octets avec terminaison. */
+static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *, const kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+
+/* Détermine la zone de couverture finale d'une correspondance. */
+static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttribute *, const kaitai_scope_t *, const GBinContent *, const vmpa2t *, phys_t *, mrange_t *);
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      CORRESPONDANCE ENTRE ATTRIBUT ET BINAIRE                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un attribut de la spécification Kaitai. */
+G_DEFINE_TYPE(GKaitaiAttribute, g_kaitai_attribute, G_TYPE_KAITAI_PARSER);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des attributs de spécification Kaitai.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_attribute_class_init(GKaitaiAttributeClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GKaitaiParserClass *parser;             /* Version parente de la classe*/ 
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_attribute_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_kaitai_attribute_finalize;
+
+    parser = G_KAITAI_PARSER_CLASS(klass);
+
+    parser->parse = (parse_kaitai_fc)g_kaitai_attribute_parse_content;
+
+    klass->get_label = g_kaitai_attribute_get_raw_id;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = instance à initialiser.                             *
+*                                                                             *
+*  Description : Initialise un attribut de spécification Kaitai.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_attribute_init(GKaitaiAttribute *attrib)
+{
+    attrib->raw_id = NULL;
+    attrib->orig_id = NULL;
+
+    attrib->doc = NULL;
+
+    attrib->payload = KAP_UNINITIALIZED;
+
+    attrib->repetition = KAR_NO_REPETITION;
+    attrib->repeat_controller = NULL;
+
+    attrib->condition = NULL;
+
+    init_szstr(&attrib->terminator);
+    attrib->consume = true;
+    attrib->include = false;
+    attrib->eos_error = true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_attribute_dispose(GKaitaiAttribute *attrib)
+{
+    if (attrib->payload & KAP_DYNAMIC_TYPE)
+        g_clear_object(&attrib->switchon);
+
+    G_OBJECT_CLASS(g_kaitai_attribute_parent_class)->dispose(G_OBJECT(attrib));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_attribute_finalize(GKaitaiAttribute *attrib)
+{
+    if (attrib->raw_id != NULL)
+        free(attrib->raw_id);
+
+    if (attrib->orig_id != NULL)
+        free(attrib->orig_id);
+
+    if (attrib->doc != NULL)
+        free(attrib->doc);
+
+    if (attrib->payload & KAP_FIXED_CONTENT)
+        exit_szstr(&attrib->fixed_content);
+
+    else if (attrib->payload & KAP_USER_TYPE)
+        free(attrib->named_type);
+
+    if (attrib->fixed_size != NULL)
+        free(attrib->fixed_size);
+
+    if (attrib->repeat_controller != NULL)
+        free(attrib->repeat_controller);
+
+    if (attrib->condition != NULL)
+        free(attrib->condition);
+
+    exit_szstr(&attrib->terminator);
+
+    G_OBJECT_CLASS(g_kaitai_attribute_parent_class)->finalize(G_OBJECT(attrib));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = noeud Yaml contenant l'attribut à constituer.       *
+*                                                                             *
+*  Description : Construit un lecteur d'attribut Kaitai.                      *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiAttribute *g_kaitai_attribute_new(GYamlNode *parent)
+{
+    GKaitaiAttribute *result;               /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_KAITAI_ATTRIBUTE, NULL);
+
+    if (!g_kaitai_attribute_create(result, parent, true))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = lecteur d'attribut Kaitai à initialiser pleinement.*
+*                parent  = noeud Yaml contenant l'attribut à constituer.      *
+*                need_id = encadre la présence d'un champ "id".               *
+*                                                                             *
+*  Description : Met en place un lecteur d'attribut Kaitai.                   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool need_id)
+{
+    bool result;                            /* Bilan à retourner           */
+    GYamlNode *node;                        /* Noeud particulier présent   */
+    const char *value;                      /* Valeur Yaml particulière    */
+    char *rebuilt_value;                    /* Valeur Yaml rassemblée      */
+    kaitai_scope_t fake;                    /* Contexte de circonstance    */
+    resolved_value_t bytes;                 /* Données brutes obtenues     */
+    GYamlNode *other_node;                  /* Autre noeud nécessaire      */
+
+    result = false;
+
+    /* Identifiant obligatoire */
+
+    node = g_yaml_node_find_first_by_path(parent, "/id");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+        if (value == NULL)
+        {
+            g_object_unref(G_OBJECT(node));
+            goto bad_id;
+        }
+
+        attrib->raw_id = strdup(value);
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    else if (need_id)
+        goto bad_id;
+
+    /* Identifiant facultatif */
+
+    node = g_yaml_node_find_first_by_path(parent, "/-orig-id");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+        if (value == NULL)
+        {
+            g_object_unref(G_OBJECT(node));
+            goto bad_id;
+        }
+
+        attrib->orig_id = strdup(value);
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Eventuelle documentation */
+
+    node = g_yaml_node_find_first_by_path(parent, "/doc");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+        if (value == NULL)
+        {
+            g_object_unref(G_OBJECT(node));
+            goto bad_doc;
+        }
+
+        attrib->doc = strdup(value);
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Champ contents */
+
+    node = g_yaml_node_find_first_by_path(parent, "/contents");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        rebuilt_value = g_yaml_pair_aggregate_value(G_YAML_PAIR(node));
+
+        if (rebuilt_value == NULL)
+        {
+            g_object_unref(G_OBJECT(node));
+            goto bad_content;
+        }
+
+        fake.meta =  NULL;
+        fake.root =  NULL;
+        fake.parent =  NULL;
+        fake.last =  NULL;
+
+        if (!resolve_kaitai_expression_as_bytes(&fake, rebuilt_value, strlen(rebuilt_value), &bytes))
+        {
+            free(rebuilt_value);
+            g_object_unref(G_OBJECT(node));
+            goto bad_content;
+        }
+
+        free(rebuilt_value);
+
+        attrib->fixed_content = bytes.bytes;
+
+        g_object_unref(G_OBJECT(node));
+
+        attrib->payload |= KAP_FIXED_CONTENT;
+
+    }
+
+    /* Charge portée par un type */
+
+    node = g_yaml_node_find_first_by_path(parent, "/type");
+
+    if (node != NULL)
+    {
+        if (attrib->payload & KAP_FIXED_CONTENT)
+        {
+            printf("Can not handle fixed content and type definition at the same time for an attribute.\n");
+            goto bad_definition;
+        }
+
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (value != NULL)
+        {
+            if (g_kaitai_attribute_resolve_type(attrib, value))
+                attrib->payload |= KAP_BASIC_TYPE;
+
+            else
+            {
+                attrib->named_type = strdup(value);
+                attrib->payload |= KAP_USER_TYPE;
+            }
+
+        }
+
+        else
+        {
+            attrib->switchon = g_kaitai_switch_new(parent, attrib);
+            if (attrib->switchon == NULL) goto bad_definition;
+
+            attrib->payload |= KAP_DYNAMIC_TYPE;
+
+        }
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Répétitions contrôlées ? */
+
+    node = g_yaml_node_find_first_by_path(parent, "/repeat");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (value != NULL)
+        {
+            if (strcmp(value, "eos") == 0)
+                attrib->repetition = KAR_END_OF_STREAM;
+
+            else if (strcmp(value, "expr") == 0)
+            {
+                other_node = g_yaml_node_find_first_by_path(parent, "/repeat-expr");
+
+                if (other_node != NULL)
+                {
+                    if (G_IS_YAML_PAIR(other_node))
+                    {
+                        value = g_yaml_pair_get_value(G_YAML_PAIR(other_node));
+
+                        if (value != NULL)
+                        {
+                            attrib->repetition = KAR_EXPRESSION;
+                            attrib->repeat_controller = strdup(value);
+                        }
+                        else
+                            printf("Expected repeat expression\n");
+
+                    }
+
+                    g_object_unref(G_OBJECT(other_node));
+
+                }
+
+            }
+
+            else if (strcmp(value, "until") == 0)
+            {
+                other_node = g_yaml_node_find_first_by_path(parent, "/repeat-until");
+
+                if (other_node != NULL)
+                {
+                    assert(G_IS_YAML_PAIR(other_node));
+
+                    value = g_yaml_pair_get_value(G_YAML_PAIR(other_node));
+
+                    if (value != NULL)
+                    {
+                        attrib->repetition = KAR_UNTIL;
+                        attrib->repeat_controller = strdup(value);
+                    }
+                    else
+                        printf("Expected repeat expression\n");
+
+                }
+
+                g_object_unref(G_OBJECT(other_node));
+
+            }
+
+        }
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Intégration sous condition ? */
+
+    node = g_yaml_node_find_first_by_path(parent, "/if");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (value != NULL)
+            attrib->condition = strdup(value);
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Taille fixée ? */
+
+    node = g_yaml_node_find_first_by_path(parent, "/size");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (value != NULL)
+        {
+            attrib->fixed_size = strdup(value);
+            attrib->payload |= KAP_SIZED;
+        }
+
+        g_object_unref(G_OBJECT(node));
+
+        if ((attrib->payload & KAP_SIZED) == 0)
+            goto bad_content;
+
+    }
+
+    /* Prise en considération d'une taille maximale */
+
+    node = g_yaml_node_find_first_by_path(parent, "/size-eos");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (value != NULL && strcmp(value, "true") == 0)
+        {
+            if (attrib->payload != KAP_UNINITIALIZED)
+                /* printf warning */;
+
+            attrib->payload |= KAP_SIZED_EOS;
+
+        }
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Champ terminator */
+
+    node = g_yaml_node_find_first_by_path(parent, "/terminator");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        rebuilt_value = g_yaml_pair_aggregate_value(G_YAML_PAIR(node));
+
+        if (rebuilt_value == NULL)
+        {
+            g_object_unref(G_OBJECT(node));
+            goto bad_content;
+        }
+
+        fake.meta =  NULL;
+        fake.root =  NULL;
+        fake.parent =  NULL;
+        fake.last =  NULL;
+
+        if (!resolve_kaitai_expression_as_bytes(&fake, rebuilt_value, strlen(rebuilt_value), &bytes))
+        {
+            free(rebuilt_value);
+            g_object_unref(G_OBJECT(node));
+            goto bad_content;
+        }
+
+        free(rebuilt_value);
+
+        if (attrib->terminator.data != NULL)
+            printf("A ending content has already been specified (implicitly by the strz type)");
+
+        else
+        {
+            attrib->terminator.data = bytes.bytes.data;
+            attrib->terminator.len = bytes.bytes.len;
+        }
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Champ consume */
+
+    node = g_yaml_node_find_first_by_path(parent, "/consume");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (value != NULL)
+        {
+            if (strcmp(value, "true") == 0)
+                attrib->consume = true;
+
+            else if (strcmp(value, "false") == 0)
+                attrib->consume = false;
+
+            else
+                printf("Unsupported value for the 'consume' property (expecting true of false)");
+
+        }
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Champ include */
+
+    node = g_yaml_node_find_first_by_path(parent, "/include");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (value != NULL)
+        {
+            if (strcmp(value, "true") == 0)
+                attrib->include = true;
+
+            else if (strcmp(value, "false") == 0)
+                attrib->include = false;
+
+            else
+                printf("Unsupported value for the 'include' property (expecting true of false)");
+
+        }
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Champ eos-error */
+
+    node = g_yaml_node_find_first_by_path(parent, "/eos-error");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (value != NULL)
+        {
+            if (strcmp(value, "true") == 0)
+                attrib->eos_error = true;
+
+            if (strcmp(value, "false") == 0)
+                attrib->eos_error = false;
+
+            else
+                printf("Unsupported value for the 'eos_error' property (expecting true of false)");
+
+        }
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Validation finale */
+
+    result = g_kaitai_attribute_check(attrib);
+
+ bad_definition:
+
+ bad_doc:
+ bad_id:
+ bad_content:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = attribut Kaitai en cours de constitution.           *
+*                desc   = chaîne de caractère à interpréter en type.          *
+*                                                                             *
+*  Description : Traduit en type concret une chaîne de caractères.            *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_attribute_resolve_type(GKaitaiAttribute *attrib, const char *desc)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    attrib->basic = BTP_INVALID;
+    attrib->has_endian = false;
+
+    /**
+     * Cf. définition des types de base existants :
+     * http://doc.kaitai.io/user_guide.html#_fixed_size_structures
+     */
+
+#define RESOLVE_ENDIAN                      \
+    if (desc[2] == 'l')                     \
+    {                                       \
+        if (desc[3] == 'e')                 \
+        {                                   \
+            attrib->endian = SRE_LITTLE;    \
+            attrib->has_endian = true;      \
+        }                                   \
+    }                                       \
+    else if (desc[2] == 'b')                \
+    {                                       \
+        if (desc[3] == 'e')                 \
+        {                                   \
+            attrib->endian = SRE_BIG;       \
+            attrib->has_endian = true;      \
+        }                                   \
+    }                                       \
+
+    /* Analyse de la chaîne fournie */
+
+    switch (desc[0])
+    {
+        case 'f':
+            switch (desc[1])
+            {
+                case '4':
+                    attrib->basic = BTP_754R_32;
+                    RESOLVE_ENDIAN;
+                    break;
+
+                case '8':
+                    attrib->basic = BTP_754R_64;
+                    RESOLVE_ENDIAN;
+                    break;
+
+                default:
+                    result = false;
+                    break;
+
+            }
+            break;
+
+        case 's':
+            switch (desc[1])
+            {
+                case '1':
+                    attrib->basic = BTP_CHAR;
+                    RESOLVE_ENDIAN;
+                    break;
+
+                case '2':
+                    attrib->basic = BTP_SHORT;
+                    RESOLVE_ENDIAN;
+                    break;
+
+                case '4':
+                    attrib->basic = BTP_INT;
+                    RESOLVE_ENDIAN;
+                    break;
+
+                case '8':
+                    attrib->basic = BTP_LONG_LONG;
+                    RESOLVE_ENDIAN;
+                    break;
+
+                case 't':
+                    if (desc[2] == 'r')
+                    {
+                        attrib->basic = BTP_CHAR;
+                        attrib->is_string = true;
+                        if (desc[3] == 'z')
+                        {
+                            attrib->terminator.data = strdup("");
+                            attrib->terminator.len = 1;
+                        }
+                    }
+                    else
+                        result = false;
+                    break;
+
+                default:
+                    result = false;
+                    break;
+
+            }
+            break;
+
+        case 'u':
+            switch (desc[1])
+            {
+                case '1':
+                    attrib->basic = BTP_UCHAR;
+                    RESOLVE_ENDIAN;
+                    break;
+
+                case '2':
+                    attrib->basic = BTP_USHORT;
+                    RESOLVE_ENDIAN;
+                    break;
+
+                case '4':
+                    attrib->basic = BTP_UINT;
+                    RESOLVE_ENDIAN;
+                    break;
+
+                case '8':
+                    attrib->basic = BTP_ULONG_LONG;
+                    RESOLVE_ENDIAN;
+                    break;
+
+                default:
+                    result = false;
+                    break;
+
+            }
+            break;
+
+        default:
+            result = false;
+            break;
+
+    }
+
+    /* Vérification d'une comparaison complète */
+    if (result)
+        switch (attrib->basic)
+        {
+            case BTP_CHAR:
+                if (attrib->is_string)
+                {
+                    if (attrib->terminator.data != NULL)
+                        result = (desc[4] == 0);
+                    else
+                        result = (desc[3] == 0);
+                }
+                else
+                {
+                    if (attrib->has_endian)
+                        result = (desc[4] == 0);
+                    else
+                        result = (desc[2] == 0);
+                }
+                break;
+
+            default:
+                if (attrib->has_endian)
+                    result = (desc[4] == 0);
+                else
+                    result = (desc[2] == 0);
+                break;
+
+        }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = attribut Kaitai à valider.                          *
+*                                                                             *
+*  Description : Valide la cohérence des informations portées par l'attribut. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_attribute_check(const GKaitaiAttribute *attrib)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    /**
+     * Une lecture de tous les octets restants ne doit correspondre qu'à des octets bruts.
+     */
+    if (attrib->payload & KAP_SIZED_EOS && attrib->payload != KAP_SIZED_EOS)
+    {
+        result = (attrib->payload & KAP_BASIC_TYPE) && attrib->is_string;
+
+        if (!result)
+        {
+            printf("Reading all the remaining bytes should only produce bytes.");
+            result = true;
+        }
+
+    }
+
+    /**
+     * Une chaîne (type str[z]) doit comporter une séquence de terminaison.
+     */
+    if ((attrib->payload & KAP_BASIC_TYPE) && attrib->is_string)
+    {
+        result = (attrib->terminator.data != NULL) || (attrib->payload & (KAP_SIZED | KAP_SIZED_EOS));
+
+        if (!result)
+        {
+            printf("An unsized string (str type with no size attribute) has to be link to a terminator sequence.");
+            goto exit;
+        }
+
+    }
+
+    /**
+     * Si une séquence d'octets finaux est spécifiées, alors l'attribut
+     * doit correspondre à un type str[z] (lecture) ou de taille fixée
+     * (validation post-lecture).
+     */
+    if (attrib->terminator.data != NULL)
+    {
+        result = ((attrib->payload & ~(KAP_FIXED_CONTENT | KAP_BASIC_TYPE | KAP_SIZED)) == 0);
+
+        if (result && (attrib->payload & KAP_BASIC_TYPE))
+            result = attrib->is_string;
+
+        if (!result)
+        {
+            printf("A useless terminator is specified.");
+            result = true;
+            goto exit;
+        }
+
+    }
+
+    /**
+     * Il n'est pas possible d'inclure un marqueur de fin sans le consommer.
+     */
+    if (!attrib->consume && attrib->include)
+    {
+        result = false;
+        printf("It is not possible to include a terminator without consuming it.");
+    }
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = lecteur d'attribut Kaitai à dupliquer.              *
+*                type   = type utilisateur à associer au nouvel attribut.     *
+*                                                                             *
+*  Description : Dérive un lecteur d'attribut Kaitai pour un type utilisateur.*
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiAttribute *g_kaitai_attribute_dup_for_user_type(const GKaitaiAttribute *attrib, const char *type)
+{
+    GKaitaiAttribute *result;               /* Structure à retourner       */
+
+    result = g_kaitai_attribute_dup_for(attrib);
+
+    result->payload = KAP_USER_TYPE;
+
+    result->named_type = strdup(type);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = lecteur d'attribut Kaitai à dupliquer.              *
+*                                                                             *
+*  Description : Copie le coeur de la définition d'un lecteur d'attribut.     *
+*                                                                             *
+*  Retour      : Nouvelle instance à compléter.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *attrib)
+{
+    GKaitaiAttribute *result;               /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_KAITAI_ATTRIBUTE, NULL);
+
+    /**
+     * Il n'y a rien à copier dans la structure parente.
+     *
+     * Les travaux de copie ne portent ainsi que sur le présent attribut.
+     */
+
+    result->raw_id = strdup(attrib->raw_id);
+
+    if (attrib->orig_id != NULL)
+        result->orig_id = strdup(attrib->orig_id);
+
+    if (attrib->doc != NULL)
+        result->doc = strdup(attrib->doc);
+
+    if (attrib->fixed_size != NULL)
+        result->fixed_size = strdup(attrib->fixed_size);
+
+    result->repetition = attrib->repetition;
+
+    if (attrib->repeat_controller != NULL)
+        result->repeat_controller = strdup(attrib->repeat_controller);
+
+    if (attrib->condition != NULL)
+        result->condition = strdup(attrib->condition);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = lecteur d'attribut Kaitai à consulter.              *
+*                                                                             *
+*  Description : Indique l'étiquette à utiliser pour identifier un attribut.  *
+*                                                                             *
+*  Retour      : Valeur brute de l'identifiant.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_kaitai_attribute_get_label(const GKaitaiAttribute *attrib)
+{
+    const char *result;                     /* Valeur à renvoyer           */
+    GKaitaiAttributeClass *class;           /* Classe de l'instance        */
+
+    class = G_KAITAI_ATTRIBUTE_GET_CLASS(attrib);
+
+    result = class->get_label(attrib);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = lecteur d'attribut Kaitai à consulter.              *
+*                                                                             *
+*  Description : Indique la désignation brute d'un identifiant Kaitai.        *
+*                                                                             *
+*  Retour      : Valeur brute de l'identifiant.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_kaitai_attribute_get_raw_id(const GKaitaiAttribute *attrib)
+{
+    char *result;                           /* Valeur à renvoyer           */
+
+    result = attrib->raw_id;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = lecteur d'attribut Kaitai à consulter.              *
+*                                                                             *
+*  Description : Indique la désignation originelle d'un identifiant Kaitai.   *
+*                                                                             *
+*  Retour      : Valeur originelle de l'identifiant.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_kaitai_attribute_get_original_id(const GKaitaiAttribute *attrib)
+{
+    char *result;                           /* Valeur à renvoyer           */
+
+    result = attrib->orig_id;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = lecteur d'attribut Kaitai à consulter.              *
+*                                                                             *
+*  Description : Fournit une éventuelle documentation concernant l'attribut.  *
+*                                                                             *
+*  Retour      : Description enregistrée ou NULL si absente.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_kaitai_attribute_get_doc(const GKaitaiAttribute *attrib)
+{
+    char *result;                           /* Valeur à renvoyer           */
+
+    result = attrib->doc;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = lecteur d'attribut Kaitai à consulter.              *
+*                                                                             *
+*  Description : Indique la nature de la charge représentée par l'attribut.   *
+*                                                                             *
+*  Retour      : Forme de contenu représenté par le lecteur d'attribut.       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+KaitaiAttributePayload g_kaitai_attribute_get_payload(const GKaitaiAttribute *attrib)
+{
+    KaitaiAttributePayload result;          /* Type de charge à renvoyer   */
+
+    result = attrib->payload;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib    = lecteur d'attribut Kaitai à consulter.           *
+*                basic     = type de base Kaitai reconnu par le lecteur. [OUT]*
+*                is_string = nature du type BTP_CHAR en sortie. [OUT]         *
+*                                                                             *
+*  Description : Précise un éventuel type de base reconnu par le lecteur.     *
+*                                                                             *
+*  Retour      : Validité du type renseigné en argument.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_attribute_get_basic_type(const GKaitaiAttribute *attrib, BaseType *basic, bool *is_string)
+{
+    bool result;                            /* Validité à retourner        */
+
+    result = (attrib->payload & KAP_BASIC_TYPE);
+
+    if (result)
+    {        
+        *basic = attrib->basic;
+        *is_string = attrib->is_string;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = lecteur d'attribut Kaitai à consulter.             *
+*                content = contenu binaire à venir lire.                      *
+*                range   = espace disponible pour la lecture.                 *
+*                out     = tableau d'octets retournés. [OUT]                  *
+*                len     = taille de ce tableau alloué. [OUT]                 *
+*                                                                             *
+*  Description : Lit les octets d'une chaîne représentée.                     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_attribute_read_truncated_bytes(const GKaitaiAttribute *attrib, const GBinContent *content, const mrange_t *range, bin_t **out, size_t *len)
+{
+    bool result;                            /* Bilan à retourner           */
+    vmpa2t tmppos;                          /* Localisation modifiable     */
+    const bin_t *data;                      /* Accès aux données brutes    */
+
+    result = false;
+
+    if ((attrib->payload & KAP_SIZED) == 0)
+        goto bad_type;
+
+    copy_vmpa(&tmppos, get_mrange_addr(range));
+
+    *len = get_mrange_length(range);
+
+    data = g_binary_content_get_raw_access(content, &tmppos, *len);
+
+    *out = malloc(sizeof(bin_t) * (*len + 1));
+
+    memcpy(*out, data, *len);
+    (*out)[*len] = '\0';
+
+    result = true;
+
+ bad_type:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib = lecteur d'attribut Kaitai à consulter.              *
+*                                                                             *
+*  Description : Détermine si l'attribue porte une valeur entière signée.     *
+*                                                                             *
+*  Retour      : Bilan de la consultation : true si un entier signé est visé. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_attribute_handle_signed_integer(const GKaitaiAttribute *attrib)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = false;
+
+    if ((attrib->payload & KAP_BASIC_TYPE) == 0)
+        goto bad_type;
+
+    switch (attrib->basic)
+    {
+        case BTP_CHAR:
+        case BTP_SHORT:
+        case BTP_INT:
+        case BTP_LONG_LONG:
+            result = true;
+            break;
+
+        default:
+            break;
+
+    }
+
+ bad_type:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = lecteur d'attribut Kaitai à consulter.             *
+*                content = contenu binaire à venir lire.                      *
+*                range   = espace de lecture.                                 *
+*                endian  = boustime des données à respecter.                  *
+*                out     = valeur à sauvegarder sous une forme générique.[OUT]*
+*                                                                             *
+*  Description : Lit la valeur d'un élément Kaitai entier représenté.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinContent *content, const mrange_t *range, SourceEndian endian, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à retourner           */
+    vmpa2t tmppos;                          /* Localisation modifiable     */
+    const bin_t *data;                      /* Données brutes restituées   */
+    int8_t stmp8;                           /* Valeur de 8 bits lue        */
+    uint8_t tmp8;                           /* Valeur de 8 bits lue        */
+    int16_t stmp16;                         /* Valeur de 16 bits lue       */
+    uint16_t tmp16;                         /* Valeur de 16 bits lue       */
+    int32_t stmp32;                         /* Valeur de 32 bits lue       */
+    uint32_t tmp32;                         /* Valeur de 32 bits lue       */
+    int64_t stmp64;                         /* Valeur de 64 bits lue       */
+    uint64_t tmp64;                         /* Valeur de 64 bits lue       */
+
+    result = false;
+
+    if (attrib->payload & (KAP_FIXED_CONTENT | KAP_SIZED | KAP_SIZED_EOS))
+    {
+        copy_vmpa(&tmppos, get_mrange_addr(range));
+
+        data = g_binary_content_get_raw_access(content, &tmppos, get_mrange_length(range));
+        result = (data != NULL);
+
+        if (result)
+        {
+            out->type = GVT_BYTES;
+
+            out->bytes.len = get_mrange_length(range);
+
+            out->bytes.data = malloc(out->bytes.len);
+            memcpy(out->bytes.data, data, out->bytes.len);
+
+        }
+
+    }
+
+    else if (attrib->payload & KAP_BASIC_TYPE)
+    {
+        copy_vmpa(&tmppos, get_mrange_addr(range));
+
+        switch (attrib->basic)
+        {
+            case BTP_CHAR:
+                if (attrib->is_string)
+                {
+                    copy_vmpa(&tmppos, get_mrange_addr(range));
+
+                    data = g_binary_content_get_raw_access(content, &tmppos, get_mrange_length(range));
+                    result = (data != NULL);
+
+                    if (result)
+                    {
+                        out->type = GVT_BYTES;
+
+                        out->bytes.len = get_mrange_length(range);
+
+                        out->bytes.data = malloc(out->bytes.len);
+                        memcpy(out->bytes.data, data, out->bytes.len);
+
+                    }
+
+                }
+                else
+                {
+                    assert(get_mrange_length(range) == 1);
+                    result = g_binary_content_read_s8(content, &tmppos, &stmp8);
+                    out->type = GVT_SIGNED_INTEGER;
+                    out->signed_integer = stmp8;
+                }
+                break;
+
+            case BTP_UCHAR:
+                assert(get_mrange_length(range) == 1);
+                result = g_binary_content_read_u8(content, &tmppos, &tmp8);
+                out->type = GVT_UNSIGNED_INTEGER;
+                out->unsigned_integer = tmp8;
+                break;
+
+            case BTP_SHORT:
+                assert(get_mrange_length(range) == 2);
+                result = g_binary_content_read_s16(content, &tmppos, endian, &stmp16);
+                out->type = GVT_SIGNED_INTEGER;
+                out->signed_integer = stmp16;
+                break;
+
+            case BTP_USHORT:
+                assert(get_mrange_length(range) == 2);
+                result = g_binary_content_read_u16(content, &tmppos, endian, &tmp16);
+                out->type = GVT_UNSIGNED_INTEGER;
+                out->unsigned_integer = tmp16;
+                break;
+
+            case BTP_INT:
+                assert(get_mrange_length(range) == 4);
+                result = g_binary_content_read_s32(content, &tmppos, endian, &stmp32);
+                out->type = GVT_SIGNED_INTEGER;
+                out->signed_integer = stmp32;
+                break;
+
+            case BTP_UINT:
+                assert(get_mrange_length(range) == 4);
+                result = g_binary_content_read_u32(content, &tmppos, endian, &tmp32);
+                out->type = GVT_UNSIGNED_INTEGER;
+                out->unsigned_integer = tmp32;
+                break;
+
+            case BTP_LONG_LONG:
+                assert(get_mrange_length(range) == 8);
+                result = g_binary_content_read_s64(content, &tmppos, endian, &stmp64);
+                out->type = GVT_SIGNED_INTEGER;
+                out->signed_integer = stmp64;
+                break;
+
+            case BTP_ULONG_LONG:
+                assert(get_mrange_length(range) == 8);
+                result = g_binary_content_read_u64(content, &tmppos, endian, &tmp64);
+                out->type = GVT_UNSIGNED_INTEGER;
+                out->unsigned_integer = tmp64;
+                break;
+
+            default:
+                break;
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = structure Kaitai en cours de parcours.             *
+*                locals  = variables locales pour les résolutions de types.   *
+*                content = données binaires à analyser et traduire.           *
+*                pos     = tête de lecture courante. [OUT]                    *
+*                record  = noeud d'arborescence d'éléments rencontrés. [OUT]  *
+*                                                                             *
+*  Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
+*                                                                             *
+*  Retour      : Bilan de l'opératon : true pour continuer, false sinon.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+{
+    bool result;                            /* Bilan à retourner           */
+    resolved_value_t authorized;            /* Validation des traitements  */
+
+    mrange_t work_range;                    /* Définition de cette aire    */
+    GBinContent *work_area;                 /* Aire de travail             */
+    bool has_empty_size;                    /* Mémorise une taille nulle   */
+
+
+    //unsigned long long value;               /* Valeur entière finale       */
+    //bool status;                            /* Bilan d'une conversion      */
+
+
+    vmpa2t tmp;                             /* Position de travail         */
+    phys_t diff;                            /* Différentiel de positions   */
+    resolved_value_t resolved;              /* Valeur entière obtenue      */
+    phys_t max_size;                        /* Taille maximale imposée     */
+
+
+    const bin_t *data;                      /* Données à comparer          */
+    GKaitaiType *user_type;                 /* Définition particulière     */
+
+
+    mrange_t range;                         /* Couverture appliquée        */
+    SourceEndian endian;                    /* Boutisme à observer         */
+    phys_t cur_diff;                        /* Avancée de lecture courante */
+
+
+    result = false;
+    *record = NULL;
+
+    /* Lecture soumise à condition ? */
+
+    if (attrib->condition != NULL)
+    {
+        result = resolve_kaitai_expression_as_boolean(locals,
+                                                      attrib->condition,
+                                                      strlen(attrib->condition),
+                                                      &authorized);
+
+        if (!result || !authorized.status)
+            goto exit;
+
+    }
+
+    /* Zone de travail restreinte */
+
+    g_binary_content_compute_end_pos(content, &tmp);
+    diff = compute_vmpa_diff(pos, &tmp);
+
+    if (attrib->payload & KAP_SIZED)
+    {
+        result = resolve_kaitai_expression_as_integer(locals,
+                                                      attrib->fixed_size,
+                                                      strlen(attrib->fixed_size),
+                                                      &resolved);
+
+        if (result)
+        {
+            if (resolved.type == GVT_UNSIGNED_INTEGER)
+                max_size = resolved.unsigned_integer;
+            else
+            {
+                assert(resolved.type == GVT_SIGNED_INTEGER);
+
+                if (resolved.signed_integer < 0)
+                    result = false;
+                else
+                    max_size = resolved.signed_integer;
+
+            }
+
+            if (result)
+                result = (diff >= max_size);
+
+            if (!result)
+                printf("Need more data!\n");
+
+            if (result && max_size < diff)
+                diff = max_size;
+
+        }
+
+        if (!result)
+            goto exit;
+
+        init_mrange(&work_range, pos, diff);
+        work_area = g_restricted_content_new_ro(content, &work_range);
+
+        has_empty_size = (diff == 0);
+
+    }
+    else
+    {
+        work_area = content;
+        has_empty_size = false;
+    }
+
+    /* Etablissement d'une zone de correspondance */
+
+    if (attrib->payload == KAP_UNINITIALIZED)
+        assert(false);
+
+    else if (attrib->payload & KAP_SIZED_EOS)
+        result = true;
+
+    else if (attrib->payload & KAP_FIXED_CONTENT)
+    {
+        if (diff >= attrib->fixed_content.len)
+        {
+            copy_vmpa(&tmp, pos);
+
+            data = g_binary_content_get_raw_access(work_area, &tmp, attrib->fixed_content.len);
+            assert(data != NULL);
+
+            result = (memcmp(data, attrib->fixed_content.data, attrib->fixed_content.len) == 0);
+
+            if (result)
+                diff = attrib->fixed_content.len;
+
+        }
+
+    }
+
+    else if (attrib->payload & KAP_BASIC_TYPE)
+    {
+        switch (attrib->basic)
+        {
+            case BTP_CHAR:
+            case BTP_UCHAR:
+                if (attrib->is_string)
+                {
+                    if ((attrib->payload & KAP_SIZED) == 0)
+                        result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals, work_area, pos, record);
+                }
+                else
+                {
+                    result = (diff >= 1);
+                    diff = 1;
+                }
+                break;
+
+            case BTP_SHORT:
+            case BTP_USHORT:
+                result = (diff >= 2);
+                diff = 2;
+                break;
+
+            case BTP_INT:
+            case BTP_UINT:
+            case BTP_754R_32:
+                result = (diff >= 4);
+                diff = 4;
+                break;
+
+            case BTP_LONG_LONG:
+            case BTP_ULONG_LONG:
+            case BTP_754R_64:
+                result = (diff >= 8);
+                diff = 8;
+                break;
+
+            default:
+                break;
+
+        }
+
+    }
+
+    else if (attrib->payload & KAP_USER_TYPE)
+    {
+        user_type = find_sub_type(locals, attrib->named_type);
+
+        if (user_type != NULL)
+        {
+            result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(user_type),
+                                                   locals, work_area, pos, record);       
+
+            if (result)
+                /**
+                 * Le type utilisateur dérive du type GKaitaiStruct, qui ne possède pas
+                 * d'identifiant propre. La correspondance produite est ainsi nominalement
+                 * anonyme, ce qui empêche toute résolution.
+                 *
+                 * Le rattachement de l'étiquette de l'attribut d'origine est donc forcée ici.
+                 */
+                g_match_record_fix_creator(*record, G_KAITAI_PARSER(attrib));
+
+
+            g_object_unref(G_OBJECT(user_type));
+
+        }
+
+    }
+
+    else if (attrib->payload & KAP_DYNAMIC_TYPE)
+        result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, pos, record);
+
+    else if (attrib->payload & KAP_SIZED)
+    {
+        /* Cas déjà traité en début de fonction */
+
+    }
+
+    /* Enregistrement de la correspondance */
+
+    if (result && *record == NULL)
+    {
+        /**
+         * On choisit de laisser la création de correspondances nulles.
+         *
+         * Cela permet de disposer de la présence de champs valides, même vides
+         * (cf. "4.10.3. Repeat until condition is met")
+         */
+
+        /* if (diff > 0) */
+        {
+            result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content, pos, &diff, &range);
+
+            if (result)
+            {
+                if (has_empty_size)
+                    *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, pos));
+
+                else
+                {
+                    if (attrib->has_endian)
+                        endian = attrib->endian;
+                    else
+                        endian = g_kaitai_meta_get_endian(locals->meta);
+
+                    *record = G_MATCH_RECORD(g_record_item_new(attrib, work_area, &range, endian));
+
+                    if (*record != NULL)
+                        advance_vmpa(pos, diff);
+                    else
+                        result = false;
+
+                }
+
+            }
+
+        }
+
+    }
+
+    /* Libération de zone de travail restreinte ? */
+
+    if (attrib->payload & KAP_SIZED)
+    {
+        cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), pos);
+
+        /* Pour GCC... */
+        max_size = get_mrange_length(&work_range);
+
+        if (cur_diff < max_size)
+            advance_vmpa(pos, max_size - cur_diff);
+
+        assert(work_area != content);
+        g_object_unref(G_OBJECT(work_area));
+
+    }
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = structure Kaitai en cours de parcours.             *
+*                locals  = variables locales pour les résolutions de types.   *
+*                content = données binaires à analyser et traduire.           *
+*                pos     = tête de lecture courante. [OUT]                    *
+*                record  = noeud d'arborescence d'éléments rencontrés. [OUT]  *
+*                                                                             *
+*  Description : Extrait d'un contenu une série d'octets avec terminaison.    *
+*                                                                             *
+*  Retour      : Bilan de l'opératon : true pour continuer, false sinon.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *attrib, const kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+{
+    bool result;                            /* Bilan à retourner           */
+    sized_string_t marker;                  /* Marqueur potentiel à tester */
+    vmpa2t iter;                            /* Tête de lecture courante    */
+    vmpa2t end;                             /* Fin du parcours possible    */
+    vmpa2t tmp;                             /* Position à mouvante         */
+    phys_t diff;                            /* Avancée de lecture courante */
+    mrange_t range;                         /* Couverture appliquée        */
+    SourceEndian endian;                    /* Boutisme à observer         */
+
+    result = false;
+
+    /* Recherche du marqueur de fin */
+
+    marker.len = attrib->terminator.len;
+
+    copy_vmpa(&iter, pos);
+    g_binary_content_compute_end_pos(content, &end);
+
+    while (cmp_vmpa_by_phy(&iter, &end) < 0)
+    {
+        copy_vmpa(&tmp, &iter);
+
+        marker.data = (char *)g_binary_content_get_raw_access(content, &tmp, marker.len);
+        if (marker.data == NULL) break;
+
+        if (szmemcmp(&marker, &attrib->terminator) == 0)
+        {
+            result = true;
+            break;
+        }
+
+        advance_vmpa(&iter, 1);
+
+    }
+
+    /* Si la recherche a abouti */
+
+    if (result)
+    {
+        diff = compute_vmpa_diff(pos, &iter);
+
+        if (attrib->include)
+            diff += marker.len;
+
+        init_mrange(&range, pos, diff);
+
+        if (attrib->has_endian)
+            endian = attrib->endian;
+        else
+            endian = g_kaitai_meta_get_endian(locals->meta);
+
+        *record = G_MATCH_RECORD(g_record_item_new(attrib, content, &range, endian));
+
+        copy_vmpa(pos, &iter);
+
+        if (attrib->consume)
+            advance_vmpa(pos, marker.len);
+
+    }
+
+    /* Sinon l'absence de marqueur est-elle tolérée ? */
+
+    else if (!attrib->eos_error)
+    {
+        diff = compute_vmpa_diff(pos, &end);
+
+        init_mrange(&range, pos, diff);
+
+        if (attrib->has_endian)
+            endian = attrib->endian;
+        else
+            endian = g_kaitai_meta_get_endian(locals->meta);
+
+        *record = G_MATCH_RECORD(g_record_item_new(attrib, content, &range, endian));
+
+        copy_vmpa(pos, &end);
+
+        result = true;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = structure Kaitai en cours de parcours.             *
+*                locals  = variables locales pour les résolutions de types.   *
+*                content = données binaires à analyser et traduire.           *
+*                pos     = tête de lecture courante.                          *
+*                maxsize = taille maximale de la zone de correspondance. [OUT]*
+*                range   = zone de couverture à officialiser. [OUT]           *
+*                                                                             *
+*  Description : Détermine la zone de couverture finale d'une correspondance. *
+*                                                                             *
+*  Retour      : Bilan de l'opératon : true pour continuer, false sinon.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttribute *attrib, const kaitai_scope_t *locals, const GBinContent *content, const vmpa2t *pos, phys_t *maxsize, mrange_t *range)
+{
+    bool result;                            /* Bilan à retourner           */
+    sized_string_t marker;                  /* Marqueur potentiel à tester */
+    vmpa2t iter;                            /* Tête de lecture courante    */
+    vmpa2t end;                             /* Fin du parcours possible    */
+    vmpa2t tmp;                             /* Position à mouvante         */
+    phys_t diff;                            /* Avancée de lecture courante */
+
+    if (attrib->terminator.data == NULL)
+    {
+        init_mrange(range, pos, *maxsize);
+        result = true;
+    }
+
+    else
+    {
+        result = false;
+
+        if (attrib->terminator.len > *maxsize)
+            goto exit;
+
+        /* Recherche du marqueur de fin */
+
+        marker.len = attrib->terminator.len;
+
+        copy_vmpa(&iter, pos);
+
+        copy_vmpa(&tmp, pos);
+        advance_vmpa(&tmp, *maxsize - marker.len);
+
+        while (cmp_vmpa_by_phy(&iter, &end) <= 0)
+        {
+            copy_vmpa(&tmp, &iter);
+
+            marker.data = (char *)g_binary_content_get_raw_access(content, &tmp, marker.len);
+            if (marker.data == NULL) break;
+
+            if (szmemcmp(&marker, &attrib->terminator) == 0)
+            {
+                result = true;
+                break;
+            }
+
+            advance_vmpa(&iter, 1);
+
+        }
+
+        /* Si la recherche a abouti */
+
+        if (result)
+        {
+            diff = compute_vmpa_diff(pos, &iter);
+
+            if (attrib->include)
+                init_mrange(range, pos, diff + marker.len);
+            else
+                init_mrange(range, pos, diff);
+
+            assert((diff + marker.len) <= *maxsize);
+
+            if (attrib->consume)
+                *maxsize = diff + marker.len;
+            else
+                *maxsize = diff;
+
+        }
+
+        /* Sinon l'absence de marqueur est-elle tolérée ? */
+
+        else if (!attrib->eos_error)
+        {
+            init_mrange(range, pos, *maxsize);
+            result = true;
+        }
+
+    }
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = structure Kaitai en cours de parcours.             *
+*                locals  = variables locales pour les résolutions de types.   *
+*                content = données binaires à analyser et traduire.           *
+*                pos     = tête de lecture courante. [OUT]                    *
+*                record  = noeud d'arborescence d'éléments rencontrés. [OUT]  *
+*                                                                             *
+*  Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
+*                                                                             *
+*  Retour      : Bilan de l'opératon : true pour continuer, false sinon.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+{
+    bool result;                            /* Bilan à retourner           */
+    resolved_value_t authorized;            /* Validation des traitements  */
+    GRecordList *list;                      /* Constitution d'une liste    */
+    vmpa2t end;                             /* Position maximale du flux   */
+    phys_t diff;                            /* Différentiel de positions   */
+    GMatchRecord *child;                    /* Element de liste à intégrer */
+    resolved_value_t resolved;              /* Valeur entière obtenue      */
+    unsigned long long count;               /* Nombre d'itérations à mener */
+    unsigned long long i;                   /* Boucle de parcours          */
+    resolved_value_t loop;                  /* Poursuite des lectures ?    */
+
+    if (attrib->repetition == KAR_NO_REPETITION)
+        result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, record);
+
+    else
+    {
+        /* Lecture soumise à condition ? */
+
+        if (attrib->condition != NULL)
+        {
+            result = resolve_kaitai_expression_as_boolean(locals,
+                                                          attrib->condition,
+                                                          strlen(attrib->condition),
+                                                          &authorized);
+
+            if (!result || !authorized.status)
+                goto exit;
+
+        }
+
+        list = g_record_list_new(attrib, content, pos);
+
+        switch (attrib->repetition)
+        {
+            case KAR_END_OF_STREAM:
+
+                result = true;
+
+                g_binary_content_compute_end_pos(content, &end);
+                diff = compute_vmpa_diff(pos, &end);
+
+                while (diff > 0)
+                {
+                    result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child);
+                    if (!result) break;
+
+                    g_record_list_add_record(list, child);
+                    remember_last_record(locals, child);
+
+                    diff = compute_vmpa_diff(pos, &end);
+
+                }
+
+                break;
+
+            case KAR_EXPRESSION:
+
+                result = resolve_kaitai_expression_as_integer(locals,
+                                                              attrib->repeat_controller,
+                                                              strlen(attrib->repeat_controller),
+                                                              &resolved);
+
+                if (resolved.type == GVT_UNSIGNED_INTEGER)
+                    count = resolved.unsigned_integer;
+                else
+                {
+                    assert(resolved.type == GVT_SIGNED_INTEGER);
+
+                    if (resolved.signed_integer < 0)
+                    {
+                        result = false;
+                        break;
+                    }
+
+                    count = resolved.signed_integer;
+
+                }
+
+                for (i = 0; i < count; i++)
+                {
+                    result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child);
+                    if (!result) break;
+
+                    g_record_list_add_record(list, child);
+                    remember_last_record(locals, child);
+
+                }
+
+                break;
+
+            case KAR_UNTIL:
+
+                do
+                {
+                    result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child);
+                    if (!result) break;
+
+                    g_record_list_add_record(list, child);
+                    remember_last_record(locals, child);
+
+                    result = resolve_kaitai_expression_as_boolean(locals,
+                                                                  attrib->repeat_controller,
+                                                                  strlen(attrib->repeat_controller),
+                                                                  &loop);
+                    if (!result) break;
+
+                }
+                while (!loop.status);
+
+                break;
+
+            default:
+                break;
+
+        }
+
+        if (!result) g_clear_object(&list);
+
+        *record = G_MATCH_RECORD(list);
+
+    }
+
+ exit:
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parsers/attribute.h b/plugins/kaitai/parsers/attribute.h
new file mode 100644
index 0000000..38b78d7
--- /dev/null
+++ b/plugins/kaitai/parsers/attribute.h
@@ -0,0 +1,154 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * attribute.h - prototypes pour la spécification d'un attribut Kaitai
+ *
+ * Copyright (C) 2019 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_PARSERS_ATTRIBUTE_H
+#define _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/content.h>
+#include <analysis/types/basic.h>
+#include <plugins/yaml/node.h>
+
+
+#include "../expression.h"
+
+
+
+#define G_TYPE_KAITAI_ATTRIBUTE            g_kaitai_attribute_get_type()
+#define G_KAITAI_ATTRIBUTE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_ATTRIBUTE, GKaitaiAttribute))
+#define G_IS_KAITAI_ATTRIBUTE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_ATTRIBUTE))
+#define G_KAITAI_ATTRIBUTE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_ATTRIBUTE, GKaitaiAttributeClass))
+#define G_IS_KAITAI_ATTRIBUTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_ATTRIBUTE))
+#define G_KAITAI_ATTRIBUTE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_ATTRIBUTE, GKaitaiAttributeClass))
+
+
+/* Spécification d'un attribut Kaitai (instance) */
+typedef struct _GKaitaiAttribute GKaitaiAttribute;
+
+/* Spécification d'un attribut Kaitai (classe) */
+typedef struct _GKaitaiAttributeClass GKaitaiAttributeClass;
+
+
+/* Type de charge associée à un attribut */
+typedef enum _KaitaiAttributePayload
+{
+    KAP_UNINITIALIZED = (0 << 0),           /* Type non initialisé         */
+
+    KAP_FIXED_CONTENT = (1 << 0),           /* Contenu brut attendu        */
+    KAP_BASIC_TYPE    = (1 << 1),           /* Type prédéfini              */
+    KAP_USER_TYPE     = (1 << 2),           /* Type personnalisé           */
+    KAP_DYNAMIC_TYPE  = (1 << 3),           /* Type dynmatique             */
+    KAP_SIZED         = (1 << 4),           /* Bourrage dimensionné        */
+    KAP_SIZED_EOS     = (1 << 5),           /* Bourrage final              */
+
+} KaitaiAttributePayload;
+
+/* Types de base reconnus par Kaitai */
+typedef enum _KaitaiBasicType
+{
+    KBT_U1,                                 /* Octet non signé             */
+    KBT_U2,                                 /* Mot de 16 bits non signé    */
+    KBT_U2LE,                               /* Mot de 16 bits non signé    */
+    KBT_U2BE,                               /* Mot de 16 bits non signé    */
+    KBT_U4,                                 /* Mot de 32 bits non signé    */
+    KBT_U4LE,                               /* Mot de 32 bits non signé    */
+    KBT_U4BE,                               /* Mot de 32 bits non signé    */
+    KBT_U8,                                 /* Mot de 64 bits non signé    */
+    KBT_U8LE,                               /* Mot de 64 bits non signé    */
+    KBT_U8BE,                               /* Mot de 64 bits non signé    */
+    KBT_S1,                                 /* Octet signé                 */
+    KBT_S2,                                 /* Mot de 16 bits signé        */
+    KBT_S2LE,                               /* Mot de 16 bits signé        */
+    KBT_S2BE,                               /* Mot de 16 bits signé        */
+    KBT_S4,                                 /* Mot de 32 bits signé        */
+    KBT_S4LE,                               /* Mot de 32 bits signé        */
+    KBT_S4BE,                               /* Mot de 32 bits signé        */
+    KBT_S8,                                 /* Mot de 64 bits signé        */
+    KBT_S8LE,                               /* Mot de 64 bits signé        */
+    KBT_S8BE,                               /* Mot de 64 bits signé        */
+    KBT_F4,                                 /* Flottant sur 32 bits        */
+    KBT_F4BE,                               /* Flottant sur 32 bits        */
+    KBT_F4LE,                               /* Flottant sur 32 bits        */
+    KBT_F8,                                 /* Flottant sur 64 bits        */
+    KBT_F8BE,                               /* Flottant sur 64 bits        */
+    KBT_F8LE,                               /* Flottant sur 64 bits        */
+    KBT_STR,                                /* Chaîne de caractères        */
+    KBT_STRZ,                               /* Chaîne de caractères + '\0' */
+
+} KaitaiBasicType;
+
+/* Formes de répétition d'une lecture d'attribut */
+typedef enum _KaitaiAttributeRepetition
+{
+    KAR_NO_REPETITION,                      /* Aucune forme de répétition  */
+
+    KAR_END_OF_STREAM,                      /* Redites autant que possible */
+    KAR_EXPRESSION,                         /* Répétitions selon quantité  */
+    KAR_UNTIL,                              /* Répétitions sous condition  */
+
+} KaitaiAttributeRepetition;
+
+
+/* Indique le type défini pour un attribut de la spécification Kaitai. */
+GType g_kaitai_attribute_get_type(void);
+
+/* Construit un lecteur d'attribut Kaitai. */
+GKaitaiAttribute *g_kaitai_attribute_new(GYamlNode *);
+
+/* Dérive un lecteur d'attribut Kaitai pour un type utilisateur. */
+GKaitaiAttribute *g_kaitai_attribute_dup_for_user_type(const GKaitaiAttribute *, const char *);
+
+/* Indique l'étiquette à utiliser pour identifier un attribut. */
+const char *g_kaitai_attribute_get_label(const GKaitaiAttribute *);
+
+/* Indique la désignation brute d'un identifiant Kaitai. */
+const char *g_kaitai_attribute_get_raw_id(const GKaitaiAttribute *);
+
+/* Indique la désignation originelle d'un identifiant Kaitai. */
+const char *g_kaitai_attribute_get_original_id(const GKaitaiAttribute *);
+
+/* Fournit une éventuelle documentation concernant l'attribut. */
+const char *g_kaitai_attribute_get_doc(const GKaitaiAttribute *);
+
+/* Indique la nature de la charge représentée par l'attribut. */
+KaitaiAttributePayload g_kaitai_attribute_get_payload(const GKaitaiAttribute *);
+
+/* Précise un éventuel type de base reconnu par le lecteur. */
+bool g_kaitai_attribute_get_basic_type(const GKaitaiAttribute *, BaseType *, bool *);
+
+/* Lit les octets d'une chaîne représentée. */
+bool g_kaitai_attribute_read_truncated_bytes(const GKaitaiAttribute *, const GBinContent *, const mrange_t *, bin_t **, size_t *);
+
+/* Détermine si l'attribue porte une valeur entière signée. */
+bool g_kaitai_attribute_handle_signed_integer(const GKaitaiAttribute *);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+bool g_kaitai_attribute_read_value(const GKaitaiAttribute *, const GBinContent *, const mrange_t *, SourceEndian, resolved_value_t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_H */
diff --git a/plugins/kaitai/parsers/enum-int.h b/plugins/kaitai/parsers/enum-int.h
new file mode 100644
index 0000000..b62ae41
--- /dev/null
+++ b/plugins/kaitai/parsers/enum-int.h
@@ -0,0 +1,79 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enum-int.h - prototypes internes pour la gestion des énumérations Kaitai
+ *
+ * Copyright (C) 2019 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_PARSERS_ENUM_INT_H
+#define PLUGINS_KAITAI_PARSERS_ENUM_INT_H
+
+
+#include "enum.h"
+
+
+
+/* ------------------------- MANIPULATION D'UNE ENUMERATION ------------------------- */
+
+
+/* Mémorisation d'une valeur d'énumération */
+typedef struct _enum_value_t
+{
+    resolved_value_t value;                 /* Valeur entière représentée  */
+    char *label;                            /* Elément associé à une valeur*/
+    char *doc;                              /* Eventuelle documentation    */
+
+} enum_value_t;
+
+
+
+/* ----------------------- GESTION D'UN GROUPE D'ENUMERATIONS ----------------------- */
+
+
+/* Définition d'un ensemble d'énumérations Kaitai (instance) */
+struct _GKaitaiEnum
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    char *name;                             /* Désignation de l'énumération*/
+
+    enum_value_t **cases_v2l;               /* Choix indexés par valeur    */
+    size_t cases_v2l_count;                 /* Quantité de ces choix       */
+
+    enum_value_t **cases_l2v;               /* Choix indexés par étiquette */
+    size_t cases_l2v_count;                 /* Quantité de ces choix       */
+
+    enum_value_t *defcase;                  /* Choix par défaut ou NULL    */
+
+};
+
+/* Définition d'un ensemble d'énumérations Kaitai (classe) */
+struct _GKaitaiEnumClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+};
+
+
+/* Met en place un groupe d'énumérations Kaitai. */
+bool g_kaitai_enum_create(GKaitaiEnum *, GYamlNode *);
+
+
+
+#endif  /* PLUGINS_KAITAI_PARSERS_ENUM_INT_H */
diff --git a/plugins/kaitai/parsers/enum.c b/plugins/kaitai/parsers/enum.c
new file mode 100644
index 0000000..267aaba
--- /dev/null
+++ b/plugins/kaitai/parsers/enum.c
@@ -0,0 +1,765 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enum.h - gestion des énumérations Kaitai
+ *
+ * Copyright (C) 2019 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 "enum.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include <common/extstr.h>
+#include <common/sort.h>
+#include <core/logs.h>
+#include <plugins/yaml/collection.h>
+#include <plugins/yaml/pair.h>
+
+
+#include "enum-int.h"
+
+
+
+/* ------------------------- MANIPULATION D'UNE ENUMERATION ------------------------- */
+
+
+/* Construit une valeur d'énumération à partir d'indications. */
+static enum_value_t *build_enum_value(GYamlNode *, bool *);
+
+/* Supprime de la mémoire une valeur d'énumération. */
+static void delete_enum_value(enum_value_t *);
+
+/* Etablit la comparaison entre deux valeurs d'énumération. */
+static int compare_enum_values_by_value(const enum_value_t **, const enum_value_t **);
+
+/* Etablit la comparaison entre deux noms d'énumération. */
+static int compare_enum_values_by_label(const enum_value_t **, const enum_value_t **);
+
+/* Etablit la comparaison entre deux noms d'énumération. */
+static int compare_enum_values_by_sized_label(const sized_string_t *, const enum_value_t **);
+
+
+
+/* ----------------------- GESTION D'UN GROUPE D'ENUMERATIONS ----------------------- */
+
+
+/* Initialise la classe des groupes d'énumérations Kaitai. */
+static void g_kaitai_enum_class_init(GKaitaiEnumClass *);
+
+/* Initialise un groupe d'énumérations Kaitai. */
+static void g_kaitai_enum_init(GKaitaiEnum *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_enum_dispose(GKaitaiEnum *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_enum_finalize(GKaitaiEnum *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           MANIPULATION D'UNE ENUMERATION                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : node    = noeud Yaml à venir lire.                           *
+*                defcase = indique si une valeur par défaut est visée. [OUT]  *
+*                                                                             *
+*  Description : Construit une valeur d'énumération à partir d'indications.   *
+*                                                                             *
+*  Retour      : Structure de valeur mise en place.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static enum_value_t *build_enum_value(GYamlNode *node, bool *defcase)
+{
+    enum_value_t *result;                   /* Valeur à retourner          */
+    const char *key;                        /* Clef d'une énumération      */
+    kaitai_scope_t fake;                    /* Contexte de circonstance    */
+    resolved_value_t kval;                  /* Valeur à indexer            */
+    const char *value;                      /* Valeur Yaml particulière    */
+    char *path;                             /* Chemin d'accès suivant      */
+    GYamlNode *children;                    /* Sous-noeuds rattachés       */
+    GYamlNode *sub;                         /* Sous-noeud à considérer     */
+
+    result = NULL;
+
+    *defcase = false;
+
+    if (!G_IS_YAML_PAIR(node))
+        goto bad_node;
+
+    /* Identification de la valeur énumérative */
+
+    key = g_yaml_pair_get_key(G_YAML_PAIR(node));
+
+    if (strcmp(key, "_") == 0)
+    {
+        /**
+         * Exemple de choix par défaut :
+         * http://doc.kaitai.io/user_guide.html#tlv
+         */
+
+        kval.type = GVT_UNSIGNED_INTEGER;
+        kval.unsigned_integer = ~0llu;
+
+        *defcase = true;
+
+    }
+
+    else
+    {
+        fake.meta =  NULL;
+        fake.root =  NULL;
+        fake.parent =  NULL;
+        fake.last =  NULL;
+
+        if (!resolve_kaitai_expression_as_integer(&fake, key, strlen(key), &kval))
+            goto bad_node;
+
+    }
+
+    /* Récupération des éléments associés à la valeur */
+
+    value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+    if (value != NULL)
+    {
+        result = malloc(sizeof(enum_value_t));
+
+        result->value = kval;
+        result->label = strdup(value);
+        result->doc = NULL;
+
+    }
+    else
+    {
+        /**
+         * Les énumérations peuvent comporter un commentaire associé
+         * sous forme d'un élément de documentation complémentaire.
+         *
+         * Cf. http://doc.kaitai.io/user_guide.html#verbose-enums
+         */
+
+        asprintf(&path, "/%s/", key);
+        children = g_yaml_node_find_first_by_path(node, path);
+        free(path);
+
+        if (!G_IS_YAML_COLLEC(children))
+            goto bad_value;
+
+        /* Identifiant */
+
+        sub = g_yaml_node_find_first_by_path(children, "/id");
+
+        if (!G_IS_YAML_PAIR(sub))
+            goto bad_sub_value;
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(sub));
+
+        if (value == NULL)
+            goto bad_sub_value;
+
+        result = malloc(sizeof(enum_value_t));
+
+        result->value = kval;
+        result->label = strdup(value);
+        result->doc = NULL;
+
+        g_object_unref(G_OBJECT(sub));
+
+        /* Documentation */
+
+        sub = g_yaml_node_find_first_by_path(children, "/doc");
+
+        if (!G_IS_YAML_PAIR(sub))
+            goto bad_sub_value;
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(sub));
+
+        if (value == NULL)
+            goto bad_sub_value;
+
+        result->doc = strdup(value);
+
+ bad_sub_value:
+
+        g_clear_object(&sub);
+
+        g_object_unref(G_OBJECT(children));
+
+ bad_value:
+
+        ;
+
+    }
+
+ bad_node:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : value = valeur à traiter.                                    *
+*                                                                             *
+*  Description : Supprime de la mémoire une valeur d'énumération.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void delete_enum_value(enum_value_t *value)
+{
+    EXIT_RESOLVED_VALUE(value->value);
+
+    free(value->label);
+
+    if (value->doc != NULL)
+        free(value->doc);
+
+    free(value);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = premières informations à consulter.                      *
+*                b = secondes informations à consulter.                       *
+*                                                                             *
+*  Description : Etablit la comparaison entre deux valeurs d'énumération.     *
+*                                                                             *
+*  Retour      : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b).                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int compare_enum_values_by_value(const enum_value_t **a, const enum_value_t **b)
+{
+    int result;                             /* Bilan à retourner           */
+    const resolved_value_t *value_a;        /* Raccouri d'accès pour a     */
+    const resolved_value_t *value_b;        /* Raccouri d'accès pour b     */
+
+    value_a = &(*a)->value;
+    value_b = &(*b)->value;
+
+    if (value_a->type == GVT_UNSIGNED_INTEGER && value_b->type == GVT_UNSIGNED_INTEGER)
+        result = sort_unsigned_long_long(value_a->unsigned_integer, value_b->unsigned_integer);
+
+    else if (value_a->type == GVT_UNSIGNED_INTEGER && value_b->type == GVT_UNSIGNED_INTEGER)
+        result = sort_signed_long_long(value_a->signed_integer, value_b->signed_integer);
+
+    else
+    {
+        /**
+         * Le code Python a deux options : soit fournir un équivalent à la
+         * structure resolved_value_t lors de l'appel correspondant à cette
+         * fonction compare_enum_values_by_value(), soit fournir un nombre
+         * directement.
+         *
+         * Comme PyArg_ParseTuple() est obligée de trancher entre non-signé
+         * et signé, le parti est pris de considérer le non-signé coté Python.
+         * On s'adapte en conséquence ici.
+         *
+         * La structure resolved_value_t est une union, donc les valeurs
+         * sont potientiellement au mauvais format mais bien présentes.
+         */
+
+        /**
+         * result = sort_unsigned_long_long(value_a->type, value_b->type);
+         */
+
+        result = sort_unsigned_long_long(value_a->unsigned_integer, value_b->unsigned_integer);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = premières informations à consulter.                      *
+*                b = secondes informations à consulter.                       *
+*                                                                             *
+*  Description : Etablit la comparaison entre deux noms d'énumération.        *
+*                                                                             *
+*  Retour      : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b).                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int compare_enum_values_by_label(const enum_value_t **a, const enum_value_t **b)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = strcmp((*a)->label, (*b)->label);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : l = premières informations à consulter.                      *
+*                b = secondes informations à consulter.                       *
+*                                                                             *
+*  Description : Etablit la comparaison entre deux noms d'énumération.        *
+*                                                                             *
+*  Retour      : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b).                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int compare_enum_values_by_sized_label(const sized_string_t *l, const enum_value_t **b)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = szstrcmp(l, (*b)->label);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         GESTION D'UN GROUPE D'ENUMERATIONS                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un ensemble d'énumérations Kaitai. */
+G_DEFINE_TYPE(GKaitaiEnum, g_kaitai_enum, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des groupes d'énumérations Kaitai.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_enum_class_init(GKaitaiEnumClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_enum_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_kaitai_enum_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kenum = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise un groupe d'énumérations Kaitai.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_enum_init(GKaitaiEnum *kenum)
+{
+    kenum->name = NULL;
+
+    kenum->cases_v2l = NULL;
+    kenum->cases_v2l_count = 0;
+
+    kenum->cases_l2v = NULL;
+    kenum->cases_l2v_count = 0;
+
+    kenum->defcase = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kenum = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_enum_dispose(GKaitaiEnum *kenum)
+{
+    G_OBJECT_CLASS(g_kaitai_enum_parent_class)->dispose(G_OBJECT(kenum));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kenum = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_enum_finalize(GKaitaiEnum *kenum)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    if (kenum->name != NULL)
+        free(kenum->name);
+
+    for (i = 0; i < kenum->cases_v2l_count; i++)
+        delete_enum_value(kenum->cases_v2l[i]);
+
+    if (kenum->cases_v2l != NULL)
+        free(kenum->cases_v2l);
+
+    if (kenum->cases_l2v != NULL)
+        free(kenum->cases_l2v);
+
+    if (kenum->defcase != NULL)
+        delete_enum_value(kenum->defcase);
+
+    G_OBJECT_CLASS(g_kaitai_enum_parent_class)->finalize(G_OBJECT(kenum));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = noeud Yaml contenant l'attribut à constituer.       *
+*                                                                             *
+*  Description : Construit un groupe d'énumérations Kaitai.                   *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiEnum *g_kaitai_enum_new(GYamlNode *parent)
+{
+    GKaitaiEnum *result;                   /* Identifiant à retourner     */
+
+    result = g_object_new(G_TYPE_KAITAI_ENUM, NULL);
+
+    if (!g_kaitai_enum_create(result, parent))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kenum  = groupe d'énumérations à initialiser pleinement.     *
+*                parent = noeud Yaml contenant l'attribut à constituer.       *
+*                                                                             *
+*  Description : Met en place un groupe d'énumérations Kaitai.                *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_enum_create(GKaitaiEnum *kenum, GYamlNode *parent)
+{
+    bool result;                            /* Bilan à retourner           */
+    char *path;                             /* Chemin des valeurs          */
+    GYamlNode *collec;                      /* Liste de noeuds à traiter   */
+    GYamlNode **nodes;                      /* Eventuels noeuds trouvés    */
+    size_t count;                           /* Quantité de ces noeuds      */
+    size_t i;                               /* Boucle de parcours          */
+    bool defcase;                           /* Définition par défaut ?     */
+    enum_value_t *value;                    /* Valeur énumérative nouvelle */
+    bool found;                             /* Présence de partage existant*/
+    size_t index;                           /* Indice du point d'insertion */
+
+    result = false;
+
+    /* Récupération du nom */
+
+    if (!G_IS_YAML_PAIR(parent)) goto exit;
+
+    kenum->name = strdup(g_yaml_pair_get_key(G_YAML_PAIR(parent)));
+
+    /* Association de valeurs */
+
+    path = strdup("/");
+    path = stradd(path, kenum->name);
+    path = stradd(path, "/");
+
+    collec = g_yaml_node_find_first_by_path(parent, path);
+
+    free(path);
+
+    if (collec != NULL)
+    {
+        if (G_IS_YAML_COLLEC(collec))
+            nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+        else
+            count = 0;
+
+        if (count > 0)
+        {
+            for (i = 0; i < count; i++)
+            {
+                value = build_enum_value(nodes[i], &defcase);
+                if (value == NULL) break;
+
+                if (defcase)
+                {
+                    if (kenum->defcase != NULL)
+                    {
+                        log_variadic_message(LMT_WARNING,
+                                             _("Multiple definition of the defaut value for the enumeration '%s'"),
+                                             kenum->name);
+
+                        delete_enum_value(value);
+                        break;
+
+                    }
+
+                    /**
+                     * Exemple de choix par défaut :
+                     * http://doc.kaitai.io/user_guide.html#tlv
+                     */
+
+                    kenum->defcase = value;
+
+                }
+
+                else
+                {
+                    kenum->cases_v2l = qinsert(kenum->cases_v2l, &kenum->cases_v2l_count, sizeof(enum_value_t *),
+                                               (__compar_fn_t)compare_enum_values_by_value, &value);
+
+                    found = bsearch_index(&value, kenum->cases_l2v, kenum->cases_l2v_count, sizeof(enum_value_t *),
+                                          (__compar_fn_t)compare_enum_values_by_label, &index);
+
+                    if (found)
+                        log_variadic_message(LMT_WARNING,
+                                             _("Multiple occurrence of the label %s in the enumeration '%s'"),
+                                             value->label, kenum->name);
+
+                    else
+                        kenum->cases_l2v = _qinsert(kenum->cases_l2v, &kenum->cases_l2v_count, sizeof(enum_value_t *),
+                                                    &value, index);
+
+                }
+
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            }
+
+            result = (i == count);
+
+            for (; i < count; i++)
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            free(nodes);
+
+        }
+
+        g_object_unref(G_OBJECT(collec));
+
+    }
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kenum = groupe d'énumérations à consulter.                   *
+*                                                                             *
+*  Description : Fournit le nom principal d'une énumération.                  *
+*                                                                             *
+*  Retour      : Désignation de l'énumération.                                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_kaitai_enum_get_name(const GKaitaiEnum *kenum)
+{
+    const char *result;                     /* Chaîne à retourner          */
+
+    result = kenum->name;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kenum = groupe d'énumérations à consulter.                   *
+*                label = étiquette de l'élément constant à traduire.          *
+*                value = valeur concrète correspondante. [OUT]                *
+*                                                                             *
+*  Description : Traduit une étiquette brute en constante d'énumération.      *
+*                                                                             *
+*  Retour      : Bilan de la conversion.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_enum_find_value(const GKaitaiEnum *kenum, const sized_string_t *label, resolved_value_t *value)
+{
+    bool result;                            /* Présence à retourner        */
+    size_t index;                           /* Indice du point d'insertion */
+
+    result = bsearch_index(label, kenum->cases_l2v, kenum->cases_l2v_count, sizeof(enum_value_t *),
+                           (__compar_fn_t)compare_enum_values_by_sized_label, &index);
+
+    if (result)
+        *value = kenum->cases_l2v[index]->value;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kenum  = groupe d'énumérations à consulter.                  *
+*                value  = valeur concrète à transformer.                      *
+*                prefix = détermine l'ajout d'un préfixe éventuel.            *
+*                                                                             *
+*  Description : Traduit une constante d'énumération en étiquette brute.      *
+*                                                                             *
+*  Retour      : Désignation ou NULL en cas d'échec.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *g_kaitai_enum_find_label(const GKaitaiEnum *kenum, const resolved_value_t *value, bool prefix)
+{
+    char *result;                           /* Etiquette à retourner       */
+    enum_value_t faked;                     /* Copie d'élément recherché   */
+    bool found;                             /* Présence de partage existant*/
+    size_t index;                           /* Indice du point d'insertion */
+    const enum_value_t *item;               /* Elément retrouvé par valeur */
+
+    faked.value = *value;
+
+    found = bsearch_index(&faked, kenum->cases_v2l, kenum->cases_v2l_count, sizeof(enum_value_t *),
+                          (__compar_fn_t)compare_enum_values_by_value, &index);
+
+    if (found)
+        item = kenum->cases_l2v[index];
+    else
+        item = kenum->defcase;
+
+    if (item != NULL)
+    {
+        if (prefix)
+            asprintf(&result, "%s::%s", kenum->name, item->label);
+        else
+            result = strdup(item->label);
+    }
+
+    else
+        result = NULL;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kenum = groupe d'énumérations à consulter.                   *
+*                value = valeur concrète à transformer.                       *
+*                                                                             *
+*  Description : Traduit une constante d'énumération en documentation.        *
+*                                                                             *
+*  Retour      : Documentation associée à la valeur indiquée ou NULL.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *g_kaitai_enum_find_documentation(const GKaitaiEnum *kenum, const resolved_value_t *value)
+{
+    char *result;                           /* Documentation à retourner   */
+    enum_value_t faked;                     /* Copie d'élément recherché   */
+    bool found;                             /* Présence de partage existant*/
+    size_t index;                           /* Indice du point d'insertion */
+    const enum_value_t *item;               /* Elément retrouvé par valeur */
+
+    faked.value = *value;
+
+    found = bsearch_index(&faked, kenum->cases_v2l, kenum->cases_v2l_count, sizeof(enum_value_t *),
+                          (__compar_fn_t)compare_enum_values_by_value, &index);
+
+    if (found)
+        item = kenum->cases_l2v[index];
+    else
+        item = kenum->defcase;
+
+    if (item != NULL)
+        result = strdup(item->doc);
+    else
+        result = NULL;
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parsers/enum.h b/plugins/kaitai/parsers/enum.h
new file mode 100644
index 0000000..9e4bf2a
--- /dev/null
+++ b/plugins/kaitai/parsers/enum.h
@@ -0,0 +1,76 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enum.h - prototypes pour la gestion des énumérations Kaitai
+ *
+ * Copyright (C) 2019 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_PARSERS_ENUM_H
+#define _PLUGINS_KAITAI_PARSERS_ENUM_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+
+#include <common/szstr.h>
+#include <plugins/yaml/node.h>
+
+
+#include "../expression.h"
+
+
+
+#define G_TYPE_KAITAI_ENUM            g_kaitai_enum_get_type()
+#define G_KAITAI_ENUM(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_ENUM, GKaitaiEnum))
+#define G_IS_KAITAI_ENUM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_ENUM))
+#define G_KAITAI_ENUM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_ENUM, GKaitaiEnumClass))
+#define G_IS_KAITAI_ENUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_ENUM))
+#define G_KAITAI_ENUM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_ENUM, GKaitaiEnumClass))
+
+
+/* Définition d'un ensemble d'énumérations Kaitai (instance) */
+typedef struct _GKaitaiEnum GKaitaiEnum;
+
+/* Définition d'un ensemble d'énumérations Kaitai (classe) */
+typedef struct _GKaitaiEnumClass GKaitaiEnumClass;
+
+
+/* Indique le type défini pour un ensemble d'énumérations Kaitai. */
+GType g_kaitai_enum_get_type(void);
+
+/* Construit un groupe d'énumérations Kaitai. */
+GKaitaiEnum *g_kaitai_enum_new(GYamlNode *);
+
+/* Fournit le nom principal d'une énumération. */
+const char *g_kaitai_enum_get_name(const GKaitaiEnum *);
+
+/* Traduit une étiquette brute en constante d'énumération. */
+bool g_kaitai_enum_find_value(const GKaitaiEnum *, const sized_string_t *, resolved_value_t *);
+
+/* Traduit une constante d'énumération en étiquette brute. */
+char *g_kaitai_enum_find_label(const GKaitaiEnum *, const resolved_value_t *, bool);
+
+/* Traduit une constante d'énumération en documentation. */
+char *g_kaitai_enum_find_documentation(const GKaitaiEnum *, const resolved_value_t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PARSERS_ENUM_H */
diff --git a/plugins/kaitai/parsers/instance-int.h b/plugins/kaitai/parsers/instance-int.h
new file mode 100644
index 0000000..6f098b4
--- /dev/null
+++ b/plugins/kaitai/parsers/instance-int.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instance-int.h - prototypes pour les spécifications internes d'une instance Kaitai
+ *
+ * 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_PARSERS_INSTANCE_INT_H
+#define _PLUGINS_KAITAI_PARSERS_INSTANCE_INT_H
+
+
+#include "attribute-int.h"
+#include "instance.h"
+
+
+
+/* Spécification d'une instance Kaitai (instance) */
+struct _GKaitaiInstance
+{
+    GKaitaiAttribute parent;                /* A laisser en premier        */
+
+    char *name;                             /* Nom attribué à l'instance   */
+
+    char *io;                               /* Contenu binaire forcé       */
+    char *pos;                              /* Position forcée             */
+    char *value;                            /* Formule pour calcul         */
+
+};
+
+/* Spécification d'une instance Kaitai (classe) */
+struct _GKaitaiInstanceClass
+{
+    GKaitaiAttributeClass parent;           /* A laisser en premier        */
+
+};
+
+
+/* Met en place un lecteur d'instance Kaitai. */
+bool g_kaitai_instance_create(GKaitaiInstance *, GYamlNode *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PARSERS_INSTANCE_INT_H */
diff --git a/plugins/kaitai/parsers/instance.c b/plugins/kaitai/parsers/instance.c
new file mode 100644
index 0000000..63db224
--- /dev/null
+++ b/plugins/kaitai/parsers/instance.c
@@ -0,0 +1,478 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instance.c - spécification d'une instance Kaitai
+ *
+ * Copyright (C) 2019 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 "instance.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <plugins/yaml/pair.h>
+
+
+#include "instance-int.h"
+#include "../expression.h"
+#include "../records/value.h"
+
+
+
+/* -------------------- CORRESPONDANCE ENTRE INSTANCE ET BINAIRE -------------------- */
+
+
+/* Initialise la classe des instances de spécification Kaitai. */
+static void g_kaitai_instance_class_init(GKaitaiInstanceClass *);
+
+/* Initialise une instance de spécification Kaitai. */
+static void g_kaitai_instance_init(GKaitaiInstance *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_instance_dispose(GKaitaiInstance *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_instance_finalize(GKaitaiInstance *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      CORRESPONDANCE ENTRE INSTANCE ET BINAIRE                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une instance de la spécification Kaitai. */
+G_DEFINE_TYPE(GKaitaiInstance, g_kaitai_instance, G_TYPE_KAITAI_ATTRIBUTE);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des instances de spécification Kaitai.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_instance_class_init(GKaitaiInstanceClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GKaitaiParserClass *parser;             /* Ancêtre parent de la classe */
+    GKaitaiAttributeClass *attrib;          /* Version parente de la classe*/
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_instance_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_kaitai_instance_finalize;
+
+    parser = G_KAITAI_PARSER_CLASS(klass);
+
+    parser->parse = (parse_kaitai_fc)g_kaitai_instance_parse_content;
+
+    attrib = G_KAITAI_ATTRIBUTE_CLASS(klass);
+
+    attrib->get_label = (get_attribute_label_fc)g_kaitai_instance_get_name;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inst = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance de spécification Kaitai.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_instance_init(GKaitaiInstance *inst)
+{
+    inst->name = NULL;
+
+    inst->io = NULL;
+    inst->pos = NULL;
+    inst->value = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inst = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_instance_dispose(GKaitaiInstance *inst)
+{
+    G_OBJECT_CLASS(g_kaitai_instance_parent_class)->dispose(G_OBJECT(inst));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inst = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_instance_finalize(GKaitaiInstance *inst)
+{
+    if (inst->name != NULL)
+        free(inst->name);
+
+    if (inst->io != NULL)
+        free(inst->io);
+
+    if (inst->pos != NULL)
+        free(inst->pos);
+
+    if (inst->value != NULL)
+        free(inst->value);
+
+    G_OBJECT_CLASS(g_kaitai_instance_parent_class)->finalize(G_OBJECT(inst));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = noeud Yaml contenant l'instance à constituer.       *
+*                                                                             *
+*  Description : Construit un lecteur d'instance Kaitai.                      *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiInstance *g_kaitai_instance_new(GYamlNode *parent)
+{
+    GKaitaiInstance *result;               /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_KAITAI_INSTANCE, NULL);
+
+    if (!g_kaitai_instance_create(result, parent))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inst   = lecteur d'instance Kaitai à initialiser pleinement. *
+*                parent = noeud Yaml contenant l'instance à constituer.       *
+*                                                                             *
+*  Description : Met en place un lecteur d'instance Kaitai.                   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_instance_create(GKaitaiInstance *inst, GYamlNode *parent)
+{
+    bool result;                            /* Bilan à retourner           */
+    const char *name;                       /* Désignation du type         */
+    char *sub_path;                         /* Chemin d'accès suivant      */
+    GYamlNode *sub;                         /* Contenu Yaml d'un type      */
+    GYamlNode *node;                        /* Noeud particulier présent   */
+    const char *value;                      /* Valeur Yaml particulière    */
+
+    result = false;
+
+    /* Extraction du nom */
+
+    if (!G_IS_YAML_PAIR(parent))
+        goto exit;
+
+    name = g_yaml_pair_get_key(G_YAML_PAIR(parent));
+
+    inst->name = strdup(name);
+
+    /* Extraction des bases du type */
+
+    asprintf(&sub_path, "/%s/", name);
+    sub = g_yaml_node_find_first_by_path(parent, sub_path);
+    free(sub_path);
+
+    if (sub == NULL)
+        goto exit;
+
+    result = g_kaitai_attribute_create(G_KAITAI_ATTRIBUTE(inst), sub, false);
+
+    /* Eventuel contenu imposé */
+
+    node = g_yaml_node_find_first_by_path(sub, "/io");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+        if (value == NULL)
+        {
+            g_object_unref(G_OBJECT(node));
+            goto bad_loading;
+        }
+
+        inst->io = strdup(value);
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Eventuelle positiion imposée */
+
+    node = g_yaml_node_find_first_by_path(sub, "/pos");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+        if (value == NULL)
+        {
+            g_object_unref(G_OBJECT(node));
+            goto bad_loading;
+        }
+
+        inst->pos = strdup(value);
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Eventuelle formule de calcul d'une valeur */
+
+    node = g_yaml_node_find_first_by_path(sub, "/value");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        inst->value = g_yaml_pair_aggregate_value(G_YAML_PAIR(node));
+
+        g_object_unref(G_OBJECT(node));
+
+        if (inst->value == NULL)
+            goto bad_loading;
+
+    }
+
+ bad_loading:
+
+    g_object_unref(G_OBJECT(sub));
+
+ exit:
+
+    if (result)
+        result = (inst->pos != NULL || inst->value != NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inst = lecteur d'instance Kaitai à consulter.                *
+*                                                                             *
+*  Description : Indique le nom attribué à une instance Kaitai.               *
+*                                                                             *
+*  Retour      : Désignation pointant l'instance.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_kaitai_instance_get_name(const GKaitaiInstance *inst)
+{
+    char *result;                           /* Valeur à renvoyer           */
+
+    result = inst->name;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inst   = lecteur d'instance Kaitai à consulter.              *
+*                locals = variables locales pour les résolutions de types.    *
+*                value  = valeur à sauvegarder sous une forme générique. [OUT]*
+*                                                                             *
+*  Description : Détermine la valeur d'un élément Kaitai entier calculé.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_instance_compute_value(const GKaitaiInstance *inst, const kaitai_scope_t *locals, resolved_value_t *value)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (inst->value == NULL)
+        result = false;
+
+    else
+        result = resolve_kaitai_expression_as_any(locals,
+                                                      inst->value,
+                                                      strlen(inst->value),
+                                                      value);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inst    = structure Kaitai en cours de parcours.             *
+*                locals  = variables locales pour les résolutions de types.   *
+*                content = données binaires à analyser et traduire.           *
+*                pos     = tête de lecture courante. [OUT]                    *
+*                record  = noeud d'arborescence d'éléments rencontrés. [OUT]  *
+*                                                                             *
+*  Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
+*                                                                             *
+*  Retour      : Bilan de l'opératon : true pour continuer, false sinon.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinContent *work_area;                 /* Aire de travail             */
+    GKaitaiStream *stream;                  /* Flux de données pour Kaitai */
+    resolved_value_t offset;                /* Position à adopter          */
+    vmpa2t forced_pos;                      /* Tete de lecture constituée  */
+    GKaitaiParserClass *class;              /* Classe parente à solliciter */
+
+    if (inst->value != NULL)
+    {
+        *record = G_MATCH_RECORD(g_record_value_new(inst, locals));
+
+        result = (*record != NULL);
+
+    }
+
+    else
+    {
+        /* Contenu particulier */
+
+        if (inst->io == NULL)
+            work_area = content;
+
+        else
+        {
+            result = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream);
+            if (!result) goto exit;
+
+            work_area = g_kaitai_stream_get_content(stream);
+
+            g_object_unref(G_OBJECT(stream));
+
+        }
+
+        /* Tête de lecture */
+
+        g_binary_content_compute_start_pos(work_area, &forced_pos);
+
+        result = resolve_kaitai_expression_as_integer(locals, inst->pos, strlen(inst->pos), &offset);
+        if (!result) goto exit_with_content;
+
+        if (offset.type == GVT_UNSIGNED_INTEGER)
+            advance_vmpa(&forced_pos, offset.unsigned_integer);
+
+        else
+        {
+            assert(offset.type == GVT_SIGNED_INTEGER);
+
+            if (offset.signed_integer < 0)
+            {
+                result = false;
+                goto exit_with_content;
+            }
+
+            advance_vmpa(&forced_pos, offset.signed_integer);
+
+        }
+
+        /* Lecture */
+
+        class = G_KAITAI_PARSER_CLASS(g_kaitai_instance_parent_class);
+
+        result = class->parse(G_KAITAI_PARSER(inst), locals, work_area, &forced_pos, record);
+
+ exit_with_content:
+
+        if (work_area != content)
+            g_object_unref(G_OBJECT(work_area));
+
+    }
+
+ exit:
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parsers/instance.h b/plugins/kaitai/parsers/instance.h
new file mode 100644
index 0000000..a9aee9a
--- /dev/null
+++ b/plugins/kaitai/parsers/instance.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instance.h - prototypes pour la spécification d'une instance Kaitai
+ *
+ * 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_PARSERS_INSTANCE_H
+#define _PLUGINS_KAITAI_PARSERS_INSTANCE_H
+
+
+#include <glib-object.h>
+
+
+#include <plugins/yaml/node.h>
+
+
+#include "../expression.h"
+#include "../scope.h"
+
+
+
+#define G_TYPE_KAITAI_INSTANCE            g_kaitai_instance_get_type()
+#define G_KAITAI_INSTANCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_INSTANCE, GKaitaiInstance))
+#define G_IS_KAITAI_INSTANCE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_INSTANCE))
+#define G_KAITAI_INSTANCE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_INSTANCE, GKaitaiInstanceClass))
+#define G_IS_KAITAI_INSTANCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_INSTANCE))
+#define G_KAITAI_INSTANCE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_INSTANCE, GKaitaiInstanceClass))
+
+
+/* Spécification d'une instance Kaitai (instance) */
+typedef struct _GKaitaiInstance GKaitaiInstance;
+
+/* Spécification d'une instance Kaitai (classe) */
+typedef struct _GKaitaiInstanceClass GKaitaiInstanceClass;
+
+
+/* Indique le type défini pour une instance de la spécification Kaitai. */
+GType g_kaitai_instance_get_type(void);
+
+/* Construit un lecteur d'instance Kaitai. */
+GKaitaiInstance *g_kaitai_instance_new(GYamlNode *);
+
+/* Indique le nom attribué à une instance Kaitai. */
+const char *g_kaitai_instance_get_name(const GKaitaiInstance *);
+
+/* Détermine la valeur d'un élément Kaitai entier calculé. */
+bool g_kaitai_instance_compute_value(const GKaitaiInstance *, const kaitai_scope_t *, resolved_value_t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PARSERS_INSTANCE_H */
diff --git a/plugins/kaitai/parsers/meta-int.h b/plugins/kaitai/parsers/meta-int.h
new file mode 100644
index 0000000..7d847ef
--- /dev/null
+++ b/plugins/kaitai/parsers/meta-int.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * meta-int.h - prototypes internes pour la description globale d'une définition Kaitai
+ *
+ * Copyright (C) 2019 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_PARSERS_META_INT_H
+#define PLUGINS_KAITAI_PARSERS_META_INT_H
+
+
+#include "meta.h"
+
+
+
+/* Description globale d'une définition Kaitai (instance) */
+struct _GKaitaiMeta
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    char *id;                               /* Identifiant attribué        */
+    char *title;                            /* Désignation de la définition*/
+
+    SourceEndian endian;                    /* Boutisme par défaut         */
+
+};
+
+/* Description globale d'une définition Kaitai (classe) */
+struct _GKaitaiMetaClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+};
+
+
+/* Met en place une description globale Kaitai. */
+bool g_kaitai_meta_create(GKaitaiMeta *, GYamlNode *);
+
+
+
+#endif  /* PLUGINS_KAITAI_PARSERS_META_INT_H */
diff --git a/plugins/kaitai/parsers/meta.c b/plugins/kaitai/parsers/meta.c
new file mode 100644
index 0000000..dc30c73
--- /dev/null
+++ b/plugins/kaitai/parsers/meta.c
@@ -0,0 +1,319 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * meta.c - description globale d'une définition Kaitai
+ *
+ * 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 "meta.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <plugins/yaml/pair.h>
+
+
+#include "meta-int.h"
+
+
+
+/* Initialise la classe des descriptions globales Kaitai. */
+static void g_kaitai_meta_class_init(GKaitaiMetaClass *);
+
+/* Initialise une description globale de définition Kaitai. */
+static void g_kaitai_meta_init(GKaitaiMeta *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_meta_dispose(GKaitaiMeta *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_meta_finalize(GKaitaiMeta *);
+
+
+
+/* Indique le type défini pour une description globale Kaitai. */
+G_DEFINE_TYPE(GKaitaiMeta, g_kaitai_meta, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des descriptions globales Kaitai.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_meta_class_init(GKaitaiMetaClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_meta_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_kaitai_meta_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : meta = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une description globale de définition Kaitai.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_meta_init(GKaitaiMeta *meta)
+{
+    meta->id = NULL;
+    meta->title = NULL;
+
+    meta->endian = SRE_LITTLE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : meta = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_meta_dispose(GKaitaiMeta *meta)
+{
+    G_OBJECT_CLASS(g_kaitai_meta_parent_class)->dispose(G_OBJECT(meta));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : meta = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_meta_finalize(GKaitaiMeta *meta)
+{
+    if (meta->id != NULL)
+        free(meta->id);
+
+    if (meta->title != NULL)
+        free(meta->title);
+
+    G_OBJECT_CLASS(g_kaitai_meta_parent_class)->finalize(G_OBJECT(meta));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = noeud Yaml contenant l'attribut à constituer.       *
+*                                                                             *
+*  Description : Construit une description globale Kaitai.                    *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiMeta *g_kaitai_meta_new(GYamlNode *parent)
+{
+    GKaitaiMeta *result;                   /* Identifiant à retourner     */
+
+    result = g_object_new(G_TYPE_KAITAI_META, NULL);
+
+    if (!g_kaitai_meta_create(result, parent))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : meta   = description globale à initialiser pleinement.       *
+*                parent = noeud Yaml contenant l'attribut à constituer.       *
+*                                                                             *
+*  Description : Met en place une description globale Kaitai.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+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    */
+
+    result = true;
+
+    /* Identifiant */
+
+    node = g_yaml_node_find_first_by_path(parent, "/meta/id");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (value != NULL)
+            meta->id = strdup(value);
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Titre */
+
+    node = g_yaml_node_find_first_by_path(parent, "/meta/title");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (value != NULL)
+            meta->title = strdup(value);
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    /* Boutisme */
+
+    node = g_yaml_node_find_first_by_path(parent, "/meta/endian");
+
+    if (node != NULL)
+    {
+        assert(G_IS_YAML_PAIR(node));
+
+        value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+        if (strcmp(value, "le") == 0)
+            meta->endian = SRE_LITTLE;
+
+        else if (strcmp(value, "be") == 0)
+            meta->endian = SRE_BIG;
+
+        g_object_unref(G_OBJECT(node));
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : meta = description globale à consulter.                      *
+*                                                                             *
+*  Description : Fournit l'identifié associé à une définiton Kaitai.          *
+*                                                                             *
+*  Retour      : Identifiant de définition complète ou NULL.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_kaitai_meta_get_id(const GKaitaiMeta *meta)
+{
+    const char *result;                     /* Chaîne à retourner          */
+
+    result = meta->id;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : meta = description globale à consulter.                      *
+*                                                                             *
+*  Description : Fournit la désignation humaine d'une définiton Kaitai.       *
+*                                                                             *
+*  Retour      : Intitulé de définition OU NULL.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_kaitai_meta_get_title(const GKaitaiMeta *meta)
+{
+    const char *result;                     /* Chaîne à retourner          */
+
+    result = meta->title;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : meta = description globale à consulter.                      *
+*                                                                             *
+*  Description : Indique le boustime observé par défaut par une définiton.    *
+*                                                                             *
+*  Retour      : Boustime, petit par défaut.                                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *meta)
+{
+    SourceEndian result;                    /* Chaîne à retourner          */
+
+    result = meta->endian;
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parsers/meta.h b/plugins/kaitai/parsers/meta.h
new file mode 100644
index 0000000..3797823
--- /dev/null
+++ b/plugins/kaitai/parsers/meta.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * meta.h - prototypes pour la description globale d'une définition Kaitai
+ *
+ * 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_PARSERS_META_H
+#define _PLUGINS_KAITAI_PARSERS_META_H
+
+
+#include <glib-object.h>
+
+
+#include <common/endianness.h>
+#include <plugins/yaml/node.h>
+
+
+
+#define G_TYPE_KAITAI_META            g_kaitai_meta_get_type()
+#define G_KAITAI_META(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_META, GKaitaiMeta))
+#define G_IS_KAITAI_META(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_META))
+#define G_KAITAI_META_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_META, GKaitaiMetaClass))
+#define G_IS_KAITAI_META_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_META))
+#define G_KAITAI_META_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_META, GKaitaiMetaClass))
+
+
+/* Description globale d'une définition Kaitai (instance) */
+typedef struct _GKaitaiMeta GKaitaiMeta;
+
+/* Description globale d'une définition Kaitai (classe) */
+typedef struct _GKaitaiMetaClass GKaitaiMetaClass;
+
+
+/* Indique le type défini pour une description globale Kaitai. */
+GType g_kaitai_meta_get_type(void);
+
+/* Construit une description globale Kaitai. */
+GKaitaiMeta *g_kaitai_meta_new(GYamlNode *);
+
+/* Fournit l'identifié associé à une définiton Kaitai. */
+const char *g_kaitai_meta_get_id(const GKaitaiMeta *);
+
+/* Fournit la désignation humaine d'une définiton Kaitai. */
+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 *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PARSERS_META_H */
diff --git a/plugins/kaitai/parsers/struct-int.h b/plugins/kaitai/parsers/struct-int.h
new file mode 100644
index 0000000..f34be32
--- /dev/null
+++ b/plugins/kaitai/parsers/struct-int.h
@@ -0,0 +1,75 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct-int.h - prototypes internes pour la définition d'une structure Kaitai
+ *
+ * Copyright (C) 2019 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_PARSERS_STRUCT_INT_H
+#define PLUGINS_KAITAI_PARSERS_STRUCT_INT_H
+
+
+#include "attribute.h"
+#include "instance.h"
+#include "struct.h"
+#include "../parser-int.h"
+
+
+
+/* Spécification d'une structure Kaitai (instance) */
+struct _GKaitaiStruct
+{
+    GKaitaiParser parent;                   /* A laisser en premier        */
+
+    GKaitaiMeta *meta;                      /* Description globale         */
+
+    GKaitaiAttribute **seq_items;           /* Sous-attributs présents     */
+    size_t seq_items_count;                 /* Quantité de ces attributs   */
+
+    GKaitaiType **types;                    /* Types particuliers définis  */
+    size_t types_count;                     /* Quantité de ces types       */
+
+    GKaitaiInstance **instances;            /* Instances prises en charge  */
+    size_t instances_count;                 /* Quantité de ces instances   */
+
+    GKaitaiEnum **enums;                    /* Enumérations locales        */
+    size_t enums_count;                     /* Quantité de ces énumérations*/
+
+};
+
+/* Spécification d'une structure Kaitai (classe) */
+struct _GKaitaiStructClass
+{
+    GKaitaiParserClass parent;              /* A laisser en premier        */
+
+};
+
+
+/* Met en place un interpréteur de définitions Kaitai. */
+bool g_kaitai_structure_create_from_text(GKaitaiStruct *, const char *);
+
+/* Met en place un interpréteur de définitions Kaitai. */
+bool g_kaitai_structure_create_from_file(GKaitaiStruct *, const char *);
+
+/* Met en place un lecteur de définitions Kaitai. */
+bool g_kaitai_structure_create(GKaitaiStruct *, GYamlNode *);
+
+
+
+#endif  /* PLUGINS_KAITAI_PARSERS_STRUCT_INT_H */
diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c
new file mode 100644
index 0000000..6d97110
--- /dev/null
+++ b/plugins/kaitai/parsers/struct.c
@@ -0,0 +1,782 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct.c - définition d'une structure Kaitai
+ *
+ * Copyright (C) 2019 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 "struct.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include <plugins/yaml/collection.h>
+#include <plugins/yaml/parser.h>
+
+
+#include "struct-int.h"
+#include "../parser.h"
+#include "../records/empty.h"
+#include "../records/group.h"
+
+
+
+/* ---------------------- LECTURE D'UNE TRANCHE DE DEFINITIONS ---------------------- */
+
+
+/* Initialise la classe des structuts de spécification Kaitai. */
+static void g_kaitai_structure_class_init(GKaitaiStructClass *);
+
+/* Initialise un structut de spécification Kaitai. */
+static void g_kaitai_structure_init(GKaitaiStruct *);
+
+/* Supprime toutes les références externes. */
+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 un ensemble de définitions Kaitai. */
+static bool g_kaitai_structure_load(GKaitaiStruct *, GYamlNode *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        LECTURE D'UNE TRANCHE DE DEFINITIONS                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un structut de la spécification Kaitai. */
+G_DEFINE_TYPE(GKaitaiStruct, g_kaitai_structure, G_TYPE_KAITAI_PARSER);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des structuts de spécification Kaitai.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_structure_class_init(GKaitaiStructClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GKaitaiParserClass *parser;             /* Version parente de la classe*/ 
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_structure_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_kaitai_structure_finalize;
+
+    parser = G_KAITAI_PARSER_CLASS(klass);
+
+    parser->parse = (parse_kaitai_fc)g_kaitai_structure_parse_content;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = instance à initialiser.                            *
+*                                                                             *
+*  Description : Initialise un structure de spécification Kaitai.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_structure_init(GKaitaiStruct *kstruct)
+{
+    kstruct->meta = NULL;
+
+    kstruct->seq_items = NULL;
+    kstruct->seq_items_count = 0;
+
+    kstruct->types = NULL;
+    kstruct->types_count = 0;
+
+    kstruct->instances = NULL;
+    kstruct->instances_count = 0;
+
+    kstruct->enums = NULL;
+    kstruct->enums_count = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_structure_dispose(GKaitaiStruct *kstruct)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    g_clear_object(&kstruct->meta);
+
+    for (i = 0; i < kstruct->seq_items_count; i++)
+        g_clear_object(&kstruct->seq_items[i]);
+
+    for (i = 0; i < kstruct->types_count; i++)
+        g_clear_object(&kstruct->types[i]);
+
+    for (i = 0; i < kstruct->instances_count; i++)
+        g_clear_object(&kstruct->instances[i]);
+
+    for (i = 0; i < kstruct->enums_count; i++)
+        g_clear_object(&kstruct->enums[i]);
+
+    G_OBJECT_CLASS(g_kaitai_structure_parent_class)->dispose(G_OBJECT(kstruct));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_structure_finalize(GKaitaiStruct *kstruct)
+{
+    if (kstruct->seq_items != NULL)
+        free(kstruct->seq_items);
+
+    if (kstruct->types != NULL)
+        free(kstruct->types);
+
+    if (kstruct->instances != NULL)
+        free(kstruct->instances);
+
+    if (kstruct->enums != NULL)
+        free(kstruct->enums);
+
+    G_OBJECT_CLASS(g_kaitai_structure_parent_class)->finalize(G_OBJECT(kstruct));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : text = définitions textuelles d'un contenu brut.             *
+*                                                                             *
+*  Description : Crée un nouvel interpréteur de structure Kaitai.             *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiStruct *g_kaitai_structure_new_from_text(const char *text)
+{
+    GKaitaiStruct *result;                  /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_KAITAI_STRUCT, NULL);
+
+    if (!g_kaitai_structure_create_from_text(result, text))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = lecteur de définition à initialiser pleinement.    *
+*                text    = définitions textuelles d'un contenu brut.          *
+*                                                                             *
+*  Description : Met en place un interpréteur de définitions Kaitai.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_structure_create_from_text(GKaitaiStruct *kstruct, const char *text)
+{
+    bool result;                            /* Bilan à retourner           */
+    GYamlNode *root;                        /* Noeud racine YAML           */
+
+    root = parse_yaml_from_text(text, strlen(text));
+
+    if (root != NULL)
+    {
+        result = g_kaitai_structure_load(kstruct, root);
+        g_object_unref(G_OBJECT(root));
+    }
+    else
+    {
+        fprintf(stderr, "The provided YAML content seems invalid");
+        result = false;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : filename = chemin vers des définitions de règles.            *
+*                                                                             *
+*  Description : Crée un nouvel interpréteur de structure Kaitai.             *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiStruct *g_kaitai_structure_new_from_file(const char *filename)
+{
+    GKaitaiStruct *result;                  /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_KAITAI_STRUCT, NULL);
+
+    if (!g_kaitai_structure_create_from_file(result, filename))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct  = lecteur de définition à initialiser pleinement.   *
+*                filename = chemin vers des définitions de règles.            *
+*                                                                             *
+*  Description : Met en place un interpréteur de définitions Kaitai.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_structure_create_from_file(GKaitaiStruct *kstruct, const char *filename)
+{
+    bool result;                            /* Bilan à retourner           */
+    GYamlNode *root;                        /* Noeud racine YAML           */
+
+    root = parse_yaml_from_file(filename);
+
+    if (root != NULL)
+    {
+        result = g_kaitai_structure_load(kstruct, root);
+        g_object_unref(G_OBJECT(root));
+    }
+    else
+    {
+        fprintf(stderr, "The provided YAML content seems invalid");
+        result = false;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = lecteur de définition à initialiser pleinement.    *
+*                root    = racine YAML à parcourir.                           *
+*                                                                             *
+*  Description : Charge un ensemble de définitions Kaitai.                    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_structure_load(GKaitaiStruct *kstruct, GYamlNode *root)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_kaitai_structure_create(kstruct, root);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = lecteur de définition à initialiser pleinement.    *
+*                parent  = noeud Yaml contenant l'attribut à constituer.      *
+*                                                                             *
+*  Description : Met en place un lecteur de définitions Kaitai.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
+{
+    bool result;                            /* Bilan à retourner           */
+    GYamlNode *collec;                      /* Liste de noeuds à traiter   */
+    GYamlNode **nodes;                      /* Eventuels noeuds trouvés    */
+    size_t count;                           /* Quantité de ces noeuds      */
+    size_t i;                               /* Boucle de parcours          */
+    bool failed;                            /* Détection d'un échec        */
+
+    result = false;
+
+    /* Informations générales */
+
+    kstruct->meta = g_kaitai_meta_new(parent);
+    assert(kstruct->meta != NULL);
+
+    /* Séquence */
+
+    collec = g_yaml_node_find_first_by_path(parent, "/seq/");
+
+    if (collec != NULL)
+    {
+        if (G_IS_YAML_COLLEC(collec))
+            nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+        else
+            count = 0;
+
+        if (count > 0)
+        {
+            kstruct->seq_items = calloc(count, sizeof(GKaitaiAttribute *));
+            kstruct->seq_items_count = count;
+
+            for (i = 0; i < count; i++)
+            {
+                kstruct->seq_items[i] = g_kaitai_attribute_new(nodes[i]);
+                if (kstruct->seq_items[i] == NULL) break;
+
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            }
+
+            failed = (i < count);
+
+            for (; i < count; i++)
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            free(nodes);
+
+            if (failed)
+                goto bad_loading;
+
+        }
+
+        g_object_unref(G_OBJECT(collec));
+
+    }
+
+    /* Types particuliers éventuels */
+
+    collec = g_yaml_node_find_first_by_path(parent, "/types/");
+
+    if (collec != NULL)
+    {
+        if (G_IS_YAML_COLLEC(collec))
+            nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+        else
+            count = 0;
+
+        if (count > 0)
+        {
+            kstruct->types = calloc(count, sizeof(GKaitaiType *));
+            kstruct->types_count = count;
+
+            for (i = 0; i < count; i++)
+            {
+                kstruct->types[i] = g_kaitai_type_new(nodes[i]);
+                if (kstruct->types[i] == NULL) break;
+
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            }
+
+            failed = (i < count);
+
+            for (; i < count; i++)
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            free(nodes);
+
+            if (failed)
+                goto bad_loading;
+
+        }
+
+        g_object_unref(G_OBJECT(collec));
+
+    }
+
+    /* Instances éventuelles */
+
+    collec = g_yaml_node_find_first_by_path(parent, "/instances/");
+
+    if (collec != NULL)
+    {
+        if (G_IS_YAML_COLLEC(collec))
+            nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+        else
+            count = 0;
+
+        if (count > 0)
+        {
+            kstruct->instances = calloc(count, sizeof(GKaitaiInstance *));
+            kstruct->instances_count = count;
+
+            for (i = 0; i < count; i++)
+            {
+                kstruct->instances[i] = g_kaitai_instance_new(nodes[i]);
+                if (kstruct->instances[i] == NULL) break;
+
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            }
+
+            failed = (i < count);
+
+            for (; i < count; i++)
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            free(nodes);
+
+            if (failed)
+                goto bad_loading;
+
+        }
+
+        g_object_unref(G_OBJECT(collec));
+
+    }
+
+    /* Enumérations éventuelles */
+
+    collec = g_yaml_node_find_first_by_path(parent, "/enums/");
+
+    if (collec != NULL)
+    {
+        if (G_IS_YAML_COLLEC(collec))
+            nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+        else
+            count = 0;
+
+        if (count > 0)
+        {
+            kstruct->enums = calloc(count, sizeof(GKaitaiEnum *));
+            kstruct->enums_count = count;
+
+            for (i = 0; i < count; i++)
+            {
+                kstruct->enums[i] = g_kaitai_enum_new(nodes[i]);
+                if (kstruct->enums[i] == NULL) break;
+
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            }
+
+            failed = (i < count);
+
+            for (; i < count; i++)
+                g_object_unref(G_OBJECT(nodes[i]));
+
+            free(nodes);
+
+            if (failed)
+                goto bad_loading;
+
+        }
+
+        g_object_unref(G_OBJECT(collec));
+
+    }
+
+    /* Sortie heureuse */
+
+    result = true;
+
+ bad_loading:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = structure Kaitai à consulter.                      *
+*                                                                             *
+*  Description : Fournit la description globale d'une définition Kaitai.      *
+*                                                                             *
+*  Retour      : Description de la définition Kaitai courante.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiMeta *g_kaitai_structure_get_meta(const GKaitaiStruct *kstruct)
+{
+    GKaitaiMeta *result;                    /* Informations à retourner    */ 
+
+    result = kstruct->meta;
+
+    if (result != NULL)
+        g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = structure Kaitai en cours de parcours.             *
+*                name    = désignation principale des énumérations ciblées.   *
+*                                                                             *
+*  Description : Fournit un ensemble d'énumérations locales de la structure.  *
+*                                                                             *
+*  Retour      : Enumérations locales ou NULL si non trouvée.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiEnum *g_kaitai_structure_get_enum(const GKaitaiStruct *kstruct, const sized_string_t *name)
+{
+    GKaitaiEnum *result;                    /* Instance à retourner        */
+    size_t i;                               /* Boucle de parcours          */
+    const char *other;                      /* Autre désignation à comparer*/
+
+    result = NULL;
+
+    for (i = 0; i < kstruct->enums_count; i++)
+    {
+        other = g_kaitai_enum_get_name(kstruct->enums[i]);
+
+        if (szstrcmp(name, other) == 0)
+        {
+            result = kstruct->enums[i];
+            g_object_ref(G_OBJECT(result));
+            break;
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = structure Kaitai en cours de parcours.             *
+*                name    = désignation du type particulier ciblé.             *
+*                                                                             *
+*  Description : Recherche la définition d'un type nouveau pour Kaitai.       *
+*                                                                             *
+*  Retour      : Type prêt à emploi ou NULL si non trouvé.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiType *g_kaitai_structure_find_sub_type(const GKaitaiStruct *kstruct, const char *name)
+{
+    GKaitaiType *result;                    /* Instance à retourner        */
+    size_t i;                               /* Boucle de parcours          */
+    const char *other;                      /* Autre désignation à comparer*/
+
+    result = NULL;
+
+    for (i = 0; i < kstruct->types_count; i++)
+    {
+        other = g_kaitai_type_get_name(kstruct->types[i]);
+
+        if (strcmp(name, other) == 0)
+        {
+            result = kstruct->types[i];
+            g_object_ref(G_OBJECT(result));
+            break;
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = structure Kaitai en cours de parcours.             *
+*                content = contenu binaire en cours de traitement.            *
+*                                                                             *
+*  Description : Parcourt un contenu binaire selon une description Kaitai.    *
+*                                                                             *
+*  Retour      : Arborescence d'éléments rencontrés selon les spécifications. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *content)
+{
+    GMatchRecord *result;                   /* Arborescence à retourner    */ 
+    vmpa2t pos;                             /* Tête de lecture             */
+    kaitai_scope_t locals;                  /* Variables locales           */
+    bool status;                            /* Bilan de l'analyse          */
+
+    g_binary_content_compute_start_pos(content, &pos);
+
+    init_record_scope(&locals, kstruct->meta);
+
+    status = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &pos, &result);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = structure Kaitai en cours de parcours.             *
+*                locals  = variables locales pour les résolutions de types.   *
+*                content = données binaires à analyser et traduire.           *
+*                pos     = tête de lecture courante. [OUT]                    *
+*                record  = noeud d'arborescence d'éléments rencontrés. [OUT]  *
+*                                                                             *
+*  Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
+*                                                                             *
+*  Retour      : Bilan de l'opératon : true pour continuer, false sinon.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+{
+    bool result;                            /* Bilan à retourner           */
+    GRecordGroup *group;                    /* Ensemble à constituer       */
+    GMatchRecord *old;                      /* Sauvegarde de valeur        */
+    size_t i;                               /* Boucle de parcours          */
+    GMatchRecord *child;                    /* Nouvel élément mis en place */
+
+    result = true;
+
+    /* Si le groupe est vide */
+    if ((kstruct->seq_items_count + kstruct->instances_count) == 0)
+    {
+        *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, pos));
+
+        if (locals->root == NULL)
+            locals->root = *record;
+
+    }
+
+    /* Sinon on construit selon les définitions fournies */
+    else
+    {
+        group = g_record_group_new(kstruct, content);
+        *record = G_MATCH_RECORD(group);
+
+        if (locals->root == NULL)
+            locals->root = *record;
+
+        old = locals->parent;
+        locals->parent = *record;
+
+        for (i = 0; i < kstruct->seq_items_count; i++)
+        {
+            result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]),
+                                                   locals, content, pos, &child);
+            if (!result) goto exit;
+
+            if (child != NULL)
+            {
+                g_record_group_add_record(group, child);
+                g_object_unref(G_OBJECT(child));
+            }
+
+        }
+
+        for (i = 0; i < kstruct->instances_count; i++)
+        {
+            result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]),
+                                                   locals, content, pos, &child);
+            if (!result) goto exit;
+
+            if (child != NULL)
+            {
+                g_record_group_add_record(group, child);
+                g_object_unref(G_OBJECT(child));
+            }
+
+        }
+
+ exit:
+
+        locals->parent = old;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parsers/struct.h b/plugins/kaitai/parsers/struct.h
new file mode 100644
index 0000000..4a2397a
--- /dev/null
+++ b/plugins/kaitai/parsers/struct.h
@@ -0,0 +1,80 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct.h - prototypes pour la définition d'une structure Kaitai
+ *
+ * Copyright (C) 2019 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_PARSERS_STRUCT_H
+#define _PLUGINS_KAITAI_PARSERS_STRUCT_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/content.h>
+
+
+#include "enum.h"
+#include "meta.h"
+#include "type.h"
+#include "../record.h"
+
+
+
+#define G_TYPE_KAITAI_STRUCT            g_kaitai_structure_get_type()
+#define G_KAITAI_STRUCT(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_STRUCT, GKaitaiStruct))
+#define G_IS_KAITAI_STRUCT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_STRUCT))
+#define G_KAITAI_STRUCT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_STRUCT, GKaitaiStructClass))
+#define G_IS_KAITAI_STRUCT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_STRUCT))
+#define G_KAITAI_STRUCT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_STRUCT, GKaitaiStructClass))
+
+
+/* Spécification d'une structure Kaitai (instance) */
+typedef struct _GKaitaiStruct GKaitaiStruct;
+
+/* Spécification d'une structure Kaitai (classe) */
+typedef struct _GKaitaiStructClass GKaitaiStructClass;
+
+
+/* Indique le type défini pour une structure Kaitai. */
+GType g_kaitai_structure_get_type(void);
+
+/* Crée un nouvel interpréteur de structure Kaitai. */
+GKaitaiStruct *g_kaitai_structure_new_from_text(const char *);
+
+/* Crée un nouvel interpréteur de structure Kaitai. */
+GKaitaiStruct *g_kaitai_structure_new_from_file(const char *);
+
+/* Fournit la description globale d'une définition Kaitai. */
+GKaitaiMeta *g_kaitai_structure_get_meta(const GKaitaiStruct *);
+
+/* Recherche la définition d'un type nouveau pour Kaitai. */
+GKaitaiType *g_kaitai_structure_find_sub_type(const GKaitaiStruct *, const char *);
+
+/* Fournit un ensemble d'énumérations locales de la structure. */
+GKaitaiEnum *g_kaitai_structure_get_enum(const GKaitaiStruct *, const sized_string_t *);
+
+/* Parcourt un contenu binaire selon une description Kaitai. */
+GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *, GBinContent *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PARSERS_STRUCT_H */
diff --git a/plugins/kaitai/parsers/switch-int.h b/plugins/kaitai/parsers/switch-int.h
new file mode 100644
index 0000000..a087e49
--- /dev/null
+++ b/plugins/kaitai/parsers/switch-int.h
@@ -0,0 +1,78 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * switch-int.h - prototypes internes pour la gestion des énumérations Kaitai
+ *
+ * Copyright (C) 2019 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_PARSERS_SWITCH_INT_H
+#define PLUGINS_KAITAI_PARSERS_SWITCH_INT_H
+
+
+#include "switch.h"
+#include "../parser-int.h"
+
+
+
+/* ------------------------ BASCULE DYNAMIQUE SELON CONTEXTE ------------------------ */
+
+
+/* Mémorisation d'une valeur d'énumération */
+typedef struct _switch_case_t
+{
+    char *value;                            /* Valeur d'association        */
+    char *type;                             /* Désignation du type associé */
+
+} switch_case_t;
+
+
+
+/* ----------------------- SELECTION DYNAMIQUE DE TYPE KAITAI ----------------------- */
+
+
+/* Sélection d'un type selon un contexte (instance) */
+struct _GKaitaiSwitch
+{
+    GKaitaiParser parent;                   /* A laisser en premier        */
+
+    char *target;                           /* Source de bascule           */
+
+    switch_case_t **cases;                  /* Choix de types potentiels   */
+    size_t count;                           /* Quantité de ces choix       */
+
+    switch_case_t *defcase;                 /* Choix par défaut ou NULL    */
+
+    GKaitaiAttribute *generic;              /* Attribut à dériver          */
+
+};
+
+/* Sélection d'un type selon un contexte (classe) */
+struct _GKaitaiSwitchClass
+{
+    GKaitaiParserClass parent;              /* A laisser en premier        */
+
+};
+
+
+/* Met en place une sélection dynamique de type Kaitai. */
+bool g_kaitai_switch_create(GKaitaiSwitch *, GYamlNode *, GKaitaiAttribute *);
+
+
+
+#endif  /* PLUGINS_KAITAI_PARSERS_SWITCH_INT_H */
diff --git a/plugins/kaitai/parsers/switch.c b/plugins/kaitai/parsers/switch.c
new file mode 100644
index 0000000..c823f27
--- /dev/null
+++ b/plugins/kaitai/parsers/switch.c
@@ -0,0 +1,706 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * switch.h - gestion des énumérations Kaitai
+ *
+ * Copyright (C) 2019 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 "switch.h"
+
+
+#include <assert.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include <common/extstr.h>
+#include <common/sort.h>
+#include <core/logs.h>
+#include <plugins/yaml/pair.h>
+
+
+#include "switch-int.h"
+#include "../expression.h"
+
+
+
+/* ------------------------ BASCULE DYNAMIQUE SELON CONTEXTE ------------------------ */
+
+
+/* Construit une valeur d'énumération à partir d'indications. */
+static switch_case_t *build_switch_case(const GYamlNode *, bool *);
+
+/* Supprime de la mémoire une bascule selon contexte. */
+static void delete_switch_case(switch_case_t *);
+
+/* Détermine si le cas correspond à une valeur de bascule. */
+static const char *is_suitable_switch_case_for_bytes(const switch_case_t *, const resolved_value_t *);
+
+/* Détermine si le cas correspond à une valeur de bascule. */
+static const char *is_suitable_switch_case_for_integer(const switch_case_t *, kaitai_scope_t *, const resolved_value_t *);
+
+
+
+/* ----------------------- SELECTION DYNAMIQUE DE TYPE KAITAI ----------------------- */
+
+
+/* Initialise la classe des sélections dynamiques de types. */
+static void g_kaitai_switch_class_init(GKaitaiSwitchClass *);
+
+/* Initialise une sélection dynamique de type Kaitai. */
+static void g_kaitai_switch_init(GKaitaiSwitch *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_switch_dispose(GKaitaiSwitch *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_switch_finalize(GKaitaiSwitch *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Parcourt un contenu binaire selon des spécifications Kaitai. */
+static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          BASCULE DYNAMIQUE SELON CONTEXTE                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : node    = noeud Yaml à venir lire.                           *
+*                defcase = indique si une valeur par défaut est visée. [OUT]  *
+*                                                                             *
+*  Description : Construit une valeur d'énumération à partir d'indications.   *
+*                                                                             *
+*  Retour      : Structure de valeur mise en place.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static switch_case_t *build_switch_case(const GYamlNode *node, bool *defcase)
+{
+    switch_case_t *result;                  /* Enregistrement à retourner  */
+    const char *key;                        /* Clef d'une conversion       */
+    const char *value;                      /* Valeur Yaml particulière    */
+
+    result = NULL;
+
+    if (!G_IS_YAML_PAIR(node))
+        goto exit;
+
+    key = g_yaml_pair_get_key(G_YAML_PAIR(node));
+    value = g_yaml_pair_get_value(G_YAML_PAIR(node));
+
+    if (value == NULL)
+        goto exit;
+
+    result = malloc(sizeof(switch_case_t));
+
+    result->value = strdup(key);
+    result->type = strdup(value);
+
+    *defcase = (strcmp(key, "_") == 0);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : swcase = valeur à traiter.                                   *
+*                                                                             *
+*  Description : Supprime de la mémoire une bascule selon contexte.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+*****************************************************************************/
+
+static void delete_switch_case(switch_case_t *swcase)
+{
+    free(swcase->value);
+
+    free(swcase->type);
+
+    free(swcase);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : swcase = valeur à analyser.                                  *
+*                value  = valeur à comparer.                                  *
+*                                                                             *
+*  Description : Détermine si le cas correspond à une valeur de bascule.      *
+*                                                                             *
+*  Retour      : Type à utiliser ou NULL si aucune correspondance établie.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+*****************************************************************************/
+
+static const char *is_suitable_switch_case_for_bytes(const switch_case_t *swcase, const resolved_value_t *value)
+{
+    const char *result;                     /* Désignation à retourner     */
+    sized_string_t key;                     /* Changement de format        */
+    bool valid;                             /* Validité des opérations     */
+    int ret;                                /* Bilan d'une comparaison     */
+
+    result = NULL;
+
+    key.data = swcase->value;
+    key.len = strlen(swcase->value);
+
+    valid = (key.len > 2);
+
+    if (valid)
+        valid = (swcase->value[0] == '"' || swcase->value[0] == '\'');
+
+    if (valid)
+    {
+        valid = (key.data[0] == key.data[key.len - 1]);
+
+        key.data++;
+        key.len -= 2;
+
+    }
+
+    if (valid)
+    {
+        if (value->type == GVT_BYTES)
+        {
+            ret = szmemcmp(&key, &value->bytes);
+
+            if (ret == 0)
+                result = swcase->type;
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : swcase = valeur à analyser.                                  *
+*                locals = variables locales pour les résolutions de types.    *
+*                value  = valeur à comparer.                                  *
+*                                                                             *
+*  Description : Détermine si le cas correspond à une valeur de bascule.      *
+*                                                                             *
+*  Retour      : Type à utiliser ou NULL si aucune correspondance établie.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+*****************************************************************************/
+
+static const char *is_suitable_switch_case_for_integer(const switch_case_t *swcase, kaitai_scope_t *locals, const resolved_value_t *value)
+{
+    const char *result;                     /* Désignation à retourner     */
+    bool valid;                             /* Validité des opérations     */
+    resolved_value_t key;                   /* Changement de format        */
+    unsigned long long unsigned_conv;       /* Valeur convertie #1         */
+    long long signed_conv;                  /* Valeur convertie #2         */
+
+    result = NULL;
+
+    valid = (swcase->value[0] != '"' && swcase->value[0] != '\'');
+
+    if (valid)
+    {
+        if (strchr(swcase->value, ':') != NULL)
+        {
+            valid = resolve_kaitai_expression_as_integer(locals, swcase->value, strlen(swcase->value), &key);
+
+            if (valid)
+            {
+                if (key.type == GVT_UNSIGNED_INTEGER)
+                {
+                    if (value->type == GVT_UNSIGNED_INTEGER)
+                    {
+                        if (key.unsigned_integer == value->unsigned_integer)
+                            result = swcase->type;
+                    }
+                    else
+                    {
+                        if (key.unsigned_integer == value->signed_integer)
+                            result = swcase->type;
+                    }
+                }
+                else
+                {
+                    if (value->type == GVT_UNSIGNED_INTEGER)
+                    {
+                        if (key.signed_integer == value->unsigned_integer)
+                            result = swcase->type;
+                    }
+                    else
+                    {
+                        if (key.signed_integer == value->signed_integer)
+                            result = swcase->type;
+                    }
+                }
+
+            }
+
+        }
+
+        else
+        {
+            if (value->type == GVT_UNSIGNED_INTEGER)
+            {
+                unsigned_conv = strtoull(swcase->value, NULL, 10);
+
+                valid = (errno != ERANGE && errno != EINVAL);
+
+                if (valid && unsigned_conv == value->unsigned_integer)
+                    result = swcase->type;
+
+            }
+            else
+            {
+                signed_conv = strtoll(swcase->value, NULL, 10);
+
+                valid = (errno != ERANGE && errno != EINVAL);
+
+                if (valid && signed_conv == value->signed_integer)
+                    result = swcase->type;
+
+            }
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         SELECTION DYNAMIQUE DE TYPE KAITAI                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un choix dynamique de type Kaitai. */
+G_DEFINE_TYPE(GKaitaiSwitch, g_kaitai_switch, G_TYPE_KAITAI_PARSER);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des sélections dynamiques de types.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_switch_class_init(GKaitaiSwitchClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GKaitaiParserClass *parser;             /* Version parente de la classe*/ 
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_switch_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_kaitai_switch_finalize;
+
+    parser = G_KAITAI_PARSER_CLASS(klass);
+
+    parser->parse = (parse_kaitai_fc)g_kaitai_switch_parse_content;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kswitch = instance à initialiser.                            *
+*                                                                             *
+*  Description : Initialise une sélection dynamique de type Kaitai.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_switch_init(GKaitaiSwitch *kswitch)
+{
+    kswitch->target = NULL;
+
+    kswitch->cases = NULL;
+    kswitch->count = 0;
+
+    kswitch->defcase = NULL;
+
+    kswitch->generic = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kswitch = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_switch_dispose(GKaitaiSwitch *kswitch)
+{
+    g_clear_object(&kswitch->generic);
+
+    G_OBJECT_CLASS(g_kaitai_switch_parent_class)->dispose(G_OBJECT(kswitch));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kswitch = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_switch_finalize(GKaitaiSwitch *kswitch)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    if (kswitch->target != NULL)
+        free(kswitch->target);
+
+    for (i = 0; i < kswitch->count; i++)
+        delete_switch_case(kswitch->cases[i]);
+
+    if (kswitch->cases != NULL)
+        free(kswitch->cases);
+
+    if (kswitch->defcase != NULL)
+        delete_switch_case(kswitch->defcase);
+
+    G_OBJECT_CLASS(g_kaitai_switch_parent_class)->finalize(G_OBJECT(kswitch));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent  = noeud Yaml contenant l'attribut à constituer.      *
+*                generic = lecteur d'attribut Kaitai à dériver.               *
+*                                                                             *
+*  Description : Construit une sélection dynamique de type Kaitai.            *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiSwitch *g_kaitai_switch_new(GYamlNode *parent, GKaitaiAttribute *generic)
+{
+    GKaitaiSwitch *result;                   /* Identifiant à retourner     */
+
+    result = g_object_new(G_TYPE_KAITAI_SWITCH, NULL);
+
+    if (!g_kaitai_switch_create(result, parent, generic))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kswitch = sélectionneur de type  à initialiser pleinement.   *
+*                parent  = noeud Yaml contenant l'attribut à constituer.      *
+*                generic = lecteur d'attribut Kaitai à dériver.               *
+*                                                                             *
+*  Description : Met en place une sélection dynamique de type Kaitai.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAttribute *generic)
+{
+    bool result;                            /* Bilan à retourner           */
+    GYamlNode *node;                        /* Noeud de définition         */
+    GYamlNode *subnode;                     /* Noeud de précisions         */
+    const char *value;                      /* Valeur Yaml particulière    */
+    GYamlNode *collec;                      /* Liste de noeuds à traiter   */
+    GYamlNode **subnodes;                   /* Eventuels noeuds trouvés    */
+    size_t count;                           /* Quantité de ces noeuds      */
+    size_t i;                               /* Boucle de parcours          */
+    bool defcase;                           /* Définition par défaut ?     */
+    switch_case_t *swcase;                  /* Bascule à noter             */
+
+    result = false;
+
+    node = g_yaml_node_find_first_by_path(parent, "/type/");
+    if (node == NULL) goto exit;
+
+    /* Source de la bascule */
+
+    subnode = g_yaml_node_find_first_by_path(node, "/switch-on");
+    assert(G_IS_YAML_PAIR(subnode));
+
+    value = g_yaml_pair_get_value(G_YAML_PAIR(subnode));
+    if (value == NULL)
+    {
+        g_object_unref(G_OBJECT(subnode));
+        goto bad_definition;
+    }
+
+    kswitch->target = strdup(value);
+
+    g_object_unref(G_OBJECT(subnode));
+
+    /* Conditions de bascule */
+
+    collec = g_yaml_node_find_first_by_path(node, "/cases/");
+    if (collec == NULL) goto bad_definition;
+    if (!G_IS_YAML_COLLEC(collec)) goto bad_definition;
+
+    subnodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(collec), &count);
+
+    g_object_unref(G_OBJECT(collec));
+
+    if (count == 0) goto bad_definition;
+
+    for (i = 0; i < count; i++)
+    {
+        swcase = build_switch_case(subnodes[i], &defcase);
+        if (swcase == NULL) break;
+
+        g_object_unref(G_OBJECT(subnodes[i]));
+
+        kswitch->cases = realloc(kswitch->cases, ++kswitch->count * sizeof(switch_case_t *));
+        kswitch->cases[kswitch->count - 1] = swcase;
+
+    }
+
+    result = (i == count);
+
+    for (; i < count; i++)
+        g_object_unref(G_OBJECT(subnodes[i]));
+
+    if (subnodes != NULL)
+        free(subnodes);
+
+    /* Fin des procédures */
+
+    if (result)
+    {
+        kswitch->generic = generic;
+        g_object_ref(G_OBJECT(generic));
+    }
+
+ bad_definition:
+
+    g_object_unref(G_OBJECT(node));
+
+ exit:
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kswitch = structure Kaitai en cours de parcours.             *
+*                locals  = variables locales pour les résolutions de types.   *
+*                content = données binaires à analyser et traduire.           *
+*                pos     = tête de lecture courante. [OUT]                    *
+*                record  = noeud d'arborescence d'éléments rencontrés. [OUT]  *
+*                                                                             *
+*  Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
+*                                                                             *
+*  Retour      : Bilan de l'opératon : true pour continuer, false sinon.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+{
+    bool result;                            /* Bilan à retourner           */
+    GMatchRecord *reference;                /* Correspondance à utiliser   */
+    GKaitaiParser *creator;                 /* Lecteur d'origine           */
+    KaitaiAttributePayload payload;         /* Type de charge supportée    */
+    BaseType basic;                         /* Type de base reconnu        */
+    bool is_string;                         /* Type lié à une chaîne ?     */
+#ifndef NDEBUG
+    bool status;                            /* Bilan d'une consultation    */
+#endif
+    const char *final_type;                 /* Type à utiliser au final    */
+    resolved_value_t value;                 /* Valeur de cible entière     */
+    size_t i;                               /* Boucle de parcours          */
+    GKaitaiAttribute *attrib;               /* Lecteur approprié           */
+
+    result = false;
+
+    /* Détermination de la forme de comparaison */
+
+    reference = g_match_record_find_by_name(locals->parent,
+                                            kswitch->target, strlen(kswitch->target),
+                                            DIRECT_SEARCH_DEEP_LEVEL);
+
+    if (reference == NULL)
+        goto exit;
+
+    creator = g_match_record_get_creator(reference);
+
+    if (creator == NULL)
+        goto exit_with_ref;
+
+    if (!G_IS_KAITAI_ATTRIBUTE(creator))
+        goto exit_with_creator;
+
+    payload = g_kaitai_attribute_get_payload(G_KAITAI_ATTRIBUTE(creator));
+
+    if ((payload & KAP_BASIC_TYPE) == 0)
+        goto exit_with_creator;
+
+#ifndef NDEBUG
+    status = g_kaitai_attribute_get_basic_type(G_KAITAI_ATTRIBUTE(creator), &basic, &is_string);
+    assert(status);
+#else
+    g_kaitai_attribute_get_basic_type(G_KAITAI_ATTRIBUTE(creator), &basic, &is_string);
+#endif
+
+    /* Détermination du type visé */
+
+    final_type = NULL;
+
+    if (is_string)
+    {
+        result = resolve_kaitai_expression_as_bytes(locals,
+                                                    kswitch->target,
+                                                    strlen(kswitch->target),
+                                                    &value);
+        if (!result) goto exit_with_creator;
+
+        for (i = 0; i < kswitch->count; i++)
+        {
+            final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value);
+
+            if (final_type != NULL)
+                break;
+
+        }
+
+    }
+
+    else
+    {
+        if (basic == BTP_UCHAR || basic == BTP_USHORT || basic == BTP_UINT || basic == BTP_ULONG_LONG)
+        {
+            result = resolve_kaitai_expression_as_integer(locals,
+                                                          kswitch->target,
+                                                          strlen(kswitch->target),
+                                                          &value);
+            if (!result) goto exit_with_creator;
+
+            for (i = 0; i < kswitch->count; i++)
+            {
+                final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value);
+
+                if (final_type != NULL)
+                    break;
+
+            }
+
+        }
+
+        else
+            printf("other type: %u\n", basic);
+
+    }
+
+    if (final_type == NULL && kswitch->defcase != NULL)
+        final_type = kswitch->defcase->type;
+
+    /* Mise en place d'un attribut et analyse */
+
+    if (final_type != NULL)
+    {
+        attrib = g_kaitai_attribute_dup_for_user_type(kswitch->generic, final_type);
+
+        result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib), locals, content, pos, record);
+
+        g_object_unref(G_OBJECT(attrib));
+
+    }
+
+ exit_with_creator:
+
+    g_object_unref(G_OBJECT(creator));
+
+ exit_with_ref:
+
+    g_object_unref(G_OBJECT(reference));
+
+ exit:
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parsers/switch.h b/plugins/kaitai/parsers/switch.h
new file mode 100644
index 0000000..c45237a
--- /dev/null
+++ b/plugins/kaitai/parsers/switch.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * switch.h - prototypes pour la gestion des énumérations Kaitai
+ *
+ * Copyright (C) 2019 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_PARSERS_SWITCH_H
+#define _PLUGINS_KAITAI_PARSERS_SWITCH_H
+
+
+#include <glib-object.h>
+
+
+#include <plugins/yaml/node.h>
+
+
+#include "attribute.h"
+
+
+
+#define G_TYPE_KAITAI_SWITCH            g_kaitai_switch_get_type()
+#define G_KAITAI_SWITCH(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_SWITCH, GKaitaiSwitch))
+#define G_IS_KAITAI_SWITCH(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_SWITCH))
+#define G_KAITAI_SWITCH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_SWITCH, GKaitaiSwitchClass))
+#define G_IS_KAITAI_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_SWITCH))
+#define G_KAITAI_SWITCH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_SWITCH, GKaitaiSwitchClass))
+
+
+/* Sélection d'un type selon un contexte (instance) */
+typedef struct _GKaitaiSwitch GKaitaiSwitch;
+
+/* Sélection d'un type selon un contexte (classe) */
+typedef struct _GKaitaiSwitchClass GKaitaiSwitchClass;
+
+
+/* Indique le type défini pour un choix dynamique de type Kaitai. */
+GType g_kaitai_switch_get_type(void);
+
+/* Construit une sélection dynamique de type Kaitai. */
+GKaitaiSwitch *g_kaitai_switch_new(GYamlNode *, GKaitaiAttribute *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PARSERS_SWITCH_H */
diff --git a/plugins/kaitai/parsers/type-int.h b/plugins/kaitai/parsers/type-int.h
new file mode 100644
index 0000000..4a4d939
--- /dev/null
+++ b/plugins/kaitai/parsers/type-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type-int.h - prototypes internes pour la définition d'un type particulier pour Kaitai
+ *
+ * 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_PARSERS_TYPE_INT_H
+#define PLUGINS_KAITAI_PARSERS_TYPE_INT_H
+
+
+#include "struct-int.h"
+#include "type.h"
+
+
+
+/* Définition d'un type particulier nouveau pour Kaitai (instance) */
+struct _GKaitaiType
+{
+    GKaitaiStruct parent;                   /* A laisser en premier        */
+
+    char *name;                             /* Nom du type particulier     */
+
+};
+
+/* Définition d'un type particulier nouveau pour Kaitai (classe) */
+struct _GKaitaiTypeClass
+{
+    GKaitaiStructClass parent;              /* A laisser en premier        */
+
+};
+
+
+/* Met en place un lecteur de type pour Kaitai. */
+bool g_kaitai_type_create(GKaitaiType *, GYamlNode *);
+
+
+
+#endif  /* PLUGINS_KAITAI_PARSERS_TYPE_INT_H */
diff --git a/plugins/kaitai/parsers/type.c b/plugins/kaitai/parsers/type.c
new file mode 100644
index 0000000..30d0373
--- /dev/null
+++ b/plugins/kaitai/parsers/type.c
@@ -0,0 +1,236 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct.c - définition d'une structure Kaitai
+ *
+ * Copyright (C) 2019 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 "type.h"
+
+
+#include <malloc.h>
+#include <string.h>
+#include <plugins/yaml/pair.h>
+
+
+#include "type-int.h"
+#include "../parser.h"
+
+
+
+/* Initialise la classe des types particuliers pour Kaitai. */
+static void g_kaitai_type_class_init(GKaitaiTypeClass *);
+
+/* Initialise un type particulier pour Kaitai. */
+static void g_kaitai_type_init(GKaitaiType *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_type_dispose(GKaitaiType *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_type_finalize(GKaitaiType *);
+
+
+
+/* Indique le type défini pour un type particulier pour Kaitai. */
+G_DEFINE_TYPE(GKaitaiType, g_kaitai_type, G_TYPE_KAITAI_STRUCT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des types particuliers pour Kaitai.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_type_class_init(GKaitaiTypeClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_type_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_kaitai_type_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : kstruct = instance à initialiser.                            *
+*                                                                             *
+*  Description : Initialise un type particulier pour Kaitai.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_type_init(GKaitaiType *type)
+{
+    type->name = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_type_dispose(GKaitaiType *type)
+{
+    G_OBJECT_CLASS(g_kaitai_type_parent_class)->dispose(G_OBJECT(type));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_type_finalize(GKaitaiType *type)
+{
+    if (type->name != NULL)
+        free(type->name);
+
+    G_OBJECT_CLASS(g_kaitai_type_parent_class)->finalize(G_OBJECT(type));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = noeud Yaml contenant l'attribut à constituer.       *
+*                                                                             *
+*  Description : Construit un lecteur de type pour Kaitai.                    *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiType *g_kaitai_type_new(GYamlNode *parent)
+{
+    GKaitaiType *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_KAITAI_TYPE, NULL);
+
+    if (!g_kaitai_type_create(result, parent))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type   = lecteur de type Kaitai à initialiser pleinement.    *
+*                parent = noeud Yaml contenant l'attribut à constituer.       *
+*                                                                             *
+*  Description : Met en place un lecteur de type pour Kaitai.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_type_create(GKaitaiType *type, GYamlNode *parent)
+{
+    bool result;                            /* Bilan à retourner           */
+    const char *name;                       /* Désignation du type         */
+    char *sub_path;                         /* Chemin d'accès suivant      */
+    GYamlNode *sub;                         /* Contenu Yaml d'un type      */
+
+    result = false;
+
+    /* Extraction du nom */
+
+    if (!G_IS_YAML_PAIR(parent))
+        goto exit;
+
+    name = g_yaml_pair_get_key(G_YAML_PAIR(parent));
+
+    type->name = strdup(name);
+
+    /* Extraction des bases du type */
+
+    asprintf(&sub_path, "/%s/", name);
+    sub = g_yaml_node_find_first_by_path(parent, sub_path);
+    free(sub_path);
+
+    if (sub == NULL)
+        goto exit;
+
+    result = g_kaitai_structure_create(G_KAITAI_STRUCT(type), sub);
+
+    g_object_unref(G_OBJECT(sub));
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = définition de type particulier à consulter.           *
+*                                                                             *
+*  Description : Indique le nom de scène du type représenté.                  *
+*                                                                             *
+*  Retour      : Désignation humaine.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_kaitai_type_get_name(const GKaitaiType *type)
+{
+    const char *result;                     /* Nom à retourner             */
+
+    result = type->name;
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parsers/type.h b/plugins/kaitai/parsers/type.h
new file mode 100644
index 0000000..0656c64
--- /dev/null
+++ b/plugins/kaitai/parsers/type.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.h - prototypes pour la définition d'un type particulier pour Kaitai
+ *
+ * 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_PARSERS_TYPE_H
+#define _PLUGINS_KAITAI_PARSERS_TYPE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <plugins/yaml/node.h>
+
+
+
+#define G_TYPE_KAITAI_TYPE            g_kaitai_type_get_type()
+#define G_KAITAI_TYPE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_TYPE, GKaitaiType))
+#define G_IS_KAITAI_TYPE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_TYPE))
+#define G_KAITAI_TYPE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_TYPE, GKaitaiTypeClass))
+#define G_IS_KAITAI_TYPE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_TYPE))
+#define G_KAITAI_TYPE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_TYPE, GKaitaiTypeClass))
+
+
+/* Définition d'un type particulier nouveau pour Kaitai (instance) */
+typedef struct _GKaitaiType GKaitaiType;
+
+/* Définition d'un type particulier nouveau pour Kaitai (classe) */
+typedef struct _GKaitaiTypeClass GKaitaiTypeClass;
+
+
+/* Indique le type défini pour un type particulier pour Kaitai. */
+GType g_kaitai_type_get_type(void);
+
+/* Construit un lecteur de type pour Kaitai. */
+GKaitaiType *g_kaitai_type_new(GYamlNode *);
+
+/* Indique le nom de scène du type représenté. */
+const char *g_kaitai_type_get_name(const GKaitaiType *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PARSERS_TYPE_H */
diff --git a/plugins/kaitai/python/Makefile.am b/plugins/kaitai/python/Makefile.am
new file mode 100644
index 0000000..ab40744
--- /dev/null
+++ b/plugins/kaitai/python/Makefile.am
@@ -0,0 +1,25 @@
+
+noinst_LTLIBRARIES = libkaitaipython.la
+
+libkaitaipython_la_SOURCES =				\
+	array.h array.c							\
+	module.h module.c						\
+	parser.h parser.c						\
+	record.h record.c						\
+	scope.h scope.c							\
+	stream.h stream.c
+
+libkaitaipython_la_LIBADD =					\
+	parsers/libkaitaipythonparsers.la		\
+	records/libkaitaipythonrecords.la
+
+libkaitaipython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaipython_la_SOURCES:%c=)
+
+
+SUBDIRS = parsers records
diff --git a/plugins/kaitai/python/array.c b/plugins/kaitai/python/array.c
new file mode 100644
index 0000000..4973c76
--- /dev/null
+++ b/plugins/kaitai/python/array.c
@@ -0,0 +1,265 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * array.h - équivalent Python du fichier "plugins/kaitai/array.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "array.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../array-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_array, G_TYPE_KAITAI_ARRAY);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_array_init(PyObject *, PyObject *, PyObject *);
+
+/* Convertit un tableau Kaitai en série d'octets si possible. */
+static PyObject *py_kaitai_array___bytes__(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_kaitai_array_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int ret;                                /* Bilan de lecture des args.  */
+
+#define KAITAI_ARRAY_DOC                                                \
+    "KaitaiArray defines an array for collecting various Kaitai items." \
+    "\n"                                                                \
+    "Instances can be created using following constructor:\n"           \
+    "\n"                                                                \
+    "    KaitaiArray()"                                                 \
+    "\n"                                                                \
+    "In this implementation, arrays do not have to carry items all"     \
+    " belonging to the same type. Access and conversions to bytes are"  \
+    " handled and checked at runtime."
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = classe représentant un binaire.                       *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Convertit un tableau Kaitai en série d'octets si possible.   *
+*                                                                             *
+*  Retour      : Série d'octets ou None.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_array___bytes__(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Représentation à renvoyer   */
+    GKaitaiArray *array;                    /* Tableau à manipuler         */
+    sized_string_t bytes;                   /* Version en série d'octets   */
+    bool status;                            /* Bilan de la conversion      */
+
+#define KAITAI_ARRAY_AS_BYTES_METHOD PYTHON_METHOD_DEF              \
+(                                                                   \
+    __bytes__, "$self, /",                                          \
+    METH_NOARGS, py_kaitai_array,                                   \
+    "Provide a bytes representation of the array, when possible"    \
+    " and without implementing the Python buffer protocol.\n"       \
+    "\n"                                                            \
+    "THe result is bytes or a *TypeError* exception is raised if"   \
+    " the array is not suitable for a conversion to bytes."         \
+)
+
+    array = G_KAITAI_ARRAY(pygobject_get(self));
+
+    status = g_kaitai_array_convert_to_bytes(array, &bytes);
+
+    if (status)
+    {
+        result = PyBytes_FromStringAndSize(bytes.data, bytes.len);
+        exit_szstr(&bytes);
+    }
+    else
+    {
+        PyErr_SetString(PyExc_TypeError, "unable to convert the Kaitai array to bytes");
+        result = NULL;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_array_type(void)
+{
+    static PyMethodDef py_kaitai_array_methods[] = {
+        KAITAI_ARRAY_AS_BYTES_METHOD,
+        { NULL }
+    };
+
+    static PyGetSetDef py_kaitai_array_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_kaitai_array_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.KaitaiArray",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = KAITAI_ARRAY_DOC,
+
+        .tp_methods     = py_kaitai_array_methods,
+        .tp_getset      = py_kaitai_array_getseters,
+
+        .tp_init        = py_kaitai_array_init,
+        .tp_new         = py_kaitai_array_new,
+
+    };
+
+    return &py_kaitai_array_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiArray. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_kaitai_array_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'KaitaiArray'  */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_kaitai_array_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+        dict = PyModule_GetDict(module);
+
+        if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_ARRAY, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en tableau d'éléments Kaitai.             *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_kaitai_array(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_array_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai array");
+            break;
+
+        case 1:
+            *((GKaitaiArray **)dst) = G_KAITAI_ARRAY(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/array.h b/plugins/kaitai/python/array.h
new file mode 100644
index 0000000..aeba541
--- /dev/null
+++ b/plugins/kaitai/python/array.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * array.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/array.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_ARRAY_H
+#define _PLUGINS_KAITAI_PYTHON_ARRAY_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_array_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.KaitaiArray'. */
+bool ensure_python_kaitai_array_is_registered(void);
+
+/* Tente de convertir en tableau d'éléments Kaitai. */
+int convert_to_kaitai_array(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_ARRAY_H */
diff --git a/plugins/kaitai/python/module.c b/plugins/kaitai/python/module.c
new file mode 100644
index 0000000..fa1f9c2
--- /dev/null
+++ b/plugins/kaitai/python/module.c
@@ -0,0 +1,132 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire kaitai en tant que module
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "array.h"
+#include "parser.h"
+#include "record.h"
+#include "scope.h"
+#include "stream.h"
+#include "parsers/module.h"
+#include "records/module.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Ajoute le module 'plugins.kaitai' au module Python.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool add_kaitai_module_to_python_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *super;                        /* Module à compléter          */
+    PyObject *module;                       /* Sous-module mis en place    */
+
+#define PYCHRYSALIDE_PLUGINS_KAITAI_DOC                                                         \
+    "kaitai is a module trying to reverse some of the effects produced by ProGuard.\n"          \
+    "\n"                                                                                        \
+    "Its action is focused on reverting name obfuscation by running binary diffing against"     \
+    " OpenSource packages from the AOSP."
+
+    static PyModuleDef py_chrysalide_kaitai_module = {
+
+        .m_base = PyModuleDef_HEAD_INIT,
+
+        .m_name = "pychrysalide.plugins.kaitai",
+        .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_DOC,
+
+        .m_size = -1,
+
+    };
+
+    result = false;
+
+    super = get_access_to_python_module("pychrysalide.plugins");
+
+    module = build_python_module(super, &py_chrysalide_kaitai_module);
+
+    result = (module != NULL);
+
+    assert(result);
+
+    if (result) result = add_kaitai_parsers_module();
+    if (result) result = add_kaitai_records_module();
+
+    if (!result)
+        Py_XDECREF(module);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Intègre les objets du module 'plugins.kaitai'.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool populate_kaitai_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    if (result) result = ensure_python_kaitai_array_is_registered();
+    if (result) result = ensure_python_kaitai_parser_is_registered();
+    if (result) result = ensure_python_match_record_is_registered();
+    if (result) result = ensure_python_kaitai_scope_is_registered();
+    if (result) result = ensure_python_kaitai_stream_is_registered();
+
+    if (result) result = populate_kaitai_parsers_module();
+    if (result) result = populate_kaitai_records_module();
+
+    assert(result);
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/module.h b/plugins/kaitai/python/module.h
new file mode 100644
index 0000000..939de07
--- /dev/null
+++ b/plugins/kaitai/python/module.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire kaitai en tant que module
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_MODULE_H
+#define _PLUGINS_KAITAI_PYTHON_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.kaitai' au module Python. */
+bool add_kaitai_module_to_python_module(void);
+
+/* Intègre les objets du module 'plugins.kaitai'. */
+bool populate_kaitai_module(void);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_MODULE_H */
diff --git a/plugins/kaitai/python/parser.c b/plugins/kaitai/python/parser.c
new file mode 100644
index 0000000..067d3b0
--- /dev/null
+++ b/plugins/kaitai/python/parser.c
@@ -0,0 +1,205 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.h - équivalent Python du fichier "plugins/kaitai/parser.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "parser.h"
+
+
+#include <pygobject.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../parser.h"
+
+
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(kaitai_parser, G_TYPE_KAITAI_PARSER, NULL);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_parser_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_kaitai_parser_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int ret;                                /* Bilan de lecture des args.  */
+
+#define KAITAI_PARSER_DOC                                                       \
+    "KaitaiParser is the class providing support for parsing binary contents"   \
+    " using a special declarative language."                                    \
+    "\n"                                                                        \
+    "It is the Python bindings for a C implementation of the specifications"    \
+    " described at http://kaitai.io/."
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_parser_type(void)
+{
+    static PyMethodDef py_kaitai_parser_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_kaitai_parser_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_kaitai_parser_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.KaitaiParser",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = KAITAI_PARSER_DOC,
+
+        .tp_methods     = py_kaitai_parser_methods,
+        .tp_getset      = py_kaitai_parser_getseters,
+
+        .tp_init        = py_kaitai_parser_init,
+        .tp_new         = py_kaitai_parser_new,
+
+    };
+
+    return &py_kaitai_parser_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiParser.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_kaitai_parser_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'KaitaiParser'  */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_kaitai_parser_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+        dict = PyModule_GetDict(module);
+
+        if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_PARSER, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en lecteur de données Kaitai.             *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_kaitai_parser(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_parser_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai parser");
+            break;
+
+        case 1:
+            *((GKaitaiParser **)dst) = G_KAITAI_PARSER(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/parser.h b/plugins/kaitai/python/parser.h
new file mode 100644
index 0000000..f4b6c96
--- /dev/null
+++ b/plugins/kaitai/python/parser.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parser.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSER_H
+#define _PLUGINS_KAITAI_PYTHON_PARSER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_parser_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.KaitaiParser'. */
+bool ensure_python_kaitai_parser_is_registered(void);
+
+/* Tente de convertir en lecteur de données Kaitai. */
+int convert_to_kaitai_parser(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_PARSER_H */
diff --git a/plugins/kaitai/python/parsers/Makefile.am b/plugins/kaitai/python/parsers/Makefile.am
new file mode 100644
index 0000000..4c418af
--- /dev/null
+++ b/plugins/kaitai/python/parsers/Makefile.am
@@ -0,0 +1,19 @@
+
+noinst_LTLIBRARIES = libkaitaipythonparsers.la
+
+libkaitaipythonparsers_la_SOURCES = 		\
+	attribute.h attribute.c					\
+	enum.h enum.c							\
+	instance.h instance.c					\
+	meta.h meta.c							\
+	module.h module.c						\
+	struct.h struct.c						\
+	type.h type.c
+
+libkaitaipythonparsers_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaipythonparsers_la_SOURCES:%c=)
diff --git a/plugins/kaitai/python/parsers/attribute.c b/plugins/kaitai/python/parsers/attribute.c
new file mode 100644
index 0000000..c8ea314
--- /dev/null
+++ b/plugins/kaitai/python/parsers/attribute.c
@@ -0,0 +1,420 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * attribute.h - équivalent Python du fichier "plugins/kaitai/parsers/attribute.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "attribute.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "../parser.h"
+#include "../../parsers/attribute-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_attribute, G_TYPE_KAITAI_ATTRIBUTE);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_attribute_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique la désignation brute d'un identifiant Kaitai. */
+static PyObject *py_kaitai_attribute_get_raw_id(PyObject *, void *);
+
+/* Indique la désignation originelle d'un identifiant Kaitai. */
+static PyObject *py_kaitai_attribute_get_original_id(PyObject *, void *);
+
+/* Fournit une éventuelle documentation concernant l'attribut. */
+static PyObject *py_kaitai_attribute_get_doc(PyObject *, void *);
+
+/* Détermine si l'attribue porte une valeur entière signée. */
+static PyObject *py_kaitai_attribute_get_handle_signed_integer(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_kaitai_attribute_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GYamlNode *parent;                      /* Noeud Yaml de l'attribut    */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiAttribute *attrib;               /* Création GLib à transmettre */
+
+#define KAITAI_ATTRIBUTE_DOC                                                    \
+    "KaitaiAttribute is the class providing support for parsing binary"         \
+    " contents using a special declarative language."                           \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    KaitaiAttribute(parent)"                                               \
+    "\n"                                                                        \
+    "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing"  \
+    " to Yaml data to load.\n"                                                  \
+    "\n"                                                                        \
+    "The class is the Python bindings for a C implementation of the Attribute"  \
+    " structure described at https://doc.kaitai.io/ksy_diagram.html."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
+
+    if (!g_kaitai_attribute_create(attrib, parent, true))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai attribute."));
+        return -1;
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique la désignation brute d'un identifiant Kaitai.        *
+*                                                                             *
+*  Retour      : Valeur brute de l'identifiant.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_attribute_get_raw_id(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiAttribute *attrib;               /* Version native de l'attribut*/
+    const char *value;                      /* Valeur à transmettre        */
+
+#define KAITAI_ATTRIBUTE_RAW_ID_ATTRIB PYTHON_GET_DEF_FULL  \
+(                                                           \
+    raw_id, py_kaitai_attribute,                            \
+    "Raw value used by Kaitai to identify one attribute"    \
+    " among others.\n"                                      \
+    "\n"                                                    \
+    "The returned indentifier is a string value."           \
+)
+
+    attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
+
+    value = g_kaitai_attribute_get_raw_id(attrib);
+    assert(value != NULL);
+
+    result = PyUnicode_FromString(value);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique la désignation originelle d'un identifiant Kaitai.   *
+*                                                                             *
+*  Retour      : Valeur originelle de l'identifiant.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_attribute_get_original_id(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiAttribute *attrib;               /* Version native de l'attribut*/
+    const char *value;                      /* Valeur à transmettre        */
+
+#define KAITAI_ATTRIBUTE_ORIGINAL_ID_ATTRIB PYTHON_GET_DEF_FULL     \
+(                                                                   \
+    original_id, py_kaitai_attribute,                               \
+    "Optional alternative identifier for the attribute, as seen in" \
+    " the original specifications.\n"                               \
+    "\n"                                                            \
+    "The returned value is a string or *None*."                     \
+)
+
+    attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
+
+    value = g_kaitai_attribute_get_original_id(attrib);
+
+    if (value == NULL)
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+    else
+        result = PyUnicode_FromString(value);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit une éventuelle documentation concernant l'attribut.  *
+*                                                                             *
+*  Retour      : Description enregistrée ou None si absente.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_attribute_get_doc(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiAttribute *attrib;               /* Version native de l'attribut*/
+    const char *doc;                        /* Documentation à transmettre */
+
+#define KAITAI_ATTRIBUTE_DOC_ATTRIB PYTHON_GET_DEF_FULL     \
+(                                                           \
+    doc, py_kaitai_attribute,                               \
+    "Optional documentation for the attribute.\n"           \
+    "\n"                                                    \
+    "The returned value is a string or *None*."             \
+)
+
+    attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
+
+    doc = g_kaitai_attribute_get_doc(attrib);
+
+    if (doc == NULL)
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+    else
+        result = PyUnicode_FromString(doc);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Détermine si l'attribue porte une valeur entière signée.     *
+*                                                                             *
+*  Retour      : Bilan de la consultation : True si un entier signé est visé. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_attribute_get_handle_signed_integer(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiAttribute *attrib;               /* Version native de l'attribut*/
+    bool status;                            /* Bilan d'une consultation    */ 
+
+#define KAITAI_ATTRIBUTE_HANDLE_SIGNED_INTEGER_ATTRIB PYTHON_GET_DEF_FULL   \
+(                                                                           \
+    handle_signed_integer, py_kaitai_attribute,                             \
+    "Sign of the carried integer value, if any: positive or negative?\n"    \
+    "\n"                                                                    \
+    "This status is provided as a boolean value."                           \
+)
+
+    attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
+
+    status = g_kaitai_attribute_handle_signed_integer(attrib);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_attribute_type(void)
+{
+    static PyMethodDef py_kaitai_attribute_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_kaitai_attribute_getseters[] = {
+        KAITAI_ATTRIBUTE_RAW_ID_ATTRIB,
+        KAITAI_ATTRIBUTE_ORIGINAL_ID_ATTRIB,
+        KAITAI_ATTRIBUTE_DOC_ATTRIB,
+        KAITAI_ATTRIBUTE_HANDLE_SIGNED_INTEGER_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_kaitai_attribute_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.parsers.KaitaiAttribute",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = KAITAI_ATTRIBUTE_DOC,
+
+        .tp_methods     = py_kaitai_attribute_methods,
+        .tp_getset      = py_kaitai_attribute_getseters,
+
+        .tp_init        = py_kaitai_attribute_init,
+        .tp_new         = py_kaitai_attribute_new,
+
+    };
+
+    return &py_kaitai_attribute_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....KaitaiAttribute.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_kaitai_attribute_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type 'KaitaiAttribute'      */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_kaitai_attribute_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_kaitai_parser_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_ATTRIBUTE, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en attribut de données Kaitai.            *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_kaitai_attribute(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_attribute_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai attribute");
+            break;
+
+        case 1:
+            *((GKaitaiAttribute **)dst) = G_KAITAI_ATTRIBUTE(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/attribute.h b/plugins/kaitai/python/parsers/attribute.h
new file mode 100644
index 0000000..931e769
--- /dev/null
+++ b/plugins/kaitai/python/parsers/attribute.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * attribute.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/attribute.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSERS_ATTRIBUTE_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_ATTRIBUTE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_attribute_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiAttribute'. */
+bool ensure_python_kaitai_attribute_is_registered(void);
+
+/* Tente de convertir en attribut de données Kaitai. */
+int convert_to_kaitai_attribute(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_PARSERS_ATTRIBUTE_H */
diff --git a/plugins/kaitai/python/parsers/enum.c b/plugins/kaitai/python/parsers/enum.c
new file mode 100644
index 0000000..9200c6f
--- /dev/null
+++ b/plugins/kaitai/python/parsers/enum.c
@@ -0,0 +1,468 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enum.h - équivalent Python du fichier "plugins/kaitai/parsers/enum.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "enum.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "../../parsers/enum-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_enum, G_TYPE_KAITAI_ENUM);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_enum_init(PyObject *, PyObject *, PyObject *);
+
+/* Traduit une étiquette brute en constante d'énumération. */
+static PyObject *py_kaitai_enum_find_value(PyObject *, PyObject *);
+
+/* Traduit une constante d'énumération en étiquette brute. */
+static PyObject *py_kaitai_enum_find_label(PyObject *, PyObject *);
+
+/* Traduit une constante d'énumération en documentation. */
+static PyObject *py_kaitai_enum_find_documentation(PyObject *, PyObject *);
+
+/* Fournit le nom principal d'une énumération. */
+static PyObject *py_kaitai_enum_get_name(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_kaitai_enum_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GYamlNode *parent;                      /* Noeud Yaml de l'attribut    */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiEnum *kenum;                 /* Création GLib à transmettre */
+
+#define KAITAI_ENUM_DOC                                                         \
+    "The KaitaiEnum class maps integer constants to symbolic names using"       \
+    " Kaitai definitions.\n"                                                    \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    KaitaiEnum(parent)"                                                    \
+    "\n"                                                                        \
+    "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing"  \
+    " to Yaml data to load.\n"                                                  \
+    "\n"                                                                        \
+    "The class is the Python bindings for a C implementation of the EnumSpec"   \
+    " structure described at https://doc.kaitai.io/ksy_diagram.html."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    kenum = G_KAITAI_ENUM(pygobject_get(self));
+
+    if (!g_kaitai_enum_create(kenum, parent))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai enumeration."));
+        return -1;
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = instance de l'énumération Kaitai à manipuler.         *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Traduit une étiquette brute en constante d'énumération.      *
+*                                                                             *
+*  Retour      : Valeur retrouvée ou None en cas d'échec.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_enum_find_value(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    const char *label;                      /* Etiquette à rechercher      */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiEnum *kenum;                     /* Enumération Kaitai courante */
+    sized_string_t cstr;                    /* CHaîne avec sa longueur     */
+    bool status;                            /* Bilan de la conversion      */
+    resolved_value_t value;                 /* valeur à transformer        */
+
+#define KAITAI_ENUM_FIND_VALUE_METHOD PYTHON_METHOD_DEF                     \
+(                                                                           \
+    find_value, "$self, label",                                             \
+    METH_VARARGS, py_kaitai_enum,                                           \
+    "Translate a given enumeration label into its relative value.\n"        \
+    "\n"                                                                    \
+    "The *label* argument is expected to be a string.\n"                    \
+    "\n"                                                                    \
+    "The result is an integer or *None* in case of resolution failure."     \
+)
+
+    ret = PyArg_ParseTuple(args, "s", &label);
+    if (!ret) return NULL;
+
+    kenum = G_KAITAI_ENUM(pygobject_get(self));
+
+    cstr.data = (char *)label;
+    cstr.len = strlen(label);
+
+    status = g_kaitai_enum_find_value(kenum, &cstr, &value);
+
+    if (status)
+    {
+        if (value.type == GVT_UNSIGNED_INTEGER)
+            result = PyLong_FromUnsignedLongLong(value.unsigned_integer);
+        else
+        {
+            assert(value.type == GVT_SIGNED_INTEGER);
+            result = PyLong_FromLongLong(value.signed_integer);
+        }
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = instance de l'énumération Kaitai à manipuler.         *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Traduit une constante d'énumération en étiquette brute.      *
+*                                                                             *
+*  Retour      : Désignation ou None en cas d'échec.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_enum_find_label(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    int prefix;                             /* Préfixe attendu ?           */
+    resolved_value_t value;                 /* valeur à transformer        */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiEnum *kenum;                     /* Enumération Kaitai courante */
+    char *label;                            /* Etiquette reconstruite      */
+
+#define KAITAI_ENUM_FIND_LABEL_METHOD PYTHON_METHOD_DEF                     \
+(                                                                           \
+    find_label, "$self, value, / , prefix=False",                           \
+    METH_VARARGS, py_kaitai_enum,                                           \
+    "Provide the label linked to a constant value within the current"       \
+    " enumeration.\n"                                                       \
+    "\n"                                                                    \
+    "The *value* is a simple integer, and *prefix* is a boolean indicating" \
+    " if the result has to integrate the enumeration name as a prefix.\n"   \
+    "\n"                                                                    \
+    "The result is a string or *None* in case of resolution failure."       \
+)
+
+    prefix = 0;
+
+    ret = PyArg_ParseTuple(args, "K|p", &value.unsigned_integer, prefix);
+    if (!ret) return NULL;
+
+    kenum = G_KAITAI_ENUM(pygobject_get(self));
+
+    value.type = GVT_UNSIGNED_INTEGER;
+    label = g_kaitai_enum_find_label(kenum, &value, prefix);
+
+    if (label != NULL)
+    {
+        result = PyUnicode_FromString(label);
+        free(label);
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = instance de l'énumération Kaitai à manipuler.         *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Traduit une constante d'énumération en documentation.        *
+*                                                                             *
+*  Retour      : Documentation associée à la valeur indiquée ou None.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_enum_find_documentation(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    resolved_value_t value;                 /* valeur à transformer        */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiEnum *kenum;                     /* Enumération Kaitai courante */
+    char *doc;                              /* Documentation obtenue       */
+
+#define KAITAI_ENUM_FIND_DOCUMENTATION_METHOD PYTHON_METHOD_DEF             \
+(                                                                           \
+    find_documentation, "$self, value",                                     \
+    METH_VARARGS, py_kaitai_enum,                                           \
+    "Provide the optional documentation linked to a constant value within"  \
+    " the current enumeration.\n"                                           \
+    "\n"                                                                    \
+    "The *value* is a simple integer.\n"                                    \
+    "\n"                                                                    \
+    "The result is a string or *None* if no documentation is registered"    \
+    " for the provided value."                                              \
+)
+
+    ret = PyArg_ParseTuple(args, "K", &value.unsigned_integer);
+    if (!ret) return NULL;
+
+    kenum = G_KAITAI_ENUM(pygobject_get(self));
+
+    value.type = GVT_UNSIGNED_INTEGER;
+    doc = g_kaitai_enum_find_documentation(kenum, &value);
+
+    if (doc != NULL)
+    {
+        result = PyUnicode_FromString(doc);
+        free(doc);
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit le nom principal d'une énumération.                  *
+*                                                                             *
+*  Retour      : Désignation de l'énumération.                                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_enum_get_name(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiEnum *kenum;                     /* Version native de l'objet   */
+    const char *name;                       /* Valeur à transmettre        */
+
+#define KAITAI_ENUM_NAME_ATTRIB PYTHON_GET_DEF_FULL     \
+(                                                       \
+    name, py_kaitai_enum,                               \
+    "Name of the enumeration group, as a string value." \
+)
+
+    kenum = G_KAITAI_ENUM(pygobject_get(self));
+
+    name = g_kaitai_enum_get_name(kenum);
+
+    result = PyUnicode_FromString(name);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_enum_type(void)
+{
+    static PyMethodDef py_kaitai_enum_methods[] = {
+        KAITAI_ENUM_FIND_VALUE_METHOD,
+        KAITAI_ENUM_FIND_LABEL_METHOD,
+        KAITAI_ENUM_FIND_DOCUMENTATION_METHOD,
+        { NULL }
+    };
+
+    static PyGetSetDef py_kaitai_enum_getseters[] = {
+        KAITAI_ENUM_NAME_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_kaitai_enum_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.parsers.KaitaiEnum",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = KAITAI_ENUM_DOC,
+
+        .tp_methods     = py_kaitai_enum_methods,
+        .tp_getset      = py_kaitai_enum_getseters,
+
+        .tp_init        = py_kaitai_enum_init,
+        .tp_new         = py_kaitai_enum_new
+
+    };
+
+    return &py_kaitai_enum_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiEnum.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_kaitai_enum_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'KaitaiEnum'    */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_kaitai_enum_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+        dict = PyModule_GetDict(module);
+
+        if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_ENUM, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en ensemble d'énumérations Kaitai.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_kaitai_enum(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_enum_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai enumeration");
+            break;
+
+        case 1:
+            *((GKaitaiEnum **)dst) = G_KAITAI_ENUM(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/enum.h b/plugins/kaitai/python/parsers/enum.h
new file mode 100644
index 0000000..7172e69
--- /dev/null
+++ b/plugins/kaitai/python/parsers/enum.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * enum.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/enum.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSERS_ENUM_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_ENUM_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_enum_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiEnum'. */
+bool ensure_python_kaitai_enum_is_registered(void);
+
+/* Tente de convertir en ensemble d'énumérations Kaitai. */
+int convert_to_kaitai_enum(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_PARSERS_ENUM_H */
diff --git a/plugins/kaitai/python/parsers/instance.c b/plugins/kaitai/python/parsers/instance.c
new file mode 100644
index 0000000..d55b58c
--- /dev/null
+++ b/plugins/kaitai/python/parsers/instance.c
@@ -0,0 +1,280 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instance.h - équivalent Python du fichier "plugins/kaitai/parsers/instance.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "instance.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "attribute.h"
+#include "../../parsers/instance-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_instance, G_TYPE_KAITAI_INSTANCE);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_instance_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le nom attribué à une instance Kaitai. */
+static PyObject *py_kaitai_instance_get_name(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_kaitai_instance_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GYamlNode *parent;                      /* Noeud Yaml de l'attribut    */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiInstance *attrib;               /* Création GLib à transmettre */
+
+#define KAITAI_INSTANCE_DOC                                                     \
+    "KaitaiInstance is the class providing support for Kaitai computed"         \
+    " values.\n"                                                                \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    KaitaiInstance(parent)"                                                \
+    "\n"                                                                        \
+    "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing"  \
+    " to Yaml data to load.\n"                                                  \
+    "\n"                                                                        \
+    "The class is the Python bindings for a C implementation of the Instance"   \
+    " structure described at https://doc.kaitai.io/ksy_diagram.html."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    attrib = G_KAITAI_INSTANCE(pygobject_get(self));
+
+    if (!g_kaitai_instance_create(attrib, parent))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai instance."));
+        return -1;
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique le nom attribué à une instance Kaitai.               *
+*                                                                             *
+*  Retour      : Désignation pointant l'instance.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_instance_get_name(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiInstance *inst;                  /* Version native de l'instance*/
+    const char *name;                       /* Désignation à transmettre   */
+
+#define KAITAI_INSTANCE_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+(                                                       \
+    name, py_kaitai_instance,                           \
+    "Name used by Kaitai to identify the instance"      \
+    " among others.\n"                                  \
+    "\n"                                                \
+    "The returned indentifier is a string value."       \
+)
+
+    inst = G_KAITAI_INSTANCE(pygobject_get(self));
+
+    name = g_kaitai_instance_get_name(inst);
+    assert(name != NULL);
+
+    result = PyUnicode_FromString(name);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_instance_type(void)
+{
+    static PyMethodDef py_kaitai_instance_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_kaitai_instance_getseters[] = {
+        KAITAI_INSTANCE_NAME_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_kaitai_instance_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.parsers.KaitaiInstance",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = KAITAI_INSTANCE_DOC,
+
+        .tp_methods     = py_kaitai_instance_methods,
+        .tp_getset      = py_kaitai_instance_getseters,
+
+        .tp_init        = py_kaitai_instance_init,
+        .tp_new         = py_kaitai_instance_new,
+
+    };
+
+    return &py_kaitai_instance_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....KaitaiInstance.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_kaitai_instance_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type 'KaitaiInstance'      */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_kaitai_instance_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_kaitai_attribute_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_INSTANCE, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en instance Kaitai.                       *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_kaitai_instance(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_instance_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai instance");
+            break;
+
+        case 1:
+            *((GKaitaiInstance **)dst) = G_KAITAI_INSTANCE(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/instance.h b/plugins/kaitai/python/parsers/instance.h
new file mode 100644
index 0000000..8a0a6cf
--- /dev/null
+++ b/plugins/kaitai/python/parsers/instance.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instance.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/instance.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSERS_INSTANCE_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_INSTANCE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_instance_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiInstance'. */
+bool ensure_python_kaitai_instance_is_registered(void);
+
+/* Tente de convertir en instance Kaitai. */
+int convert_to_kaitai_instance(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_PARSERS_INSTANCE_H */
diff --git a/plugins/kaitai/python/parsers/meta.c b/plugins/kaitai/python/parsers/meta.c
new file mode 100644
index 0000000..3432640
--- /dev/null
+++ b/plugins/kaitai/python/parsers/meta.c
@@ -0,0 +1,366 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * meta.h - équivalent Python du fichier "plugins/kaitai/parsers/meta.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "meta.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "../../parsers/meta-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_meta, G_TYPE_KAITAI_META);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_meta_init(PyObject *, PyObject *, PyObject *);
+
+/* Fournit l'identifié associé à une définiton Kaitai. */
+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 *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_kaitai_meta_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GYamlNode *parent;                      /* Noeud Yaml de l'attribut    */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiMeta *kmeta;                 /* Création GLib à transmettre */
+
+#define KAITAI_META_DOC                                                         \
+    "The KaitaiMeta class stores general information about a Kaitai definition,"\
+    " such as required imports or the default endianness for reading values.\n" \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    KaitaiMeta(parent)"                                                    \
+    "\n"                                                                        \
+    "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing"  \
+    " to Yaml data to load.\n"                                                  \
+    "\n"                                                                        \
+    "The class is the Python bindings for a C implementation of the MetaSpec"   \
+    " structure described at https://doc.kaitai.io/ksy_diagram.html."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    kmeta = G_KAITAI_META(pygobject_get(self));
+
+    if (!g_kaitai_meta_create(kmeta, parent))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai global description."));
+        return -1;
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit l'identifié associé à une définiton Kaitai.          *
+*                                                                             *
+*  Retour      : Identifiant de définition complète ou None.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_meta_get_id(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiMeta *meta;                      /* Version native de l'objet   */
+    const char *id;                         /* Valeur à transmettre        */
+
+#define KAITAI_META_ID_ATTRIB PYTHON_GET_DEF_FULL       \
+(                                                       \
+    id, py_kaitai_meta,                                 \
+    "Identifier for the Kaitai definition, as a string" \
+    " value or *None* if any."                          \
+)
+
+    meta = G_KAITAI_META(pygobject_get(self));
+
+    id = g_kaitai_meta_get_id(meta);
+
+    if (id != NULL)
+        result = PyUnicode_FromString(id);
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit la désignation humaine d'une définiton Kaitai.       *
+*                                                                             *
+*  Retour      : Intitulé de définition OU None.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_meta_get_title(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiMeta *meta;                      /* Version native de l'objet   */
+    const char *title;                      /* Valeur à transmettre        */
+
+#define KAITAI_META_TITLE_ATTRIB PYTHON_GET_DEF_FULL        \
+(                                                           \
+    title, py_kaitai_meta,                                  \
+    "Humain description for the Kaitai definition, as a"    \
+    " string value or *None* if any."                       \
+)
+
+    meta = G_KAITAI_META(pygobject_get(self));
+
+    title = g_kaitai_meta_get_title(meta);
+
+    if (title != NULL)
+        result = PyUnicode_FromString(title);
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit la désignation humaine d'une définiton Kaitai.       *
+*                                                                             *
+*  Retour      : Intitulé de définition OU None.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_meta_get_endian(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiMeta *meta;                      /* Version native de l'objet   */
+    SourceEndian endian;                    /* Valeur à transmettre        */
+
+#define KAITAI_META_ENDIAN_ATTRIB PYTHON_GET_DEF_FULL       \
+(                                                           \
+    endian, py_kaitai_meta,                                 \
+    "Default endianness for the Kaitai definition, as a"    \
+    " pychrysalide.analysis.BinContent.SourceEndian value." \
+)
+
+    meta = G_KAITAI_META(pygobject_get(self));
+
+    endian = g_kaitai_meta_get_endian(meta);
+
+    result = cast_with_constants_group_from_type(get_python_binary_content_type(), "SourceEndian", endian);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_meta_type(void)
+{
+    static PyMethodDef py_kaitai_meta_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_kaitai_meta_getseters[] = {
+        KAITAI_META_ID_ATTRIB,
+        KAITAI_META_TITLE_ATTRIB,
+        KAITAI_META_ENDIAN_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_kaitai_meta_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.parsers.KaitaiMeta",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = KAITAI_META_DOC,
+
+        .tp_methods     = py_kaitai_meta_methods,
+        .tp_getset      = py_kaitai_meta_getseters,
+
+        .tp_init        = py_kaitai_meta_init,
+        .tp_new         = py_kaitai_meta_new
+
+    };
+
+    return &py_kaitai_meta_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiMeta.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_kaitai_meta_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'KaitaiMeta'    */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_kaitai_meta_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+        dict = PyModule_GetDict(module);
+
+        if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_META, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en description globale Kaitai.            *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_kaitai_meta(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_meta_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai global description");
+            break;
+
+        case 1:
+            *((GKaitaiMeta **)dst) = G_KAITAI_META(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/meta.h b/plugins/kaitai/python/parsers/meta.h
new file mode 100644
index 0000000..383cad9
--- /dev/null
+++ b/plugins/kaitai/python/parsers/meta.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * meta.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/meta.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSERS_META_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_META_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_meta_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiMeta'. */
+bool ensure_python_kaitai_meta_is_registered(void);
+
+/* Tente de convertir en description globale Kaitai. */
+int convert_to_kaitai_meta(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_PARSERS_META_H */
diff --git a/plugins/kaitai/python/parsers/module.c b/plugins/kaitai/python/parsers/module.c
new file mode 100644
index 0000000..549f728
--- /dev/null
+++ b/plugins/kaitai/python/parsers/module.c
@@ -0,0 +1,124 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire parsers en tant que module
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "attribute.h"
+#include "enum.h"
+#include "instance.h"
+#include "meta.h"
+#include "struct.h"
+#include "type.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Ajoute le module 'plugins.kaitai.parsers' au module Python.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool add_kaitai_parsers_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *super;                        /* Module à compléter          */
+    PyObject *module;                       /* Sous-module mis en place    */
+
+#define PYCHRYSALIDE_PLUGINS_KAITAI_PARSERS_DOC                     \
+    "This module provides implementation for several Kaitai"        \
+    " definitions parsers."
+
+    static PyModuleDef py_chrysalide_kaitai_parsers_module = {
+
+        .m_base = PyModuleDef_HEAD_INIT,
+
+        .m_name = "pychrysalide.plugins.kaitai.parsers",
+        .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_PARSERS_DOC,
+
+        .m_size = -1,
+
+    };
+
+    result = false;
+
+    super = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+    module = build_python_module(super, &py_chrysalide_kaitai_parsers_module);
+
+    result = (module != NULL);
+
+    assert(result);
+
+    if (!result)
+        Py_XDECREF(module);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Intègre les objets du module 'plugins.kaitai.parsers'.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool populate_kaitai_parsers_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    if (result) result = ensure_python_kaitai_attribute_is_registered();
+    if (result) result = ensure_python_kaitai_enum_is_registered();
+    if (result) result = ensure_python_kaitai_instance_is_registered();
+    if (result) result = ensure_python_kaitai_meta_is_registered();
+    if (result) result = ensure_python_kaitai_structure_is_registered();
+    if (result) result = ensure_python_kaitai_type_is_registered();
+
+    assert(result);
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/module.h b/plugins/kaitai/python/parsers/module.h
new file mode 100644
index 0000000..d0fdd66
--- /dev/null
+++ b/plugins/kaitai/python/parsers/module.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire parsers en tant que module
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSERS_MODULE_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.kaitai.parsers' au module Python. */
+bool add_kaitai_parsers_module(void);
+
+/* Intègre les objets du module 'plugins.kaitai.parsers'. */
+bool populate_kaitai_parsers_module(void);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_PARSERS_MODULE_H */
diff --git a/plugins/kaitai/python/parsers/struct.c b/plugins/kaitai/python/parsers/struct.c
new file mode 100644
index 0000000..900cd1b
--- /dev/null
+++ b/plugins/kaitai/python/parsers/struct.c
@@ -0,0 +1,376 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct.h - équivalent Python du fichier "plugins/kaitai/struct.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "struct.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+
+
+#include "../parser.h"
+#include "../../parsers/struct-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_structure, G_TYPE_KAITAI_STRUCT);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_structure_init(PyObject *, PyObject *, PyObject *);
+
+/* Parcourt un contenu binaire selon une description Kaitai. */
+static PyObject *py_kaitai_structure_parse(PyObject *, PyObject *);
+
+/* Fournit la désignation humaine d'une définiton Kaitai. */
+static PyObject *py_kaitai_structure_get_meta(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_kaitai_structure_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    const char *text;                       /* Contenu de règles à traiter */
+    const char *filename;                   /* Fichier de définitions      */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiStruct *kstruct;                 /* Création GLib à transmettre */
+
+    static char *kwlist[] = { "text", "filename", NULL };
+
+#define KAITAI_STRUCT_DOC                                                       \
+    "KaitaiStruct is the class providing support for parsing binary contents"   \
+    " using a special declarative language."                                    \
+    "\n"                                                                        \
+    "Instances can be created using one of the following constructors:\n"       \
+    "\n"                                                                        \
+    "    KaitaiStruct(text=str)"                                                \
+    "\n"                                                                        \
+    "    KaitaiStruct(filename=str)"                                            \
+    "\n"                                                                        \
+    "Where *text* is a string containg a markup content to parse; the"          \
+    " *filename* argument is an alternative string for a path pointing to the"  \
+    " same kind of content. This path can be a real filename or a resource"     \
+    " URI."                                                                     \
+    "\n"                                                                        \
+    "It is the Python bindings for a C implementation of the specifications"    \
+    " described at http://kaitai.io/."
+
+    /* Récupération des paramètres */
+
+    text = NULL;
+    filename = NULL;
+
+    ret = PyArg_ParseTupleAndKeywords(args, kwds, "|ss", kwlist, &text, &filename);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    kstruct = G_KAITAI_STRUCT(pygobject_get(self));
+
+    if (text != NULL)
+    {
+        if (!g_kaitai_structure_create_from_text(kstruct, text))
+        {
+            PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai structure."));
+            return -1;
+        }
+
+    }
+
+    else if (filename != NULL)
+    {
+        if (!g_kaitai_structure_create_from_file(kstruct, filename))
+        {
+            PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai structure."));
+            return -1;
+        }
+
+    }
+
+    else
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create empty Kaitai structure."));
+        return -1;
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = instance de l'interpréteur Kaitai à manipuler.        *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Parcourt un contenu binaire selon une description Kaitai.    *
+*                                                                             *
+*  Retour      : Arborescence d'éléments rencontrés selon les spécifications. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_structure_parse(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    GBinContent *content;                   /* Contenu binaire à traiter   */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiStruct *kstruct;                 /* Interpréteur Kaitai courant */
+    GMatchRecord *record;                   /* Ensemble de correspondances */
+
+#define KAITAI_STRUCTURE_PARSE_METHOD PYTHON_METHOD_DEF                     \
+(                                                                           \
+    parse, "$self, content",                                                \
+    METH_VARARGS, py_kaitai_structure,                                      \
+    "Parse a binary content with the loaded specifications."                \
+    "\n"                                                                    \
+    "The content has to be a pychrysalide.analysis.BinContent instance.\n"  \
+    "\n"                                                                    \
+    "The result is *None* if the parsing failed, or a"                      \
+    " pychrysalide.plugins.kaitai.MatchRecord object for each attribute"    \
+    " met."                                                                 \
+)
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content);
+    if (!ret) return NULL;
+
+    kstruct = G_KAITAI_STRUCT(pygobject_get(self));
+
+    record = g_kaitai_structure_parse(kstruct, content);
+
+    if (record != NULL)
+    {
+        result = pygobject_new(G_OBJECT(record));
+        g_object_unref(G_OBJECT(record));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit la désignation humaine d'une définiton Kaitai.       *
+*                                                                             *
+*  Retour      : Intitulé de définition OU None.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_structure_get_meta(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiStruct *kstruct;                 /* Version native de l'objet   */
+    GKaitaiMeta *meta;                      /* Informations à transmettre  */
+
+#define KAITAI_STRUCTURE_META_ATTRIB PYTHON_GET_DEF_FULL            \
+(                                                                   \
+    meta, py_kaitai_structure,                                      \
+    "Global description provided for the Kaitai definition, as a"   \
+    " pychrysalide.plugins.kaitai.parsers.KaitaiMeta instance."     \
+)
+
+    kstruct = G_KAITAI_STRUCT(pygobject_get(self));
+
+    meta = g_kaitai_structure_get_meta(kstruct);
+
+    if (meta != NULL)
+    {
+        result = pygobject_new(G_OBJECT(meta));
+        g_object_unref(G_OBJECT(meta));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_structure_type(void)
+{
+    static PyMethodDef py_kaitai_structure_methods[] = {
+        KAITAI_STRUCTURE_PARSE_METHOD,
+        { NULL }
+    };
+
+    static PyGetSetDef py_kaitai_structure_getseters[] = {
+        KAITAI_STRUCTURE_META_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_kaitai_structure_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.parsers.KaitaiStruct",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = KAITAI_STRUCT_DOC,
+
+        .tp_methods     = py_kaitai_structure_methods,
+        .tp_getset      = py_kaitai_structure_getseters,
+
+        .tp_init        = py_kaitai_structure_init,
+        .tp_new         = py_kaitai_structure_new
+
+    };
+
+    return &py_kaitai_structure_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiStruct.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_kaitai_structure_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'KaitaiStruct'  */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_kaitai_structure_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_kaitai_parser_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_STRUCT, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en structure de données Kaitai.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_kaitai_structure(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_structure_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai structure");
+            break;
+
+        case 1:
+            *((GKaitaiStruct **)dst) = G_KAITAI_STRUCT(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/struct.h b/plugins/kaitai/python/parsers/struct.h
new file mode 100644
index 0000000..872f744
--- /dev/null
+++ b/plugins/kaitai/python/parsers/struct.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * struct.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/struct.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSERS_STRUCT_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_STRUCT_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_structure_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiStruct'. */
+bool ensure_python_kaitai_structure_is_registered(void);
+
+/* Tente de convertir en structure de données Kaitai. */
+int convert_to_kaitai_structure(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_PARSERS_STRUCT_H */
diff --git a/plugins/kaitai/python/parsers/type.c b/plugins/kaitai/python/parsers/type.c
new file mode 100644
index 0000000..64a3419
--- /dev/null
+++ b/plugins/kaitai/python/parsers/type.c
@@ -0,0 +1,278 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.h - équivalent Python du fichier "plugins/kaitai/parsers/type.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "type.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "struct.h"
+#include "../../parsers/type-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_type, G_TYPE_KAITAI_TYPE);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_type_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le nom de scène du type représenté. */
+static PyObject *py_kaitai_type_get_name(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_kaitai_type_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GYamlNode *parent;                      /* Noeud Yaml de l'attribut    */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiType *attrib;               /* Création GLib à transmettre */
+
+#define KAITAI_TYPE_DOC                                                         \
+    "The KaitaiType class provides support for user-defined type used in"       \
+    " Kaitai definitions.\n"                                                    \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    KaitaiType(parent)"                                                    \
+    "\n"                                                                        \
+    "Where *parent* is a pychrysalide.plugins.yaml.YamlNode instance pointing"  \
+    " to Yaml data to load.\n"                                                  \
+    "\n"                                                                        \
+    "The class is the Python bindings for a C implementation of the TypesSpec"  \
+    " structure described at https://doc.kaitai.io/ksy_diagram.html."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_yaml_node, &parent);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    attrib = G_KAITAI_TYPE(pygobject_get(self));
+
+    if (!g_kaitai_type_create(attrib, parent))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai type."));
+        return -1;
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique le nom de scène du type représenté.                  *
+*                                                                             *
+*  Retour      : Désignation humaine.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_type_get_name(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiType *type;                      /* Version native du type      */
+    const char *name;                       /* Désignation à transmettre   */
+
+#define KAITAI_TYPE_NAME_ATTRIB PYTHON_GET_DEF_FULL         \
+(                                                           \
+    name, py_kaitai_type,                                   \
+    "Name of the user-defined type, provided as a unique"   \
+    " string value."                                        \
+)
+
+    type = G_KAITAI_TYPE(pygobject_get(self));
+
+    name = g_kaitai_type_get_name(type);
+    assert(name != NULL);
+
+    result = PyUnicode_FromString(name);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_type_type(void)
+{
+    static PyMethodDef py_kaitai_type_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_kaitai_type_getseters[] = {
+        KAITAI_TYPE_NAME_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_kaitai_type_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.parsers.KaitaiType",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = KAITAI_TYPE_DOC,
+
+        .tp_methods     = py_kaitai_type_methods,
+        .tp_getset      = py_kaitai_type_getseters,
+
+        .tp_init        = py_kaitai_type_init,
+        .tp_new         = py_kaitai_type_new,
+
+    };
+
+    return &py_kaitai_type_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....parsers.KaitaiType. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_kaitai_type_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type 'KaitaiType'           */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_kaitai_type_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.parsers");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_kaitai_structure_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_TYPE, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en type particulier pour Kaitai.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_kaitai_type(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_type_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai type");
+            break;
+
+        case 1:
+            *((GKaitaiType **)dst) = G_KAITAI_TYPE(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/parsers/type.h b/plugins/kaitai/python/parsers/type.h
new file mode 100644
index 0000000..320bc71
--- /dev/null
+++ b/plugins/kaitai/python/parsers/type.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/parsers/type.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_PARSERS_TYPE_H
+#define _PLUGINS_KAITAI_PYTHON_PARSERS_TYPE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_type_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.parsers.KaitaiType'. */
+bool ensure_python_kaitai_type_is_registered(void);
+
+/* Tente de convertir en type particulier pour Kaitai. */
+int convert_to_kaitai_type(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_PARSERS_TYPE_H */
diff --git a/plugins/kaitai/python/record.c b/plugins/kaitai/python/record.c
new file mode 100644
index 0000000..4194a9a
--- /dev/null
+++ b/plugins/kaitai/python/record.c
@@ -0,0 +1,420 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * record.h - équivalent Python du fichier "plugins/kaitai/record.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "record.h"
+
+
+#include <pygobject.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/arch/vmpa.h>
+
+
+#include "parser.h"
+#include "../record.h"
+
+
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(match_record, G_TYPE_MATCH_RECORD, NULL);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_match_record_init(PyObject *, PyObject *, PyObject *);
+
+/* Modifie la référence au créateur de la correspondance. */
+static int py_match_record_set_creator(PyObject *, PyObject *, void *);
+
+/* Renvoie vers le lecteur à l'origine de la correspondance. */
+static PyObject *py_match_record_get_creator(PyObject *, void *);
+
+/* Fournit le contenu lié à une correspondance établie. */
+static PyObject *py_match_record_get_content(PyObject *, void *);
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static PyObject *py_match_record_get_range(PyObject *, void *);
+
+/* Lit les octets bruts couverts par une correspondance. */
+static PyObject *py_match_record_get_raw_bytes(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_match_record_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int ret;                                /* Bilan de lecture des args.  */
+
+#define MATCH_RECORD_DOC                                                    \
+    "MatchRecord is an abstract class providing mainly location and raw"    \
+    " data of an area which has matched a part of a binary content."
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = correspondance à manipuler.                        *
+*                value   = lecteur à l'origine de la correspondance.          *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Modifie la référence au créateur de la correspondance.       *
+*                                                                             *
+*  Retour      : Bilan de la définition.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_match_record_set_creator(PyObject *self, PyObject *value, void *closure)
+{
+    int result;                             /* Bilan à renvoyer            */
+    GMatchRecord *record;                   /* Version GLib de l'objet     */
+    GKaitaiParser *parser;                  /* Lecteur à l'origine         */
+
+    record = G_MATCH_RECORD(pygobject_get(self));
+
+    if (!convert_to_kaitai_parser(value, &parser))
+        result = -1;
+
+    else
+    {
+        g_match_record_fix_creator(record, parser);
+        result = 0;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = correspondance à manipuler.                        *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Renvoie vers le lecteur à l'origine de la correspondance.    *
+*                                                                             *
+*  Retour      : Lecteur à l'origine de la création.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_match_record_get_creator(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    GMatchRecord *record;                   /* Version GLib de l'objet     */
+    GKaitaiParser *parser;                  /* Lecteur à l'origine         */
+
+#define MATCH_RECORD_CREATOR_ATTRIB PYTHON_GETSET_DEF_FULL                      \
+(                                                                               \
+    creator, py_match_record,                                                   \
+    "Provide or define the pychrysalide.plugins.kaitai.KaitaiParser instance"   \
+    " which has created the record.\n"                                          \
+    "\n"                                                                        \
+    "This field should not be defined after the record creation in most cases." \
+)
+
+    record = G_MATCH_RECORD(pygobject_get(self));
+
+    parser = g_match_record_get_creator(record);
+
+    result = pygobject_new(G_OBJECT(parser));
+    g_object_unref(parser);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit le contenu lié à une correspondance établie.         *
+*                                                                             *
+*  Retour      : Contenu binaire associé.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_match_record_get_content(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GMatchRecord *record;                   /* Conservation à consulter    */
+    GBinContent *content;                   /* Contenu associé             */
+
+#define MATCH_RECORD_CONTENT_ATTRIB PYTHON_GET_DEF_FULL     \
+(                                                           \
+    content, py_match_record,                               \
+    "pychrysalide.analysis.BinContent instance linked to"   \
+    " the match record."                                    \
+)
+
+    record = G_MATCH_RECORD(pygobject_get(self));
+    content = g_match_record_get_content(record);
+
+    if (content != NULL)
+    {
+        result = pygobject_new(G_OBJECT(content));
+        g_object_unref(G_OBJECT(content));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Calcule ou fournit la zone couverte par une correspondance.  *
+*                                                                             *
+*  Retour      : Zone de couverture déterminée.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_match_record_get_range(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GMatchRecord *record;                   /* Conservation à consulter    */
+    mrange_t range;                         /* Couverture courante         */
+
+#define MATCH_RECORD_RANGE_ATTRIB PYTHON_GET_DEF_FULL       \
+(                                                           \
+    range, py_match_record,                                 \
+    "Area of the matched data for the parsed attribute"     \
+    " against a given binary content.\n"                    \
+    "\n"                                                    \
+    "This property is a pychrysalide.arch.mrange instance." \
+)
+
+    record = G_MATCH_RECORD(pygobject_get(self));
+    g_match_record_get_range(record, &range);
+
+    result = build_from_internal_mrange(&range);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Lit les octets bruts couverts par une correspondance.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_match_record_get_raw_bytes(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GMatchRecord *record;                   /* Conservation à consulter    */
+    bin_t *out;                             /* Données brutes à transmettre*/
+    size_t len;                             /* Quantité de ces données     */
+
+#define MATCH_RECORD_RAW_BYTES_ATTRIB PYTHON_GET_DEF_FULL   \
+(                                                           \
+    raw_bytes, py_match_record,                             \
+    "Raw bytes from the area covered by the record."        \
+)
+
+    record = G_MATCH_RECORD(pygobject_get(self));
+
+    g_match_record_read_raw_bytes(record, &out, &len);
+
+    result = PyBytes_FromStringAndSize((char *)out, len);
+    free(out);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_match_record_type(void)
+{
+    static PyMethodDef py_match_record_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_match_record_getseters[] = {
+        MATCH_RECORD_CREATOR_ATTRIB,
+        MATCH_RECORD_CONTENT_ATTRIB,
+        MATCH_RECORD_RANGE_ATTRIB,
+        MATCH_RECORD_RAW_BYTES_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_match_record_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.MatchRecord",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = MATCH_RECORD_DOC,
+
+        .tp_methods     = py_match_record_methods,
+        .tp_getset      = py_match_record_getseters,
+
+        .tp_init        = py_match_record_init,
+        .tp_new         = py_match_record_new,
+
+    };
+
+    return &py_match_record_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.plugins...MatchRecord. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_match_record_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'MatchRecord'   */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_match_record_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+        dict = PyModule_GetDict(module);
+
+        if (!register_class_for_pygobject(dict, G_TYPE_MATCH_RECORD, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en conservation de correspondance.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_match_record(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_match_record_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to match record");
+            break;
+
+        case 1:
+            *((GMatchRecord **)dst) = G_MATCH_RECORD(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/record.h b/plugins/kaitai/python/record.h
new file mode 100644
index 0000000..edf75fc
--- /dev/null
+++ b/plugins/kaitai/python/record.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * record.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/record.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORD_H
+#define _PLUGINS_KAITAI_PYTHON_RECORD_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_match_record_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.MatchRecord'. */
+bool ensure_python_match_record_is_registered(void);
+
+/* Tente de convertir en conservation de correspondance. */
+int convert_to_match_record(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_RECORD_H */
diff --git a/plugins/kaitai/python/records/Makefile.am b/plugins/kaitai/python/records/Makefile.am
new file mode 100644
index 0000000..1413228
--- /dev/null
+++ b/plugins/kaitai/python/records/Makefile.am
@@ -0,0 +1,18 @@
+
+noinst_LTLIBRARIES = libkaitaipythonrecords.la
+
+libkaitaipythonrecords_la_SOURCES = 		\
+	empty.h empty.c							\
+	group.h group.c							\
+	item.h item.c							\
+	list.h list.c							\
+	module.h module.c						\
+	value.h value.c
+
+libkaitaipythonrecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaipythonrecords_la_SOURCES:%c=)
diff --git a/plugins/kaitai/python/records/empty.c b/plugins/kaitai/python/records/empty.c
new file mode 100644
index 0000000..9861a39
--- /dev/null
+++ b/plugins/kaitai/python/records/empty.c
@@ -0,0 +1,286 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * empty.c - équivalent Python du fichier "plugins/kaitai/parsers/empty.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "empty.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/arch/vmpa.h>
+
+
+#include "../parser.h"
+#include "../record.h"
+#include "../../records/empty-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_empty, G_TYPE_RECORD_EMPTY);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_empty_init(PyObject *, PyObject *, PyObject *);
+
+/* Produit une absence de valeur pour la correspondance. */
+static PyObject *py_record_empty_get_value(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_record_empty_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GKaitaiParser *parser;                  /* Analyseur défini créateur   */
+    GBinContent *content;                   /* Contenu binaire manipulé    */
+    vmpa2t *pos;                            /* Tête de lecture courante    */
+    int ret;                                /* Bilan de lecture des args.  */
+    GRecordEmpty *empty;                    /* Création GLib à transmettre */
+
+#define RECORD_EMPTY_DOC                                                        \
+    "The RecordEmpty object reflects absolutely no match and should only get"   \
+    " in some rare cases.\n"                                                    \
+    "\n"                                                                        \
+    "Instances can be created using following constructor:\n"                   \
+    "\n"                                                                        \
+    "    RecordEmpty(parser, content, pos)"                                     \
+    "\n"                                                                        \
+    "Where *parser* is the creator of the record, as a"                         \
+    " pychrysalide.plugins.kaitai.KaitaiParser instance, *content* is a"        \
+    " pychrysalide.analysis.BinContent instance providing the processed data"   \
+    " and *pos* defines the current reading location, as a"                     \
+    " pychrysalide.arch.vmpa value."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&O&O&",
+                           convert_to_kaitai_parser, &parser,
+                           convert_to_binary_content, &content,
+                           convert_any_to_vmpa, &pos);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    empty = G_RECORD_EMPTY(pygobject_get(self));
+
+    if (!g_record_empty_create(empty, parser, content, pos))
+    {
+        clean_vmpa_arg(pos);
+
+        PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai stream."));
+        return -1;
+
+    }
+
+    clean_vmpa_arg(pos);
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Produit une absence de valeur pour la correspondance.        *
+*                                                                             *
+*  Retour      : None.                                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_record_empty_get_value(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+
+#define RECORD_EMPTY_VALUE_ATTRIB PYTHON_GET_DEF_FULL   \
+(                                                       \
+    value, py_record_empty,                             \
+    "Always *None*.\n"                                  \
+    "\n"                                                \
+    "This attribute is only provided to mimic other"    \
+    " record types."                                    \
+)
+
+    result = Py_None;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_record_empty_type(void)
+{
+    static PyMethodDef py_record_empty_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_record_empty_getseters[] = {
+        RECORD_EMPTY_VALUE_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_record_empty_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.records.RecordEmpty",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = RECORD_EMPTY_DOC,
+
+        .tp_methods     = py_record_empty_methods,
+        .tp_getset      = py_record_empty_getseters,
+
+        .tp_init        = py_record_empty_init,
+        .tp_new         = py_record_empty_new,
+
+    };
+
+    return &py_record_empty_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide...records.RecordEmpty. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_record_empty_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'RecordEmpty'   */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_record_empty_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.records");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_match_record_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_RECORD_EMPTY, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en zone de correspondance vide.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_record_empty(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_record_empty_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record empty");
+            break;
+
+        case 1:
+            *((GRecordEmpty **)dst) = G_RECORD_EMPTY(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/records/empty.h b/plugins/kaitai/python/records/empty.h
new file mode 100644
index 0000000..ecd5fc9
--- /dev/null
+++ b/plugins/kaitai/python/records/empty.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * empty.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/empty.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_EMPTY_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_EMPTY_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_empty_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordEmpty'. */
+bool ensure_python_record_empty_is_registered(void);
+
+/* Tente de convertir en zone de correspondance vide. */
+int convert_to_record_empty(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_RECORDS_EMPTY_H */
diff --git a/plugins/kaitai/python/records/group.c b/plugins/kaitai/python/records/group.c
new file mode 100644
index 0000000..a050043
--- /dev/null
+++ b/plugins/kaitai/python/records/group.c
@@ -0,0 +1,305 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * group.h - équivalent Python du fichier "plugins/kaitai/parsers/group.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "group.h"
+
+
+#include <pygobject.h>
+#include <string.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/arch/vmpa.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "../record.h"
+#include "../parsers/struct.h"
+#include "../../records/group-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_group, G_TYPE_RECORD_GROUP);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_group_init(PyObject *, PyObject *, PyObject *);
+
+/* Assure l'encadrement des accès aux champs d'une séquence. */
+static PyObject *py_record_group_getattr(PyObject *, char *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_record_group_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GKaitaiStruct *kstruct;                 /* Séquence définie créatrice  */
+    GBinContent *content;                   /* Contenu binaire analysé     */
+    int ret;                                /* Bilan de lecture des args.  */
+    GRecordGroup *group;                    /* Création GLib à transmettre */
+
+#define RECORD_GROUP_DOC                                                        \
+    "The RecordGroup class stores a map of parsed attributes with their"        \
+    " relative values. Each of theses Kaitai attributes can be accessed as"     \
+    " usual Python attribute.\n"                                                \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    RecordGroup(kstruct, content)"                                         \
+    "\n"                                                                        \
+    "Where the *kstruct* refers to a"                                           \
+    " pychrysalide.plugins.kaitai.parsers.KaitaiStructure instance as the"      \
+    " creator of the newly created object, and *content* points to a"           \
+    " pychrysalide.analysis.BinContent instance."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&O&",
+                           convert_to_kaitai_structure, &kstruct,
+                           convert_to_binary_content, &content);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    group = G_RECORD_GROUP(pygobject_get(self));
+
+    if (!g_record_group_create(group, kstruct, content))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create record group."));
+        return -1;
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = structure C convertie en Python.                      *
+*                name = nom du champ auquel un accès est demandé.             *
+*                                                                             *
+*  Description : Assure l'encadrement des accès aux champs d'une séquence.    *
+*                                                                             *
+*  Retour      : Valeur du champ demandé.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_record_group_getattr(PyObject *self, char *name)
+{
+    PyObject *result;                       /* Elément à retourner         */
+    GRecordGroup *group;                    /* Version native de l'objet   */
+    GMatchRecord *found;                    /* Sous-élément identifié      */
+    PyObject *w;                            /* Conversion du nom de champ  */
+    PyTypeObject *tp;                       /* Type de l'objet manipulé    */
+
+    group = G_RECORD_GROUP(pygobject_get(self));
+
+    found = g_match_record_find_by_name(G_MATCH_RECORD(group), name, strlen(name), DIRECT_SEARCH_DEEP_LEVEL);
+
+    if (found != NULL)
+    {
+        result = pygobject_new(G_OBJECT(found));
+        g_object_unref(G_OBJECT(found));
+    }
+
+    else
+    {
+        w = PyUnicode_InternFromString(name);
+        if (w == NULL) return NULL;
+
+        tp = Py_TYPE(self);
+
+        if (tp->tp_base->tp_getattro != NULL)
+            result = tp->tp_base->tp_getattro(self, w);
+
+        else
+        {
+            PyErr_Format(PyExc_AttributeError,
+                         "type object '%.50s' has no attribute '%U'",
+                         tp->tp_name, name);
+            result = NULL;
+        }
+
+        Py_DECREF(w);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_record_group_type(void)
+{
+    static PyMethodDef py_record_group_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_record_group_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_record_group_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.records.RecordGroup",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_getattr     = py_record_group_getattr,
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = RECORD_GROUP_DOC,
+
+        .tp_methods     = py_record_group_methods,
+        .tp_getset      = py_record_group_getseters,
+
+        .tp_init        = py_record_group_init,
+        .tp_new         = py_record_group_new,
+
+    };
+
+    return &py_record_group_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide...records.RecordGroup. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_record_group_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'RecordGroup'   */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_record_group_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.records");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_match_record_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_RECORD_GROUP, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en correspondances attribut/binaire.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_record_group(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_record_group_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record group");
+            break;
+
+        case 1:
+            *((GRecordGroup **)dst) = G_RECORD_GROUP(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/records/group.h b/plugins/kaitai/python/records/group.h
new file mode 100644
index 0000000..3e12ffc
--- /dev/null
+++ b/plugins/kaitai/python/records/group.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * group.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/group.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_GROUP_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_GROUP_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_group_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordGroup'. */
+bool ensure_python_record_group_is_registered(void);
+
+/* Tente de convertir en correspondances attribut/binaire. */
+int convert_to_record_group(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_RECORDS_GROUP_H */
diff --git a/plugins/kaitai/python/records/item.c b/plugins/kaitai/python/records/item.c
new file mode 100644
index 0000000..84c2c58
--- /dev/null
+++ b/plugins/kaitai/python/records/item.c
@@ -0,0 +1,394 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - équivalent Python du fichier "plugins/kaitai/parsers/item.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "item.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/arch/vmpa.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "../record.h"
+#include "../parsers/attribute.h"
+#include "../../records/item-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_item, G_TYPE_RECORD_ITEM);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_item_init(PyObject *, PyObject *, PyObject *);
+
+/* Lit la série d'octets d'un élément Kaitai entier représenté. */
+static PyObject *py_record_item_get_truncated_bytes(PyObject *, void *);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+static PyObject *py_record_item_get_value(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_record_item_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GKaitaiAttribute *attrib;               /* Attribut défini créateur    */
+    GBinContent *content;                   /* Contenu binaire analysé     */
+    mrange_t range;                         /* Espace couvert              */
+    SourceEndian endian;                    /* Boutisme à observer         */
+    int ret;                                /* Bilan de lecture des args.  */
+    GRecordItem *item;                      /* Création GLib à transmettre */
+
+#define RECORD_ITEM_DOC                                                         \
+    "The RecordItem class remembers a match between a described attribute and"  \
+    " its concret value read from parsed binary data."                          \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    RecordItem(content, range, endian, attrib)"                            \
+    "\n"                                                                        \
+    "Where the *attrib* arguments refers to a"                                  \
+    " pychrysalide.plugins.kaitai.parsers.KaitaiAttribute instance as the"      \
+    " creator of the newly created object, *content* points to a"               \
+    " pychrysalide.analysis.BinContent instance, *range* is a"                  \
+    " pychrysalide.arch.mrange object, *endian* states with a"                  \
+    " pychrysalide.analysis.BinContent.SourceEndian hint the endianness used"   \
+    " to read integer values."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&O&O&",
+                           convert_to_kaitai_attribute, &attrib,
+                           convert_to_binary_content, &content,
+                           convert_any_to_mrange, &range,
+                           convert_to_binary_content, &endian);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    item = G_RECORD_ITEM(pygobject_get(self));
+
+    if (!g_record_item_create(item, attrib, content, &range, endian))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create record item."));
+        return -1;
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Lit la série d'octets d'un élément Kaitai entier représenté. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_record_item_get_truncated_bytes(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GRecordItem *item;                      /* Version native de l'élément */
+    bool status;                            /* Bilan d'opération           */ 
+    bin_t *out;                             /* Données brutes à transmettre*/
+    size_t len;                             /* Quantité de ces données     */
+
+#define RECORD_ITEM_TRUNCATED_BYTES_ATTRIB PYTHON_GET_DEF_FULL      \
+(                                                                   \
+    truncated_bytes, py_record_item,                                \
+    "Raw bytes carried by the item (truncated if a separator"       \
+    " is defined in the linked attribute), or None if irrelevant"   \
+    " regarding to the type of the attribute."                      \
+)
+
+    item = G_RECORD_ITEM(pygobject_get(self));
+
+    status = g_record_item_get_truncated_bytes(item, &out, &len);
+
+    if (status)
+    {
+        result = PyBytes_FromStringAndSize((char *)out, len);
+        free(out);
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Lit la valeur d'un élément Kaitai entier représenté.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_record_item_get_value(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GRecordItem *item;                      /* Version native de l'élément */
+    resolved_value_t resolved;              /* Valeur sous forme générique */
+    bool status;                            /* Bilan d'opération           */
+
+#define RECORD_ITEM_VALUE_ATTRIB PYTHON_GET_DEF_FULL                \
+(                                                                   \
+    value, py_record_item,                                          \
+    "Carried value (as integer, bytes), or None in case of error."  \
+)
+
+    result = NULL;
+
+    item = G_RECORD_ITEM(pygobject_get(self));
+
+    status = g_record_item_get_value(item, &resolved);
+
+    if (status)
+        switch (resolved.type)
+        {
+            case GVT_ERROR:
+                assert(false);
+                PyErr_Format(PyExc_RuntimeError,
+                             _("Error got while parsing Kaitai definition should not have been exported!"));
+                result = NULL;
+                break;
+
+            case GVT_UNSIGNED_INTEGER:
+                result = PyLong_FromUnsignedLongLong(resolved.unsigned_integer);
+                break;
+
+            case GVT_SIGNED_INTEGER:
+                result = PyLong_FromLongLong(resolved.signed_integer);
+                break;
+
+            case GVT_FLOAT:
+                result = PyFloat_FromDouble(resolved.floating_number);
+                break;
+
+            case GVT_BOOLEAN:
+                result = resolved.status ? Py_True : Py_False;
+                Py_INCREF(result);
+                break;
+
+            case GVT_BYTES:
+                result = PyBytes_FromStringAndSize(resolved.bytes.data, resolved.bytes.len);
+                exit_szstr(&resolved.bytes);
+                break;
+
+            case GVT_ARRAY:
+                result = pygobject_new(G_OBJECT(resolved.array));
+                break;
+
+            case GVT_RECORD:
+                result = pygobject_new(G_OBJECT(resolved.record));
+                break;
+
+            case GVT_STREAM:
+                result = pygobject_new(G_OBJECT(resolved.stream));
+                break;
+
+        }
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_record_item_type(void)
+{
+    static PyMethodDef py_record_item_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_record_item_getseters[] = {
+        RECORD_ITEM_TRUNCATED_BYTES_ATTRIB,
+        RECORD_ITEM_VALUE_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_record_item_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.records.RecordItem",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = RECORD_ITEM_DOC,
+
+        .tp_methods     = py_record_item_methods,
+        .tp_getset      = py_record_item_getseters,
+
+        .tp_init        = py_record_item_init,
+        .tp_new         = py_record_item_new,
+
+    };
+
+    return &py_record_item_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....records.RecordItem. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_record_item_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'RecordItem'    */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_record_item_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.records");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_match_record_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_RECORD_ITEM, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en correspondance attribut/binaire.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_record_item(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_record_item_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record item");
+            break;
+
+        case 1:
+            *((GRecordItem **)dst) = G_RECORD_ITEM(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/records/item.h b/plugins/kaitai/python/records/item.h
new file mode 100644
index 0000000..bde8a55
--- /dev/null
+++ b/plugins/kaitai/python/records/item.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/item.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_ITEM_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_ITEM_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_item_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordItem'. */
+bool ensure_python_record_item_is_registered(void);
+
+/* Tente de convertir en correspondance attribut/binaire. */
+int convert_to_record_item(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_RECORDS_ITEM_H */
diff --git a/plugins/kaitai/python/records/list.c b/plugins/kaitai/python/records/list.c
new file mode 100644
index 0000000..d2eecbb
--- /dev/null
+++ b/plugins/kaitai/python/records/list.c
@@ -0,0 +1,336 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.h - équivalent Python du fichier "plugins/kaitai/parsers/list.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "list.h"
+
+
+#include <pygobject.h>
+#include <string.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/arch/vmpa.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "../record.h"
+#include "../parsers/attribute.h"
+#include "../../records/list-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_list, G_TYPE_RECORD_LIST);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_list_init(PyObject *, PyObject *, PyObject *);
+
+/* Dénombre le nombre de correspondances enregistrées. */
+static Py_ssize_t py_record_list_sq_length(PyObject *);
+
+/* Fournit un élément ciblé dans la liste de correspondances. */
+static PyObject *py_record_list_sq_item(PyObject *, Py_ssize_t);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_record_list_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int result;                             /* Bilan à retourner           */
+    GKaitaiAttribute *attrib;               /* Attribut défini créateur    */
+    GBinContent *content;                   /* Contenu binaire analysé     */
+    vmpa2t *addr;                           /* Adresse de symbole à ajouter*/
+    int ret;                                /* Bilan de lecture des args.  */
+    GRecordList *list;                      /* Création GLib à transmettre */
+
+#define RECORD_LIST_DOC                                                         \
+    "The RecordList class collects a list of parsed attributes with their"      \
+    " relative values. Each of theses Kaitai attributes can be accessed as"     \
+    " subscriptable Python attribute.\n"                                        \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    RecordList(content, attrib)"                                           \
+    "\n"                                                                        \
+    "Where the *attrib* argument refers to the"                                 \
+    " pychrysalide.plugins.kaitai.parsers.KaitaiAttribute instance used to"     \
+    " create each record contained by the list and *content* points to a"       \
+    " pychrysalide.analysis.BinContent instance."
+
+    result = 0;
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&O&",
+                           convert_to_kaitai_attribute, &attrib,
+                           convert_to_binary_content, &content,
+                           convert_any_to_vmpa, &addr);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1)
+    {
+        result = -1;
+        goto exit;
+    }
+
+    /* Eléments de base */
+
+    list = G_RECORD_LIST(pygobject_get(self));
+
+    if (!g_record_list_create(list, attrib, content, addr))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create record list."));
+        result = -1;
+        goto exit;
+    }
+
+ exit:
+
+    clean_vmpa_arg(addr);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = instance Python manipulée.                            *
+*                                                                             *
+*  Description : Dénombre le nombre de correspondances enregistrées.          *
+*                                                                             *
+*  Retour      : Taille de la liste représentée.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static Py_ssize_t py_record_list_sq_length(PyObject *self)
+{
+    Py_ssize_t result;                      /* Quantité à retourner        */
+    GRecordList *list;                      /* Version native de l'objet   */
+
+    list = G_RECORD_LIST(pygobject_get(self));
+
+    result = g_record_list_count_records(list);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = structure C convertie en Python.                      *
+*                index = indice de la correspondance visée.                   *
+*                                                                             *
+*  Description : Fournit un élément ciblé dans la liste de correspondances.   *
+*                                                                             *
+*  Retour      : Instance de correspondance particulière, voire None.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_record_list_sq_item(PyObject *self, Py_ssize_t index)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    GRecordList *list;                      /* Version native de l'objet   */
+    GMatchRecord *record;                   /* Correspondance retrouvée    */
+
+    list = G_RECORD_LIST(pygobject_get(self));
+
+    record = g_record_list_get_record(list, index);
+
+    if (record != NULL)
+    {
+        result = pygobject_new(G_OBJECT(record));
+        g_object_unref(G_OBJECT(record));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_record_list_type(void)
+{
+    static PySequenceMethods py_record_list_sequence_methods = {
+
+        .sq_length = py_record_list_sq_length,
+        .sq_item   = py_record_list_sq_item,
+
+    };
+
+    static PyMethodDef py_record_list_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_record_list_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_record_list_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.records.RecordList",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_as_sequence = &py_record_list_sequence_methods,
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = RECORD_LIST_DOC,
+
+        .tp_methods     = py_record_list_methods,
+        .tp_getset      = py_record_list_getseters,
+
+        .tp_init        = py_record_list_init,
+        .tp_new         = py_record_list_new,
+
+    };
+
+    return &py_record_list_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....records.RecordList. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_record_list_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'RecordList'    */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_record_list_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.records");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_match_record_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_RECORD_LIST, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en correspondance attribut/binaire.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_record_list(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_record_list_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record list");
+            break;
+
+        case 1:
+            *((GRecordList **)dst) = G_RECORD_LIST(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/records/list.h b/plugins/kaitai/python/records/list.h
new file mode 100644
index 0000000..53572a9
--- /dev/null
+++ b/plugins/kaitai/python/records/list.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/list.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_LIST_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_LIST_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_list_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordList'. */
+bool ensure_python_record_list_is_registered(void);
+
+/* Tente de convertir en correspondance attribut/binaire. */
+int convert_to_record_list(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_RECORDS_LIST_H */
diff --git a/plugins/kaitai/python/records/module.c b/plugins/kaitai/python/records/module.c
new file mode 100644
index 0000000..ea33c31
--- /dev/null
+++ b/plugins/kaitai/python/records/module.c
@@ -0,0 +1,122 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire records en tant que module
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "empty.h"
+#include "group.h"
+#include "item.h"
+#include "list.h"
+#include "value.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Ajoute le module 'plugins.kaitai.records' au module Python.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool add_kaitai_records_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *super;                        /* Module à compléter          */
+    PyObject *module;                       /* Sous-module mis en place    */
+
+#define PYCHRYSALIDE_PLUGINS_KAITAI_RECORDS_DOC                 \
+    "This module is providing objects used to link structure"   \
+    " definitions with their data."
+
+    static PyModuleDef py_chrysalide_kaitai_records_module = {
+
+        .m_base = PyModuleDef_HEAD_INIT,
+
+        .m_name = "pychrysalide.plugins.kaitai.records",
+        .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_RECORDS_DOC,
+
+        .m_size = -1,
+
+    };
+
+    result = false;
+
+    super = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+    module = build_python_module(super, &py_chrysalide_kaitai_records_module);
+
+    result = (module != NULL);
+
+    assert(result);
+
+    if (!result)
+        Py_XDECREF(module);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Intègre les objets du module 'plugins.kaitai.records'.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool populate_kaitai_records_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    if (result) result = ensure_python_record_empty_is_registered();
+    if (result) result = ensure_python_record_group_is_registered();
+    if (result) result = ensure_python_record_item_is_registered();
+    if (result) result = ensure_python_record_list_is_registered();
+    if (result) result = ensure_python_record_value_is_registered();
+
+    assert(result);
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/records/module.h b/plugins/kaitai/python/records/module.h
new file mode 100644
index 0000000..ff631dc
--- /dev/null
+++ b/plugins/kaitai/python/records/module.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire records en tant que module
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_MODULE_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.kaitai.records' au module Python. */
+bool add_kaitai_records_module(void);
+
+/* Intègre les objets du module 'plugins.kaitai.records'. */
+bool populate_kaitai_records_module(void);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_RECORDS_MODULE_H */
diff --git a/plugins/kaitai/python/records/value.c b/plugins/kaitai/python/records/value.c
new file mode 100644
index 0000000..bd4ad74
--- /dev/null
+++ b/plugins/kaitai/python/records/value.c
@@ -0,0 +1,335 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * value.c - équivalent Python du fichier "plugins/kaitai/parsers/value.c"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "value.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/arch/vmpa.h>
+#include <plugins/yaml/python/node.h>
+
+
+#include "../record.h"
+#include "../scope.h"
+#include "../parsers/instance.h"
+#include "../../records/value-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_value, G_TYPE_RECORD_VALUE);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_value_init(PyObject *, PyObject *, PyObject *);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+static PyObject *py_record_value_get_value(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_record_value_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GKaitaiInstance *inst;                  /* Instance définie créatrice  */
+    kaitai_scope_t *locals;                 /* Environnement local         */
+    int ret;                                /* Bilan de lecture des args.  */
+    GRecordValue *value;                    /* Création GLib à transmettre */
+
+#define RECORD_VALUE_DOC                                                        \
+    "The RecordValue class stores a link to an instance used to compute a"      \
+    " given value."                                                             \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    RecordValue(inst, locals)"                                             \
+    "\n"                                                                        \
+    "Where the *inst* arguments refers to a"                                    \
+    " pychrysalide.plugins.kaitai.parsers.KaitaiInstance instance as the"       \
+    " creator of the newly created object, *locals* points to a"                \
+    " pychrysalide.plugins.kaitai.KaitaiScope structure used as current scope."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&O&",
+                           convert_to_kaitai_instance, &inst,
+                           convert_to_kaitai_scope, &locals);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    value = G_RECORD_VALUE(pygobject_get(self));
+
+    if (!g_record_value_create(value, inst, locals))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create record value."));
+        return -1;
+    }
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Lit la valeur d'un élément Kaitai entier représenté.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_record_value_get_value(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GRecordValue *value;                    /* Version native de l'élément */
+    resolved_value_t resolved;              /* Valeur sous forme générique */
+    bool status;                            /* Bilan d'opération           */
+
+#define RECORD_VALUE_VALUE_ATTRIB PYTHON_GET_DEF_FULL               \
+(                                                                   \
+    value, py_record_value,                                         \
+    "Carried value (as integer, bytes), or None in case of error."  \
+)
+
+    result = NULL;
+
+    value = G_RECORD_VALUE(pygobject_get(self));
+
+    status = g_record_value_compute_and_aggregate_value(value, &resolved);
+
+    if (status)
+        switch (resolved.type)
+        {
+            case GVT_ERROR:
+                assert(false);
+                PyErr_Format(PyExc_RuntimeError,
+                             _("Error got while parsing Kaitai definition should not have been exported!"));
+                result = NULL;
+                break;
+
+            case GVT_UNSIGNED_INTEGER:
+                result = PyLong_FromUnsignedLongLong(resolved.unsigned_integer);
+                break;
+
+            case GVT_SIGNED_INTEGER:
+                result = PyLong_FromLongLong(resolved.signed_integer);
+                break;
+
+            case GVT_FLOAT:
+                result = PyFloat_FromDouble(resolved.floating_number);
+                break;
+
+            case GVT_BOOLEAN:
+                result = resolved.status ? Py_True : Py_False;
+                Py_INCREF(result);
+                break;
+
+            case GVT_BYTES:
+                result = PyBytes_FromStringAndSize(resolved.bytes.data, resolved.bytes.len);
+                exit_szstr(&resolved.bytes);
+                break;
+
+            case GVT_ARRAY:
+                result = pygobject_new(G_OBJECT(resolved.array));
+                break;
+
+            case GVT_RECORD:
+                result = pygobject_new(G_OBJECT(resolved.record));
+                break;
+
+            case GVT_STREAM:
+                result = pygobject_new(G_OBJECT(resolved.stream));
+                break;
+
+        }
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_record_value_type(void)
+{
+    static PyMethodDef py_record_value_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_record_value_getseters[] = {
+        RECORD_VALUE_VALUE_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_record_value_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.records.RecordValue",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = RECORD_VALUE_DOC,
+
+        .tp_methods     = py_record_value_methods,
+        .tp_getset      = py_record_value_getseters,
+
+        .tp_init        = py_record_value_init,
+        .tp_new         = py_record_value_new,
+
+    };
+
+    return &py_record_value_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide...records.RecordValue. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_record_value_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'RecordValue'   */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_record_value_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai.records");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_match_record_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_RECORD_VALUE, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en valeur calculée.                       *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_record_value(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_record_value_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record value");
+            break;
+
+        case 1:
+            *((GRecordValue **)dst) = G_RECORD_VALUE(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/records/value.h b/plugins/kaitai/python/records/value.h
new file mode 100644
index 0000000..16cadcb
--- /dev/null
+++ b/plugins/kaitai/python/records/value.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * value.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/value.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_value_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordValue'. */
+bool ensure_python_record_value_is_registered(void);
+
+/* Tente de convertir en valeur calculée. */
+int convert_to_record_value(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H */
diff --git a/plugins/kaitai/python/scope.c b/plugins/kaitai/python/scope.c
new file mode 100644
index 0000000..b11dc81
--- /dev/null
+++ b/plugins/kaitai/python/scope.c
@@ -0,0 +1,542 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scope.c - équivalent Python du fichier "plugins/kaitai/scope.c"
+ *
+ * Copyright (C) 2020 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "scope.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "record.h"
+#include "parsers/meta.h"
+#include "../record.h"
+#include "../parsers/meta.h"
+
+
+
+/* Rassemblement de données d'un paquet */
+typedef struct _py_kaitai_scope_t
+{
+    PyObject_HEAD                           /* A laisser en premier        */
+
+    kaitai_scope_t *native;                /* Tampon de données lié       */
+
+} py_kaitai_scope_t;
+
+
+/* Libère de la mémoire un objet Python 'py_kaitai_scope_t'. */
+static void py_kaitai_scope_dealloc(py_kaitai_scope_t *);
+
+/* Initialise un objet Python de type 'py_kaitai_scope_t'. */
+static int py_kaitai_scope_init(py_kaitai_scope_t *, PyObject *, PyObject *);
+
+/* Conserve le souvenir de la dernière correspondance effectuée. */
+static PyObject *py_kaitai_scope_remember_last_record(PyObject *, PyObject *);
+
+/* Recherche la définition d'un type nouveau pour Kaitai. */
+static PyObject *py_kaitai_scope_find_sub_type(PyObject *, PyObject *);
+
+/* Retourne le souvenir d'une correspondance racine. */
+static PyObject *py_kaitai_scope_get_root_record(PyObject *, void *);
+
+/* Retourne le souvenir de la correspondance parente effectuée. */
+static PyObject *py_kaitai_scope_get_parent_record(PyObject *, void *);
+
+/* Retourne le souvenir de la dernière correspondance effectuée. */
+static PyObject *py_kaitai_scope_get_last_record(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = tampon de données à supprimer.                        *
+*                                                                             *
+*  Description : Libère de la mémoire un objet Python 'py_kaitai_scope_t'.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void py_kaitai_scope_dealloc(py_kaitai_scope_t *self)
+{
+    reset_record_scope(self->native);
+
+    Py_TYPE(self)->tp_free((PyObject *)self);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = instance d'objet à initialiser.                       *
+*                args = arguments passés pour l'appel.                        *
+*                kwds = mots clefs éventuellement fournis en complément.      *
+*                                                                             *
+*  Description : Initialise un objet Python de type 'py_kaitai_scope_t'.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_kaitai_scope_init(py_kaitai_scope_t *self, PyObject *args, PyObject *kwds)
+{
+    int result;                             /* Bilan à retourner           */
+    GKaitaiMeta *meta;                      /* Informations globale        */
+    int ret;                                /* Bilan de lecture des args.  */
+
+#define KAITAI_SCOPE_DOC                                                \
+    "The KaitaiScope object stores a local environment which freezes"   \
+    " a particular state of the Kaitai parser. It allows the dynamic"   \
+    " resolving of values contained in a Kaitai expression.\n"          \
+    "\n"                                                                \
+    "Instances can be created using the following constructor:\n"       \
+    "\n"                                                                \
+    "    KaitaiScope(meta)"                                             \
+    "\n"                                                                \
+    "Where *meta* is a pychrysalide.plugins.kaitai.parsers.KaitaiMeta"  \
+    " instance pointing to global information about the Kaitai"         \
+    " definition."
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_kaitai_meta, &meta);
+    if (!ret) return -1;
+
+    self->native = malloc(sizeof(kaitai_scope_t));
+
+    init_record_scope(self->native, meta);
+
+    result = 0;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = environnement local à manipuler.                      *
+*                args = arguments fournis pour la conduite de l'opération.    *
+*                                                                             *
+*  Description : Conserve le souvenir de la dernière correspondance effectuée.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_scope_remember_last_record(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à faire remonter      */
+    GMatchRecord *record;                   /* Correspondance à utiliser   */
+    int ret;                                /* Bilan de lecture des args.  */
+    py_kaitai_scope_t *locals;              /* Instance à manipuler        */
+
+#define KAITAI_SCOPE_REMEMBER_LAST_RECORD_METHOD PYTHON_METHOD_DEF  \
+(                                                                   \
+    remember_last_record, "$self, record, /",                       \
+    METH_VARARGS, py_kaitai_scope,                                  \
+    "Store a record as the last parsed record.\n"                   \
+    "\n"                                                            \
+    "This *record* is expected to be a"                             \
+    " pychrysalide.plugins.kaitai.MatchRecord instance."            \
+)
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_match_record, &record);
+    if (!ret) return NULL;
+
+    locals = (py_kaitai_scope_t *)self;
+
+    remember_last_record(locals->native, record);
+
+    result = Py_None;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = environnement local à manipuler.                      *
+*                args = arguments fournis pour la conduite de l'opération.    *
+*                                                                             *
+*  Description : Recherche la définition d'un type nouveau pour Kaitai.       *
+*                                                                             *
+*  Retour      : Type prêt à emploi ou NULL si non trouvé.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_scope_find_sub_type(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à faire remonter      */
+    const char *name;                       /* Désignation à retrouver     */
+    int ret;                                /* Bilan de lecture des args.  */
+    py_kaitai_scope_t *locals;              /* Instance à manipuler        */
+    GKaitaiType *type;                      /* Définition à identifier     */
+
+#define KAITAI_SCOPE_FIND_SUB_TYPE_METHOD PYTHON_METHOD_DEF     \
+(                                                               \
+    find_sub_type, "$self, name, /",                            \
+    METH_VARARGS, py_kaitai_scope,                              \
+    "Retrieve the type structure linked to a given name.\n"     \
+    "\n"                                                        \
+    "This *name* has to be a string.\n"                         \
+    "\n"                                                        \
+    "The result is a known"                                     \
+    " pychrysalide.plugins.kaitai.parsers.KaitaiType instance"  \
+    " or *None* if the name has not been registered during"     \
+    " the parsing."                                             \
+)
+
+    ret = PyArg_ParseTuple(args, "s", &name);
+    if (!ret) return NULL;
+
+    locals = (py_kaitai_scope_t *)self;
+
+    type = find_sub_type(locals->native, name);
+
+    result = pygobject_new(G_OBJECT(type));
+    g_object_unref(G_OBJECT(type));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = environnement local à consulter.                      *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Retourne le souvenir d'une correspondance racine.            *
+*                                                                             *
+*  Retour      : Dernière correspondance établie ou None.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_scope_get_root_record(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Conversion à retourner      */
+    py_kaitai_scope_t *locals;              /* Instance à manipuler        */
+    GMatchRecord *record;                   /* Correspondance à convertir  */
+
+#define KAITAI_SCOPE_ROOT_RECORD_ATTRIB PYTHON_GET_DEF_FULL     \
+(                                                               \
+    root_record, py_kaitai_scope,                               \
+    "Provide the first record for a parsed content.\n"          \
+    "\n"                                                        \
+    "The result is a pychrysalide.plugins.kaitai.MatchRecord"   \
+    " instance or *None*."                                      \
+)
+
+    locals = (py_kaitai_scope_t *)self;
+
+    record = get_root_record(locals->native);
+
+    if (record != NULL)
+    {
+        result = pygobject_new(G_OBJECT(record));
+        g_object_unref(G_OBJECT(record));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = environnement local à consulter.                      *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Retourne le souvenir de la correspondance parente effectuée. *
+*                                                                             *
+*  Retour      : Dernière correspondance établie ou None.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_scope_get_parent_record(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Conversion à retourner      */
+    py_kaitai_scope_t *locals;              /* Instance à manipuler        */
+    GMatchRecord *record;                   /* Correspondance à convertir  */
+
+#define KAITAI_SCOPE_PARENT_RECORD_ATTRIB PYTHON_GET_DEF_FULL   \
+(                                                               \
+    parent_record, py_kaitai_scope,                             \
+    "Provide the current parent record for a parsed content.\n" \
+    "\n"                                                        \
+    "The result is a pychrysalide.plugins.kaitai.MatchRecord"   \
+    " instance or *None*."                                      \
+)
+
+    locals = (py_kaitai_scope_t *)self;
+
+    record = get_parent_record(locals->native);
+
+    if (record != NULL)
+    {
+        result = pygobject_new(G_OBJECT(record));
+        g_object_unref(G_OBJECT(record));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = environnement local à consulter.                      *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Retourne le souvenir de la dernière correspondance effectuée.*
+*                                                                             *
+*  Retour      : Dernière correspondance établie ou None.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_scope_get_last_record(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Conversion à retourner      */
+    py_kaitai_scope_t *locals;              /* Instance à manipuler        */
+    GMatchRecord *record;                   /* Correspondance à convertir  */
+
+#define KAITAI_SCOPE_LAST_RECORD_ATTRIB PYTHON_GET_DEF_FULL     \
+(                                                               \
+    last_record, py_kaitai_scope,                               \
+    "Provide the last createdrecord for a parsed content.\n"    \
+    "\n"                                                        \
+    "The result is a pychrysalide.plugins.kaitai.MatchRecord"   \
+    " instance or *None*."                                      \
+)
+
+    locals = (py_kaitai_scope_t *)self;
+
+    record = get_last_record(locals->native);
+
+    if (record != NULL)
+    {
+        result = pygobject_new(G_OBJECT(record));
+        g_object_unref(G_OBJECT(record));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_scope_type(void)
+{
+    static PyMethodDef py_kaitai_scope_methods[] = {
+        KAITAI_SCOPE_REMEMBER_LAST_RECORD_METHOD,
+        KAITAI_SCOPE_FIND_SUB_TYPE_METHOD,
+        { NULL }
+    };
+
+    static PyGetSetDef py_kaitai_scope_getseters[] = {
+        KAITAI_SCOPE_ROOT_RECORD_ATTRIB,
+        KAITAI_SCOPE_PARENT_RECORD_ATTRIB,
+        KAITAI_SCOPE_LAST_RECORD_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_kaitai_scope_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.KaitaiScope",
+        .tp_basicsize   = sizeof(py_kaitai_scope_t),
+
+        .tp_dealloc     = (destructor)py_kaitai_scope_dealloc,
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = KAITAI_SCOPE_DOC,
+
+        .tp_methods     = py_kaitai_scope_methods,
+        .tp_getset      = py_kaitai_scope_getseters,
+
+        .tp_init        = (initproc)py_kaitai_scope_init,
+        .tp_new         = PyType_GenericNew,
+
+    };
+
+    return &py_kaitai_scope_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.common.PackedBuffer'.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_kaitai_scope_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'PackedBuffer'  */
+    PyObject *module;                       /* Module à recompléter        */
+
+    type = get_python_kaitai_scope_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        if (PyType_Ready(type) != 0)
+            return false;
+
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+        if (!register_python_module_object(module, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = structure interne à copier en objet Python.         *
+*                                                                             *
+*  Description : Convertit une structure 'kaitai_scope_t' en objet Python.    *
+*                                                                             *
+*  Retour      : Object Python résultant de la conversion opérée.             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyObject *build_from_internal_kaitai_scope(const kaitai_scope_t *locals)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    PyTypeObject *type;                     /* Type à instancier           */
+
+    type = get_python_kaitai_scope_type();
+
+    result = PyObject_CallObject((PyObject *)type, NULL);
+
+    copy_record_scope(((py_kaitai_scope_t *)result)->native, locals);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en environnement local pour Kaitai.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_kaitai_scope(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_scope_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai scope");
+            break;
+
+        case 1:
+            *((kaitai_scope_t **)dst) = ((py_kaitai_scope_t *)arg)->native;
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/scope.h b/plugins/kaitai/python/scope.h
new file mode 100644
index 0000000..9353b06
--- /dev/null
+++ b/plugins/kaitai/python/scope.h
@@ -0,0 +1,51 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scope.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/scope.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_SCOPE_H
+#define _PLUGINS_KAITAI_PYTHON_SCOPE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+#include "../scope.h"
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_scope_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.common.PackedBuffer'. */
+bool ensure_python_kaitai_scope_is_registered(void);
+
+/* Convertit une structure 'kaitai_scope_t' en objet Python. */
+PyObject *build_from_internal_kaitai_scope(const kaitai_scope_t *);
+
+/* Tente de convertir en environnement local pour Kaitai. */
+int convert_to_kaitai_scope(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_SCOPE_H */
diff --git a/plugins/kaitai/python/stream.c b/plugins/kaitai/python/stream.c
new file mode 100644
index 0000000..985e3c3
--- /dev/null
+++ b/plugins/kaitai/python/stream.c
@@ -0,0 +1,278 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * stream.h - équivalent Python du fichier "plugins/kaitai/stream.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "stream.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/arch/vmpa.h>
+
+
+#include "../stream-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_stream, G_TYPE_KAITAI_STREAM);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_stream_init(PyObject *, PyObject *, PyObject *);
+
+/* Détermine si la fin des données a été atteinte. */
+static PyObject *py_kaitai_stream_get_eof(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_kaitai_stream_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GBinContent *content;                   /* Contenu binaire manipulé    */
+    vmpa2t *pos;                            /* Tête de lecture courante    */
+    int ret;                                /* Bilan de lecture des args.  */
+    GKaitaiStream *stream;                  /* Création GLib à transmettre */
+
+#define KAITAI_STREAM_DOC                                                       \
+    "KaitaiStream collects all the information useful for the processing of"    \
+    " binary data."                                                             \
+    "\n"                                                                        \
+    "Instances can be created using following constructor:\n"                   \
+    "\n"                                                                        \
+    "    KaitaiStream(content, pos)"                                            \
+    "\n"                                                                        \
+    "Where *content* is a pychrysalide.analysis.BinContent instance providing"  \
+    " the processed data and *pos* defines the current reading location, as a"  \
+    " pychrysalide.arch.vmpa value."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&O&", convert_to_binary_content, &content, convert_any_to_vmpa, &pos);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    stream = G_KAITAI_STREAM(pygobject_get(self));
+
+    if (!g_kaitai_stream_create(stream, content, pos))
+    {
+        clean_vmpa_arg(pos);
+
+        PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai stream."));
+        return -1;
+
+    }
+
+    clean_vmpa_arg(pos);
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Détermine si la fin des données a été atteinte.              *
+*                                                                             *
+*  Retour      : True si la tête de lecture est en position finale, ou False. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_kaitai_stream_get_eof(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GKaitaiStream *stream;                  /* Version native dyu flux     */
+    bool status;                            /* Etat de la position courante*/
+
+#define KAITAI_STREAM_EOF_ATTRIB PYTHON_GET_DEF_FULL    \
+(                                                       \
+    eof, py_kaitai_stream,                              \
+    "Boolean value stating if the end of the stream"    \
+    " has been reached or not."                         \
+)
+
+    stream = G_KAITAI_STREAM(pygobject_get(self));
+
+    status = g_kaitai_stream_has_reached_eof(stream);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_stream_type(void)
+{
+    static PyMethodDef py_kaitai_stream_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_kaitai_stream_getseters[] = {
+        KAITAI_STREAM_EOF_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_kaitai_stream_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.KaitaiStream",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = KAITAI_STREAM_DOC,
+
+        .tp_methods     = py_kaitai_stream_methods,
+        .tp_getset      = py_kaitai_stream_getseters,
+
+        .tp_init        = py_kaitai_stream_init,
+        .tp_new         = py_kaitai_stream_new,
+
+    };
+
+    return &py_kaitai_stream_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.plugins...KaitaiStream.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_kaitai_stream_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'KaitaiStream'  */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_kaitai_stream_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+        dict = PyModule_GetDict(module);
+
+        if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_STREAM, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en flux de données pour Kaitai.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_kaitai_stream(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_stream_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai stream");
+            break;
+
+        case 1:
+            *((GKaitaiStream **)dst) = G_KAITAI_STREAM(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/stream.h b/plugins/kaitai/python/stream.h
new file mode 100644
index 0000000..4f61358
--- /dev/null
+++ b/plugins/kaitai/python/stream.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * stream.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/stream.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_STREAM_H
+#define _PLUGINS_KAITAI_PYTHON_STREAM_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_stream_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.KaitaiStream'. */
+bool ensure_python_kaitai_stream_is_registered(void);
+
+/* Tente de convertir en flux de données pour Kaitai. */
+int convert_to_kaitai_stream(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_STREAM_H */
diff --git a/plugins/kaitai/record-int.h b/plugins/kaitai/record-int.h
new file mode 100644
index 0000000..5ce5b2c
--- /dev/null
+++ b/plugins/kaitai/record-int.h
@@ -0,0 +1,73 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * record-int.h - prototypes internes pour la mémorisation d'une correspondance avec un attribut Kaitai
+ *
+ * Copyright (C) 2019 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_RECORD_INT_H
+#define PLUGINS_KAITAI_RECORD_INT_H
+
+
+#include "record.h"
+
+
+#include "parser.h"
+
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+typedef void (* get_record_range_fc) (const GMatchRecord *, mrange_t *);
+
+/* Recherche la correspondance associée à un identifiant. */
+typedef GMatchRecord * (* find_record_by_name_fc) (GMatchRecord *, const char *, size_t, unsigned int);
+
+/* Transforme une énumération en constante entière. */
+typedef bool (* resolve_record_enum_fc) (const GMatchRecord *, const sized_string_t *, const sized_string_t *, resolved_value_t *);
+
+
+/* Correspondance entre un attribut et du binaire (instance) */
+struct _GMatchRecord
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    GKaitaiParser *creator;                 /* Lecteur à l'origine         */
+
+    GBinContent *content;                   /* Contenu binaire analysé     */
+
+};
+
+/* Correspondance entre un attribut et du binaire (classe) */
+struct _GMatchRecordClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+    get_record_range_fc get_range;          /* Fourniture de couverture    */
+    find_record_by_name_fc find;            /* Recherche selon identifiant */
+    resolve_record_enum_fc resolve;         /* Conversion d'une énumération*/
+
+};
+
+
+/* Met en place une correspondance entre attribut et binaire. */
+bool g_match_record_create(GMatchRecord *, GKaitaiParser *, GBinContent *);
+
+
+
+#endif  /* PLUGINS_KAITAI_RECORD_INT_H */
diff --git a/plugins/kaitai/record.c b/plugins/kaitai/record.c
new file mode 100644
index 0000000..5717b17
--- /dev/null
+++ b/plugins/kaitai/record.c
@@ -0,0 +1,408 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * record.c - définition d'une correspondance avec un attribut Kaitai
+ *
+ * Copyright (C) 2019 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 "record.h"
+
+
+#include <assert.h>
+
+
+#include "expression.h"
+#include "record-int.h"
+#include "parsers/attribute.h"
+
+
+
+/* Initialise la classe des correspondances avec du binaire. */
+static void g_match_record_class_init(GMatchRecordClass *);
+
+/* Initialise une correspondance avec du binaire. */
+static void g_match_record_init(GMatchRecord *);
+
+/* Supprime toutes les références externes. */
+static void g_match_record_dispose(GMatchRecord *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_match_record_finalize(GMatchRecord *);
+
+/* Recherche la correspondance associée à un identifiant. */
+static GMatchRecord *_g_match_record_find_by_name(GMatchRecord *, const char *, size_t, unsigned int);
+
+
+
+/* Indique le type défini pour une correspondance avec du binaire. */
+G_DEFINE_TYPE(GMatchRecord, g_match_record, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des correspondances avec du binaire.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_match_record_class_init(GMatchRecordClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_match_record_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_match_record_finalize;
+
+    klass->find = (find_record_by_name_fc)_g_match_record_find_by_name;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record = instance à initialiser.                             *
+*                                                                             *
+*  Description : Initialise une correspondance avec du binaire.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_match_record_init(GMatchRecord *record)
+{
+    record->creator = NULL;
+
+    record->content = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_match_record_dispose(GMatchRecord *record)
+{
+    G_OBJECT_CLASS(g_match_record_parent_class)->dispose(G_OBJECT(record));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_match_record_finalize(GMatchRecord *record)
+{
+    G_OBJECT_CLASS(g_match_record_parent_class)->finalize(G_OBJECT(record));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record  = correspondance à initialiser pleinement.           *
+*                creator = lecteur à l'origine de la correspondance.          *
+*                content = contenu binaire lié à la correspondance.           *
+*                                                                             *
+*  Description : Met en place une correspondance entre attribut et binaire.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_match_record_create(GMatchRecord *record, GKaitaiParser *creator, GBinContent *content)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    record->creator = creator;
+    g_object_ref(G_OBJECT(creator));
+
+    record->content = content;
+
+    if (content != NULL)
+        g_object_ref(G_OBJECT(content));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record = correspondance à consulter.                         *
+*                                                                             *
+*  Description : Renvoie vers le lecteur à l'origine de la correspondance.    *
+*                                                                             *
+*  Retour      : Lecteur à l'origine de la création.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiParser *g_match_record_get_creator(const GMatchRecord *record)
+{
+    GKaitaiParser *result;                  /* Instance à retourner        */
+
+    result = record->creator;
+
+    g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record  = correspondance à modifier.                         *
+*                creator = lecteur à l'origine de la correspondance.          *
+*                                                                             *
+*  Description : Modifie la référence au créateur de la correspondance.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_match_record_fix_creator(GMatchRecord *record, GKaitaiParser *creator)
+{
+    g_object_unref(G_OBJECT(record->creator));
+
+    record->creator = creator;
+    g_object_ref(G_OBJECT(creator));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record = correspondance à consulter.                         *
+*                                                                             *
+*  Description : Fournit le contenu lié à une correspondance établie.         *
+*                                                                             *
+*  Retour      : Contenu binaire associé.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_match_record_get_content(const GMatchRecord *record)
+{
+    GBinContent *result;                    /* Instance à retourner        */
+
+    result = record->content;
+
+    if (result != NULL)
+        g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record = correspondance à consulter.                         *
+*                range  = zone de couverture déterminée. [OUT]                *
+*                                                                             *
+*  Description : Calcule ou fournit la zone couverte par une correspondance.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_match_record_get_range(const GMatchRecord *record, mrange_t *range)
+{
+    GMatchRecordClass *class;               /* Classe de l'instance        */
+
+    class = G_MATCH_RECORD_GET_CLASS(record);
+
+    class->get_range(record, range);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record = correspondance établie à consulter.                 *
+*                out    = tableau d'octets retournés. [OUT]                   *
+*                len    = taille de ce tableau alloué. [OUT]                  *
+*                                                                             *
+*  Description : Lit les octets bruts couverts par une correspondance.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_match_record_read_raw_bytes(const GMatchRecord *record, bin_t **out, size_t *len)
+{
+    mrange_t range;                         /* Zone de correspondance      */
+    const bin_t *data;                      /* Accès aux données brutes    */
+
+    g_match_record_get_range(record, &range);
+
+    *len = get_mrange_length(&range);
+
+    data = g_binary_content_get_raw_access(record->content, get_mrange_addr(&range), *len);
+    assert(data != NULL);
+
+    *out = malloc(sizeof(bin_t) * (*len + 1));
+
+    memcpy(*out, data, *len);
+    (*out)[*len] = '\0';
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record = correspondance à consulter.                         *
+*                name   = désignation de l'élément recherché.                 *
+*                len    = taille de cette désignation.                        *
+*                level  = profondeur maximale à atteindre (fond : 0).         *
+*                                                                             *
+*  Description : Recherche la correspondance associée à un identifiant.       *
+*                                                                             *
+*  Retour      : Correspondance trouvée ou NULL.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GMatchRecord *_g_match_record_find_by_name(GMatchRecord *record, const char *name, size_t len, unsigned int level)
+{
+    GMatchRecord *result;                   /* Trouvaille à retourner      */
+    const char *label;                      /* Etiquette à manipuler       */
+    size_t label_len;                       /* Taille de cette étiquette   */
+
+    result = NULL;
+
+    if (G_IS_KAITAI_ATTRIBUTE(record->creator))
+    {
+        label = g_kaitai_attribute_get_label(G_KAITAI_ATTRIBUTE(record->creator));
+
+        label_len = strlen(label);
+
+        if (label_len == len && strncmp(label, name, len) == 0)
+        {
+            result = record;
+            g_object_ref(G_OBJECT(result));
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record = correspondance à consulter.                         *
+*                name   = désignation de l'élément recherché.                 *
+*                len    = taille de cette désignation.                        *
+*                level  = profondeur maximale à atteindre (fond : 0).         *
+*                                                                             *
+*  Description : Recherche la correspondance associée à un identifiant.       *
+*                                                                             *
+*  Retour      : Correspondance trouvée ou NULL.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GMatchRecord *g_match_record_find_by_name(GMatchRecord *record, const char *name, size_t len, unsigned int level)
+{
+    GMatchRecord *result;                   /* Trouvaille à retourner      */
+    GMatchRecordClass *class;               /* Classe de l'instance        */
+
+    class = G_MATCH_RECORD_GET_CLASS(record);
+
+    result = class->find(record, name, len, level);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : record = correspondance à consulter.                         *
+*                name   = désignation de l'élément recherché.                 *
+*                label  = étiquette de l'élément constant à traduire.         *
+*                value  = valeur entière correspondante. [OUT]                *
+*                                                                             *
+*  Description : Transforme une énumération en constante entière.             *
+*                                                                             *
+*  Retour      : Bilan de l'opération : true si la résolution est réalisée.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_match_record_resolve_enum(const GMatchRecord *record, const sized_string_t *name, const sized_string_t *label, resolved_value_t *value)
+{
+    bool result;                            /* Bilan à retourner           */
+    GMatchRecordClass *class;               /* Classe de l'instance        */
+
+    class = G_MATCH_RECORD_GET_CLASS(record);
+
+    if (class->resolve == NULL)
+        result = false;
+
+    else
+        result = class->resolve(record, name, label, value);
+
+    return result;
+
+}
diff --git a/plugins/kaitai/record.h b/plugins/kaitai/record.h
new file mode 100644
index 0000000..7db8187
--- /dev/null
+++ b/plugins/kaitai/record.h
@@ -0,0 +1,88 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * record.h - prototypes pour la définition d'une correspondance avec un attribut Kaitai
+ *
+ * Copyright (C) 2019 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_RECORD_H
+#define _PLUGINS_KAITAI_RECORD_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/content.h>
+#include <arch/vmpa.h>
+#include <common/szstr.h>
+
+
+
+/* Depuis parser.h : spécification d'un lecteur Kaitai (instance) */
+typedef struct _GKaitaiParser GKaitaiParser;
+
+/* Depuis expression.h : informations transportées par une expression */
+typedef struct _resolved_value_t resolved_value_t;
+
+
+
+#define G_TYPE_MATCH_RECORD            g_match_record_get_type()
+#define G_MATCH_RECORD(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_MATCH_RECORD, GMatchRecord))
+#define G_IS_MATCH_RECORD(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_MATCH_RECORD))
+#define G_MATCH_RECORD_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_MATCH_RECORD, GMatchRecordClass))
+#define G_IS_MATCH_RECORD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_MATCH_RECORD))
+#define G_MATCH_RECORD_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_MATCH_RECORD, GMatchRecordClass))
+
+
+/* Correspondance entre un attribut et du binaire (instance) */
+typedef struct _GMatchRecord GMatchRecord;
+
+/* Correspondance entre un attribut et du binaire (classe) */
+typedef struct _GMatchRecordClass GMatchRecordClass;
+
+
+/* Indique le type défini pour une correspondance avec du binaire. */
+GType g_match_record_get_type(void);
+
+/* Renvoie vers le lecteur à l'origine de la correspondance. */
+GKaitaiParser *g_match_record_get_creator(const GMatchRecord *);
+
+/* Modifie la référence au créateur de la correspondance. */
+void g_match_record_fix_creator(GMatchRecord *, GKaitaiParser *);
+
+/* Fournit le contenu lié à une correspondance établie. */
+GBinContent *g_match_record_get_content(const GMatchRecord *);
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+void g_match_record_get_range(const GMatchRecord *, mrange_t *);
+
+/* Lit les octets bruts couverts par une correspondance. */
+void g_match_record_read_raw_bytes(const GMatchRecord *, bin_t **, size_t *);
+
+#define DIRECT_SEARCH_DEEP_LEVEL 1
+
+/* Recherche la correspondance associée à un identifiant. */
+GMatchRecord *g_match_record_find_by_name(GMatchRecord *, const char *, size_t, unsigned int);
+
+/* Transforme une énumération en constante entière. */
+bool g_match_record_resolve_enum(const GMatchRecord *, const sized_string_t *, const sized_string_t *, resolved_value_t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORD_H */
diff --git a/plugins/kaitai/records/Makefile.am b/plugins/kaitai/records/Makefile.am
new file mode 100644
index 0000000..c11e823
--- /dev/null
+++ b/plugins/kaitai/records/Makefile.am
@@ -0,0 +1,21 @@
+
+noinst_LTLIBRARIES = libkaitairecords.la
+
+libkaitairecords_la_SOURCES =				\
+	empty-int.h								\
+	empty.h empty.c							\
+	group-int.h								\
+	group.h group.c							\
+	item-int.h								\
+	item.h item.c							\
+	list-int.h								\
+	list.h list.c							\
+	value-int.h								\
+	value.h value.c
+
+libkaitairecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitairecords_la_SOURCES:%c=)
diff --git a/plugins/kaitai/records/empty-int.h b/plugins/kaitai/records/empty-int.h
new file mode 100644
index 0000000..2c6cefa
--- /dev/null
+++ b/plugins/kaitai/records/empty-int.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * empty-int.h - prototypes internes pour la notification d'une absence de correspondance attendue
+ *
+ * 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_RECORDS_EMPTY_INT_H
+#define _PLUGINS_KAITAI_RECORDS_EMPTY_INT_H
+
+
+#include "empty.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Marque d'une zone de correspondance vide (instance) */
+struct _GRecordEmpty
+{
+    GMatchRecord parent;                    /* A laisser en premier        */
+
+    vmpa2t pos;                             /* Début d'une zone vide       */
+
+};
+
+/* Marque d'une zone de correspondance vide (classe) */
+struct _GRecordEmptyClass
+{
+    GMatchRecordClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Met en place une zone de correspondance vide. */
+bool g_record_empty_create(GRecordEmpty *, GKaitaiParser *, GBinContent *, const vmpa2t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_EMPTY_INT_H */
diff --git a/plugins/kaitai/records/empty.c b/plugins/kaitai/records/empty.c
new file mode 100644
index 0000000..e5121e1
--- /dev/null
+++ b/plugins/kaitai/records/empty.c
@@ -0,0 +1,236 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * empty.c - conservation d'une correspondance entre attribut et binaire
+ *
+ * Copyright (C) 2019 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 "empty.h"
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+#include "empty-int.h"
+
+
+
+/* ------------------ DEFINITION D'UNE ZONE DE CORRESPONDANCE VIDE ------------------ */
+
+
+/* Initialise la classe des zones de correspondance vides. */
+static void g_record_empty_class_init(GRecordEmptyClass *);
+
+/* Initialise une zone de correspondance vide. */
+static void g_record_empty_init(GRecordEmpty *);
+
+/* Supprime toutes les références externes. */
+static void g_record_empty_dispose(GRecordEmpty *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_empty_finalize(GRecordEmpty *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_empty_get_range(const GRecordEmpty *, mrange_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                    DEFINITION D'UNE ZONE DE CORRESPONDANCE VIDE                    */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une zone de correspondance vide. */
+G_DEFINE_TYPE(GRecordEmpty, g_record_empty, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des zones de correspondance vides.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_empty_class_init(GRecordEmptyClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GMatchRecordClass *record;              /* Version parente de la classe*/
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_record_empty_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_record_empty_finalize;
+
+    record = G_MATCH_RECORD_CLASS(klass);
+
+    record->get_range = (get_record_range_fc)g_record_empty_get_range;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : empty = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une zone de correspondance vide.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_empty_init(GRecordEmpty *empty)
+{
+    init_vmpa(&empty->pos, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : empty = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_empty_dispose(GRecordEmpty *empty)
+{
+    G_OBJECT_CLASS(g_record_empty_parent_class)->dispose(G_OBJECT(empty));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : empty = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_empty_finalize(GRecordEmpty *empty)
+{
+    G_OBJECT_CLASS(g_record_empty_parent_class)->finalize(G_OBJECT(empty));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parser  = analyseur à l'origine de la correspondance.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                pos     = emplacement de la zone vide à construire.          *
+*                                                                             *
+*  Description : Crée une zone de correspondance vide à une position donnée.  *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRecordEmpty *g_record_empty_new(GKaitaiParser *parser, GBinContent *content, const vmpa2t *pos)
+{
+    GRecordEmpty *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_RECORD_EMPTY, NULL);
+
+    if (!g_record_empty_create(result, parser, content, pos))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : empty   = correspondance à initialiser pleinement.           *
+*                parser  = analyseur à l'origine de la correspondance.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                pos     = emplacement de la zone vide à construire.          *
+*                                                                             *
+*  Description : Met en place une zone de correspondance vide.                *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_record_empty_create(GRecordEmpty *empty, GKaitaiParser *parser, GBinContent *content, const vmpa2t *pos)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_match_record_create(G_MATCH_RECORD(empty), parser, content);
+
+    if (result)
+        copy_vmpa(&empty->pos, pos);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : empty  = correspondance à consulter.                         *
+*                range = zone de couverture déterminée. [OUT]                 *
+*                                                                             *
+*  Description : Calcule ou fournit la zone couverte par une correspondance.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_empty_get_range(const GRecordEmpty *empty, mrange_t *range)
+{
+    init_mrange(range, &empty->pos, 0);
+
+}
diff --git a/plugins/kaitai/records/empty.h b/plugins/kaitai/records/empty.h
new file mode 100644
index 0000000..4e89b62
--- /dev/null
+++ b/plugins/kaitai/records/empty.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * empty.h - prototypes pour la notification d'une absence de correspondance attendue
+ *
+ * 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_RECORDS_EMPTY_H
+#define _PLUGINS_KAITAI_RECORDS_EMPTY_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+
+
+
+#define G_TYPE_RECORD_EMPTY            g_record_empty_get_type()
+#define G_RECORD_EMPTY(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_EMPTY, GRecordEmpty))
+#define G_IS_RECORD_EMPTY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_EMPTY))
+#define G_RECORD_EMPTY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_EMPTY, GRecordEmptyClass))
+#define G_IS_RECORD_EMPTY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_EMPTY))
+#define G_RECORD_EMPTY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_EMPTY, GRecordEmptyClass))
+
+
+/* Marque d'une zone de correspondance vide (instance) */
+typedef struct _GRecordEmpty GRecordEmpty;
+
+/* Marque d'une zone de correspondance vide (classe) */
+typedef struct _GRecordEmptyClass GRecordEmptyClass;
+
+
+/* Indique le type défini pour une zone de correspondance vide. */
+GType g_record_empty_get_type(void);
+
+/* Crée une zone de correspondance vide à une position donnée. */
+GRecordEmpty *g_record_empty_new(GKaitaiParser *, GBinContent *, const vmpa2t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_EMPTY_H */
diff --git a/plugins/kaitai/records/group-int.h b/plugins/kaitai/records/group-int.h
new file mode 100644
index 0000000..1fd0162
--- /dev/null
+++ b/plugins/kaitai/records/group-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * group-int.h - prototypes internes pour la conservation d'un groupe de correspondance avec du binaire
+ *
+ * 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_RECORDS_GROUP_INT_H
+#define _PLUGINS_KAITAI_RECORDS_GROUP_INT_H
+
+
+#include "group.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Groupe de correspondances établies entre attributs et binaire (instance) */
+struct _GRecordGroup
+{
+    GMatchRecord parent;                    /* A laisser en premier        */
+
+    GMatchRecord **children;                /* Sous-correspondances        */
+    size_t count;                           /* Taille de cette série       */
+
+};
+
+/* Groupe de correspondances établies entre attributs et binaire (classe) */
+struct _GRecordGroupClass
+{
+    GMatchRecordClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Met en place une série de correspondances attribut/binaire. */
+bool g_record_group_create(GRecordGroup *, GKaitaiStruct *, GBinContent *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_GROUP_INT_H */
diff --git a/plugins/kaitai/records/group.c b/plugins/kaitai/records/group.c
new file mode 100644
index 0000000..13327c8
--- /dev/null
+++ b/plugins/kaitai/records/group.c
@@ -0,0 +1,382 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * group.c - conservation d'un groupe de correspondance avec du binaire
+ *
+ * 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 "group.h"
+
+
+#include <malloc.h>
+
+
+#include "group-int.h"
+#include "../parsers/attribute.h"
+
+
+
+/* ------------------ DEFINITION D'UNE SEQUENCE DE CORRESPONDANCES ------------------ */
+
+
+/* Initialise la classe des groupes de correspondances. */
+static void g_record_group_class_init(GRecordGroupClass *);
+
+/* Initialise une série de correspondances attributs/binaire. */
+static void g_record_group_init(GRecordGroup *);
+
+/* Supprime toutes les références externes. */
+static void g_record_group_dispose(GRecordGroup *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_group_finalize(GRecordGroup *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_group_get_range(const GRecordGroup *, mrange_t *);
+
+/* Recherche la correspondance associée à un identifiant. */
+static GMatchRecord *g_record_group_find_by_name(GRecordGroup *, const char *, size_t, unsigned int);
+
+/* Transforme une énumération en constante entière. */
+static bool g_record_group_resolve_enum(const GRecordGroup *, const sized_string_t *, const sized_string_t *, resolved_value_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                    DEFINITION D'UNE SEQUENCE DE CORRESPONDANCES                    */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une série de correspondances entre attributes et binaire. */
+G_DEFINE_TYPE(GRecordGroup, g_record_group, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des groupes de correspondances.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_group_class_init(GRecordGroupClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GMatchRecordClass *record;              /* Version parente de la classe*/
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_record_group_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_record_group_finalize;
+
+    record = G_MATCH_RECORD_CLASS(klass);
+
+    record->get_range = (get_record_range_fc)g_record_group_get_range;
+    record->find = (find_record_by_name_fc)g_record_group_find_by_name;
+    record->resolve = (resolve_record_enum_fc)g_record_group_resolve_enum;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : group = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une série de correspondances attributs/binaire.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_group_init(GRecordGroup *group)
+{
+    group->children = NULL;
+    group->count = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : group = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_group_dispose(GRecordGroup *group)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < group->count; i++)
+        g_clear_object(&group->children[i]);
+
+    G_OBJECT_CLASS(g_record_group_parent_class)->dispose(G_OBJECT(group));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : group = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_group_finalize(GRecordGroup *group)
+{
+    if (group->children != NULL)
+        free(group->children);
+
+    G_OBJECT_CLASS(g_record_group_parent_class)->finalize(G_OBJECT(group));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire lié à la correspondance.           *
+*                kstruct = analyseur à l'origine de la correspondance.        *
+*                                                                             *
+*  Description : Crée une nouvelle série de correspondances attribut/binaire. *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRecordGroup *g_record_group_new(GKaitaiStruct *kstruct, GBinContent *content)
+{
+    GRecordGroup *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_RECORD_GROUP, NULL);
+
+    if (!g_record_group_create(result, kstruct, content))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : group   = correspondance à initialiser pleinement.           *
+*                kstruct = analyseur à l'origine de la correspondance.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                                                                             *
+*  Description : Met en place une série de correspondances attribut/binaire.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_record_group_create(GRecordGroup *group, GKaitaiStruct *kstruct, GBinContent *content)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_match_record_create(G_MATCH_RECORD(group), G_KAITAI_PARSER(kstruct), content);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : group  = ensemble de correspondances attribut/binaire.       *
+*                record = sous-corresponde à intégrer.                        *
+*                                                                             *
+*  Description : Ajoute une correspondance supplémentaire à une série.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_record_group_add_record(GRecordGroup *group, GMatchRecord *record)
+{
+    group->children = realloc(group->children, ++group->count * sizeof(GMatchRecord));
+
+    group->children[group->count - 1] = record;
+    g_object_ref(G_OBJECT(record));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : group = correspondance à consulter.                          *
+*                range = zone de couverture déterminée. [OUT]                 *
+*                                                                             *
+*  Description : Calcule ou fournit la zone couverte par une correspondance.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_group_get_range(const GRecordGroup *group, mrange_t *range)
+{
+    vmpa2t start;                           /* Position de départ          */
+    mrange_t range_0;                       /* Première zone couverte      */
+    mrange_t range_n;                       /* Dernière zone couverte      */
+    vmpa2t end;                             /* Position de d'arrivée       */
+    phys_t length;                          /* Taille de zone couverte     */
+
+    if (group->count == 0)
+    {
+        init_vmpa(&start, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+        init_mrange(range, &start, VMPA_NO_PHYSICAL);
+    }
+
+    else
+    {
+        g_match_record_get_range(group->children[0], &range_0);
+        g_match_record_get_range(group->children[group->count - 1], &range_n);
+
+        copy_vmpa(&start, get_mrange_addr(&range_0));
+
+        compute_mrange_end_addr(&range_n, &end);
+        length = compute_vmpa_diff(&start, &end);
+
+        init_mrange(range, &start, length);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : group = ensemble de correspondances attribut/binaire.        *
+*                name  = désignation de l'élément recherché.                  *
+*                len   = taille de cette désignation.                         *
+*                level  = profondeur maximale à atteindre (fond : 0).         *
+*                                                                             *
+*  Description : Recherche la correspondance associée à un identifiant.       *
+*                                                                             *
+*  Retour      : Correspondance trouvée ou NULL.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GMatchRecord *g_record_group_find_by_name(GRecordGroup *group, const char *name, size_t len, unsigned int level)
+{
+    GMatchRecord *result;                   /* Correspondance à renvoyer   */
+    GMatchRecordClass *class;               /* Classe parente normalisée   */
+    size_t i;                               /* Boucle de parcours          */
+
+    class = G_MATCH_RECORD_CLASS(g_record_group_parent_class);
+
+    /**
+     * Le cas d'un type utilisateur peut rattacher un attribut Kaitai à un groupe...
+     */
+    result = class->find(G_MATCH_RECORD(group), name, len, level);
+
+    if (level > 0)
+    {
+        level--;
+
+        for (i = 0; i < group->count && result == NULL; i++)
+            result = g_match_record_find_by_name(group->children[i], name, len, level);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : group = ensemble de correspondances attribut/binaire.        *
+*                name  = désignation de l'élément recherché.                  *
+*                label = étiquette de l'élément constant à traduire.          *
+*                value = valeur entière correspondante. [OUT]                 *
+*                                                                             *
+*  Description : Transforme une énumération en constante entière.             *
+*                                                                             *
+*  Retour      : Bilan de l'opération : true si la résolution est réalisée.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_record_group_resolve_enum(const GRecordGroup *group, const sized_string_t *name, const sized_string_t *label, resolved_value_t *value)
+{
+    bool result;                            /* Bilan à retourner           */
+    GMatchRecord *base;                     /* Autre version du groupe     */
+    size_t i;                               /* Boucle de parcours          */
+    GKaitaiEnum *kenum;                     /* Enumération à consulter     */
+
+    result = false;
+
+    base = G_MATCH_RECORD(group);
+
+    if (G_IS_KAITAI_STRUCT(base->creator))
+    {
+        kenum = g_kaitai_structure_get_enum(G_KAITAI_STRUCT(base->creator), name);
+
+        if (kenum != NULL)
+        {
+            result = g_kaitai_enum_find_value(kenum, label, value);
+            g_object_unref(G_OBJECT(kenum));
+        }
+
+    }
+
+    for (i = 0; i < group->count && !result; i++)
+        result = g_match_record_resolve_enum(group->children[i], name, label, value);
+
+    return result;
+
+}
diff --git a/plugins/kaitai/records/group.h b/plugins/kaitai/records/group.h
new file mode 100644
index 0000000..454dade
--- /dev/null
+++ b/plugins/kaitai/records/group.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * group.h - prototypes pour la conservation d'un groupe de correspondance avec du binaire
+ *
+ * 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_RECORDS_GROUP_H
+#define _PLUGINS_KAITAI_RECORDS_GROUP_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/content.h>
+
+
+#include "../record.h"
+#include "../parsers/struct.h"
+
+
+
+#define G_TYPE_RECORD_GROUP            g_record_group_get_type()
+#define G_RECORD_GROUP(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_GROUP, GRecordGroup))
+#define G_IS_RECORD_GROUP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_GROUP))
+#define G_RECORD_GROUP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_GROUP, GRecordGroupClass))
+#define G_IS_RECORD_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_GROUP))
+#define G_RECORD_GROUP_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_GROUP, GRecordGroupClass))
+
+
+/* Groupe de correspondances établies entre attributs et binaire (instance) */
+typedef struct _GRecordGroup GRecordGroup;
+
+/* Groupe de correspondances établies entre attributs et binaire (classe) */
+typedef struct _GRecordGroupClass GRecordGroupClass;
+
+
+/* Indique le type défini pour une série de correspondances entre attributes et binaire. */
+GType g_record_group_get_type(void);
+
+/* Crée une nouvelle série de correspondances attribut/binaire. */
+GRecordGroup *g_record_group_new(GKaitaiStruct *, GBinContent *);
+
+/* Ajoute une correspondance supplémentaire à une série. */
+void g_record_group_add_record(GRecordGroup *, GMatchRecord *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_GROUP_H */
diff --git a/plugins/kaitai/records/item-int.h b/plugins/kaitai/records/item-int.h
new file mode 100644
index 0000000..56e0a41
--- /dev/null
+++ b/plugins/kaitai/records/item-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item-int.h - prototypes internes pour la conservation d'une correspondance entre attribut et binaire
+ *
+ * Copyright (C) 2019 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_RECORDS_ITEM_INT_H
+#define _PLUGINS_KAITAI_RECORDS_ITEM_INT_H
+
+
+#include "item.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Correspondance établie entre un attribut et du binaire (instance) */
+struct _GRecordItem
+{
+    GMatchRecord parent;                    /* A laisser en premier        */
+
+    mrange_t range;                         /* Zone de binaire couverte    */
+    SourceEndian endian;                    /* Boutisme des données imposé */
+
+};
+
+/* Correspondance établie entre un attribut et du binaire (classe) */
+struct _GRecordItemClass
+{
+    GMatchRecordClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Met en place une correspondance entre attribut et binaire. */
+bool g_record_item_create(GRecordItem *, GKaitaiAttribute *, GBinContent *, const mrange_t *, SourceEndian);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_ITEM_INT_H */
diff --git a/plugins/kaitai/records/item.c b/plugins/kaitai/records/item.c
new file mode 100644
index 0000000..0bcf9f7
--- /dev/null
+++ b/plugins/kaitai/records/item.c
@@ -0,0 +1,309 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.c - conservation d'une correspondance entre attribut et binaire
+ *
+ * Copyright (C) 2019 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 "item.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include "item-int.h"
+
+
+
+/* -------------------- DEFINITION D'UNE CORRESPONDANCE UNITAIRE -------------------- */
+
+
+/* Initialise la classe des correspondances attribut/binaire. */
+static void g_record_item_class_init(GRecordItemClass *);
+
+/* Initialise une correspondance entre attribut et binaire. */
+static void g_record_item_init(GRecordItem *);
+
+/* Supprime toutes les références externes. */
+static void g_record_item_dispose(GRecordItem *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_item_finalize(GRecordItem *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_item_get_range(const GRecordItem *, mrange_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      DEFINITION D'UNE CORRESPONDANCE UNITAIRE                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une correspondance entre un attribut et du binaire. */
+G_DEFINE_TYPE(GRecordItem, g_record_item, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des correspondances attribut/binaire.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_item_class_init(GRecordItemClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GMatchRecordClass *record;              /* Version parente de la classe*/
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_record_item_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_record_item_finalize;
+
+    record = G_MATCH_RECORD_CLASS(klass);
+
+    record->get_range = (get_record_range_fc)g_record_item_get_range;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une correspondance entre attribut et binaire.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_item_init(GRecordItem *item)
+{
+    copy_mrange(&item->range, UNUSED_MRANGE_PTR);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_item_dispose(GRecordItem *item)
+{
+    G_OBJECT_CLASS(g_record_item_parent_class)->dispose(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_item_finalize(GRecordItem *item)
+{
+    G_OBJECT_CLASS(g_record_item_parent_class)->finalize(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = analyseur à l'origine de la correspondance.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                range   = zone couverture par la correspondance.             *
+*                endian  = boustime des données à respecter.                  *
+*                                                                             *
+*  Description : Crée une nouvelle correspondance entre attribut et binaire.  *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRecordItem *g_record_item_new(GKaitaiAttribute *attrib, GBinContent *content, const mrange_t *range, SourceEndian endian)
+{
+    GRecordItem *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_RECORD_ITEM, NULL);
+
+    if (!g_record_item_create(result, attrib, content, range, endian))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item    = correspondance à initialiser pleinement.           *
+*                attrib  = analyseur à l'origine de la correspondance.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                range   = zone couverte par la correspondance.               *
+*                endian  = boustime des données à respecter.                  *
+*                                                                             *
+*  Description : Met en place une correspondance entre attribut et binaire.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_record_item_create(GRecordItem *item, GKaitaiAttribute *attrib, GBinContent *content, const mrange_t *range, SourceEndian endian)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_match_record_create(G_MATCH_RECORD(item), G_KAITAI_PARSER(attrib), content);
+
+    if (result)
+    {
+        copy_mrange(&item->range, range);
+
+        item->endian = endian;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = correspondance à consulter.                           *
+*                out  = tableau d'octets retournés. [OUT]                     *
+*                len  = taille de ce tableau alloué. [OUT]                    *
+*                                                                             *
+*  Description : Lit la série d'octets d'un élément Kaitai entier représenté. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_record_item_get_truncated_bytes(const GRecordItem *item, bin_t **out, size_t *len)
+{
+    bool result;                            /* Bilan à retourner           */
+    GKaitaiParser *parser;                  /* Attribut associé à l'élément*/
+
+    parser = g_match_record_get_creator(G_MATCH_RECORD(item));
+    assert(G_IS_KAITAI_ATTRIBUTE(parser));
+
+    result = g_kaitai_attribute_read_truncated_bytes(G_KAITAI_ATTRIBUTE(parser),
+                                                     G_MATCH_RECORD(item)->content,
+                                                     &item->range,
+                                                     out, len);
+
+    g_object_unref(G_OBJECT(parser));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = correspondance à consulter.                           *
+*                out  = valeur à sauvegarder sous une forme générique. [OUT]  *
+*                                                                             *
+*  Description : Lit la valeur d'un élément Kaitai entier représenté.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_record_item_get_value(const GRecordItem *item, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à retourner           */
+    GKaitaiParser *parser;                  /* Attribut associé à l'élément*/
+
+    parser = g_match_record_get_creator(G_MATCH_RECORD(item));
+    assert(G_IS_KAITAI_ATTRIBUTE(parser));
+
+    result = g_kaitai_attribute_read_value(G_KAITAI_ATTRIBUTE(parser),
+                                           G_MATCH_RECORD(item)->content,
+                                           &item->range,
+                                           item->endian, out);
+
+    g_object_unref(G_OBJECT(parser));
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = correspondance à consulter.                          *
+*                range = zone de couverture déterminée. [OUT]                 *
+*                                                                             *
+*  Description : Calcule ou fournit la zone couverte par une correspondance.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_item_get_range(const GRecordItem *item, mrange_t *range)
+{
+    copy_mrange(range, &item->range);
+
+}
diff --git a/plugins/kaitai/records/item.h b/plugins/kaitai/records/item.h
new file mode 100644
index 0000000..1286a89
--- /dev/null
+++ b/plugins/kaitai/records/item.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - prototypes pour la conservation d'une correspondance entre attribut et binaire
+ *
+ * Copyright (C) 2019 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_RECORDS_ITEM_H
+#define _PLUGINS_KAITAI_RECORDS_ITEM_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+#include "../parsers/attribute.h"
+
+
+
+#define G_TYPE_RECORD_ITEM            g_record_item_get_type()
+#define G_RECORD_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_ITEM, GRecordItem))
+#define G_IS_RECORD_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_ITEM))
+#define G_RECORD_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_ITEM, GRecordItemClass))
+#define G_IS_RECORD_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_ITEM))
+#define G_RECORD_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_ITEM, GRecordItemClass))
+
+
+/* Correspondance établie entre un attribut et du binaire (instance) */
+typedef struct _GRecordItem GRecordItem;
+
+/* Correspondance établie entre un attribut et du binaire (classe) */
+typedef struct _GRecordItemClass GRecordItemClass;
+
+
+/* Indique le type défini pour une correspondance entre un attribut et du binaire. */
+GType g_record_item_get_type(void);
+
+/* Crée une nouvelle correspondance entre attribut et binaire. */
+GRecordItem *g_record_item_new(GKaitaiAttribute *, GBinContent *, const mrange_t *, SourceEndian);
+
+/* Lit la série d'octets d'un élément Kaitai entier représenté. */
+bool g_record_item_get_truncated_bytes(const GRecordItem *, bin_t **, size_t *);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+bool g_record_item_get_value(const GRecordItem *, resolved_value_t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_ITEM_H */
diff --git a/plugins/kaitai/records/list-int.h b/plugins/kaitai/records/list-int.h
new file mode 100644
index 0000000..88b411d
--- /dev/null
+++ b/plugins/kaitai/records/list-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list-int.h - prototypes internes pour la conservation d'une liste de correspondance avec du binaire
+ *
+ * Copyright (C) 2019 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_RECORDS_LIST_INT_H
+#define _PLUGINS_KAITAI_RECORDS_LIST_INT_H
+
+
+#include "list.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Liste de correspondances établies entre attributs et binaire (instance) */
+struct _GRecordList
+{
+    GMatchRecord parent;                    /* A laisser en premier        */
+
+    vmpa2t pos;                             /* Début de zone               */
+
+    GMatchRecord **children;                /* Sous-correspondances        */
+    size_t count;                           /* Taille de cette série       */
+
+};
+
+/* Liste de correspondances établies entre attributs et binaire (classe) */
+struct _GRecordListClass
+{
+    GMatchRecordClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Met en place une série de correspondances attribut/binaire. */
+bool g_record_list_create(GRecordList *, GKaitaiAttribute *, GBinContent *, const vmpa2t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_LIST_INT_H */
diff --git a/plugins/kaitai/records/list.c b/plugins/kaitai/records/list.c
new file mode 100644
index 0000000..1a36bf5
--- /dev/null
+++ b/plugins/kaitai/records/list.c
@@ -0,0 +1,424 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.c - conservation d'une liste de correspondance avec du binaire
+ *
+ * Copyright (C) 2019 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 "list.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "list-int.h"
+
+
+
+/* ------------------ DEFINITION D'UNE SEQUENCE DE CORRESPONDANCES ------------------ */
+
+
+/* Initialise la classe des listes de correspondances. */
+static void g_record_list_class_init(GRecordListClass *);
+
+/* Initialise une série de correspondances attributs/binaire. */
+static void g_record_list_init(GRecordList *);
+
+/* Supprime toutes les références externes. */
+static void g_record_list_dispose(GRecordList *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_list_finalize(GRecordList *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_list_get_range(const GRecordList *, mrange_t *);
+
+/* Recherche la correspondance associée à un identifiant. */
+static GMatchRecord *g_record_list_find_by_name(GRecordList *, const char *, size_t, unsigned int);
+
+/* Transforme une énumération en constante entière. */
+static bool g_record_list_resolve_enum(const GRecordList *, const sized_string_t *, const sized_string_t *, resolved_value_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                    DEFINITION D'UNE SEQUENCE DE CORRESPONDANCES                    */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une série de correspondances entre attributes et binaire. */
+G_DEFINE_TYPE(GRecordList, g_record_list, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des listes de correspondances.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_list_class_init(GRecordListClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GMatchRecordClass *record;              /* Version parente de la classe*/
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_record_list_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_record_list_finalize;
+
+    record = G_MATCH_RECORD_CLASS(klass);
+
+    record->get_range = (get_record_range_fc)g_record_list_get_range;
+    record->find = (find_record_by_name_fc)g_record_list_find_by_name;
+    record->resolve = (resolve_record_enum_fc)g_record_list_resolve_enum;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une série de correspondances attributs/binaire.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_list_init(GRecordList *list)
+{
+    list->children = NULL;
+    list->count = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_list_dispose(GRecordList *list)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < list->count; i++)
+        g_clear_object(&list->children[i]);
+
+    G_OBJECT_CLASS(g_record_list_parent_class)->dispose(G_OBJECT(list));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_list_finalize(GRecordList *list)
+{
+    if (list->children != NULL)
+        free(list->children);
+
+    G_OBJECT_CLASS(g_record_list_parent_class)->finalize(G_OBJECT(list));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = analyseur à l'origine de la correspondance.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                pos     = début de la zone de couverture de la liste.        *
+*                                                                             *
+*  Description : Crée une nouvelle série de correspondances attribut/binaire. *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRecordList *g_record_list_new(GKaitaiAttribute *attrib, GBinContent *content, const vmpa2t *pos)
+{
+    GRecordList *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_RECORD_LIST, NULL);
+
+    if (!g_record_list_create(result, attrib, content, pos))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list    = correspondance à initialiser pleinement.           *
+*                attrib  = analyseur à l'origine de la correspondance.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                                                                             *
+*  Description : Met en place une série de correspondances attribut/binaire.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_record_list_create(GRecordList *list, GKaitaiAttribute *attrib, GBinContent *content, const vmpa2t *pos)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_match_record_create(G_MATCH_RECORD(list), G_KAITAI_PARSER(attrib), content);
+
+    if (result)
+        copy_vmpa(&list->pos, pos);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = ensemble de correspondances attribut/binaire.         *
+*                                                                             *
+*  Description : Dénombre le nombre de correspondances enregistrées.          *
+*                                                                             *
+*  Retour      : Taille de la liste représentée.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t g_record_list_count_records(const GRecordList *list)
+{
+    size_t result;                          /* Quantité à retourner        */
+
+    result = list->count;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list   = ensemble de correspondances attribut/binaire.       *
+*                record = sous-corresponde à intégrer.                        *
+*                                                                             *
+*  Description : Ajoute une correspondance supplémentaire à une série.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_record_list_add_record(GRecordList *list, GMatchRecord *record)
+{
+    list->children = realloc(list->children, ++list->count * sizeof(GMatchRecord));
+
+    list->children[list->count - 1] = record;
+    g_object_ref(G_OBJECT(record));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list  = ensemble de correspondances attribut/binaire.        *
+*                index = indice de la correspondance visée.                   *
+*                                                                             *
+*  Description : Fournit un élément ciblé dans la liste de correspondances.   *
+*                                                                             *
+*  Retour      : Instance de correspondance particulière, voire NULL.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GMatchRecord *g_record_list_get_record(const GRecordList *list, size_t index)
+{
+    GMatchRecord *result;                   /* Instance à retourner        */
+
+    if (index < list->count)
+    {
+        result = list->children[index];
+        g_object_ref(G_OBJECT(result));
+    }
+    else
+        result = NULL;
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list  = correspondance à consulter.                          *
+*                range = zone de couverture déterminée. [OUT]                 *
+*                                                                             *
+*  Description : Calcule ou fournit la zone couverte par une correspondance.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_list_get_range(const GRecordList *list, mrange_t *range)
+{
+    vmpa2t start;                           /* Position de départ          */
+    mrange_t range_0;                       /* Première zone couverte      */
+    mrange_t range_n;                       /* Dernière zone couverte      */
+    vmpa2t end;                             /* Position de d'arrivée       */
+    phys_t length;                          /* Taille de zone couverte     */
+
+    assert(list->count > 0);
+
+    if (list->count == 0)
+    {
+        init_vmpa(&start, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+        init_mrange(range, &start, VMPA_NO_PHYSICAL);
+    }
+
+    else
+    {
+        g_match_record_get_range(list->children[0], &range_0);
+        g_match_record_get_range(list->children[list->count - 1], &range_n);
+
+        copy_vmpa(&start, get_mrange_addr(&range_0));
+
+        compute_mrange_end_addr(&range_n, &end);
+        length = compute_vmpa_diff(&start, &end);
+
+        init_mrange(range, &start, length);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list  = ensemble de correspondances attribut/binaire.        *
+*                name  = désignation de l'élément recherché.                  *
+*                len   = taille de cette désignation.                         *
+*                level  = profondeur maximale à atteindre (fond : 0).         *
+*                                                                             *
+*  Description : Recherche la correspondance associée à un identifiant.       *
+*                                                                             *
+*  Retour      : Correspondance trouvée ou NULL.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GMatchRecord *g_record_list_find_by_name(GRecordList *list, const char *name, size_t len, unsigned int level)
+{
+    GMatchRecord *result;                   /* Correspondance à renvoyer   */
+    GMatchRecordClass *class;               /* Classe parente normalisée   */
+    size_t i;                               /* Boucle de parcours          */
+
+    class = G_MATCH_RECORD_CLASS(g_record_list_parent_class);
+
+    result = class->find(G_MATCH_RECORD(list), name, len, level);
+
+    if (level > 0)
+    {
+        for (i = 0; i < list->count && result == NULL; i++)
+            result = g_match_record_find_by_name(list->children[i], name, len, level);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list  = ensemble de correspondances attribut/binaire.        *
+*                name  = désignation de l'élément recherché.                  *
+*                label = étiquette de l'élément constant à traduire.          *
+*                value = valeur entière correspondante. [OUT]                 *
+*                                                                             *
+*  Description : Transforme une énumération en constante entière.             *
+*                                                                             *
+*  Retour      : Bilan de l'opération : true si la résolution est réalisée.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_record_list_resolve_enum(const GRecordList *list, const sized_string_t *name, const sized_string_t *label, resolved_value_t *value)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+
+    /**
+     * Comme les types peuvent être sélectionnés dynamiquement, le parcours
+     * de l'ensemble des sous-noeuds doit être effectué.
+     */
+
+    result = false;
+
+    for (i = 0; i < list->count && !result; i++)
+        result = g_match_record_resolve_enum(list->children[i], name, label, value);
+
+    return result;
+
+}
diff --git a/plugins/kaitai/records/list.h b/plugins/kaitai/records/list.h
new file mode 100644
index 0000000..03e593e
--- /dev/null
+++ b/plugins/kaitai/records/list.h
@@ -0,0 +1,71 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.h - prototypes pour la conservation d'une liste de correspondance avec du binaire
+ *
+ * Copyright (C) 2019 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_RECORDS_LIST_H
+#define _PLUGINS_KAITAI_RECORDS_LIST_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/content.h>
+
+
+#include "../record.h"
+#include "../parsers/attribute.h"
+
+
+
+#define G_TYPE_RECORD_LIST            g_record_list_get_type()
+#define G_RECORD_LIST(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_LIST, GRecordList))
+#define G_IS_RECORD_LIST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_LIST))
+#define G_RECORD_LIST_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_LIST, GRecordListClass))
+#define G_IS_RECORD_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_LIST))
+#define G_RECORD_LIST_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_LIST, GRecordListClass))
+
+
+/* Liste de correspondances établies entre attributs et binaire (instance) */
+typedef struct _GRecordList GRecordList;
+
+/* Liste de correspondances établies entre attributs et binaire (classe) */
+typedef struct _GRecordListClass GRecordListClass;
+
+
+/* Indique le type défini pour une série de correspondances entre attributes et binaire. */
+GType g_record_list_get_type(void);
+
+/* Crée une nouvelle série de correspondances attribut/binaire. */
+GRecordList *g_record_list_new(GKaitaiAttribute *, GBinContent *, const vmpa2t *);
+
+/* Dénombre le nombre de correspondances enregistrées. */
+size_t g_record_list_count_records(const GRecordList *);
+
+/* Ajoute une correspondance supplémentaire à une série. */
+void g_record_list_add_record(GRecordList *, GMatchRecord *);
+
+/* Fournit un élément ciblé dans la liste de correspondances. */
+GMatchRecord *g_record_list_get_record(const GRecordList *, size_t);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_LIST_H */
diff --git a/plugins/kaitai/records/value-int.h b/plugins/kaitai/records/value-int.h
new file mode 100644
index 0000000..6a84a7f
--- /dev/null
+++ b/plugins/kaitai/records/value-int.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * value-int.h - prototypes internes pour la conservation d'une instance virtuelle
+ *
+ * Copyright (C) 2019 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_RECORDS_VALUE_INT_H
+#define _PLUGINS_KAITAI_RECORDS_VALUE_INT_H
+
+
+#include "value.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Valeur calculée selon des correspondances parallèles (instance) */
+struct _GRecordValue
+{
+    GMatchRecord parent;                    /* A laisser en premier        */
+
+    kaitai_scope_t locals;                  /* Sauvegarde de contexte      */
+
+};
+
+/* Valeur calculée selon des correspondances parallèles (classe) */
+struct _GRecordValueClass
+{
+    GMatchRecordClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Met en place une valeur calculée selon des correspondances. */
+bool g_record_value_create(GRecordValue *, GKaitaiInstance *, const kaitai_scope_t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_VALUE_INT_H */
diff --git a/plugins/kaitai/records/value.c b/plugins/kaitai/records/value.c
new file mode 100644
index 0000000..cafe5c3
--- /dev/null
+++ b/plugins/kaitai/records/value.c
@@ -0,0 +1,336 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * value.c - conservation d'une correspondance entre attribut et binaire
+ *
+ * Copyright (C) 2019 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 "value.h"
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+#include "value-int.h"
+#include "../parsers/attribute.h"
+
+
+
+/* -------------------- DEFINITION D'UNE CORRESPONDANCE UNITAIRE -------------------- */
+
+
+/* Initialise la classe des valeurs purement calculées. */
+static void g_record_value_class_init(GRecordValueClass *);
+
+/* Initialise une correspondance entre attribut et binaire. */
+static void g_record_value_init(GRecordValue *);
+
+/* Supprime toutes les références externes. */
+static void g_record_value_dispose(GRecordValue *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_value_finalize(GRecordValue *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_value_get_range(const GRecordValue *, mrange_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      DEFINITION D'UNE CORRESPONDANCE UNITAIRE                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une valeur calculée selon des correspondances établies. */
+G_DEFINE_TYPE(GRecordValue, g_record_value, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des valeurs purement calculées.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_value_class_init(GRecordValueClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GMatchRecordClass *record;              /* Version parente de la classe*/
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_record_value_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_record_value_finalize;
+
+    record = G_MATCH_RECORD_CLASS(klass);
+
+    record->get_range = (get_record_range_fc)g_record_value_get_range;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : value = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une correspondance entre attribut et binaire.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_value_init(GRecordValue *value)
+{
+    init_record_scope(&value->locals, NULL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : value = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_value_dispose(GRecordValue *value)
+{
+    reset_record_scope(&value->locals);
+
+    G_OBJECT_CLASS(g_record_value_parent_class)->dispose(G_OBJECT(value));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : value = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_value_finalize(GRecordValue *value)
+{
+    G_OBJECT_CLASS(g_record_value_parent_class)->finalize(G_OBJECT(value));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inst   = analyseur à l'origine de la correspondance.         *
+*                locals = correspondances courantes pour résolutions.         *
+*                                                                             *
+*  Description : Crée une nouvelle valeur calculée à partir d'une instance.   *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRecordValue *g_record_value_new(GKaitaiInstance *inst, const kaitai_scope_t *locals)
+{
+    GRecordValue *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_RECORD_VALUE, NULL);
+
+    if (!g_record_value_create(result, inst, locals))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : value  = correspondance à initialiser pleinement.            *
+*                inst   = analyseur à l'origine de la correspondance.         *
+*                locals = correspondances courantes pour résolutions.         *
+*                                                                             *
+*  Description : Met en place une valeur calculée à partir d'une instance.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_record_value_create(GRecordValue *value, GKaitaiInstance *inst, const kaitai_scope_t *locals)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_match_record_create(G_MATCH_RECORD(value), G_KAITAI_PARSER(inst), NULL);
+
+    if (result)
+        copy_record_scope(&value->locals, locals);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : value = correspondance à consulter.                          *
+*                value = valeur à sauvegarder sous une forme générique. [OUT] *
+*                                                                             *
+*  Description : Détermine la valeur d'un élément Kaitai calculé.             *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_record_value_compute_value(const GRecordValue *value, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à retourner           */
+    GKaitaiParser *parser;                  /* Instance liée à l'élément   */
+
+    parser = g_match_record_get_creator(G_MATCH_RECORD(value));
+    assert(G_IS_KAITAI_ATTRIBUTE(parser));
+
+    result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser),
+                                             &value->locals,
+                                             out);
+
+    g_object_unref(G_OBJECT(parser));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : value = correspondance à consulter.                          *
+*                value = valeur à sauvegarder sous une forme générique. [OUT] *
+*                                                                             *
+*  Description : Détermine et ajuste la valeur d'un élément Kaitai calculé.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_record_value_compute_and_aggregate_value(const GRecordValue *value, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à retourner           */
+    GKaitaiParser *parser;                  /* Instance liée à l'élément   */
+    sized_string_t converted;               /* Conversion finale ?         */
+
+    parser = g_match_record_get_creator(G_MATCH_RECORD(value));
+    assert(G_IS_KAITAI_ATTRIBUTE(parser));
+
+    result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser),
+                                             &value->locals,
+                                             out);
+
+    g_object_unref(G_OBJECT(parser));
+
+    if (result)
+    {
+        /**
+         * Lorsque c'est possible, les tableaux Kaitai sont transformés en série
+         * d'octets.
+         *
+         * Même si les tableaux ont une grande portée en interne des règles
+         * Kaitai (par exemple pour constituer une table de constantes de
+         * référence), il en est différemment à l'extérieur du processus de
+         * traitement : les tableaux sont le plus souvent destinés à manipuler
+         * les octets représentés directement (par exemple :
+         * "contents: [0xca, 0xfe, 0xba, 0xbe]").
+         *
+         * Pour les valeurs d'instance dont le type n'est pas explicite,
+         * le choix est fait de tenter de simplifier la vie de l'utilisateur
+         * en lui fournissant directement les octets qu'il attend probablement
+         * plutôt qu'un tableau contenant des octets à extraire.
+         */
+
+        if (out->type == GVT_ARRAY)
+        {
+            if (g_kaitai_array_convert_to_bytes(out->array, &converted))
+            {
+                EXIT_RESOLVED_VALUE(*out);
+
+                out->bytes = converted;
+                out->type = GVT_BYTES;
+
+            }
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : value  = correspondance à consulter.                         *
+*                range = zone de couverture déterminée. [OUT]                 *
+*                                                                             *
+*  Description : Calcule ou fournit la zone couverte par une correspondance.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_value_get_range(const GRecordValue *value, mrange_t *range)
+{
+    copy_mrange(range, UNUSED_MRANGE_PTR);
+
+}
diff --git a/plugins/kaitai/records/value.h b/plugins/kaitai/records/value.h
new file mode 100644
index 0000000..8ee9cdd
--- /dev/null
+++ b/plugins/kaitai/records/value.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * value.h - prototypes pour la conservation d'une correspondance entre attribut et binaire
+ *
+ * Copyright (C) 2019 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_RECORDS_VALUE_H
+#define _PLUGINS_KAITAI_RECORDS_VALUE_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+#include "../parsers/instance.h"
+
+
+
+#define G_TYPE_RECORD_VALUE            g_record_value_get_type()
+#define G_RECORD_VALUE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_VALUE, GRecordValue))
+#define G_IS_RECORD_VALUE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_VALUE))
+#define G_RECORD_VALUE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_VALUE, GRecordValueClass))
+#define G_IS_RECORD_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_VALUE))
+#define G_RECORD_VALUE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_VALUE, GRecordValueClass))
+
+
+/* Valeur calculée selon des correspondances parallèles (instance) */
+typedef struct _GRecordValue GRecordValue;
+
+/* Valeur calculée selon des correspondances parallèles (classe) */
+typedef struct _GRecordValueClass GRecordValueClass;
+
+
+/* Indique le type défini pour une valeur calculée selon des correspondances établies. */
+GType g_record_value_get_type(void);
+
+/* Crée une nouvelle valeur calculée à partir d'une instance. */
+GRecordValue *g_record_value_new(GKaitaiInstance *, const kaitai_scope_t *);
+
+/* Détermine la valeur d'un élément Kaitai entier calculé. */
+bool g_record_value_compute_value(const GRecordValue *, resolved_value_t *);
+
+/* Détermine et ajuste la valeur d'un élément Kaitai calculé. */
+bool g_record_value_compute_and_aggregate_value(const GRecordValue *, resolved_value_t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_VALUE_H */
diff --git a/plugins/kaitai/scope.c b/plugins/kaitai/scope.c
new file mode 100644
index 0000000..6d1d47a
--- /dev/null
+++ b/plugins/kaitai/scope.c
@@ -0,0 +1,257 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scope.c - recherches d'éléments de lecture
+ *
+ * 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 "scope.h"
+
+
+#include "parsers/struct.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = contexte de variables locales à initialiser.        *
+*                meta   = informations générales à disposition.               *
+*                                                                             *
+*  Description : Initialise un contexte pour correspondances Kaitai établies. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void init_record_scope(kaitai_scope_t *locals, GKaitaiMeta *meta)
+{
+    locals->meta = meta;
+
+    if (meta != NULL)
+        g_object_ref(G_OBJECT(meta));
+
+    locals->root = NULL;
+    locals->parent = NULL;
+    locals->last = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = contexte de variables locales à réinitialiser.      *
+*                                                                             *
+*  Description : Vide un contexte de correspondances Kaitai établies.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void reset_record_scope(kaitai_scope_t *locals)
+{
+    g_clear_object(&locals->meta);
+
+    g_clear_object(&locals->root);
+    g_clear_object(&locals->parent);
+    g_clear_object(&locals->last);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : dest = contexte de variables locales à initialiser.          *
+*                src  = contexte de variables locales à copier.               *
+*                                                                             *
+*  Description : Copie un contexte de correspondances Kaitai établies.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void copy_record_scope(kaitai_scope_t *dest, const kaitai_scope_t *src)
+{
+    reset_record_scope(dest);
+
+#define COPY_SCOPE_ITEM(itm)                    \
+    dest->itm = src->itm;                       \
+    if (dest->itm != NULL)                      \
+        g_object_ref(G_OBJECT(dest->itm));
+
+    COPY_SCOPE_ITEM(meta);
+
+    COPY_SCOPE_ITEM(root);
+    COPY_SCOPE_ITEM(parent);
+    COPY_SCOPE_ITEM(last);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                                                                             *
+*  Description : Retourne le souvenir d'une correspondance racine.            *
+*                                                                             *
+*  Retour      : Dernière correspondance établie ou NULL.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GMatchRecord *get_root_record(const kaitai_scope_t *locals)
+{
+    GMatchRecord *result;                   /* Instance à retourner        */
+
+    result = locals->root;
+
+    if (result != NULL)
+        g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                                                                             *
+*  Description : Retourne le souvenir de la correspondance parente effectuée. *
+*                                                                             *
+*  Retour      : Dernière correspondance établie ou NULL.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GMatchRecord *get_parent_record(const kaitai_scope_t *locals)
+{
+    GMatchRecord *result;                   /* Instance à retourner        */
+
+    result = locals->parent;
+
+    if (result != NULL)
+        g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                record = dernière correspondance établie.                    *
+*                                                                             *
+*  Description : Conserve le souvenir de la dernière correspondance effectuée.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void remember_last_record(kaitai_scope_t *locals, GMatchRecord *record)
+{
+    g_clear_object(&locals->last);
+
+    locals->last = record;
+
+    if (record != NULL)
+        g_object_ref(G_OBJECT(record));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                                                                             *
+*  Description : Retourne le souvenir de la dernière correspondance effectuée.*
+*                                                                             *
+*  Retour      : Dernière correspondance établie ou NULL.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GMatchRecord *get_last_record(const kaitai_scope_t *locals)
+{
+    GMatchRecord *result;                   /* Instance à retourner        */
+
+    result = locals->last;
+
+    if (result != NULL)
+        g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : locals = variables locales pour les résolutions de types.    *
+*                name   = désignation du type particulier ciblé.              *
+*                                                                             *
+*  Description : Recherche la définition d'un type nouveau pour Kaitai.       *
+*                                                                             *
+*  Retour      : Type prêt à emploi ou NULL si non trouvé.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiType *find_sub_type(const kaitai_scope_t *locals, const char *name)
+{
+    GKaitaiType *result;                    /* Instance à retourner        */
+    size_t i;                               /* Boucle de parcours          */
+    GKaitaiParser *parser;                  /* Lecteur d'origine           */
+
+    GMatchRecord *list[] = { locals->root, locals->parent, locals->last };
+
+    result = NULL;
+
+    for (i = 0; i < 3; i++)
+    {
+        if (list[i] == NULL)
+            continue;
+
+        parser = g_match_record_get_creator(list[i]);
+
+        if (G_IS_KAITAI_STRUCT(parser))
+            result = g_kaitai_structure_find_sub_type(G_KAITAI_STRUCT(parser), name);
+
+        g_object_unref(G_OBJECT(parser));
+
+        if (result != NULL)
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/scope.h b/plugins/kaitai/scope.h
new file mode 100644
index 0000000..5dc52bf
--- /dev/null
+++ b/plugins/kaitai/scope.h
@@ -0,0 +1,72 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scope.h - prototypes pour les recherches d'éléments de lecture
+ *
+ * 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_SCOPE_H
+#define _PLUGINS_KAITAI_SCOPE_H
+
+
+#include "record.h"
+#include "parsers/meta.h"
+#include "parsers/type.h"
+
+
+
+/* Accès aux différentes variables de contexte */
+typedef struct _kaitai_scope_t
+{
+    GKaitaiMeta *meta;                      /* Informations globales       */
+
+    GMatchRecord *root;                     /* Variable "_root"            */
+    GMatchRecord *parent;                   /* Variable "_parent"          */
+    GMatchRecord *last;                     /* Variable "_"                */
+
+} kaitai_scope_t;
+
+
+/* Initialise un contexte pour correspondances Kaitai établies. */
+void init_record_scope(kaitai_scope_t *, GKaitaiMeta *);
+
+/* Vide un contexte de correspondances Kaitai établies. */
+void reset_record_scope(kaitai_scope_t *);
+
+/* Copie un contexte de correspondances Kaitai établies. */
+void copy_record_scope(kaitai_scope_t *, const kaitai_scope_t *);
+
+/* Retourne le souvenir d'une correspondance racine. */
+GMatchRecord *get_root_record(const kaitai_scope_t *);
+
+/* Retourne le souvenir de la correspondance parente effectuée. */
+GMatchRecord *get_parent_record(const kaitai_scope_t *);
+
+/* Conserve le souvenir de la dernière correspondance effectuée. */
+void remember_last_record(kaitai_scope_t *, GMatchRecord *);
+
+/* Retourne le souvenir de la dernière correspondance effectuée. */
+GMatchRecord *get_last_record(const kaitai_scope_t *);
+
+/* Recherche la définition d'un type nouveau pour Kaitai. */
+GKaitaiType *find_sub_type(const kaitai_scope_t *, const char *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_SCOPE_H */
diff --git a/plugins/kaitai/stream-int.h b/plugins/kaitai/stream-int.h
new file mode 100644
index 0000000..50b71df
--- /dev/null
+++ b/plugins/kaitai/stream-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * stream-int.h - prototypes pour les données associées à un flux de données Kaitai
+ *
+ * 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_STREAM_INT_H
+#define PLUGINS_KAITAI_STREAM_INT_H
+
+
+#include "stream.h"
+
+
+
+/* Flux de données à disposition d'une analyse Kaitai (instance) */
+struct _GKaitaiStream
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    GBinContent *content;                   /* Contenu brut manipulé       */
+    vmpa2t pos;                             /* Tête de lecture dans le flux*/
+
+};
+
+/* Flux de données à disposition d'une analyse Kaitai (classe) */
+struct _GKaitaiStreamClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+};
+
+
+/* Met en place un flux de données pour Kaitai. */
+bool g_kaitai_stream_create(GKaitaiStream *, GBinContent *, const vmpa2t *);
+
+
+
+#endif  /* PLUGINS_KAITAI_STREAM_INT_H */
diff --git a/plugins/kaitai/stream.c b/plugins/kaitai/stream.c
new file mode 100644
index 0000000..66d0f8e
--- /dev/null
+++ b/plugins/kaitai/stream.c
@@ -0,0 +1,237 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * stream.c - données associées à un flux de données Kaitai
+ *
+ * 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 "stream.h"
+
+
+#include "stream-int.h"
+
+
+
+/* Initialise la classe des flux de données pour Kaitai. */
+static void g_kaitai_stream_class_init(GKaitaiStreamClass *);
+
+/* Initialise un flux de données accessibles à Kaitai. */
+static void g_kaitai_stream_init(GKaitaiStream *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_stream_dispose(GKaitaiStream *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_stream_finalize(GKaitaiStream *);
+
+
+
+/* Indique le type défini pour un flux de données manipulé par une lecture Kaitai. */
+G_DEFINE_TYPE(GKaitaiStream, g_kaitai_stream, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des flux de données pour Kaitai.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_stream_class_init(GKaitaiStreamClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_stream_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_kaitai_stream_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : stream = instance à initialiser.                             *
+*                                                                             *
+*  Description : Initialise un flux de données accessibles à Kaitai.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_stream_init(GKaitaiStream *stream)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : stream = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_stream_dispose(GKaitaiStream *stream)
+{
+    G_OBJECT_CLASS(g_kaitai_stream_parent_class)->dispose(G_OBJECT(stream));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : stream = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_kaitai_stream_finalize(GKaitaiStream *stream)
+{
+    G_OBJECT_CLASS(g_kaitai_stream_parent_class)->finalize(G_OBJECT(stream));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire parcouru par une analyse Kaitai.   *
+*                pos     = tête de lecture courante.                          *
+*                                                                             *
+*  Description : Rassemble les éléments constituant un flux de données Kaitai.*
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GKaitaiStream *g_kaitai_stream_new(GBinContent *content, const vmpa2t *pos)
+{
+    GKaitaiStream *result;                  /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_KAITAI_STREAM, NULL);
+
+    if (!g_kaitai_stream_create(result, content, pos))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = lecteur d'attribut Kaitai à initialiser pleinement.*
+*                content = contenu binaire parcouru par une analyse Kaitai.   *
+*                pos     = tête de lecture courante.                          *
+*                                                                             *
+*  Description : Met en place un flux de données pour Kaitai.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_stream_create(GKaitaiStream *stream, GBinContent *content, const vmpa2t *pos)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    stream->content = content;
+    g_object_ref(G_OBJECT(content));
+
+    copy_vmpa(&stream->pos, pos);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : stream  = flux de données Kaitai à consulter.                *
+*                                                                             *
+*  Description : Indique le contenu de données binaires lié au flux Kaitai.   *
+*                                                                             *
+*  Retour      : Contenu binaire associé au flux de données.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_kaitai_stream_get_content(const GKaitaiStream *stream)
+{
+    GBinContent *result;                    /* Instance à renvoyer         */
+
+    result = stream->content;
+
+    g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : stream  = flux de données Kaitai à consulter.                *
+*                                                                             *
+*  Description : Détermine si la fin des données a été atteinte.              *
+*                                                                             *
+*  Retour      : true si la tête de lecture est en position finale, ou false. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_stream_has_reached_eof(const GKaitaiStream *stream)
+{
+    bool result;                            /* Bilan à retourner           */
+    vmpa2t end;                             /* Position finale du flux     */
+    int ret;                                /* Bilan d'une comparaison     */
+
+    g_binary_content_compute_end_pos(stream->content, &end);
+
+    ret = cmp_vmpa_by_phy(&stream->pos, &end);
+
+    result = (ret == 0);
+
+    return result;
+
+}
diff --git a/plugins/kaitai/stream.h b/plugins/kaitai/stream.h
new file mode 100644
index 0000000..ee82c6d
--- /dev/null
+++ b/plugins/kaitai/stream.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * stream.h - prototypes pour les données associées à un flux de données Kaitai
+ *
+ * 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_STREAM_H
+#define PLUGINS_KAITAI_STREAM_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/content.h>
+
+
+
+#define G_TYPE_KAITAI_STREAM            g_kaitai_stream_get_type()
+#define G_KAITAI_STREAM(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_STREAM, GKaitaiStream))
+#define G_IS_KAITAI_STREAM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_STREAM))
+#define G_KAITAI_STREAM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_STREAM, GKaitaiStreamClass))
+#define G_IS_KAITAI_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_STREAM))
+#define G_KAITAI_STREAM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_STREAM, GKaitaiStreamClass))
+
+
+/* Flux de données à disposition d'une analyse Kaitai (instance) */
+typedef struct _GKaitaiStream GKaitaiStream;
+
+/* Flux de données à disposition d'une analyse Kaitai (classe) */
+typedef struct _GKaitaiStreamClass GKaitaiStreamClass;
+
+
+/* Indique le type défini pour un flux de données manipulé par une lecture Kaitai. */
+GType g_kaitai_stream_get_type(void);
+
+/* Rassemble les éléments constituant un flux de données Kaitai. */
+GKaitaiStream *g_kaitai_stream_new(GBinContent *, const vmpa2t *);
+
+/* Indique le contenu de données binaires lié au flux Kaitai. */
+GBinContent *g_kaitai_stream_get_content(const GKaitaiStream *);
+
+/* Détermine si la fin des données a été atteinte. */
+bool g_kaitai_stream_has_reached_eof(const GKaitaiStream *);
+
+
+
+#endif  /* PLUGINS_KAITAI_STREAM_H */
diff --git a/plugins/kaitai/tokens.l b/plugins/kaitai/tokens.l
new file mode 100644
index 0000000..3ddf40d
--- /dev/null
+++ b/plugins/kaitai/tokens.l
@@ -0,0 +1,327 @@
+
+%top {
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+#include <common/extstr.h>
+
+#include "grammar.h"
+
+}
+
+
+%{
+
+#define PUSH_STATE(s) yy_push_state(s, yyscanner)
+#define POP_STATE     yy_pop_state(yyscanner)
+
+%}
+
+
+%option bison-bridge reentrant
+%option stack
+%option nounput
+ //%option noinput
+%option noyywrap
+%option noyy_top_state
+%option yylineno
+%option never-interactive
+
+
+%x encoding
+%x escaped_str
+%x plain_str
+
+
+%%
+
+
+%{
+
+    /* no init C code */
+
+%}
+
+
+"+"                                     { return PLUS; }
+"-"                                     { return MINUS; }
+"*"                                     { return MUL; }
+"/"                                     { return DIV; }
+"%"                                     { return MOD; }
+
+"<"                                     { return LT; }
+"<="                                    { return LE; }
+"=="                                    { return EQ; }
+"!="                                    { return NE; }
+">"                                     { return GT; }
+">="                                    { return GE; }
+
+"<<"                                    { return SHIFT_LEFT; }
+">>"                                    { return SHIFT_RIGHT; }
+"&"                                     { return BIT_AND; }
+"|"                                     { return BIT_OR; }
+"^"                                     { return BIT_XOR; }
+
+"not"                                   { return NOT; }
+"and"                                   { return AND; }
+"or"                                    { return OR; }
+
+"("                                     { return PAREN_O; }
+")"                                     { return PAREN_C; }
+"["                                     { return HOOK_O; }
+"]"                                     { return HOOK_C; }
+","                                     { return COMMA; }
+"."                                     { return DOT; }
+
+"?"                                     { return QMARK; }
+":"                                     { return COLON; }
+"::"                                    { return DOUBLE_COLON; }
+
+".size"                                 { return METH_SIZE; }
+".length"                               { return METH_LENGTH; }
+".reverse"                              { return METH_REVERSE; }
+".substring"                            { return METH_SUBSTRING; }
+".to_i"                                 { return METH_TO_I; }
+".to_i("                                { return METH_TO_I_RAD; }
+".to_s"                                 { return METH_TO_S; }
+".to_s("                                { PUSH_STATE(encoding); return METH_TO_S_ENC; }
+
+"_root"                                 { return ROOT; }
+"_parent"                               { return PARENT; }
+"_"                                     { return LAST; }
+"._io"                                  { return METH_IO; }
+
+"true"                                  { return TRUE_CONST; }
+"false"                                 { return FALSE_CONST; }
+
+
+%{ /* Lecteurs de valeurs entières */ %}
+
+0[bB][01]+                              {
+                                            char *__end;
+                                            yylval->unsigned_integer = strtoull(yytext + 2, &__end, 2);
+                                            if (__end != (yytext + yyleng))
+                                                YY_FATAL_ERROR("failed to parse integer");
+                                            return UNSIGNED_INTEGER;
+                                        }
+
+0[bB][01]{1,4}(_[01]{4})+               {
+                                            char *__tmp;
+                                            char *__end;
+                                            __tmp = strdup(yytext);
+                                            __tmp = strrpl(__tmp, "_", "");
+                                            yylval->unsigned_integer = strtoull(__tmp + 2, &__end, 2);
+                                            if (__end != (__tmp + strlen(__tmp)))
+                                            {
+                                                free(__tmp);
+                                                YY_FATAL_ERROR("failed to parse integer");
+                                            }
+                                            else free(__tmp);
+                                            return UNSIGNED_INTEGER;
+                                        }
+
+(0|[1-9][0-9]*)                         {
+                                            char *__end;
+                                            yylval->unsigned_integer = strtoull(yytext, &__end, 10);
+                                            if (__end != (yytext + yyleng))
+                                                YY_FATAL_ERROR("failed to parse integer");
+                                            return UNSIGNED_INTEGER;
+                                        }
+
+[1-9][0-9]{0,2}(_[1-9][0-9]{2})+        {
+                                            char *__tmp;
+                                            char *__end;
+                                            __tmp = strdup(yytext);
+                                            __tmp = strrpl(__tmp, "_", "");
+                                            yylval->unsigned_integer = strtoull(__tmp, &__end, 10);
+                                            if (__end != (__tmp + strlen(__tmp)))
+                                            {
+                                                free(__tmp);
+                                                YY_FATAL_ERROR("failed to parse integer");
+                                            }
+                                            else free(__tmp);
+                                            return UNSIGNED_INTEGER;
+                                        }
+
+-(0|[1-9][0-9]*)                        {
+                                            char *__end;
+                                            yylval->signed_integer = strtoll(yytext, &__end, 10);
+                                            if (__end != (yytext + yyleng))
+                                                YY_FATAL_ERROR("failed to parse integer");
+                                            return SIGNED_INTEGER;
+                                        }
+
+-[1-9][0-9]{0,2}(_[1-9][0-9]{2})+       {
+                                            char *__tmp;
+                                            char *__end;
+                                            __tmp = strdup(yytext);
+                                            __tmp = strrpl(__tmp, "_", "");
+                                            yylval->signed_integer = strtoll(__tmp, &__end, 10);
+                                            if (__end != (__tmp + strlen(__tmp)))
+                                            {
+                                                free(__tmp);
+                                                YY_FATAL_ERROR("failed to parse integer");
+                                            }
+                                            else free(__tmp);
+                                            return SIGNED_INTEGER;
+                                        }
+
+0[xX][0-9a-fA-F]+                       {
+                                            char *__end;
+                                            yylval->unsigned_integer = strtoull(yytext, &__end, 16);
+                                            if (__end != (yytext + yyleng))
+                                                YY_FATAL_ERROR("failed to parse integer");
+                                            return UNSIGNED_INTEGER;
+                                        }
+
+0[xX][0-9a-fA-F]{1,4}(_[0-9a-fA-F]{4})+ {
+                                            char *__tmp;
+                                            char *__end;
+                                            __tmp = strdup(yytext);
+                                            __tmp = strrpl(__tmp, "_", "");
+                                            yylval->unsigned_integer = strtoull(__tmp, &__end, 16);
+                                            if (__end != (__tmp + strlen(__tmp)))
+                                            {
+                                                free(__tmp);
+                                                YY_FATAL_ERROR("failed to parse integer");
+                                            }
+                                            else free(__tmp);
+                                            return UNSIGNED_INTEGER;
+                                        }
+
+
+
+-?(0|[1-9][0-9]*\.[0-9]+)               {
+                                            char *__end;
+                                            yylval->floating_number = strtod(yytext, &__end);
+                                            if (__end != (yytext + yyleng))
+                                                YY_FATAL_ERROR("failed to parse float");
+                                            return FLOAT;
+                                        }
+
+
+%{ /* Paramètre d'encodage */ %}
+
+<encoding>["'][-_A-Za-z0-9 ]+["']       {
+                                            yylval->sized_cstring.data = yytext + 1;
+                                            yylval->sized_cstring.len = yyleng - 2;
+                                            return ENCODING_NAME;
+                                        }
+
+<encoding>")"                           { POP_STATE; return PAREN_C; }
+
+
+[a-z][a-z0-9_]*                         {
+                                            yylval->sized_cstring.data = yytext;
+                                            yylval->sized_cstring.len = yyleng;
+                                            return IDENTIFIER;
+                                        }
+
+[^\\\[\],"'()\.: ]+                     {
+                                            yylval->sized_cstring.data = yytext;
+                                            yylval->sized_cstring.len = yyleng;
+                                            return PLAIN_BYTES;
+                                        }
+
+
+%{ /* Lecteurs des tableaux de définition d'octets */ %}
+
+"\""                                    { PUSH_STATE(escaped_str); }
+
+
+<escaped_str>[^\\"]+                    {
+                                            yylval->sized_cstring.data = yytext;
+                                            yylval->sized_cstring.len = yyleng;
+                                            return RAW_BYTES;
+                                        }
+
+<escaped_str>"\\a"                      { yylval->byte = '\a'; return RAW_BYTE; }
+<escaped_str>"\\b"                      { yylval->byte = '\b'; return RAW_BYTE; }
+<escaped_str>"\\t"                      { yylval->byte = '\t'; return RAW_BYTE; }
+<escaped_str>"\\n"                      { yylval->byte = '\n'; return RAW_BYTE; }
+<escaped_str>"\\v"                      { yylval->byte = '\v'; return RAW_BYTE; }
+<escaped_str>"\\f"                      { yylval->byte = '\f'; return RAW_BYTE; }
+<escaped_str>"\\r"                      { yylval->byte = '\r'; return RAW_BYTE; }
+<escaped_str>"\\e"                      { yylval->byte = '\e'; return RAW_BYTE; }
+<escaped_str>"\\\""                     { yylval->byte = '"';  return RAW_BYTE; }
+<escaped_str>"\\'"                      { yylval->byte = '\''; return RAW_BYTE; }
+<escaped_str>"\\\\"                     { yylval->byte = '\\'; return RAW_BYTE; }
+<escaped_str>"\\0"                      { yylval->byte = '\0'; return RAW_BYTE; }
+
+<escaped_str>\\[0-9]{1,3}               {
+                                            char __tmp[4];
+                                            memcpy(__tmp, yytext + 1, yyleng - 1);
+                                            __tmp[yyleng] = '\0';
+                                            yylval->byte = strtoull(__tmp, NULL, 8);
+                                            return RAW_BYTE;
+                                        }
+
+<escaped_str>"\""                       { POP_STATE; }
+
+
+
+
+"'"                                     { PUSH_STATE(plain_str); }
+
+<plain_str>[^']+                        {
+                                            yylval->sized_cstring.data = yytext;
+                                            yylval->sized_cstring.len = yyleng;
+                                            return PLAIN_BYTES;
+                                        }
+
+<plain_str>[']                          { POP_STATE; }
+
+[.]$                                    {
+#ifndef NDEBUG
+                                            int ch;
+#endif
+                                            yylval->sized_cstring.data = yytext;
+                                            yylval->sized_cstring.len = yyleng;
+#ifndef NDEBUG
+                                            ch = input(yyscanner);
+                                            assert(ch == '\n');
+#else
+                                            input(yyscanner);
+#endif
+                                            return RAW_BYTES_WITH_ENDING_DOT;
+                                        }
+
+[^\\\[\],"'()\.: ]+[.]$                 {
+#ifndef NDEBUG
+                                            int ch;
+#endif
+                                            yylval->sized_cstring.data = yytext;
+                                            yylval->sized_cstring.len = yyleng;
+#ifndef NDEBUG
+                                            ch = input(yyscanner);
+                                            assert(ch == '\n');
+#else
+                                            input(yyscanner);
+#endif
+                                            return RAW_BYTES_WITH_ENDING_DOT;
+                                        }
+
+
+%{ /* Actions par défaut */ %}
+
+<*>[ \t\n]+                             { }
+
+<*>.                                    {
+                                            char *msg;
+                                            int ret;
+                                            ret = asprintf(&msg,
+                                                           "Unhandled token in rule definition: '%s'",
+                                                           yytext);
+                                            if (ret == -1)
+                                                YY_FATAL_ERROR("Unhandled token in undisclosed rule definition");
+                                            else
+                                            {
+                                                YY_FATAL_ERROR(msg);
+                                                free(msg);
+                                            }
+                                        }
+
+
+%%
diff --git a/tests/plugins/kaitai.py b/tests/plugins/kaitai.py
new file mode 100644
index 0000000..b1e8881
--- /dev/null
+++ b/tests/plugins/kaitai.py
@@ -0,0 +1,2474 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+import locale
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.plugins.kaitai.parsers import KaitaiStruct
+
+
+class TestKaitaiStruct(ChrysalideTestCase):
+    """TestCase for the KaitaiStruct parsing."""
+
+
+    @classmethod
+    def setUpClass(cls):
+
+        super(TestKaitaiStruct, cls).setUpClass()
+
+        cls.log('Setting locale suitable for floats...')
+
+        cls._old_locale = locale.getlocale(locale.LC_NUMERIC)
+
+        locale.setlocale(locale.LC_NUMERIC, 'C')
+
+
+    @classmethod
+    def tearDownClass(cls):
+
+        super(TestKaitaiStruct, cls).tearDownClass()
+
+        cls.log('Reverting locale...')
+
+        locale.setlocale(locale.LC_NUMERIC, cls._old_locale)
+
+
+
+    #################################
+    ### 4. Kaitai Struct language
+    #################################
+
+
+    def testKaitaiFixedLength(self):
+        """Load fixed-size structures."""
+
+        # Cf. 4.1. Fixed-size structures
+
+        definitions = '''
+meta:
+  id: mydesc
+  title: My Long Title
+  endian: be
+seq:
+  - id: field0
+    type: u4
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        self.assertEqual(kstruct.meta.id, 'mydesc')
+        self.assertEqual(kstruct.meta.title, 'My Long Title')
+
+        content = MemoryContent(b'\x01\x02\x03\x04')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field0.range.length, 4)
+        self.assertEqual(parsed.field0.value, 0x01020304)
+
+        definitions = '''
+meta:
+  endian: le
+seq:
+  - id: field0
+    type: u4
+  - id: field1
+    type: u4be
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        self.assertIsNone(kstruct.meta.id)
+        self.assertIsNone(kstruct.meta.title)
+
+        content = MemoryContent(b'\x01\x02\x03\x04\x01\x02\x03\x04')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field0.range.length, 4)
+        self.assertEqual(parsed.field0.value, 0x04030201)
+
+        self.assertEqual(parsed.field1.range.length, 4)
+        self.assertEqual(parsed.field1.value, 0x01020304)
+
+
+        definitions = '''
+seq:
+  - id: field0
+    type: u1
+  - id: field1
+    size: 2
+  - id: field2
+    size: field0 + 1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x03\x04\x05')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field0.range.length, 1)
+        self.assertEqual(parsed.field0.value, 0x01)
+
+        self.assertEqual(parsed.field1.range.length, 2)
+        self.assertEqual(parsed.field1.truncated_bytes, b'\x02\x03')
+
+        self.assertEqual(parsed.field2.range.length, 2)
+        self.assertEqual(parsed.field2.truncated_bytes, b'\x04\x05')
+
+
+    def testDocstrings(self):
+        """Handle Kaitai documentation."""
+
+        # Cf. 4.2. Docstrings
+
+        definitions = '''
+seq:
+  - id: rating
+    type: s4
+    doc: Rating, can be negative
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x02\x04')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.rating.creator.doc, 'Rating, can be negative')
+
+
+    def testKaitaiContents(self):
+        """Read various forms of fixed content."""
+
+        # Cf. 4.3. Checking for "magic" signatures
+
+        definitions = '''
+seq:
+  - id: field0
+    contents: [ 0, 0x10, '22', "50 ]
+'''
+
+        # ValueError: Unable to create Kaitai structure.
+        with self.assertRaisesRegex(ValueError, "Unable to create Kaitai structure"):
+            kstruct = KaitaiStruct(definitions)
+            self.assertIsNotNone(kstruct)
+
+
+        definitions = '''
+seq:
+  - id: field0
+    contents: [ 0x41, 66, 'CD' ]
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'ABCD')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field0.range.length, 4)
+
+        self.assertEqual(parsed.field0.value, b'ABCD')
+
+
+        definitions = '''
+seq:
+  - id: field0
+    contents: ABCD
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'ABCD')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field0.range.length, 4)
+
+
+        definitions = '''
+seq:
+  - id: field0
+    contents: "ABCD"
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'ABCD')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field0.range.length, 4)
+
+
+        definitions = '''
+seq:
+  - id: field0
+    contents:
+      - 0x41
+      - "B"
+      - CD
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'ABCD')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field0.range.length, 4)
+
+
+    def testVariableLengthStructures(self):
+        """Parse variable-length structures."""
+
+        # Cf. 4.4. Variable-length structures
+
+        definitions = '''
+seq:
+  - id: my_len
+    type: u1
+  - id: my_str
+    type: str
+    size: my_len
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x03ABC')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.my_len.value, 3)
+
+        self.assertEqual(parsed.my_str.value, b'ABC')
+
+
+        definitions = '''
+seq:
+  - id: my_len
+    type: u1
+  - id: my_str
+    type: str
+    size: my_len * 2
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x03ABCDEF')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.my_len.value, 3)
+
+        self.assertEqual(parsed.my_str.value, b'ABCDEF')
+
+
+        definitions = '''
+seq:
+  - id: field0
+    size-eos: true
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x02\x03')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(content, parsed.content)
+
+        self.assertEqual(parsed.range.addr.phys, 0)
+        self.assertEqual(parsed.range.length, len(content.data))
+
+
+    def testDelimitedStructures(self):
+        """Parse delimited structures."""
+
+        # Cf. 4.5. Delimited structures
+
+        definitions = '''
+seq:
+  - id: my_string
+    type: str
+    terminator: 0
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'ABC\x00DEF')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.my_string.value, b'ABC')
+
+
+        definitions = '''
+seq:
+  - id: my_string
+    type: strz
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'ABC\x00DEF')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.my_string.value, b'ABC')
+
+
+        definitions = '''
+seq:
+  - id: name
+    type: str
+    size: 8
+    terminator: 0
+  - id: guard
+    size: 1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'ABC\x00\x00\x00\x00\x00x\x00')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.name.value, b'ABC')
+
+        self.assertEqual(parsed.guard.value, b'x')
+
+
+    def __passed__testEnums(self):
+        """Parse delimited structures."""
+
+        # Cf. 4.6. Enums (named integer constants)
+
+        pass
+
+
+    def testSubTypes(self):
+        """Includes subtypes definitions."""
+
+        # Cf. 4.7. Substructures (subtypes)
+
+        definitions = '''
+seq:
+  - id: field0
+    type: custom_type
+  - id: field1
+    type: custom_type
+  - id: field2
+    type: custom_type
+types:
+  custom_type:
+    seq:
+      - id: len
+        type: u1
+      - id: value
+        size: len
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\xaa\x02\xbb\xbb\x03\xcc\xcc\xcc')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field0.len.value, 1)
+        self.assertEqual(parsed.field0.value.truncated_bytes, b'\xaa')
+
+        self.assertEqual(parsed.field1.len.value, 2)
+        self.assertEqual(parsed.field1.value.truncated_bytes, b'\xbb\xbb')
+
+        self.assertEqual(parsed.field2.len.value, 3)
+        self.assertEqual(parsed.field2.value.truncated_bytes, b'\xcc\xcc\xcc')
+
+
+    def testOtherAttributesAccess(self):
+        """Access attributes in other types."""
+
+        # Cf. 4.8. Accessing attributes in other types
+
+        definitions = '''
+seq:
+  - id: header
+    type: main_header
+  - id: body
+    size: header.body_len
+types:
+  main_header:
+    seq:
+      - id: magic
+        contents: FMT
+      - id: body_len
+        type: u1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'FMT\x04\xaa\xbb\xcc\xdd')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.header.magic.raw_bytes, b'FMT')
+        self.assertEqual(parsed.header.magic.range.length, 3)
+
+        self.assertEqual(parsed.header.body_len.value, 4)
+
+        self.assertEqual(parsed.body.raw_bytes, b'\xaa\xbb\xcc\xdd')
+        self.assertEqual(parsed.body.range.length, 4)
+
+
+    def testConditionals(self):
+        """Read Kaitai values according to previous loaded values."""
+
+        # Cf. 4.9. Conditionals
+
+        definitions = '''
+seq:
+  - id: field1
+    type: u1
+  - id: field2
+    type: u1
+  - id: field3
+    type: u1
+    if: field1 + field2 > 10
+  - id: field4
+    type: u1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x03\x04')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field1.value, 0x01)
+        self.assertEqual(parsed.field2.value, 0x02)
+        self.assertFalse(hasattr(parsed, 'field3'))
+        self.assertEqual(parsed.field4.value, 0x03)
+
+
+        definitions = '''
+seq:
+  - id: field1
+    type: u1
+  - id: field2
+    type: u1
+  - id: field3
+    type: u1
+    if: field1 + field2 > 1
+  - id: field4
+    type: u1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x03\x04')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field1.value, 0x01)
+        self.assertEqual(parsed.field2.value, 0x02)
+        self.assertTrue(hasattr(parsed, 'field3'))
+        self.assertEqual(parsed.field4.value, 0x04)
+
+
+        definitions = '''
+seq:
+  - id: field1
+    type: u1
+  - id: field2
+    type: u1
+  - id: field3
+    type: u1
+    if: field1 + field2 == threshold::three
+  - id: field4
+    type: u1
+enums:
+  threshold:
+    1: one
+    2: two
+    3: three
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x03\x04')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field1.value, 0x01)
+        self.assertEqual(parsed.field2.value, 0x02)
+        self.assertTrue(hasattr(parsed, 'field3'))
+        self.assertEqual(parsed.field4.value, 0x04)
+
+
+    def testRepeatedReadUntilEOS(self):
+        """Read items until the end of the stream."""
+
+        # Cf. 4.10.1. Repeat until end of stream
+
+        definitions = '''
+seq:
+  - id: field0
+    type: u2be
+    repeat: eos
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x00\x02\x00\x03\x00\x04\x00')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(len(parsed.field0), len(content.data) / 2)
+
+        for i in range(4):
+            self.assertEqual(parsed.field0[i].value, (i + 1) << 8)
+
+
+    def testRepeatedReadAccordingToCounter(self):
+        """Repeat read of items for a nomber of times."""
+
+        # Cf. 4.10.2. Repeat for a number of times
+
+        definitions = '''
+seq:
+  - id: field0
+    type: u1
+  - id: field1
+    type: u1
+    repeat: expr
+    repeat-expr: 1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x01')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field0.value, 0x01)
+
+        self.assertEqual(len(parsed.field1), 1)
+
+        for i in range(1):
+            self.assertEqual(parsed.field1[i].value, i + 1)
+
+        definitions = '''
+seq:
+  - id: field0
+    type: u1
+  - id: field1
+    type: u1
+  - id: field2
+    type: u2
+    repeat: expr
+    repeat-expr: field0 + field1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x01\x00\x02\x00\x03\x00')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field0.value, 0x01)
+        self.assertEqual(parsed.field1.value, 0x02)
+
+        self.assertEqual(len(parsed.field2), 3)
+
+        for i in range(3):
+            self.assertEqual(parsed.field2[i].value, i + 1)
+
+
+    def testRepeatUntilConditionIsMet(self):
+        """Repeat until condition is met."""
+
+        # Cf. 4.10.3. Repeat until condition is met
+
+        definitions = '''
+seq:
+  - id: numbers
+    type: u1
+    repeat: until
+    repeat-until: _ == 0xff
+  - id: extra
+    type: u1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\xff\xcc')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(len(parsed.numbers), 3)
+
+        for i in range(2):
+            self.assertEqual(parsed.numbers[i].value, i + 1)
+
+        self.assertEqual(parsed.numbers[2].value, 0xff)
+
+        self.assertEqual(parsed.extra.value, 0xcc)
+
+        definitions = '''
+seq:
+  - id: records
+    type: buffer_with_len
+    repeat: until
+    repeat-until: _.len == 0
+types:
+  buffer_with_len:
+    seq:
+      - id: len
+        type: u1
+      - id: value
+        size: len
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x02\xaa\xaa\x01\xbb\x00')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.records[0].len.value, 2)
+        self.assertEqual(parsed.records[0].value.raw_bytes, b'\xaa\xaa')
+
+        self.assertEqual(parsed.records[1].len.value, 1)
+        self.assertEqual(parsed.records[1].value.raw_bytes, b'\xbb')
+
+        self.assertEqual(parsed.records[2].len.value, 0)
+        self.assertEqual(parsed.records[2].value.raw_bytes, b'')
+
+
+    def testParseTLVImplementation(self):
+        """Parse a typical TLV implementation."""
+
+        # Cf. 4.11. Typical TLV implementation (switching types on an expression)
+
+        definitions = '''
+seq:
+  - id: record
+    type: rec_def
+    repeat: eos
+types:
+  rec_def:
+    seq:
+      - id: rec_type
+        type: u1
+      - id: len
+        type: u1
+      - id: body
+        size: len
+        type:
+          switch-on: rec_type
+          cases:
+            1: rec_type_1
+            2: rec_type_2
+  rec_type_1:
+    seq:
+      - id: field1
+        type: u1
+  rec_type_2:
+    seq:
+      - id: field2
+        type: u2
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x01\xaa\x02\x02\xcc\xbb')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(len(parsed.record), 2)
+
+        self.assertEqual(parsed.record[0].rec_type.value, 1)
+        self.assertEqual(parsed.record[0].len.value, 1)
+        self.assertEqual(parsed.record[0].body.field1.value, 0xaa)
+
+        self.assertEqual(parsed.record[1].rec_type.value, 2)
+        self.assertEqual(parsed.record[1].len.value, 2)
+        self.assertEqual(parsed.record[1].body.field2.value, 0xbbcc)
+
+
+    def testInstanceWithDataBeyondTheSequence(self):
+        """Build instances with data beyond the sequence."""
+
+        # Cf. 4.12. Instances: data beyond the sequence
+
+        definitions = '''
+instances:
+  some_integer:
+    pos: 0x4
+    type: u1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x03\x04\x05\x06\x07\x08')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.some_integer.value, 5)
+
+
+        definitions = '''
+seq:
+  - id: file_offset
+    type: u1
+  - id: file_size
+    type: u1
+instances:
+  body:
+    pos: file_offset
+    size: file_size
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x04\x02\x90\x90ABCD')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.file_offset.value, 4)
+
+        self.assertEqual(parsed.file_size.value, 2)
+
+        self.assertEqual(parsed.body.value, b'AB')
+
+
+    def testValueInstances(self):
+        """Build value instances"""
+
+        # Cf. 4.13. Value instances
+
+        definitions = '''
+seq:
+  - id: length
+    type: u1
+  - id: extra
+    type: u1
+instances:
+  length_extended:
+    value: length * 3 + extra
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x03\x04')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.length.value, 1)
+
+        self.assertEqual(parsed.extra.value, 2)
+
+        self.assertEqual(parsed.length_extended.value, 5)
+
+
+    def testBitSizedIntegers(self):
+        """Read bit-sized integers."""
+
+        # Cf. 4.14. Bit-sized integers
+
+        definitions = '''
+seq:
+  - id: packed_1
+    type: u1
+instances:
+  version:
+    value: (packed_1 & 0b11110000) >> 4
+  len_header:
+    value:  packed_1 & 0b00001111
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x9a')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.packed_1.value, 0x9a)
+
+        self.assertEqual(parsed.version.value, 0x9)
+
+        self.assertEqual(parsed.len_header.value, 0xa)
+
+
+    def __passed__testBitSizedIntegersBigEndian(self):
+        """Read bit-sized integers."""
+
+        # Cf. 4.14.1. Big-endian order
+
+        pass
+
+
+    def __passed__testBitSizedIntegersLittleEndian(self):
+        """Read bit-sized integers."""
+
+        # Cf. 4.14.2. Little-endian order
+
+        pass
+
+
+    def __passed__testBitSizedIntegersSpecifiedEndianness(self):
+        """Read bit-sized integers with specified bit endianness."""
+
+        # Cf. 4.14.3. Specifying bit endianness
+
+        pass
+
+
+
+    #################################
+    ### 5. Streams and substreams
+    #################################
+
+
+    def testTotalSizeLimit(self):
+        """Limit total size of structure."""
+
+        # Cf. 5.1. Limiting total size of structure
+
+        definitions = '''
+seq:
+  - id: body_len
+    type: u1
+  - id: random
+    size: 2
+  - id: comment
+    size: body_len - 2
+  - id: extra
+    type: u1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x05\x01\x02---\xbb')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.body_len.value, 0x05)
+
+        self.assertEqual(parsed.random.raw_bytes, b'\x01\x02')
+
+        self.assertEqual(parsed.comment.raw_bytes, b'---')
+
+        self.assertEqual(parsed.extra.raw_bytes, b'\xbb')
+
+
+        definitions = '''
+seq:
+  - id: body_len
+    type: u1
+  - id: body
+    type: record_body
+    size: body_len
+  - id: extra
+    type: u1
+types:
+  record_body:
+    seq:
+      - id: random
+        size: 2
+      - id: comment
+        size-eos: true
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x05\x01\x02---\xbb')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.body_len.value, 0x05)
+
+        self.assertEqual(parsed.body.random.raw_bytes, b'\x01\x02')
+
+        self.assertEqual(parsed.body.comment.raw_bytes, b'---')
+
+        self.assertEqual(parsed.extra.raw_bytes, b'\xbb')
+
+
+    def testRepeatSizeLimit(self):
+        """Repeating until total size reaches limit."""
+
+        # Cf. 5.2. Repeating until total size reaches limit
+
+        content = MemoryContent(b'\x03\x00\x01\x02\xbb')
+
+        definitions = '''
+seq:
+  - id: total_len
+    type: u1
+  - id: files
+    type: file_entries
+    size: total_len
+  - id: extra
+    type: u1
+types:
+  file_entries:
+    seq:
+      - id: entries
+        type: entry
+        repeat: eos
+  entry:
+    seq:
+      - id: index
+        type: u1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.total_len.value, 3)
+
+        self.assertEqual(len(parsed.files.entries), 3)
+
+        for i in range(3):
+            self.assertEqual(parsed.files.entries[i].index.value, i)
+
+        self.assertEqual(parsed.extra.value, 0xbb)
+
+
+    def testRelativePositioning(self):
+        """Parse with relative positioning."""
+
+        # Cf. 5.3. Relative positioning
+
+        content = MemoryContent(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\0xe\x0f')
+
+        definitions = '''
+seq:
+  - id: some_header
+    size: 4
+  - id: body
+    type: block
+    size: 12
+types:
+  block:
+    seq:
+      - id: foo
+        type: u1
+    instances:
+      some_bytes_in_the_middle:
+        pos: 4
+        size: 4
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.some_header.value, b'\x00\x01\x02\x03')
+        self.assertEqual(parsed.body.foo.value, 0x04)
+
+        self.assertEqual(parsed.body.some_bytes_in_the_middle.value, b'\x08\x09\x0a\x0b')
+
+
+    def testAbsolutePositioning(self):
+        """Read from absolute position."""
+
+        # Cf. 5.4. Absolute positioning
+
+        content = MemoryContent(b'\x06\x03\x00\x00\x00\x00\x01\x02\x03\xbb')
+
+        definitions = '''
+seq:
+  - id: items
+    size: 10
+    type: entry
+    repeat: eos
+types:
+  entry:
+    seq:
+      - id: ofs_body
+        type: u1
+      - id: len_body
+        type: u1
+    instances:
+      body:
+        io: _root._io
+        pos: ofs_body
+        size: len_body
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.items[0].ofs_body.value, 6)
+        self.assertEqual(parsed.items[0].len_body.value, 3)
+
+        self.assertEqual(parsed.items[0].body.value, b'\x01\x02\x03')
+
+
+    def testSubstreamChoice(self):
+        """Choose a substream."""
+
+        # Cf. 5.5. Choosing a substream
+
+        content = MemoryContent(b'\xaa\xaa\xaa\xaa\x01\x02\x03\x04\x05\x06\x07\x08\x02\x03')
+
+        definitions = '''
+seq:
+  - id: global_header
+    size: 4
+  - id: block_one
+    type: big_container
+    size: 8
+  - id: block_two
+    type: smaller_container
+    size: 2
+types:
+  big_container:
+    seq:
+      - id: some_header
+        size: 8
+  smaller_container:
+    seq:
+      - id: ofs_in_big
+        type: u1
+      - id: len_in_big
+        type: u1
+    instances:
+      something_in_big:
+        io: _root.block_one._io
+        pos: ofs_in_big
+        size: len_in_big
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.block_two.ofs_in_big.value, 2)
+        self.assertEqual(parsed.block_two.len_in_big.value, 3)
+
+        self.assertEqual(parsed.block_two.something_in_big.value, b'\x03\x04\x05')
+
+
+    def __passed__testContentPreProcessing(self):
+        """Process content before parsing."""
+
+        # Cf. 5.6. Processing: dealing with compressed, obfuscated and encrypted data
+
+        pass
+
+
+
+    ##############################
+    ### 6. Expression language
+    ##############################
+
+
+    def testBasicDataTypes(self):
+        """Handle basic data types."""
+
+        # Cf. 6.1. Basic data types
+
+        definitions = '''
+seq:
+  - id: field1
+    type: u1
+  - id: field2
+    type: u2
+  - id: field4
+    type: u4
+  - id: field8
+    type: u8
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x02\x04\x04\x04\x04\x08\x08\x08\x08\x08\x08\x08\x08')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field1.range.length, 1)
+        self.assertEqual(parsed.field2.range.length, 2)
+        self.assertEqual(parsed.field4.range.length, 4)
+        self.assertEqual(parsed.field8.range.length, 8)
+
+        definitions = '''
+seq:
+  - id: field1
+    type: u1
+  - id: field4
+    type: u4le
+  - id: field4bis
+    type: u4be
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x03\x04\x05\x02\x03\x04\x05')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field1.value, 0x01)
+        self.assertEqual(parsed.field4.value, 0x05040302)
+        self.assertEqual(parsed.field4bis.value, 0x02030405)
+
+
+        definitions = '''
+instances:
+  number1:
+    value: 0xdead_cafe
+  number2:
+    value: 0xdead_cafe_dead_cafe
+  number3:
+    value: 12_345_678
+  number4:
+    value: 0b10100011
+  number5:
+    value: 0b1010_0011_1010_0011
+'''
+
+        content = MemoryContent(b'')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.number1.value, 0xdeadcafe)
+
+        self.assertEqual(parsed.number2.value, 0xdeadcafedeadcafe)
+
+        self.assertEqual(parsed.number3.value, 12345678)
+
+        self.assertEqual(parsed.number4.value, 0b10100011)
+
+        self.assertEqual(parsed.number5.value, 0b1010001110100011)
+
+
+        definitions = '''
+seq:
+  - id: op0
+    type: u1
+instances:
+  result:
+    value: 0xdeadcafe + op0
+  result2:
+    value: 0XdeadCAFE + op0
+'''
+
+        content = MemoryContent(b'\x00')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.result.value, 0xdeadcafe)
+
+        self.assertEqual(parsed.result2.value, 0xdeadcafe)
+
+
+        definitions = '''
+instances:
+  bytes1:
+    value: []
+  bytes2:
+    value: [ ]
+  bytes3:
+    value: [ 0x90 ]
+  bytes4:
+    value: [foo, 0, A, 0xa, 42]
+'''
+
+        content = MemoryContent(b'')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.bytes1.value, b'')
+
+        self.assertEqual(parsed.bytes2.value, b'')
+
+        self.assertEqual(parsed.bytes3.value, b'\x90')
+
+        self.assertEqual(parsed.bytes4.value, b'\x66\x6f\x6f\x00\x41\x0a\x2a')
+
+
+        definitions = '''
+instances:
+  escaped:
+    value: '[ "\\a\\b\\t\\n\\v\\f", "\\0", 0, " \\r\\e\\\"\\123" ]'
+'''
+
+        content = MemoryContent(b'')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.escaped.value, b'\x07\x08\x09\x0a\x0b\x0c\x00\x00 \x0d\x1b\x22\x53')
+
+
+        definitions_0 = r'''
+instances:
+  escaped:
+    value: "[ \"\\a\\b\\t\\n\\v\\f\", \"\\0\", 0, \"\\r\\e\\\"'\\123\" ]"
+'''
+
+        definitions_1 = r'''
+instances:
+  escaped:
+    value: [ "\\a\\b\\t\\n\\v\\f", "\\0", 0, "\\r\\e\\\"'\\123" ]
+'''
+
+        definitions_2 = '''
+instances:
+  escaped:
+    value: [ "\\\\a\\\\b\\\\t\\\\n\\\\v\\\\f", "\\\\0", 0, "\\\\r\\\\e\\\\\\"'\\\\123" ]
+'''
+
+        for d in [ definitions_0, definitions_1, definitions_2 ]:
+
+            content = MemoryContent(b'')
+
+            kstruct = KaitaiStruct(d)
+
+            parsed = kstruct.parse(content)
+
+            self.assertEqual(parsed.escaped.value, b'\x07\x08\x09\x0a\x0b\x0c\x00\x00\x0d\x1b\x22\x27\x53')
+
+
+    def __passed__testUserDefinedTypes(self):
+        """Create user-defined types."""
+
+        # Cf. 6.2.1. User-defined types
+
+        pass
+
+
+    def testArrays(self):
+        """Create various arrays."""
+
+        # Cf. 6.2.2. Arrays
+
+        definitions = '''
+instances:
+  result_0:
+    value: "[]"
+  result_1:
+    value: "[CAFE, 0, BABE]"
+  result_2:
+    value: "[CAFE, 0, BABE] == 'CAFE' + [ 0x00 ] + 'BABE'"
+  result_3:
+    value: "[CAFE, 0, BABE] == [ 0x43, 0x41, 0x46, 0x45, 0x00, 0x42, 0x41, 0x42, 0x45 ]"
+  result_4:
+    value: "[foo, 0, A, 0xa, 42] == [ 0x66, 0x6f, 0x6f, 0x00, 0x41, 0x0a, 0x2a ]"
+  result_5:
+    value: "[1, 0x55, '▒,3', 3] == [ 0x01, 0x55, 0xe2, 0x96, 0x92, 0x2c, 0x33, 0x03 ]"
+'''
+
+        content = MemoryContent(b'')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.result_0.value, b'')
+
+        self.assertEqual(parsed.result_1.value, b'CAFE\x00BABE')
+
+
+        definitions = '''
+seq:
+  - id: indexes
+    type: u1
+    repeat: eos
+instances:
+  table:
+    value: "[ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]"
+  ref:
+    value: indexes
+  result_0:
+    value: table
+  result_1:
+    value: ref
+  result_2:
+    value: table[indexes[0]][indexes[1] - 1]
+  result_3:
+    value: table[indexes[0]][ref[1]]
+'''
+
+        content = MemoryContent(b'\x01\x02\x03\x04')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.result_0.value.value, b'\x01\x02\x03\x04\x05\x06\x07\x08\x09')
+
+        self.assertEqual(type(parsed.result_1).__name__, 'RecordValue')            # result_1
+        self.assertEqual(type(parsed.result_1.value).__name__, 'RecordValue')      # result_1.ref
+        self.assertEqual(type(parsed.result_1.value.value).__name__, 'RecordList') # result_1.ref.table
+
+        self.assertEqual(parsed.result_1.value.value[3].value, 0x04)
+
+        self.assertEqual(parsed.result_2.value, 5)
+
+        self.assertEqual(parsed.result_3.value, 6)
+
+
+    def testArithmeticOperators(self):
+        """Compute with arithmetic operators."""
+
+        # Cf. 6.3.1. Arithmetic operators
+
+        definitions = '''
+seq:
+  - id: op0
+    type: u1
+  - id: op1
+    type: u1
+instances:
+  result_0:
+    value: op0 + op1 * 3
+  result_1:
+    value: (2 + op0) * op1
+  result_2:
+    value: 7 * 2.0
+  result_3:
+    value: 7 / 2.0
+  result_4:
+    value: -5 % 3
+  result_5:
+    value: 4 % 3
+  result_6:
+    value: 6 - 3 - -4.0
+'''
+
+        content = MemoryContent(b'\x02\x03\x04\x05')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.result_0.value, 11)
+
+        self.assertEqual(parsed.result_1.value, 12)
+
+        self.assertEqual(parsed.result_2.value, 14.0)
+
+        self.assertEqual(parsed.result_3.value, 3.5)
+
+        self.assertEqual(parsed.result_4.value, 1)
+
+        self.assertEqual(parsed.result_5.value, 1)
+
+        self.assertEqual(parsed.result_6.value, 7.0)
+
+
+        definitions = '''
+seq:
+  - id: base
+    size: 3
+instances:
+  result_0:
+    value: "'xXx ' + base + ' -- %< --'"
+'''
+
+        content = MemoryContent(b'ABC')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.result_0.value, b'xXx ABC -- %< --')
+
+
+        definitions = '''
+seq:
+  - id: nums
+    type: u1
+    repeat: eos
+instances:
+  computed:
+    value: nums[0] + nums[3]
+  computed2:
+    value: nums[0] * nums.size + nums[3]
+  computed3:
+    value: nums[0] * nums[nums.size - 1]
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x03\x04')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.computed.value, 5)
+
+        self.assertEqual(parsed.computed2.value, 8)
+
+        self.assertEqual(parsed.computed3.value, 4)
+
+
+    def testRelationalOperators(self):
+        """Compute with relational operators."""
+
+        # Cf. 6.3.2. Relational operators
+
+        definitions = '''
+seq:
+  - id: op0
+    type: u1
+  - id: op1
+    type: u1
+  - id: op2
+    size: 3
+instances:
+  result0:
+    value: op0 == op1
+  result1:
+    value: op0 != op1
+  result2:
+    value: op2 == 'ABC'
+  result3:
+    value: op2 < 'ABCD'
+  result4:
+    value: (op0 + 1) >= op1
+  result5:
+    value: "(op0 + 1) == 'ABC'.length"
+'''
+
+        content = MemoryContent(b'\x02\x03ABCD')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertFalse(parsed.result0.value)
+
+        self.assertTrue(parsed.result1.value)
+
+        self.assertTrue(parsed.result2.value)
+
+        self.assertTrue(parsed.result3.value)
+
+        self.assertTrue(parsed.result4.value)
+
+        self.assertTrue(parsed.result5.value)
+
+
+    def testBitwiseOperators(self):
+        """Compute with bitwise operators."""
+
+        # Cf. 6.3.3. Bitwise operators
+
+        definitions = '''
+seq:
+  - id: op0
+    type: u1
+  - id: op1
+    type: u1
+  - id: op2
+    type: u1
+instances:
+  result_0:
+    value: op0 & op1
+  result_1:
+    value: op1 << op0 >> 1
+  result_2:
+    value: (op2 | 0x80) >> 1
+'''
+
+        content = MemoryContent(b'\x02\x07\x01')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.result_0.value, 0x2)
+
+        self.assertEqual(parsed.result_1.value, 14)
+
+        self.assertEqual(parsed.result_2.value, 0x40)
+
+
+    def testLogicalOperators(self):
+        """Compute with logical boolean operators."""
+
+        # Cf. 6.3.4. Logical (boolean) operators
+
+        definitions = '''
+seq:
+  - id: op0
+    type: u1
+  - id: op1
+    type: u1
+instances:
+  result_0:
+    value: (op0 > 0) and not false
+  result_1:
+    value: op0 == 1 or op1 == 2
+'''
+
+        content = MemoryContent(b'\x01\x02')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertTrue(parsed.result_0.value)
+
+        self.assertTrue(parsed.result_1.value)
+
+
+    def testTernaryOperator(self):
+        """Offer challenges to the ternary operator."""
+
+        # Cf. 6.3.5. Ternary (if-then-else) operator
+
+        definitions = '''
+seq:
+  - id: op0
+    type: u1
+  - id: op1
+    type: u1
+  - id: op2
+    type: u1
+instances:
+  result_0:
+    value: 'op0 == 0x80 ? op1 + 1 : op1 * op2'
+  result_1:
+    value: 'op0 < 0x80 ? op1 + 1 : op1 * op2'
+  result_1:
+    value: 'op0 < 0x80 ? op1 + 1 : op1 * op2'
+  result_2:
+    value: '(op0 + 0x10) >= 0x90 ? true : 123'
+  result_3:
+    value: '(op0 + 0x10) >= 0x90 and false ? true : 123'
+'''
+
+        content = MemoryContent(b'\x80\x03\x04')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.result_0.value, 4)
+
+        self.assertEqual(parsed.result_1.value, 12)
+
+        self.assertTrue(parsed.result_2.value)
+
+        self.assertEqual(parsed.result_3.value, 123)
+
+
+    def testIntegersMethods(self):
+        """Run methods from integers."""
+
+        # Cf. 6.4.1. Integers
+
+        definitions = '''
+instances:
+  bytes1:
+    value: 123.to_s == "123" and -123.to_s == '-123'
+'''
+
+        content = MemoryContent(b'')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertTrue(parsed.bytes1.value)
+
+
+    def testFloatsMethods(self):
+        """Run methods from floating numbers."""
+
+        # Cf. 6.4.2. Floating point numbers
+
+        definitions = '''
+instances:
+  result_0:
+    value: 2.32.to_i == 2 and -7.0.to_i == -7
+'''
+
+        content = MemoryContent(b'')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertTrue(parsed.result_0.value)
+
+
+    def XXXtestByteArraysAndStringsMethods(self):
+        """Run methods from byte arrays and strings."""
+
+        # Cf. 6.4.3. Byte arrays
+        #     6.4.4. Strings
+
+        definitions = '''
+instances:
+  result_1:
+    value: '[].length == 0'
+  result_2:
+    value: "'edcba'.reverse == 'XXabcdeXX'.substring(2, 6)"
+  result_3:
+    value: "'123'.to_i == 123 and '-123'.to_i == -123"
+  result_4:
+    value: "[ 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x63, 0x69, 0xc3, 0xb3, 0x6e, 0x2e, 0x73, 0x78, 0x69 ].to_s('utf-8')"
+  result_5:
+    value: "'1010'.to_i(2) == 10 and 'cc'.to_i(16) == 204"
+'''
+
+        content = MemoryContent(b'')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertTrue(parsed.result_1.value)
+
+        self.assertTrue(parsed.result_2.value)
+
+        self.assertTrue(parsed.result_3.value)
+
+        # Cf. https://docs.gtk.org/glib/character-set.html
+        #     https://developer-old.gnome.org/glib/stable/glib-Character-Set-Conversion.html#g-convert
+        self.assertEqual(parsed.result_4.value.decode('utf-8'), 'Presentación.sxi')
+
+        self.assertTrue(parsed.result_5.value)
+
+
+    def __passed__testEnumsMethods(self):
+        """Run methods from booleans."""
+
+        # Cf. 6.4.5. Enums
+
+        pass
+
+
+    def testBooleansMethods(self):
+        """Run methods from booleans."""
+
+        # Cf. 6.4.6. Booleans
+
+        definitions = '''
+instances:
+  result_0:
+    value: true.to_i == 1
+  result_1:
+    value: (1 == 2).to_i == 0
+'''
+
+        content = MemoryContent(b'')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertTrue(parsed.result_0.value)
+
+        self.assertTrue(parsed.result_1.value)
+
+
+    def testUserDefinedTypes(self):
+        """Retrieve user-defined types."""
+
+        # Cf. 6.4.7. User-defined types
+
+        definitions = '''
+instances:
+  result_0:
+    value: _root
+'''
+
+        content = MemoryContent(b'')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.result_0.value, parsed)
+
+
+    def __passed__testArraysMethods(self):
+        """Run methods from arrays."""
+
+        # Cf. 6.4.8. Array types
+
+        pass
+
+
+    def __passed__testStreamsMethods(self):
+        """Run methods from streams."""
+
+        # Cf. 6.4.9. Streams
+
+        pass
+
+
+
+    ##############################
+    ### 7. Advanced techniques
+    ##############################
+
+
+    def testSwitchOverStrings(self):
+        """Switch over strings."""
+
+        # Cf. 7.1.1. Switching over strings
+
+        definitions = '''
+seq:
+  - id: rec_type
+    type: strz
+  - id: body
+    type:
+      switch-on: rec_type
+      cases:
+        '"KETCHUP"': rec_type_1
+        '"MUSTARD"': rec_type_2
+        '"GUACAMOLE"': rec_type_3
+types:
+  rec_type_1:
+    instances:
+      direct:
+        value: 1
+  rec_type_2:
+    instances:
+      direct:
+        value: 2
+  rec_type_3:
+    instances:
+      direct:
+        value: 3
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'GUACAMOLE\x00')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.rec_type.value, b'GUACAMOLE')
+
+        self.assertEqual(parsed.body.direct.value, 3)
+
+
+    def testSwitchOverEnums(self):
+        """Switch over enumerations."""
+
+        # Cf. 7.1.2. Switching over enums
+
+        definitions = '''
+seq:
+  - id: rec_type
+    type: u1
+    enum: media
+  - id: body
+    type:
+      switch-on: rec_type
+      cases:
+        'media::cdrom': rec_type_1
+        'media::dvdrom': rec_type_2
+        'media::cassette': rec_type_3
+types:
+  rec_type_1:
+    instances:
+      direct:
+        value: 1
+  rec_type_2:
+    instances:
+      direct:
+        value: 2
+  rec_type_3:
+    instances:
+      direct:
+        value: 3
+enums:
+  media:
+    1: cdrom
+    2: dvdrom
+    3: cassette
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.rec_type.value, 1)
+
+        self.assertEqual(parsed.body.direct.value, 1)
+
+
+    def testFourCC(self):
+        """Recognize four character code."""
+
+        # Cf. 7.1.3. FourCC
+
+        definitions = '''
+seq:
+  - id: fourcc
+    type: u4le
+    enum: pixel_formats
+  - id: len
+    type: u1
+  - id: body
+    size: len
+    type:
+      switch-on: fourcc
+      cases:
+        'pixel_formats::rgb2': block_rgb2
+        'pixel_formats::rle4': block_rle4
+        'pixel_formats::rle8': block_rle8
+types:
+  block_rgb2:
+    instances:
+      direct:
+        value: 2
+  block_rle4:
+    instances:
+      direct:
+        value: 4
+  block_rle8:
+    instances:
+      direct:
+        value: 8
+enums:
+  pixel_formats:
+    0x32424752: rgb2
+    0x34454C52: rle4
+    0x38454C52: rle8
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'RLE4\x05ABCDE')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.fourcc.value, 0x34454C52)
+
+        self.assertEqual(parsed.len.value, 0x5)
+
+        self.assertEqual(parsed.body.direct.value, 4)
+
+
+    def testNothing(self):
+        """Do nothing."""
+
+        # Cf. 7.2. Do nothing
+
+        definitions = '''
+seq:
+  - id: field_0
+    size: 1
+  - id: field_1
+    type: dummy_1
+  - id: field_2
+    type: dummy_2
+  - id: field_3
+    type: dummy_3
+  - id: field_4
+    type: dummy_4
+  - id: field_5
+    size: 1
+types:
+  # One can use empty JSON object syntax to avoid specifying any of
+  # `seq`, `instances`, etc, sections.
+  dummy_1: {}
+  # One can use explicit doc to note that there's nothing there.
+  dummy_2:
+    doc: This type is intentionally left blank.
+  # One can use empty `seq` or `instances` or `types` section, any
+  # other empty sections, or any combination of thereof.
+  dummy_3:
+    seq: []
+    instances: {}
+    types: {}
+  # One can use a very explicit notion of the fact that we want to parse 0 bytes.
+  dummy_4:
+    seq:
+      - id: no_value
+        size: 0
+'''
+
+        content = MemoryContent(b'az')
+
+        kstruct = KaitaiStruct(definitions)
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.field_0.value, b'a')
+
+        self.assertEqual(type(parsed.field_1).__name__, 'RecordEmpty')
+        self.assertEqual(parsed.field_1.range.length, 0)
+
+        self.assertEqual(type(parsed.field_2).__name__, 'RecordEmpty')
+        self.assertEqual(parsed.field_2.range.length, 0)
+
+        self.assertEqual(type(parsed.field_3).__name__, 'RecordEmpty')
+        self.assertEqual(parsed.field_3.range.length, 0)
+
+        self.assertEqual(type(parsed.field_4.no_value).__name__, 'RecordEmpty')
+        self.assertEqual(parsed.field_4.no_value.range.length, 0)
+
+        self.assertEqual(parsed.field_5.value, b'z')
+
+
+    def testConsumeIncludeTerminators(self):
+        """Consume and/or include terminators."""
+
+        # Cf. 7.3.1. Terminator: consume or include?
+
+        definitions = '''
+seq:
+  - id: str1
+    type: str
+    terminator: 0x2e # `.`
+  - id: str2
+    type: str
+    terminator: 0x2e # `.`
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'foo.bar.')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.str1.value, b'foo')
+
+        self.assertEqual(parsed.str2.value, b'bar')
+
+
+        definitions = '''
+seq:
+  - id: str1
+    type: str
+    terminator: 0x2e # `.`
+    include: true
+  - id: str2
+    type: str
+    terminator: 0x2e # `.`
+    eos-error: false
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'foo.bar')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.str1.value, b'foo.')
+
+        self.assertEqual(parsed.str2.value, b'bar')
+
+
+        definitions = '''
+seq:
+  - id: str1
+    type: str
+    terminator: 0x2e # `.`
+    consume: false
+  - id: the_rest
+    type: str
+    size-eos: true
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'foo.bar.')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.str1.value, b'foo')
+
+        self.assertEqual(parsed.the_rest.value, b'.bar.')
+
+
+        definitions = '''
+seq:
+  - id: str1
+    type: str
+    terminator: .
+  - id: the_rest
+    type: str
+    size-eos: true
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'foo.bar.')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.str1.value, b'foo')
+
+        self.assertEqual(parsed.the_rest.value, b'bar.')
+
+
+        definitions = '''
+seq:
+  - id: str1
+    type: str
+    terminator: xxx.
+  - id: the_rest
+    type: str
+    size-eos: true
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'fooxxx.bar.')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.str1.value, b'foo')
+
+        self.assertEqual(parsed.the_rest.value, b'bar.')
+
+
+    def testIgnoreErrorsInDelimitedStructures(self):
+        """Ignore errors in delimited structures."""
+
+        # Cf. 7.3.2. Ignoring errors in delimited structures
+
+        definitions = '''
+seq:
+  - id: my_string
+    type: str
+    terminator: 0
+    eos-error: false
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x61\x62\x63\x00\x64\x65\x66')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.my_string.value, b'abc')
+
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x61\x62\x63\x00')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.my_string.value, b'abc')
+
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x61\x62\x63')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.my_string.value, b'abc')
+
+
+    def __passed__testImportTypesFromOtherFiles(self):
+        """Import types from other files."""
+
+        # Cf. 7.4. Importing types from other files
+
+        pass
+
+
+    def __passed__testPlugExternalCodeForOpaqueTypes(self):
+        """Plug external code for opaque types."""
+
+        # Cf. 7.5. Opaque types: plugging in external code
+
+        pass
+
+
+    def __passed__testCustomProcessingRoutines(self):
+        """Handle custom processing routines."""
+
+        # Cf. 7.6. Custom processing routines
+
+        pass
+
+
+    def __passed__testParentTypeEnforcing(self):
+        """Enforce parent type."""
+
+        # Cf. 7.7. Enforcing parent type
+
+        pass
+
+
+    def testTypecasting(self):
+        """Ensure there is no need for typecasting."""
+
+        # Cf. 7.8. Typecasting
+
+        definitions = '''
+seq:
+  - id: num_sections
+    type: u1
+  - id: sections
+    type: section
+    repeat: expr
+    repeat-expr: num_sections
+types:
+  section:
+    seq:
+      - id: sect_type
+        type: u1
+      - id: body
+        type:
+          switch-on: sect_type
+          cases:
+            1: sect_header
+            2: sect_color_data
+  sect_header:
+    seq:
+      - id: width
+        type: u1
+      - id: height
+        type: u1
+  sect_color_data:
+    seq:
+      - id: rgb
+        size: 3
+instances:
+  check_0:
+    value: sections[0].body.width * sections[0].body.height
+  check_1:
+    value: sections[1].body.rgb
+  check_2:
+    value: sections[2].body.width * sections[2].body.height
+  check_3:
+    value: sections[3].body.rgb
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x04\x01\x02\x04\x02ABC\x01\x03\x05\x02UVW')
+
+        parsed = kstruct.parse(content)
+
+        # Vérifications externes
+
+        self.assertEqual(parsed.num_sections.value, 4)
+
+        self.assertEqual(len(parsed.sections), 4)
+
+        self.assertEqual(parsed.sections[0].body.width.value + parsed.sections[0].body.height.value, 6)
+
+        self.assertEqual(parsed.sections[1].body.rgb.value, b'ABC')
+
+        self.assertEqual(parsed.sections[2].body.width.value + parsed.sections[2].body.height.value, 8)
+
+        self.assertEqual(parsed.sections[3].body.rgb.value, b'UVW')
+
+        # Vérifications internes
+
+        self.assertEqual(parsed.check_0.value, 8)
+
+        self.assertEqual(parsed.check_1.value.value, b'ABC')
+
+        self.assertEqual(parsed.check_2.value, 15)
+
+        self.assertEqual(parsed.check_3.value.value, b'UVW')
+
+
+
+    ##########################
+    ### 8. Common pitfalls
+    ##########################
+
+
+    def testReadTypeWithSubstream(self):
+        """Read user-type with substream."""
+
+        # Cf. 8.1. Specifying size creates a substream
+
+        definitions = '''
+seq:
+  - id: header
+    size: 4
+  - id: block
+    type: block
+    size: 4 # <= important size designation, creates a substream
+instances:
+  byte_3:
+    pos: 3
+    type: u1
+types:
+  block:
+    instances:
+      byte_3:
+        pos: 3
+        type: u1
+      byte_3_alt:
+        io: _root._io # <= thanks to this, always points to a byte in main stream
+        pos: 3
+        type: u1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x00\x01\x02\x03\x04\x05\x06\x07')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.header.value, b'\x00\x01\x02\x03')
+
+        self.assertEqual(parsed.byte_3.value, 0x03)
+
+        self.assertEqual(parsed.block.byte_3.value, 0x07)
+
+        self.assertEqual(parsed.block.byte_3_alt.value, 0x03)
+
+
+        definitions = '''
+seq:
+  - id: header
+    size: 4
+  - id: block
+    type: block
+instances:
+  byte_3:
+    pos: 3
+    type: u1
+types:
+  block:
+    instances:
+      byte_3:
+        pos: 3
+        type: u1
+      byte_3_alt:
+        io: _root._io # <= thanks to this, always points to a byte in main stream
+        pos: 3
+        type: u1
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x00\x01\x02\x03\x04\x05\x06\x07')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.header.value, b'\x00\x01\x02\x03')
+
+        self.assertEqual(parsed.byte_3.value, 0x03)
+
+        self.assertEqual(parsed.block.byte_3.value, 0x03)
+
+        self.assertEqual(parsed.block.byte_3_alt.value, 0x03)
+
+
+    def testReadTypeWithoutSubstream(self):
+        """Read user-type without substream."""
+
+        # Cf. 8.2. Not specifying size does not create a substream
+
+        definitions = '''
+seq:
+  - id: header
+    size: 2
+  - id: block_as_type1
+    type: type1
+    size: 2 # <= important, creates a substream
+types:
+  type1:
+    seq:
+      - id: val1
+        size: 2
+  type2:
+    seq:
+      - id: val2
+        size: 2
+instances:
+  block_as_type2:
+    io: block_as_type1._io
+    pos: 0
+    type: type2
+  internal_check:
+    value: block_as_type2._io == _root._io
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'aabb')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.header.value, b'aa')
+
+        self.assertEqual(parsed.block_as_type1.val1.value, b'bb')
+
+        self.assertEqual(parsed.block_as_type2.val2.value, b'bb')
+
+        self.assertFalse(parsed.internal_check.value)
+
+
+        definitions = '''
+seq:
+  - id: header
+    size: 2
+  - id: block_as_type1
+    type: type1
+types:
+  type1:
+    seq:
+      - id: val1
+        size: 2
+  type2:
+    seq:
+      - id: val2
+        size: 2
+instances:
+  block_as_type2:
+    io: block_as_type1._io
+    pos: 0
+    type: type2
+  internal_check:
+    value: block_as_type2._io == _root._io
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'aabb')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.header.value, b'aa')
+
+        self.assertEqual(parsed.block_as_type1.val1.value, b'bb')
+
+        self.assertEqual(parsed.block_as_type2.val2.value, b'aa')
+
+        self.assertTrue(parsed.internal_check.value)
+
+
+    def __passed__testSizedProcess(self):
+        """Provide a sized data to processing."""
+
+        # Cf. 8.3. Applying process without a size
+
+        pass
+
+
+    def __passed__testRelatedKeys(self):
+        """Check refering keys and their related YAML nodes."""
+
+        # Cf. 8.4. Keys relating to the whole array and to each element in repeated attributes
+
+        pass
+
+
+
+    #######################
+    ### x. Extra checks
+    #######################
+
+
+    def testMssingField(self):
+        """Raise error on missing field."""
+
+        definitions = '''
+seq:
+  - id: field0
+    size-eos: true
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\x01\x02\x02\x03')
+
+        parsed = kstruct.parse(content)
+        self.assertIsNotNone(parsed)
+
+        self.assertEqual(parsed.field0.creator.raw_id, 'field0')
+
+        self.assertEqual(parsed.field0.value, b'\x01\x02\x02\x03')
+
+        # AttributeError: 'pychrysalide.plugins.kaitai.records.RecordList' object has no attribute 'xxxx'
+        with self.assertRaisesRegex(AttributeError, "object has no attribute 'xxxx'"):
+            print(parsed.xxxx)
+
+
+    def testLEB128Values(self):
+        """Read some Little Endian Base 128 values."""
+
+        definitions = '''
+seq:
+  - id: groups
+    type: group
+    repeat: until
+    repeat-until: not _.has_next
+types:
+  group:
+    -webide-representation: '{value}'
+    doc: |
+      One byte group, clearly divided into 7-bit "value" chunk and 1-bit "continuation" flag.
+    seq:
+      - id: b
+        type: u1
+    instances:
+      has_next:
+        value: (b & 0b1000_0000) != 0
+        doc: If true, then we have more bytes to read
+      value:
+        value: b & 0b0111_1111
+        doc: The 7-bit (base128) numeric value chunk of this group
+instances:
+  len:
+    value: groups.size
+  value:
+    value: >-
+      groups[0].value
+      + (len >= 2 ? (groups[1].value << 7) : 0)
+      + (len >= 3 ? (groups[2].value << 14) : 0)
+      + (len >= 4 ? (groups[3].value << 21) : 0)
+      + (len >= 5 ? (groups[4].value << 28) : 0)
+      + (len >= 6 ? (groups[5].value << 35) : 0)
+      + (len >= 7 ? (groups[6].value << 42) : 0)
+      + (len >= 8 ? (groups[7].value << 49) : 0)
+    doc: Resulting unsigned value as normal integer
+  sign_bit:
+    value: '1 << (7 * len - 1)'
+  value_signed:
+    value: '(value ^ sign_bit) - sign_bit'
+    doc-ref: https://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend
+'''
+
+        kstruct = KaitaiStruct(definitions)
+
+        content = MemoryContent(b'\xe5\x8e\x26')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.len.value, 3)
+
+        self.assertEqual(parsed.value.value, parsed.value_signed.value)
+
+        self.assertEqual(parsed.value.value, 624485)
+
+
+        content = MemoryContent(b'\xc0\xbb\x78')
+
+        parsed = kstruct.parse(content)
+
+        self.assertEqual(parsed.len.value, 3)
+
+        self.assertNotEqual(parsed.value.value, parsed.value_signed.value)
+
+        self.assertEqual(parsed.value_signed.value, -123456)
-- 
cgit v0.11.2-87-g4458