From 7c6fe94c90d320813d0d78a9dbef707696f31505 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 10 Oct 2023 00:49:59 +0200
Subject: Support some last missing features from Kaitai: bit fields, instance
 search order and stream EOF.

---
 plugins/kaitai/grammar.y                  |  53 ++++-
 plugins/kaitai/import.c                   |   2 +-
 plugins/kaitai/import.h                   |   2 +-
 plugins/kaitai/parser-int.h               |   2 +-
 plugins/kaitai/parser.c                   |  15 +-
 plugins/kaitai/parser.h                   |   2 +-
 plugins/kaitai/parsers/attribute-int.h    |   3 +
 plugins/kaitai/parsers/attribute.c        | 206 ++++++++++++++---
 plugins/kaitai/parsers/attribute.h        |  20 +-
 plugins/kaitai/parsers/instance.c         | 149 +++++++------
 plugins/kaitai/parsers/instance.h         |   3 +
 plugins/kaitai/parsers/struct.c           |  45 +++-
 plugins/kaitai/parsers/switch.c           | 112 +++-------
 plugins/kaitai/python/records/Makefile.am |   5 +-
 plugins/kaitai/python/records/bits.c      | 318 +++++++++++++++++++++++++++
 plugins/kaitai/python/records/bits.h      |  45 ++++
 plugins/kaitai/python/records/delayed.c   | 341 +++++++++++++++++++++++++++++
 plugins/kaitai/python/records/delayed.h   |  45 ++++
 plugins/kaitai/python/records/module.c    |   6 +-
 plugins/kaitai/python/records/value.c     | 335 ----------------------------
 plugins/kaitai/python/records/value.h     |  45 ----
 plugins/kaitai/record.c                   |   4 +
 plugins/kaitai/records/Makefile.am        |   8 +-
 plugins/kaitai/records/bits-int.h         |  59 +++++
 plugins/kaitai/records/bits.c             | 283 ++++++++++++++++++++++++
 plugins/kaitai/records/bits.h             |  62 ++++++
 plugins/kaitai/records/delayed-int.h      |  60 +++++
 plugins/kaitai/records/delayed.c          | 352 ++++++++++++++++++++++++++++++
 plugins/kaitai/records/delayed.h          |  65 ++++++
 plugins/kaitai/records/value-int.h        |  57 -----
 plugins/kaitai/records/value.c            | 336 ----------------------------
 plugins/kaitai/records/value.h            |  65 ------
 plugins/kaitai/rost/browser.c             |  14 +-
 plugins/kaitai/tokens.l                   |   2 +
 src/analysis/content.c                    |  88 ++++++++
 src/analysis/content.h                    |   3 +
 src/arch/vmpa.h                           |  56 +++++
 tests/plugins/kaitai/language.py          |   4 +-
 tests/plugins/kaitai/rost.py              |   2 +-
 39 files changed, 2213 insertions(+), 1061 deletions(-)
 create mode 100644 plugins/kaitai/python/records/bits.c
 create mode 100644 plugins/kaitai/python/records/bits.h
 create mode 100644 plugins/kaitai/python/records/delayed.c
 create mode 100644 plugins/kaitai/python/records/delayed.h
 delete mode 100644 plugins/kaitai/python/records/value.c
 delete mode 100644 plugins/kaitai/python/records/value.h
 create mode 100644 plugins/kaitai/records/bits-int.h
 create mode 100644 plugins/kaitai/records/bits.c
 create mode 100644 plugins/kaitai/records/bits.h
 create mode 100644 plugins/kaitai/records/delayed-int.h
 create mode 100644 plugins/kaitai/records/delayed.c
 create mode 100644 plugins/kaitai/records/delayed.h
 delete mode 100644 plugins/kaitai/records/value-int.h
 delete mode 100644 plugins/kaitai/records/value.c
 delete mode 100644 plugins/kaitai/records/value.h

diff --git a/plugins/kaitai/grammar.y b/plugins/kaitai/grammar.y
index 2f2b820..9745dc8 100644
--- a/plugins/kaitai/grammar.y
+++ b/plugins/kaitai/grammar.y
@@ -31,9 +31,10 @@ typedef void *yyscan_t;
 
 #include "expression.h"
 #include "record.h"
+#include "records/bits.h"
+#include "records/delayed.h"
 #include "records/item.h"
 #include "records/list.h"
-#include "records/value.h"
 
 }
 
@@ -580,7 +581,9 @@ YY_DECL;
 %token ROOT             "_root"
 %token PARENT           "_parent"
 %token LAST             "_"
+%token IO               "_io"
 %token METH_IO          "._io"
+%token IO_EOF           ".eof"
 
 %token TRUE_CONST       "true"
 %token FALSE_CONST      "false"
@@ -622,6 +625,7 @@ YY_DECL;
 %type <value> field
 %type <value> enumeration
 %type <value> stream
+%type <value> stream_meths
 
 
 
@@ -714,6 +718,7 @@ YY_DECL;
                     | field             { $$ = $1; }
                     | enumeration       { $$ = $1; }
                     | stream            { $$ = $1; }
+                    | stream_meths      { $$ = $1; }
                     | arithmetic_expr   { $$ = $1; }
                     | relational_expr   { $$ = $1; }
                     | logical_expr      { $$ = $1; }
@@ -1487,7 +1492,35 @@ YY_DECL;
                     }
 
 
-             stream : any_expr "._io"
+             stream : "_io"
+                    {
+                        GBinContent *__content;
+                        mrange_t __range;
+                        vmpa2t __next;
+
+                        if (locals->last == NULL)
+                        {
+                            __content = g_match_record_get_content(locals->root);
+
+                            g_binary_content_compute_start_pos(__content, &__next);
+
+                        }
+                        else
+                        {
+                            __content = g_match_record_get_content(locals->last);
+
+                            g_match_record_get_range(locals->last, &__range);
+                            compute_mrange_end_addr(&__range, &__next);
+
+                        }
+
+                        $$.stream = g_kaitai_stream_new(__content, &__next);
+                        $$.type = GVT_STREAM;
+
+                        g_object_unref(G_OBJECT(__content));
+
+                    }
+                    | any_expr "._io"
                     {
                         GBinContent *__content;
                         mrange_t __range;
@@ -1508,6 +1541,15 @@ YY_DECL;
                     }
                     ;
 
+       stream_meths : stream ".eof"
+                    {
+                        $$.status = g_kaitai_stream_has_reached_eof($1.stream);;
+                        $$.type = GVT_BOOLEAN;
+
+                        EXIT_RESOLVED_VALUE($1);
+
+                    }
+                    ;
 
 %%
 
@@ -1656,8 +1698,11 @@ static bool reduce_resolved_kaitai_expression(resolved_value_t *in_out)
 
     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);
+        if (G_IS_RECORD_BIT_FIELD(in_out->record))
+            result = g_record_bit_field_get_value(G_RECORD_BIT_FIELD(in_out->record), &deeper);
+
+        else if (G_IS_RECORD_DELAYED(in_out->record))
+            result = g_record_delayed_compute_value(G_RECORD_DELAYED(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);
diff --git a/plugins/kaitai/import.c b/plugins/kaitai/import.c
index f645eae..88cd03a 100644
--- a/plugins/kaitai/import.c
+++ b/plugins/kaitai/import.c
@@ -170,7 +170,7 @@ static GKaitaiStruct *load_relative_kaitai_definition(const char *target, const
 *                                                                             *
 ******************************************************************************/
 
-GKaitaiStruct *load_relative_kaitai_definition(const char *target, const char *reference)
+GKaitaiStruct *load_kaitai_definition(const char *target, const char *reference)
 {
     GKaitaiStruct *result;                  /* Structure chargée à renvoyer*/
 
diff --git a/plugins/kaitai/import.h b/plugins/kaitai/import.h
index 12fde07..66a0f5a 100644
--- a/plugins/kaitai/import.h
+++ b/plugins/kaitai/import.h
@@ -34,7 +34,7 @@
 GKaitaiType *import_kaitai_definition(const char *, const char *);
 
 /* Met en place un interpréteur pour une définition désignée. */
-GKaitaiStruct *load_relative_kaitai_definition(const char *, const char *);
+GKaitaiStruct *load_kaitai_definition(const char *, const char *);
 
 
 
diff --git a/plugins/kaitai/parser-int.h b/plugins/kaitai/parser-int.h
index 4ddb0f9..8bac523 100644
--- a/plugins/kaitai/parser-int.h
+++ b/plugins/kaitai/parser-int.h
@@ -30,7 +30,7 @@
 
 
 /* Parcourt un contenu binaire selon des spécifications Kaitai. */
-typedef bool (* parse_kaitai_fc) (GKaitaiParser *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+typedef bool (* parse_kaitai_fc) (GKaitaiParser *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
 
 
 
diff --git a/plugins/kaitai/parser.c b/plugins/kaitai/parser.c
index 77c15b3..cfe1aa1 100644
--- a/plugins/kaitai/parser.c
+++ b/plugins/kaitai/parser.c
@@ -24,6 +24,9 @@
 #include "parser.h"
 
 
+#include <assert.h>
+
+
 #include "parser-int.h"
 
 
@@ -131,7 +134,7 @@ static void g_kaitai_parser_finalize(GKaitaiParser *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]                    *
+*                epos    = 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. *
@@ -142,18 +145,22 @@ static void g_kaitai_parser_finalize(GKaitaiParser *parser)
 *                                                                             *
 ******************************************************************************/
 
-bool g_kaitai_parser_parse_content(GKaitaiParser *parser, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+bool g_kaitai_parser_parse_content(GKaitaiParser *parser, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
 {
     bool result;                            /* Bilan à retourner           */
     GKaitaiParserClass *class;              /* Classe de l'instance        */
 
+    *record = NULL;
+
     class = G_KAITAI_PARSER_GET_CLASS(parser);
 
-    result = class->parse(parser, locals, content, pos, record);
+    result = class->parse(parser, locals, content, epos, record);
 
-    if (result)
+    if (result && *record != NULL)
         remember_last_record(locals, *record);
 
+    assert((!result && *record == NULL) || result);
+
     return result;
 
 }
diff --git a/plugins/kaitai/parser.h b/plugins/kaitai/parser.h
index 4c17087..64d759d 100644
--- a/plugins/kaitai/parser.h
+++ b/plugins/kaitai/parser.h
@@ -56,7 +56,7 @@ typedef struct _GKaitaiParserClass GKaitaiParserClass;
 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 **);
+bool g_kaitai_parser_parse_content(GKaitaiParser *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
 
 
 
diff --git a/plugins/kaitai/parsers/attribute-int.h b/plugins/kaitai/parsers/attribute-int.h
index ef64089..7d37af3 100644
--- a/plugins/kaitai/parsers/attribute-int.h
+++ b/plugins/kaitai/parsers/attribute-int.h
@@ -51,6 +51,9 @@ struct _GKaitaiAttribute
         /* KAP_FIXED_CONTENT */
         sized_string_t fixed_content;       /* Données brutes attendues    */
 
+        /* KAP_BIT_FIELD_TYPE */
+        uint8_t bf_size;                    /* Nombre de bits visés        */
+
         /* KAP_BASIC_TYPE */
         struct
         {
diff --git a/plugins/kaitai/parsers/attribute.c b/plugins/kaitai/parsers/attribute.c
index 58d8dd1..d0505d8 100644
--- a/plugins/kaitai/parsers/attribute.c
+++ b/plugins/kaitai/parsers/attribute.c
@@ -25,6 +25,7 @@
 
 
 #include <assert.h>
+#include <stdlib.h>
 #include <string.h>
 
 
@@ -35,6 +36,7 @@
 #include "attribute-int.h"
 #include "../expression.h"
 #include "../scope.h"
+#include "../records/bits.h"
 #include "../records/empty.h"
 #include "../records/item.h"
 #include "../records/list.h"
@@ -56,6 +58,9 @@ 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 champ de bits une chaîne de caractères. */
+static bool g_kaitai_attribute_resolve_bit_field(GKaitaiAttribute *, const char *);
+
 /* Traduit en type concret une chaîne de caractères. */
 static bool g_kaitai_attribute_resolve_type(GKaitaiAttribute *, const char *);
 
@@ -71,7 +76,7 @@ static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *);
 
 
 /* Parcourt un contenu binaire selon des spécifications Kaitai. */
-static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, 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 **);
@@ -80,7 +85,7 @@ static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *, const
 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 **);
+static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
 
 
 
@@ -399,7 +404,10 @@ bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool
 
         if (value != NULL)
         {
-            if (g_kaitai_attribute_resolve_type(attrib, value))
+            if (g_kaitai_attribute_resolve_bit_field(attrib, value))
+                attrib->payload |= KAP_BIT_FIELD_TYPE;
+
+            else if (g_kaitai_attribute_resolve_type(attrib, value))
                 attrib->payload |= KAP_BASIC_TYPE;
 
             else
@@ -701,6 +709,54 @@ bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool
 *  Paramètres  : attrib = attribut Kaitai en cours de constitution.           *
 *                desc   = chaîne de caractère à interpréter en type.          *
 *                                                                             *
+*  Description : Traduit en champ de bits une chaîne de caractères.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_kaitai_attribute_resolve_bit_field(GKaitaiAttribute *attrib, const char *desc)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t len;                             /* Taille de la chaîne à lire  */
+    char *end;                              /* Prochain caractère à lire   */
+    unsigned long size;                     /* Taille du champ de bits     */
+
+    result = false;
+
+    if (desc[0] == 'b')
+    {
+        len = strlen(desc);
+
+        size = strtoul(&desc[1], &end, 10);
+
+        if (size > 64)
+        {
+            printf("Unsupported size for bit field: %lu\n", size);
+            goto exit;
+        }
+
+        result = ((desc + len) == end);
+
+        if (result)
+            attrib->bf_size = size;
+
+    }
+
+ exit:
+
+    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.                                        *
@@ -930,7 +986,7 @@ static bool g_kaitai_attribute_check(const GKaitaiAttribute *attrib)
     }
 
     /**
-     * Si une séquence d'octets finaux est spécifiées, alors l'attribut
+     * Si une séquence d'octets finaux est spécifiée, alors l'attribut
      * doit correspondre à un type str[z] (lecture) ou de taille fixée
      * (validation post-lecture).
      */
@@ -1429,6 +1485,50 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = lecteur d'attribut Kaitai à consulter.             *
+*                content = contenu binaire à venir lire.                      *
+*                epos    = tête de lecture avec granularité en bits.          *
+*                size    = quantité de bits à prendre en compte.              *
+*                endian  = boustime des données à respecter.                  *
+*                out     = valeur à sauvegarder sous une forme générique.[OUT]*
+*                                                                             *
+*  Description : Lit la valeur d'un champ de bits Kaitai représenté.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_kaitai_attribute_read_bit_field_value(const GKaitaiAttribute *attrib, const GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à retourner           */
+    ext_vmpa_t tmpepos;                     /* Localisation modifiable     */
+    uint64_t tmp64;                         /* Valeur de 64 bits lue       */
+
+    result = false;
+
+    if (attrib->payload & KAP_BIT_FIELD_TYPE)
+    {
+        copy_evmpa(&tmpepos, epos);
+
+        result = g_binary_content_read_bits(content, &tmpepos, size, endian, &tmp64);
+
+        if (result)
+        {
+            out->type = GVT_UNSIGNED_INTEGER;
+            out->unsigned_integer = tmp64;
+        }
+
+    }
+
+    return result;
+
+}
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
@@ -1440,7 +1540,7 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon
 *  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]                    *
+*                epos    = 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. *
@@ -1451,7 +1551,7 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon
 *                                                                             *
 ******************************************************************************/
 
-static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
 {
     bool result;                            /* Bilan à retourner           */
     resolved_value_t authorized;            /* Validation des traitements  */
@@ -1483,6 +1583,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
     result = false;
     *record = NULL;
 
+    printf("\n");
+    printf("------------parsing %s -( payload: %x - ut=%d )-----------\n",
+           attrib->raw_id, attrib->payload, attrib->payload & KAP_USER_TYPE);
+
     /* Lecture soumise à condition ? */
 
     if (attrib->condition != NULL)
@@ -1492,6 +1596,8 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
                                                       strlen(attrib->condition),
                                                       &authorized);
 
+        printf("condition '%s': res=%d  auth=%d\n", attrib->condition, result, authorized.status);
+
         if (!result || !authorized.status)
             goto exit;
 
@@ -1500,7 +1606,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
     /* Zone de travail restreinte */
 
     g_binary_content_compute_end_pos(content, &tmp);
-    diff = compute_vmpa_diff(pos, &tmp);
+    diff = compute_vmpa_diff(&epos->base, &tmp);
+
+    if (epos->consumed_extra_bits > 0 && diff > 0)
+        diff--;
 
     if (attrib->payload & KAP_SIZED)
     {
@@ -1538,7 +1647,9 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
         if (!result)
             goto exit;
 
-        init_mrange(&work_range, pos, diff);
+        align_evmpa_on_byte(epos);
+
+        init_mrange(&work_range, &epos->base, diff);
         work_area = g_restricted_content_new(content, &work_range);
 
         has_empty_size = (diff == 0);
@@ -1553,16 +1664,24 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
     /* Etablissement d'une zone de correspondance */
 
     if (attrib->payload == KAP_UNINITIALIZED)
-        assert(false);
+    {
+        printf("attrib: '%s'\n", attrib->raw_id);
+        //assert(false);
+    }
 
     else if (attrib->payload & KAP_SIZED_EOS)
+    {
+        align_evmpa_on_byte(epos);
         result = true;
+    }
 
     else if (attrib->payload & KAP_FIXED_CONTENT)
     {
         if (diff >= attrib->fixed_content.len)
         {
-            copy_vmpa(&tmp, pos);
+            align_evmpa_on_byte(epos);
+
+            copy_vmpa(&tmp, &epos->base);
 
             data = g_binary_content_get_raw_access(work_area, &tmp, attrib->fixed_content.len);
             assert(data != NULL);
@@ -1576,8 +1695,26 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
 
     }
 
+    else if (attrib->payload & KAP_BIT_FIELD_TYPE)
+    {
+        if (attrib->has_endian)
+            endian = attrib->endian;
+        else
+            endian = g_kaitai_meta_get_endian(locals->meta);
+
+        *record = g_record_bit_field_new(attrib, work_area, epos, attrib->bf_size, endian);
+
+        result = (*record != NULL);
+
+        if (result)
+            advance_evmpa_bits(epos, attrib->bf_size);
+
+    }
+
     else if (attrib->payload & KAP_BASIC_TYPE)
     {
+        align_evmpa_on_byte(epos);
+
         switch (attrib->basic)
         {
             case BTP_CHAR:
@@ -1585,7 +1722,8 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
                 if (attrib->is_string)
                 {
                     if ((attrib->payload & KAP_SIZED) == 0)
-                        result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals, work_area, pos, record);
+                        result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals,
+                                                                           work_area, &epos->base, record);
                 }
                 else
                 {
@@ -1625,10 +1763,13 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
     {
         user_type = find_sub_type(locals, attrib->named_type);
 
+        printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> find '%s' => %p\n",
+               attrib->named_type, user_type);
+
         if (user_type != NULL)
         {
             result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(user_type),
-                                                   locals, work_area, pos, record);       
+                                                   locals, work_area, epos, record);
 
             if (result)
                 /**
@@ -1648,7 +1789,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
     }
 
     else if (attrib->payload & KAP_DYNAMIC_TYPE)
-        result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, pos, record);
+        result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, epos, record);
 
     else if (attrib->payload & KAP_SIZED)
     {
@@ -1661,6 +1802,11 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
     if (result && *record == NULL)
     {
         /**
+         * A ce stade, la granularité des travaux est l'octet.
+         */
+        assert(epos->consumed_extra_bits == 0);
+
+        /**
          * On choisit de laisser la création de correspondances nulles.
          *
          * Cela permet de disposer de la présence de champs valides, même vides
@@ -1669,12 +1815,13 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
 
         /* if (diff > 0) */
         {
-            result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content, pos, &diff, &range);
+            result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content,
+                                                                       &epos->base, &diff, &range);
 
             if (result)
             {
                 if (has_empty_size)
-                    *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, pos));
+                    *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, &epos->base));
 
                 else
                 {
@@ -1686,7 +1833,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
                     *record = G_MATCH_RECORD(g_record_item_new(attrib, work_area, &range, endian));
 
                     if (*record != NULL)
-                        advance_vmpa(pos, diff);
+                        advance_vmpa(&epos->base, diff);
                     else
                         result = false;
 
@@ -1702,13 +1849,16 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
 
     if (attrib->payload & KAP_SIZED)
     {
-        cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), pos);
+        /* Réalignement éventuel suite aux lectures dans la zone périmétrée... */
+        align_evmpa_on_byte(epos);
+
+        cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), &epos->base);
 
         /* Pour GCC... */
         max_size = get_mrange_length(&work_range);
 
         if (cur_diff < max_size)
-            advance_vmpa(pos, max_size - cur_diff);
+            advance_vmpa(&epos->base, max_size - cur_diff);
 
         assert(work_area != content);
         g_object_unref(G_OBJECT(work_area));
@@ -1717,6 +1867,8 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
 
  exit:
 
+    printf(" ===[[ %s / %p ]]===  >>  %d\n", attrib->raw_id, attrib, result);
+
     return result;
 
 }
@@ -1933,7 +2085,7 @@ static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttri
 *  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]                    *
+*                epos    = 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. *
@@ -1944,7 +2096,7 @@ static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttri
 *                                                                             *
 ******************************************************************************/
 
-static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
 {
     bool result;                            /* Bilan à retourner           */
     resolved_value_t authorized;            /* Validation des traitements  */
@@ -1958,7 +2110,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc
     resolved_value_t loop;                  /* Poursuite des lectures ?    */
 
     if (attrib->repetition == KAR_NO_REPETITION)
-        result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, record);
+        result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, record);
 
     else
     {
@@ -1976,7 +2128,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc
 
         }
 
-        list = g_record_list_new(attrib, content, pos);
+        list = g_record_list_new(attrib, content, &epos->base);
 
         switch (attrib->repetition)
         {
@@ -1985,17 +2137,17 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc
                 result = true;
 
                 g_binary_content_compute_end_pos(content, &end);
-                diff = compute_vmpa_diff(pos, &end);
+                diff = compute_vmpa_diff(&epos->base, &end);
 
                 while (diff > 0)
                 {
-                    result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child);
+                    result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child);
                     if (!result) break;
 
                     g_record_list_add_record(list, child);
                     remember_last_record(locals, child);
 
-                    diff = compute_vmpa_diff(pos, &end);
+                    diff = compute_vmpa_diff(&epos->base, &end);
 
                 }
 
@@ -2026,7 +2178,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc
 
                 for (i = 0; i < count; i++)
                 {
-                    result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child);
+                    result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child);
                     if (!result) break;
 
                     g_record_list_add_record(list, child);
@@ -2040,7 +2192,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc
 
                 do
                 {
-                    result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child);
+                    result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child);
                     if (!result) break;
 
                     g_record_list_add_record(list, child);
diff --git a/plugins/kaitai/parsers/attribute.h b/plugins/kaitai/parsers/attribute.h
index 38b78d7..9b43936 100644
--- a/plugins/kaitai/parsers/attribute.h
+++ b/plugins/kaitai/parsers/attribute.h
@@ -56,18 +56,19 @@ typedef struct _GKaitaiAttributeClass GKaitaiAttributeClass;
 /* Type de charge associée à un attribut */
 typedef enum _KaitaiAttributePayload
 {
-    KAP_UNINITIALIZED = (0 << 0),           /* Type non initialisé         */
+    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              */
+    KAP_FIXED_CONTENT  = (1 << 0),          /* Contenu brut attendu        */
+    KAP_BIT_FIELD_TYPE = (1 << 1),          /* Champ d'un ou plusieurs bits*/
+    KAP_BASIC_TYPE     = (1 << 2),          /* Type prédéfini              */
+    KAP_USER_TYPE      = (1 << 3),          /* Type personnalisé           */
+    KAP_DYNAMIC_TYPE   = (1 << 4),          /* Type dynmatique             */
+    KAP_SIZED          = (1 << 5),          /* Bourrage dimensionné        */
+    KAP_SIZED_EOS      = (1 << 6),          /* Bourrage final              */
 
 } KaitaiAttributePayload;
 
-/* Types de base reconnus par Kaitai */
+/* Types de base reconnus par Kaitai */ /* TODO : REMME ? (car non utilisé) */
 typedef enum _KaitaiBasicType
 {
     KBT_U1,                                 /* Octet non signé             */
@@ -149,6 +150,9 @@ 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 *);
 
+/* Lit la valeur d'un champ de bits Kaitai représenté. */
+bool g_kaitai_attribute_read_bit_field_value(const GKaitaiAttribute *, const GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian, resolved_value_t *);
+
 
 
 #endif  /* _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_H */
diff --git a/plugins/kaitai/parsers/instance.c b/plugins/kaitai/parsers/instance.c
index 63db224..d62c1f6 100644
--- a/plugins/kaitai/parsers/instance.c
+++ b/plugins/kaitai/parsers/instance.c
@@ -34,7 +34,7 @@
 
 #include "instance-int.h"
 #include "../expression.h"
-#include "../records/value.h"
+#include "../records/delayed.h"
 
 
 
@@ -59,7 +59,7 @@ static void g_kaitai_instance_finalize(GKaitaiInstance *);
 
 
 /* Parcourt un contenu binaire selon des spécifications Kaitai. */
-static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
 
 
 
@@ -349,74 +349,30 @@ const char *g_kaitai_instance_get_name(const GKaitaiInstance *inst)
 *                                                                             *
 *  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]*
+*                content = contenu binaire lié à la correspondance.           *
 *                                                                             *
-*  Description : Détermine la valeur d'un élément Kaitai entier calculé.      *
+*  Description : Détermine la valeur effective d'un élément Kaitai dynamique. *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : valeur à sauvegarder sous une forme générique.               *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool g_kaitai_instance_compute_value(const GKaitaiInstance *inst, const kaitai_scope_t *locals, resolved_value_t *value)
+GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content)
 {
-    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           */
+    GMatchRecord *result;                   /* Enregistrement à retourner  */
     GBinContent *work_area;                 /* Aire de travail             */
     GKaitaiStream *stream;                  /* Flux de données pour Kaitai */
-    resolved_value_t offset;                /* Position à adopter          */
+    bool status;                            /* Bilan intermédiaire         */
     vmpa2t forced_pos;                      /* Tete de lecture constituée  */
+    resolved_value_t offset;                /* Position à adopter          */
     GKaitaiParserClass *class;              /* Classe parente à solliciter */
+    ext_vmpa_t epos;                        /* Tête de lecture complète    */
 
-    if (inst->value != NULL)
-    {
-        *record = G_MATCH_RECORD(g_record_value_new(inst, locals));
+    result = NULL;
 
-        result = (*record != NULL);
-
-    }
-
-    else
+    if (inst->value == NULL)
     {
         /* Contenu particulier */
 
@@ -425,8 +381,8 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_
 
         else
         {
-            result = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream);
-            if (!result) goto exit;
+            status = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream);
+            if (!status) goto exit;
 
             work_area = g_kaitai_stream_get_content(stream);
 
@@ -438,8 +394,8 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_
 
         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;
+        status = resolve_kaitai_expression_as_integer(locals, inst->pos, strlen(inst->pos), &offset);
+        if (!status) goto exit_with_content;
 
         if (offset.type == GVT_UNSIGNED_INTEGER)
             advance_vmpa(&forced_pos, offset.unsigned_integer);
@@ -450,7 +406,7 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_
 
             if (offset.signed_integer < 0)
             {
-                result = false;
+                status = false;
                 goto exit_with_content;
             }
 
@@ -462,7 +418,9 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_
 
         class = G_KAITAI_PARSER_CLASS(g_kaitai_instance_parent_class);
 
-        result = class->parse(G_KAITAI_PARSER(inst), locals, work_area, &forced_pos, record);
+        init_evmpa_from_vmpa(&epos, &forced_pos);
+
+        class->parse(G_KAITAI_PARSER(inst), locals, work_area, &epos, &result);
 
  exit_with_content:
 
@@ -476,3 +434,70 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_
     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.           *
+*                epos    = 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, ext_vmpa_t *epos, GMatchRecord **record)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    *record = G_MATCH_RECORD(g_record_delayed_new(inst, locals, inst->value == NULL ? content : NULL));
+
+    result = (*record != NULL);
+
+    return result;
+
+}
diff --git a/plugins/kaitai/parsers/instance.h b/plugins/kaitai/parsers/instance.h
index a9aee9a..4594137 100644
--- a/plugins/kaitai/parsers/instance.h
+++ b/plugins/kaitai/parsers/instance.h
@@ -60,6 +60,9 @@ 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 effective d'un élément Kaitai dynamique. */
+GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *, const kaitai_scope_t *, GBinContent *);
+
 /* 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 *);
 
diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c
index f23a264..62dc25a 100644
--- a/plugins/kaitai/parsers/struct.c
+++ b/plugins/kaitai/parsers/struct.c
@@ -64,7 +64,7 @@ static bool g_kaitai_structure_load_imports(GKaitaiStruct *);
 
 
 /* Parcourt un contenu binaire selon des spécifications Kaitai. */
-static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
 
 
 
@@ -712,13 +712,17 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont
     GMatchRecord *result;                   /* Arborescence à retourner    */ 
     vmpa2t pos;                             /* Tête de lecture             */
     kaitai_scope_t locals;                  /* Variables locales           */
-    bool status;                            /* Bilan de l'analyse          */
+    ext_vmpa_t epos;                        /* Tête de lecture complète    */
 
     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);
+    init_evmpa_from_vmpa(&epos, &pos);
+
+    g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &epos, &result);
+
+    printf("FINAL STATUS :: %d\n", result != NULL);
 
     return result;
 
@@ -736,7 +740,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont
 *  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]                    *
+*                epos    = 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. *
@@ -747,7 +751,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont
 *                                                                             *
 ******************************************************************************/
 
-static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
 {
     bool result;                            /* Bilan à retourner           */
     GRecordGroup *group;                    /* Ensemble à constituer       */
@@ -760,7 +764,7 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
     /* 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));
+        *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, &epos->base));
 
         if (locals->root == NULL)
             locals->root = *record;
@@ -779,10 +783,18 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
         old = locals->parent;
         locals->parent = *record;
 
-        for (i = 0; i < kstruct->seq_items_count; i++)
+        /**
+         * Les instances sont à charger avant les éléments fixes car
+         * des références au premières peuvent être attendues dans ces derniers.
+         *
+         * Les évolutions de la tête de lecture n'ont en revanche normalement
+         * pas d'incidence sur le chargement des éléments fixes.
+         */
+
+        for (i = 0; i < kstruct->instances_count; i++)
         {
-            result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]),
-                                                   locals, content, pos, &child);
+            result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]),
+                                                   locals, content, epos, &child);
             if (!result) goto exit;
 
             if (child != NULL)
@@ -793,10 +805,16 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
 
         }
 
-        for (i = 0; i < kstruct->instances_count; i++)
+        /**
+         * Seconde phase.
+         */
+
+        locals->parent = *record;
+
+        for (i = 0; i < kstruct->seq_items_count; i++)
         {
-            result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]),
-                                                   locals, content, pos, &child);
+            result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]),
+                                                   locals, content, epos, &child);
             if (!result) goto exit;
 
             if (child != NULL)
@@ -811,6 +829,9 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
 
         locals->parent = old;
 
+        if (!result)
+            g_clear_object(record);
+
     }
 
     return result;
diff --git a/plugins/kaitai/parsers/switch.c b/plugins/kaitai/parsers/switch.c
index c823f27..6cfc96b 100644
--- a/plugins/kaitai/parsers/switch.c
+++ b/plugins/kaitai/parsers/switch.c
@@ -83,7 +83,7 @@ static void g_kaitai_switch_finalize(GKaitaiSwitch *);
 
 
 /* Parcourt un contenu binaire selon des spécifications Kaitai. */
-static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
 
 
 
@@ -285,7 +285,7 @@ static const char *is_suitable_switch_case_for_integer(const switch_case_t *swca
         {
             if (value->type == GVT_UNSIGNED_INTEGER)
             {
-                unsigned_conv = strtoull(swcase->value, NULL, 10);
+                unsigned_conv = strtoull(swcase->value, NULL, 0);
 
                 valid = (errno != ERANGE && errno != EINVAL);
 
@@ -295,7 +295,7 @@ static const char *is_suitable_switch_case_for_integer(const switch_case_t *swca
             }
             else
             {
-                signed_conv = strtoll(swcase->value, NULL, 10);
+                signed_conv = strtoll(swcase->value, NULL, 0);
 
                 valid = (errno != ERANGE && errno != EINVAL);
 
@@ -569,7 +569,7 @@ bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAt
 *  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]                    *
+*                epos    = 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. *
@@ -580,127 +580,65 @@ bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAt
 *                                                                             *
 ******************************************************************************/
 
-static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, 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     */
+    bool status;                            /* Bilan intermédiaire         */
     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é */
+    result = true;
 
     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;
+    /* Tenative n°1 : version "entier" */
+
+    status = resolve_kaitai_expression_as_integer(locals, kswitch->target, strlen(kswitch->target), &value);
 
+    if (status)
         for (i = 0; i < kswitch->count; i++)
         {
-            final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value);
+            final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value);
 
             if (final_type != NULL)
-                break;
+                goto next_step;
 
         }
 
-    }
-
-    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;
+    status = resolve_kaitai_expression_as_bytes(locals, kswitch->target, strlen(kswitch->target), &value);
 
-            for (i = 0; i < kswitch->count; i++)
-            {
-                final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value);
+    /* Tenative n°1 : version "chaîne" */
 
-                if (final_type != NULL)
-                    break;
+    if (status)
+        for (i = 0; i < kswitch->count; i++)
+        {
+            final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value);
 
-            }
+            if (final_type != NULL)
+                goto next_step;
 
         }
 
-        else
-            printf("other type: %u\n", basic);
-
-    }
-
     if (final_type == NULL && kswitch->defcase != NULL)
         final_type = kswitch->defcase->type;
 
+ next_step:
+
     /* 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);
+        result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib), locals, content, epos, 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 true;
     return result;
 
 }
diff --git a/plugins/kaitai/python/records/Makefile.am b/plugins/kaitai/python/records/Makefile.am
index 1413228..3a3c672 100644
--- a/plugins/kaitai/python/records/Makefile.am
+++ b/plugins/kaitai/python/records/Makefile.am
@@ -2,12 +2,13 @@
 noinst_LTLIBRARIES = libkaitaipythonrecords.la
 
 libkaitaipythonrecords_la_SOURCES = 		\
+	bits.h bits.c							\
+	delayed.h delayed.c						\
 	empty.h empty.c							\
 	group.h group.c							\
 	item.h item.c							\
 	list.h list.c							\
-	module.h module.c						\
-	value.h value.c
+	module.h module.c
 
 libkaitaipythonrecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
 	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
diff --git a/plugins/kaitai/python/records/bits.c b/plugins/kaitai/python/records/bits.c
new file mode 100644
index 0000000..f94148b
--- /dev/null
+++ b/plugins/kaitai/python/records/bits.c
@@ -0,0 +1,318 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.h - équivalent Python du fichier "plugins/kaitai/parsers/bits.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 "bits.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 "../record.h"
+#include "../parsers/attribute.h"
+#include "../../records/bits-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_bit_field, G_TYPE_RECORD_BIT_FIELD);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_bit_field_init(PyObject *, PyObject *, PyObject *);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+static PyObject *py_record_bit_field_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_bit_field_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+#if 0
+    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.  */
+    GRecordBitField *field;                 /* Création GLib à transmettre */
+#endif
+
+#define RECORD_BIT_FIELD_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 */
+
+#if 0   /* FIXME */
+
+    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 */
+
+    field = G_RECORD_BIT_FIELD(pygobject_get(self));
+
+    if (!g_record_bit_field_create(field, attrib, content, &range, endian))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create record bit field."));
+        return -1;
+    }
+
+    return 0;
+
+#endif
+
+    PyErr_SetString(PyExc_ValueError, _("Unable to create record bit field at the moment."));
+    return -1;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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_bit_field_get_value(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GRecordBitField *field;                 /* Version native de l'élément */
+    resolved_value_t resolved;              /* Valeur sous forme générique */
+    bool status;                            /* Bilan d'opération           */
+
+#define RECORD_BIT_FIELD_VALUE_ATTRIB PYTHON_GET_DEF_FULL   \
+(                                                           \
+    value, py_record_bit_field,                             \
+    "Carried value (as integer), or None in case of error." \
+)
+
+    result = NULL;
+
+    field = G_RECORD_BIT_FIELD(pygobject_get(self));
+
+    status = g_record_bit_field_get_value(field, &resolved);
+
+    if (status)
+        switch (resolved.type)
+        {
+            case GVT_UNSIGNED_INTEGER:
+                result = PyLong_FromUnsignedLongLong(resolved.unsigned_integer);
+                break;
+
+            default:
+                assert(false);
+                result = Py_None;
+                Py_INCREF(result);
+                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_bit_field_type(void)
+{
+    static PyMethodDef py_record_bit_field_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_record_bit_field_getseters[] = {
+        RECORD_BIT_FIELD_VALUE_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_record_bit_field_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.records.RecordBitField",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = RECORD_BIT_FIELD_DOC,
+
+        .tp_methods     = py_record_bit_field_methods,
+        .tp_getset      = py_record_bit_field_getseters,
+
+        .tp_init        = py_record_bit_field_init,
+        .tp_new         = py_record_bit_field_new,
+
+    };
+
+    return &py_record_bit_field_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.....RecordBitField.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_record_bit_field_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'RecordItem'    */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_record_bit_field_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_BIT_FIELD, 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_bit_field(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_record_bit_field_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 bit field");
+            break;
+
+        case 1:
+            *((GRecordBitField **)dst) = G_RECORD_BIT_FIELD(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/records/bits.h b/plugins/kaitai/python/records/bits.h
new file mode 100644
index 0000000..6c833bb
--- /dev/null
+++ b/plugins/kaitai/python/records/bits.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/bits.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_BITS_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_BITS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_bit_field_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordBitField'. */
+bool ensure_python_record_bit_field_is_registered(void);
+
+/* Tente de convertir en correspondance attribut/binaire. */
+int convert_to_record_bit_field(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_RECORDS_BITS_H */
diff --git a/plugins/kaitai/python/records/delayed.c b/plugins/kaitai/python/records/delayed.c
new file mode 100644
index 0000000..32e3db1
--- /dev/null
+++ b/plugins/kaitai/python/records/delayed.c
@@ -0,0 +1,341 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * delayed.c - équivalent Python du fichier "plugins/kaitai/parsers/delayed.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 "delayed.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/delayed-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_delayed, G_TYPE_RECORD_DELAYED);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_delayed_init(PyObject *, PyObject *, PyObject *);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+static PyObject *py_record_delayed_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_delayed_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GKaitaiInstance *inst;                  /* Instance définie créatrice  */
+    kaitai_scope_t *locals;                 /* Environnement local         */
+    GBinContent *content;                   /* Contenu binaire analysé     */
+    int ret;                                /* Bilan de lecture des args.  */
+    GRecordDelayed *delayed;                /* Création GLib à transmettre */
+
+#define RECORD_DELAYED_DOC                                                      \
+    "The RecordDelayed class stores a link to an instance used to compute a"    \
+    " given value."                                                             \
+    "\n"                                                                        \
+    "Instances can be created using the following constructor:\n"               \
+    "\n"                                                                        \
+    "    RecordDelayed(inst, locals, content)"                                  \
+    "\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." \
+    " The *content* argument is a pychrysalide.analysis.BinContent instance if" \
+    " the delayed instance does not define a direct value."
+
+    /* Récupération des paramètres */
+
+    content = NULL;
+
+    ret = PyArg_ParseTuple(args, "O&O&|O&",
+                           convert_to_kaitai_instance, &inst,
+                           convert_to_kaitai_scope, &locals,
+                           convert_to_binary_content_or_none, &content);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    delayed = G_RECORD_DELAYED(pygobject_get(self));
+
+    if (!g_record_delayed_create(delayed, inst, locals, content))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create record delayed."));
+        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_delayed_get_value(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GRecordDelayed *delayed;                /* Version native de l'élément */
+    resolved_value_t resolved;              /* Valeur sous forme générique */
+    bool status;                            /* Bilan d'opération           */
+
+#define RECORD_DELAYED_VALUE_ATTRIB PYTHON_GET_DEF_FULL             \
+(                                                                   \
+    value, py_record_delayed,                                       \
+    "Carried value (as integer, bytes), or None in case of error."  \
+)
+
+    result = NULL;
+
+    delayed = G_RECORD_DELAYED(pygobject_get(self));
+
+    status = g_record_delayed_compute_and_aggregate_value(delayed, &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_delayed_type(void)
+{
+    static PyMethodDef py_record_delayed_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_record_delayed_getseters[] = {
+        RECORD_DELAYED_VALUE_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_record_delayed_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.plugins.kaitai.records.RecordDelayed",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = RECORD_DELAYED_DOC,
+
+        .tp_methods     = py_record_delayed_methods,
+        .tp_getset      = py_record_delayed_getseters,
+
+        .tp_init        = py_record_delayed_init,
+        .tp_new         = py_record_delayed_new,
+
+    };
+
+    return &py_record_delayed_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide..records.RecordDelayed.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_record_delayed_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'RecordDelayed' */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_record_delayed_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_DELAYED, 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_delayed(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_record_delayed_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 delayed");
+            break;
+
+        case 1:
+            *((GRecordDelayed **)dst) = G_RECORD_DELAYED(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/kaitai/python/records/delayed.h b/plugins/kaitai/python/records/delayed.h
new file mode 100644
index 0000000..ba2d23a
--- /dev/null
+++ b/plugins/kaitai/python/records/delayed.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * delayed.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/delayed.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_DELAYED_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_delayed_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordDelayed'. */
+bool ensure_python_record_delayed_is_registered(void);
+
+/* Tente de convertir en valeur calculée. */
+int convert_to_record_delayed(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H */
diff --git a/plugins/kaitai/python/records/module.c b/plugins/kaitai/python/records/module.c
index ea33c31..af97434 100644
--- a/plugins/kaitai/python/records/module.c
+++ b/plugins/kaitai/python/records/module.c
@@ -32,11 +32,12 @@
 #include <plugins/pychrysalide/helpers.h>
 
 
+#include "bits.h"
+#include "delayed.h"
 #include "empty.h"
 #include "group.h"
 #include "item.h"
 #include "list.h"
-#include "value.h"
 
 
 
@@ -109,11 +110,12 @@ bool populate_kaitai_records_module(void)
 
     result = true;
 
+    if (result) result = ensure_python_record_bit_field_is_registered();
+    if (result) result = ensure_python_record_delayed_is_registered();
     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);
 
diff --git a/plugins/kaitai/python/records/value.c b/plugins/kaitai/python/records/value.c
deleted file mode 100644
index bd4ad74..0000000
--- a/plugins/kaitai/python/records/value.c
+++ /dev/null
@@ -1,335 +0,0 @@
-
-/* 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
deleted file mode 100644
index 16cadcb..0000000
--- a/plugins/kaitai/python/records/value.h
+++ /dev/null
@@ -1,45 +0,0 @@
-
-/* 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/record.c b/plugins/kaitai/record.c
index db573ed..de1e80d 100644
--- a/plugins/kaitai/record.c
+++ b/plugins/kaitai/record.c
@@ -115,6 +115,10 @@ static void g_match_record_init(GMatchRecord *record)
 
 static void g_match_record_dispose(GMatchRecord *record)
 {
+    g_clear_object(&record->creator);
+
+    g_clear_object(&record->content);
+
     G_OBJECT_CLASS(g_match_record_parent_class)->dispose(G_OBJECT(record));
 
 }
diff --git a/plugins/kaitai/records/Makefile.am b/plugins/kaitai/records/Makefile.am
index c11e823..3884bfb 100644
--- a/plugins/kaitai/records/Makefile.am
+++ b/plugins/kaitai/records/Makefile.am
@@ -2,6 +2,10 @@
 noinst_LTLIBRARIES = libkaitairecords.la
 
 libkaitairecords_la_SOURCES =				\
+	bits-int.h								\
+	bits.h bits.c							\
+	delayed-int.h							\
+	delayed.h delayed.c						\
 	empty-int.h								\
 	empty.h empty.c							\
 	group-int.h								\
@@ -9,9 +13,7 @@ libkaitairecords_la_SOURCES =				\
 	item-int.h								\
 	item.h item.c							\
 	list-int.h								\
-	list.h list.c							\
-	value-int.h								\
-	value.h value.c
+	list.h list.c
 
 libkaitairecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
 
diff --git a/plugins/kaitai/records/bits-int.h b/plugins/kaitai/records/bits-int.h
new file mode 100644
index 0000000..7b03911
--- /dev/null
+++ b/plugins/kaitai/records/bits-int.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits-int.h - prototypes internes pour la conservation d'un champ de bits entre attribut et 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_BITS_INT_H
+#define _PLUGINS_KAITAI_RECORDS_BITS_INT_H
+
+
+#include "bits.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Correspondance de bits établie entre un attribut et du binaire (instance) */
+struct _GRecordBitField
+{
+    GMatchRecord parent;                    /* A laisser en premier        */
+
+    ext_vmpa_t epos;                        /* Point de départ             */
+    uint8_t size;                           /* Quantité de bits concernés  */
+    SourceEndian endian;                    /* Boutisme des données imposé */
+
+};
+
+/* Correspondance de bits établie entre un attribut et du binaire (classe) */
+struct _GRecordBitFieldClass
+{
+    GMatchRecordClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Met en place une correspondance entre attribut et binaire. */
+bool g_record_bit_field_create(GRecordBitField *, GKaitaiAttribute *, GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_BITS_INT_H */
diff --git a/plugins/kaitai/records/bits.c b/plugins/kaitai/records/bits.c
new file mode 100644
index 0000000..d224112
--- /dev/null
+++ b/plugins/kaitai/records/bits.c
@@ -0,0 +1,283 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.c - conservation d'un champ de bits entre attribut et 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 "bits.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include "bits-int.h"
+
+
+
+/* -------------------- DEFINITION D'UNE CORRESPONDANCE UNITAIRE -------------------- */
+
+
+/* Initialise la classe des correspondances attribut/binaire. */
+static void g_record_bit_field_class_init(GRecordBitFieldClass *);
+
+/* Initialise une correspondance entre attribut et binaire. */
+static void g_record_bit_field_init(GRecordBitField *);
+
+/* Supprime toutes les références externes. */
+static void g_record_bit_field_dispose(GRecordBitField *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_bit_field_finalize(GRecordBitField *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_bit_field_get_range(const GRecordBitField *, mrange_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      DEFINITION D'UNE CORRESPONDANCE UNITAIRE                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une correspondance entre un attribut et du binaire. */
+G_DEFINE_TYPE(GRecordBitField, g_record_bit_field, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des correspondances attribut/binaire.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_bit_field_class_init(GRecordBitFieldClass *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_bit_field_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_record_bit_field_finalize;
+
+    record = G_MATCH_RECORD_CLASS(klass);
+
+    record->get_range = (get_record_range_fc)g_record_bit_field_get_range;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : field = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une correspondance entre attribut et binaire.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_bit_field_init(GRecordBitField *field)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : field = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_bit_field_dispose(GRecordBitField *field)
+{
+    G_OBJECT_CLASS(g_record_bit_field_parent_class)->dispose(G_OBJECT(field));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : field = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_bit_field_finalize(GRecordBitField *field)
+{
+    G_OBJECT_CLASS(g_record_bit_field_parent_class)->finalize(G_OBJECT(field));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : attrib  = analyseur à l'origine de la correspondance.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                epos    = tête de lecture avec granularité en bits.          *
+*                size    = quantité de bits à prendre en compte.              *
+*                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   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GMatchRecord *g_record_bit_field_new(GKaitaiAttribute *attrib, GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian)
+{
+    GMatchRecord *result;                   /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_RECORD_BIT_FIELD, NULL);
+
+    if (!g_record_bit_field_create(G_RECORD_BIT_FIELD(result), attrib, content, epos, size, endian))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : field   = correspondance à initialiser pleinement.           *
+*                attrib  = analyseur à l'origine de la correspondance.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                epos    = tête de lecture avec granularité en bits.          *
+*                size    = quantité de bits à prendre en compte.              *
+*                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_bit_field_create(GRecordBitField *field, GKaitaiAttribute *attrib, GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_match_record_create(G_MATCH_RECORD(field), G_KAITAI_PARSER(attrib), content);
+
+    if (result)
+    {
+        copy_evmpa(&field->epos, epos);
+        field->size = size;
+        field->endian = endian;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : field = 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_bit_field_get_value(const GRecordBitField *field, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à retourner           */
+    GKaitaiParser *parser;                  /* Attribut associé à l'élément*/
+
+    parser = g_match_record_get_creator(G_MATCH_RECORD(field));
+    assert(G_IS_KAITAI_ATTRIBUTE(parser));
+
+    result = g_kaitai_attribute_read_bit_field_value(G_KAITAI_ATTRIBUTE(parser),
+                                                     G_MATCH_RECORD(field)->content,
+                                                     &field->epos, field->size,
+                                                     field->endian, out);
+
+    g_object_unref(G_OBJECT(parser));
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  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   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_bit_field_get_range(const GRecordBitField *record, mrange_t *range)
+{
+    phys_t len;                             /* Taille en octets            */
+
+    len = record->size / 8;
+
+    if (record->size % 8 > 0)
+        len ++;
+
+    init_mrange(range, &record->epos.base, len);
+
+}
diff --git a/plugins/kaitai/records/bits.h b/plugins/kaitai/records/bits.h
new file mode 100644
index 0000000..923e8e3
--- /dev/null
+++ b/plugins/kaitai/records/bits.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.h - prototypes pour la conservation d'un champ de bits entre attribut et 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_BITS_H
+#define _PLUGINS_KAITAI_RECORDS_BITS_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+#include "../parsers/attribute.h"
+
+
+
+#define G_TYPE_RECORD_BIT_FIELD            g_record_bit_field_get_type()
+#define G_RECORD_BIT_FIELD(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_BIT_FIELD, GRecordBitField))
+#define G_IS_RECORD_BIT_FIELD(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_BIT_FIELD))
+#define G_RECORD_BIT_FIELD_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_BIT_FIELD, GRecordBitFieldClass))
+#define G_IS_RECORD_BIT_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_BIT_FIELD))
+#define G_RECORD_BIT_FIELD_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_BIT_FIELD, GRecordBitFieldClass))
+
+
+/* Correspondance de bits établie entre un attribut et du binaire (instance) */
+typedef struct _GRecordBitField GRecordBitField;
+
+/* Correspondance de bits établie entre un attribut et du binaire (classe) */
+typedef struct _GRecordBitFieldClass GRecordBitFieldClass;
+
+
+/* Indique le type défini pour une correspondance entre un attribut et du binaire. */
+GType g_record_bit_field_get_type(void);
+
+/* Crée une nouvelle correspondance entre attribut et binaire. */
+GMatchRecord *g_record_bit_field_new(GKaitaiAttribute *, GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+bool g_record_bit_field_get_value(const GRecordBitField *, resolved_value_t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_BITS_H */
diff --git a/plugins/kaitai/records/delayed-int.h b/plugins/kaitai/records/delayed-int.h
new file mode 100644
index 0000000..9275500
--- /dev/null
+++ b/plugins/kaitai/records/delayed-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * delayed-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_DELAYED_INT_H
+#define _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H
+
+
+#include "delayed.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Valeur calculée selon des correspondances parallèles (instance) */
+struct _GRecordDelayed
+{
+    GMatchRecord parent;                    /* A laisser en premier        */
+
+    kaitai_scope_t locals;                  /* Sauvegarde de contexte      */
+
+    bool has_value;                         /* Port d'une valeur directe ? */
+    GMatchRecord *real_record;              /* Enregistrement effectif     */
+
+};
+
+/* Valeur calculée selon des correspondances parallèles (classe) */
+struct _GRecordDelayedClass
+{
+    GMatchRecordClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Met en place une valeur calculée selon des correspondances. */
+bool g_record_delayed_create(GRecordDelayed *, GKaitaiInstance *, const kaitai_scope_t *, GBinContent *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H */
diff --git a/plugins/kaitai/records/delayed.c b/plugins/kaitai/records/delayed.c
new file mode 100644
index 0000000..8c1395c
--- /dev/null
+++ b/plugins/kaitai/records/delayed.c
@@ -0,0 +1,352 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * delayed.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 "delayed.h"
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+#include "delayed-int.h"
+#include "item.h"
+#include "../parsers/attribute.h"
+
+
+
+/* -------------------- DEFINITION D'UNE CORRESPONDANCE UNITAIRE -------------------- */
+
+
+/* Initialise la classe des valeurs purement calculées. */
+static void g_record_delayed_class_init(GRecordDelayedClass *);
+
+/* Initialise une correspondance entre attribut et binaire. */
+static void g_record_delayed_init(GRecordDelayed *);
+
+/* Supprime toutes les références externes. */
+static void g_record_delayed_dispose(GRecordDelayed *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_delayed_finalize(GRecordDelayed *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_delayed_get_range(const GRecordDelayed *, mrange_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      DEFINITION D'UNE CORRESPONDANCE UNITAIRE                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une valeur calculée selon des correspondances établies. */
+G_DEFINE_TYPE(GRecordDelayed, g_record_delayed, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des valeurs purement calculées.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_delayed_class_init(GRecordDelayedClass *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_delayed_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_record_delayed_finalize;
+
+    record = G_MATCH_RECORD_CLASS(klass);
+
+    record->get_range = (get_record_range_fc)g_record_delayed_get_range;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : delayed = instance à initialiser.                            *
+*                                                                             *
+*  Description : Initialise une correspondance entre attribut et binaire.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_delayed_init(GRecordDelayed *delayed)
+{
+    init_record_scope(&delayed->locals, NULL);
+
+    delayed->real_record = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : delayed = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_delayed_dispose(GRecordDelayed *delayed)
+{
+    reset_record_scope(&delayed->locals);
+
+    G_OBJECT_CLASS(g_record_delayed_parent_class)->dispose(G_OBJECT(delayed));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : delayed = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_record_delayed_finalize(GRecordDelayed *delayed)
+{
+    G_OBJECT_CLASS(g_record_delayed_parent_class)->finalize(G_OBJECT(delayed));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inst    = analyseur à l'origine de la correspondance.        *
+*                locals  = correspondances courantes pour résolutions.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                                                                             *
+*  Description : Crée une nouvelle valeur calculée à partir d'une instance.   *
+*                                                                             *
+*  Retour      : Instance mise en place ou NULL en cas d'échec.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRecordDelayed *g_record_delayed_new(GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content)
+{
+    GRecordDelayed *result;                 /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_RECORD_DELAYED, NULL);
+
+    if (!g_record_delayed_create(result, inst, locals, content))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : delayed = correspondance à initialiser pleinement.           *
+*                inst    = analyseur à l'origine de la correspondance.        *
+*                locals  = correspondances courantes pour résolutions.        *
+*                content = contenu binaire lié à la correspondance.           *
+*                                                                             *
+*  Description : Met en place une valeur calculée à partir d'une instance.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_record_delayed_create(GRecordDelayed *delayed, GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_match_record_create(G_MATCH_RECORD(delayed), G_KAITAI_PARSER(inst), content);
+
+    if (result)
+        copy_record_scope(&delayed->locals, locals);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : delayed = correspondance à consulter.                        *
+*                out     = valeur à sauvegarder sous 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_delayed_compute_value(GRecordDelayed *delayed, 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(delayed));
+    assert(G_IS_KAITAI_ATTRIBUTE(parser));
+
+    if (G_MATCH_RECORD(delayed)->content == NULL)
+        result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser),
+                                                 &delayed->locals,
+                                                 out);
+
+    else
+    {
+        if (delayed->real_record == NULL)
+            delayed->real_record = g_kaitai_instance_compute_real_record(G_KAITAI_INSTANCE(parser),
+                                                                         &delayed->locals,
+                                                                         G_MATCH_RECORD(delayed)->content);
+
+        if (delayed->real_record == NULL)
+            result = false;
+
+        else
+        {
+            assert(G_IS_RECORD_ITEM(delayed->real_record));
+            result = g_record_item_get_value(G_RECORD_ITEM(delayed->real_record), out);
+        }
+
+    }
+
+    g_object_unref(G_OBJECT(parser));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : delayed = correspondance à consulter.                        *
+*                out     = valeur à sauvegarder sous 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_delayed_compute_and_aggregate_value(GRecordDelayed *delayed, resolved_value_t *out)
+{
+    bool result;                            /* Bilan à retourner           */
+    sized_string_t converted;               /* Conversion finale ?         */
+
+    result = g_record_delayed_compute_value(delayed, out);
+
+    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  : delayed  = 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_delayed_get_range(const GRecordDelayed *delayed, mrange_t *range)
+{
+    copy_mrange(range, UNUSED_MRANGE_PTR);
+
+}
diff --git a/plugins/kaitai/records/delayed.h b/plugins/kaitai/records/delayed.h
new file mode 100644
index 0000000..e88bb6c
--- /dev/null
+++ b/plugins/kaitai/records/delayed.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * delayed.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_DELAYED_H
+#define _PLUGINS_KAITAI_RECORDS_DELAYED_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+#include "../parsers/instance.h"
+
+
+
+#define G_TYPE_RECORD_DELAYED            g_record_delayed_get_type()
+#define G_RECORD_DELAYED(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_DELAYED, GRecordDelayed))
+#define G_IS_RECORD_DELAYED(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_DELAYED))
+#define G_RECORD_DELAYED_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_DELAYED, GRecordDelayedClass))
+#define G_IS_RECORD_DELAYED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_DELAYED))
+#define G_RECORD_DELAYED_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_DELAYED, GRecordDelayedClass))
+
+
+/* Valeur calculée selon des correspondances parallèles (instance) */
+typedef struct _GRecordDelayed GRecordDelayed;
+
+/* Valeur calculée selon des correspondances parallèles (classe) */
+typedef struct _GRecordDelayedClass GRecordDelayedClass;
+
+
+/* Indique le type défini pour une valeur calculée selon des correspondances établies. */
+GType g_record_delayed_get_type(void);
+
+/* Crée une nouvelle valeur calculée à partir d'une instance. */
+GRecordDelayed *g_record_delayed_new(GKaitaiInstance *, const kaitai_scope_t *, GBinContent *);
+
+/* Détermine la valeur d'un élément Kaitai entier calculé. */
+bool g_record_delayed_compute_value(GRecordDelayed *, resolved_value_t *);
+
+/* Détermine et ajuste la valeur d'un élément Kaitai calculé. */
+bool g_record_delayed_compute_and_aggregate_value(GRecordDelayed *, resolved_value_t *);
+
+
+
+#endif  /* _PLUGINS_KAITAI_RECORDS_DELAYED_H */
diff --git a/plugins/kaitai/records/value-int.h b/plugins/kaitai/records/value-int.h
deleted file mode 100644
index 6a84a7f..0000000
--- a/plugins/kaitai/records/value-int.h
+++ /dev/null
@@ -1,57 +0,0 @@
-
-/* 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
deleted file mode 100644
index cafe5c3..0000000
--- a/plugins/kaitai/records/value.c
+++ /dev/null
@@ -1,336 +0,0 @@
-
-/* 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
deleted file mode 100644
index 8ee9cdd..0000000
--- a/plugins/kaitai/records/value.h
+++ /dev/null
@@ -1,65 +0,0 @@
-
-/* 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/rost/browser.c b/plugins/kaitai/rost/browser.c
index 075c5ff..159915b 100644
--- a/plugins/kaitai/rost/browser.c
+++ b/plugins/kaitai/rost/browser.c
@@ -32,9 +32,10 @@
 
 
 #include "browser-int.h"
+#include "../records/bits.h"
+#include "../records/delayed.h"
 #include "../records/item.h"
 #include "../records/list.h"
-#include "../records/value.h"
 
 
 
@@ -354,11 +355,14 @@ static bool g_kaitai_browser_reduce(GKaitaiBrowser *item, GScanContext *ctx, GSc
 
     else
     {
-        if (G_IS_RECORD_ITEM(item->record))
-            result = g_record_item_get_value(G_RECORD_ITEM(item->record), &value);
+        if (G_IS_RECORD_BIT_FIELD(item->record))
+            result = g_record_bit_field_get_value(G_RECORD_BIT_FIELD(item->record), &value);
+
+        else if (G_IS_RECORD_DELAYED(item->record))
+            result = g_record_delayed_compute_and_aggregate_value(G_RECORD_DELAYED(item->record), &value);
 
-        else if (G_IS_RECORD_VALUE(item->record))
-            result = g_record_value_compute_and_aggregate_value(G_RECORD_VALUE(item->record), &value);
+        else if (G_IS_RECORD_ITEM(item->record))
+            result = g_record_item_get_value(G_RECORD_ITEM(item->record), &value);
 
         else
             result = false;
diff --git a/plugins/kaitai/tokens.l b/plugins/kaitai/tokens.l
index 3ddf40d..8c93299 100644
--- a/plugins/kaitai/tokens.l
+++ b/plugins/kaitai/tokens.l
@@ -91,7 +91,9 @@
 "_root"                                 { return ROOT; }
 "_parent"                               { return PARENT; }
 "_"                                     { return LAST; }
+"_io"                                   { return IO; }
 "._io"                                  { return METH_IO; }
+".eof"                                  { return IO_EOF; }
 
 "true"                                  { return TRUE_CONST; }
 "false"                                 { return FALSE_CONST; }
diff --git a/src/analysis/content.c b/src/analysis/content.c
index 0560d73..e12237f 100644
--- a/src/analysis/content.c
+++ b/src/analysis/content.c
@@ -474,6 +474,94 @@ bool g_binary_content_read_raw(const GBinContent *content, vmpa2t *addr, phys_t
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = contenu binaire à venir lire.                      *
+*                addr    = position de la tête de lecture complète.           *
+*                size    = quantité de bits à lire.                           *
+*                endian  = ordre des bits dans la source.                     *
+*                val     = lieu d'enregistrement de la lecture. [OUT]         *
+*                                                                             *
+*  Description : Lit un nombre non signé sur deux octets.                     *
+*                                                                             *
+*  Retour      : Bilan de l'opération : true en cas de succès, false sinon.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_content_read_bits(const GBinContent *content, ext_vmpa_t *addr, uint8_t size, SourceEndian endian, uint64_t *val)
+{
+    bool result;                            /* Bilan de lecture à renvoyer */
+    vmpa2t pos;                             /* Tête de lecture courante    */
+    uint8_t data;                           /* Données à parcourir         */
+    uint8_t i;                              /* Boucle de parcours          */
+    uint8_t remaining;                      /* Nombre de bits disponibles  */
+    uint64_t bit;                           /* Nouveau bit à intégrer      */
+
+    assert(addr->consumed_extra_bits < 8);
+    assert(size <= 64);
+
+    if (addr->consumed_extra_bits >= 8 || size > 64)
+        return false;
+
+    copy_vmpa(&pos, &addr->base);
+
+    result = g_binary_content_read_u8(content, &pos, &data);
+    if (!result) goto exit;
+
+    remaining = 8 - addr->consumed_extra_bits;
+
+    *val = 0;
+
+    for (i = 0; i < size; i++)
+    {
+        if (remaining == 0)
+        {
+            result = g_binary_content_read_u8(content, &pos, &data);
+            if (!result) goto exit;
+
+            remaining = 8;
+
+        }
+
+        bit = (data >> (remaining - 1)) & 0x1;
+
+        remaining--;
+
+        switch (endian)
+        {
+            case SRE_LITTLE:
+                *val |= (bit << i);
+                break;
+
+            case SRE_BIG:
+                *val |= (bit << (size - i - 1));
+                break;
+
+            default:
+                assert(false);
+                result = false;
+                break;
+
+        }
+
+    }
+
+    if (result)
+    {
+        advance_vmpa(&addr->base, get_phy_addr(&pos) - get_phy_addr(&addr->base) - 1);
+        addr->consumed_extra_bits = 8 - remaining;
+
+    }
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à venir lire.                      *
 *                addr    = position de la tête de lecture.                    *
 *                low     = position éventuelle des 4 bits visés. [OUT]        *
 *                val     = lieu d'enregistrement de la lecture. [OUT]         *
diff --git a/src/analysis/content.h b/src/analysis/content.h
index 5279890..ee79a9c 100644
--- a/src/analysis/content.h
+++ b/src/analysis/content.h
@@ -87,6 +87,9 @@ const bin_t *g_binary_content_get_raw_access(const GBinContent *, vmpa2t *, phys
 /* Fournit une portion des données représentées. */
 bool g_binary_content_read_raw(const GBinContent *, vmpa2t *, phys_t, bin_t *);
 
+/* Lit un nombre non signé sur deux octets. */
+bool g_binary_content_read_bits(const GBinContent *, ext_vmpa_t *, uint8_t, SourceEndian, uint64_t *);
+
 /* Lit un nombre non signé sur quatre bits. */
 bool g_binary_content_read_u4(const GBinContent *, vmpa2t *, bool *, uint8_t *);
 
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index f353ebd..4f35ebe 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -156,6 +156,62 @@ bool store_vmpa(const vmpa2t *, const char *, bound_value **, size_t *);
 
 
 
+/* ------------------------ DEFINITION DE POSITION AVEC BITS ------------------------ */
+
+
+/* Adresse mémoire ou position physique */
+typedef struct _ext_vmpa_t
+{
+    vmpa2t base;                            /* Vision macroscopique        */
+
+    uint8_t consumed_extra_bits;            /* Avancée supplémentaire      */
+
+} ext_vmpa_t;
+
+
+#define init_evmpa_from_vmpa(d, s)      \
+    do                                  \
+    {                                   \
+        copy_vmpa(&(d)->base, (s));     \
+        (d)->consumed_extra_bits = 0;   \
+    }                                   \
+    while (0)
+
+#define copy_evmpa(d, s)                                        \
+    do                                                          \
+    {                                                           \
+        copy_vmpa(&(d)->base, &(s)->base);                      \
+        (d)->consumed_extra_bits = (s)->consumed_extra_bits;    \
+    }                                                           \
+    while (0)
+
+#define advance_evmpa_bits(a, q)                    \
+    do                                              \
+    {                                               \
+        uint8_t __sum;                              \
+        __sum = (a)->consumed_extra_bits + q;       \
+        if (__sum > 8)                              \
+        {                                           \
+            advance_vmpa(&(a)->base, __sum / 8);    \
+            (a)->consumed_extra_bits = __sum % 8;   \
+        }                                           \
+        else                                        \
+            (a)->consumed_extra_bits = __sum;       \
+    }                                               \
+    while (0)
+
+#define align_evmpa_on_byte(a)              \
+    do                                      \
+    {                                       \
+        if ((a)->consumed_extra_bits > 0)   \
+        {                                   \
+            advance_vmpa(&(a)->base, 1);    \
+            (a)->consumed_extra_bits = 0;   \
+        }                                   \
+    }                                       \
+    while (0);
+
+
 /* ------------------------ AIDES FONCTIONNELLES AUXILIAIRES ------------------------ */
 
 
diff --git a/tests/plugins/kaitai/language.py b/tests/plugins/kaitai/language.py
index b1e8881..43b6185 100644
--- a/tests/plugins/kaitai/language.py
+++ b/tests/plugins/kaitai/language.py
@@ -1312,8 +1312,8 @@ instances:
 
         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).__name__, 'RecordDelayed')          # result_1
+        self.assertEqual(type(parsed.result_1.value).__name__, 'RecordDelayed')    # 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)
diff --git a/tests/plugins/kaitai/rost.py b/tests/plugins/kaitai/rost.py
index 1950222..4a29ef8 100644
--- a/tests/plugins/kaitai/rost.py
+++ b/tests/plugins/kaitai/rost.py
@@ -25,7 +25,7 @@ class TestScansWithKaitai(ChrysalideTestCase):
         cls._options.backend_for_data = AcismBackend
 
 
-    def ZZZtestSimpleKaitaiDefinitionForScanning(self):
+    def testSimpleKaitaiDefinitionForScanning(self):
         """Rely on basic Kaitai simple definition for scanning."""
 
         definitions = '''
-- 
cgit v0.11.2-87-g4458