From 4fcc35a52ccb025b6d803d85e017931cd2452960 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 6 Aug 2023 18:54:57 +0200
Subject: Extend the ROST grammar with a first batch of new features.

---
 configure.ac                                  |  41 ++
 plugins/kaitai/parsers/enum.c                 |   2 +-
 plugins/kaitai/parsers/struct.c               |   2 +-
 plugins/pychrysalide/analysis/scan/scanner.c  |  46 ++
 src/Makefile.am                               |   6 +
 src/analysis/scan/context-int.h               |  20 +-
 src/analysis/scan/context.c                   | 325 ++++++++++++-
 src/analysis/scan/context.h                   |   8 +-
 src/analysis/scan/core.c                      |  96 +++-
 src/analysis/scan/expr-int.h                  |  28 +-
 src/analysis/scan/expr.c                      | 354 +++++++++++++-
 src/analysis/scan/expr.h                      |  27 +-
 src/analysis/scan/exprs/Makefile.am           |  20 +-
 src/analysis/scan/exprs/access-int.h          |  17 +-
 src/analysis/scan/exprs/access.c              | 269 ++++++-----
 src/analysis/scan/exprs/access.h              |  27 +-
 src/analysis/scan/exprs/arithmetic-int.h      |  60 +++
 src/analysis/scan/exprs/arithmetic.c          | 638 ++++++++++++++++++++++++++
 src/analysis/scan/exprs/arithmetic.h          |  67 +++
 src/analysis/scan/exprs/arithmop-int.h        |  60 ---
 src/analysis/scan/exprs/arithmop.c            | 436 ------------------
 src/analysis/scan/exprs/arithmop.h            |  67 ---
 src/analysis/scan/exprs/boolop-int.h          |  60 ---
 src/analysis/scan/exprs/boolop.c              | 479 -------------------
 src/analysis/scan/exprs/boolop.h              |  65 ---
 src/analysis/scan/exprs/call-int.h            |  12 +-
 src/analysis/scan/exprs/call.c                | 280 +++++++----
 src/analysis/scan/exprs/call.h                |  22 +-
 src/analysis/scan/exprs/counter-int.h         |  57 +++
 src/analysis/scan/exprs/counter.c             | 248 ++++++++++
 src/analysis/scan/exprs/counter.h             |  59 +++
 src/analysis/scan/exprs/intersect-int.h       |  58 +++
 src/analysis/scan/exprs/intersect.c           | 290 ++++++++++++
 src/analysis/scan/exprs/intersect.h           |  55 +++
 src/analysis/scan/exprs/literal-int.h         |  16 +-
 src/analysis/scan/exprs/literal.c             | 363 +++++++++------
 src/analysis/scan/exprs/literal.h             |  49 +-
 src/analysis/scan/exprs/logical-int.h         |  60 +++
 src/analysis/scan/exprs/logical.c             | 508 ++++++++++++++++++++
 src/analysis/scan/exprs/logical.h             |  65 +++
 src/analysis/scan/exprs/range-int.h           |  58 +++
 src/analysis/scan/exprs/range.c               | 352 ++++++++++++++
 src/analysis/scan/exprs/range.h               |  55 +++
 src/analysis/scan/exprs/relational-int.h      |  60 +++
 src/analysis/scan/exprs/relational.c          | 408 ++++++++++++++++
 src/analysis/scan/exprs/relational.h          |  56 +++
 src/analysis/scan/exprs/relop-int.h           |  60 ---
 src/analysis/scan/exprs/relop.c               | 392 ----------------
 src/analysis/scan/exprs/relop.h               |  56 ---
 src/analysis/scan/exprs/set-int.h             |  54 +++
 src/analysis/scan/exprs/set.c                 | 379 +++++++++++++++
 src/analysis/scan/exprs/set.h                 |  58 +++
 src/analysis/scan/exprs/strop-int.h           |   8 +-
 src/analysis/scan/exprs/strop.c               | 207 ++++-----
 src/analysis/scan/exprs/strop.h               |  22 +-
 src/analysis/scan/grammar.y                   | 394 +++++++++++-----
 src/analysis/scan/items/Makefile.am           |  18 +
 src/analysis/scan/items/console/Makefile.am   |  13 +
 src/analysis/scan/items/console/log.c         | 303 ++++++++++++
 src/analysis/scan/items/console/log.h         |  58 +++
 src/analysis/scan/items/count.c               | 244 ++++++++++
 src/analysis/scan/items/count.h               |  58 +++
 src/analysis/scan/items/datasize.c            |  56 +--
 src/analysis/scan/items/datasize.h            |  22 +-
 src/analysis/scan/items/magic/Makefile.am     |  16 +
 src/analysis/scan/items/magic/cookie.c        | 122 +++++
 src/analysis/scan/items/magic/cookie.h        |  44 ++
 src/analysis/scan/items/magic/mime-encoding.c | 270 +++++++++++
 src/analysis/scan/items/magic/mime-encoding.h |  58 +++
 src/analysis/scan/items/magic/mime-type.c     | 270 +++++++++++
 src/analysis/scan/items/magic/mime-type.h     |  58 +++
 src/analysis/scan/items/magic/type.c          | 270 +++++++++++
 src/analysis/scan/items/magic/type.h          |  58 +++
 src/analysis/scan/items/time/Makefile.am      |  14 +
 src/analysis/scan/items/time/make.c           | 350 ++++++++++++++
 src/analysis/scan/items/time/make.h           |  58 +++
 src/analysis/scan/items/time/now.c            | 243 ++++++++++
 src/analysis/scan/items/time/now.h            |  58 +++
 src/analysis/scan/items/uint-int.h            |   8 +-
 src/analysis/scan/items/uint.c                | 137 ++++--
 src/analysis/scan/items/uint.h                |  23 +-
 src/analysis/scan/rule-int.h                  |   1 +
 src/analysis/scan/rule.c                      |  28 ++
 src/analysis/scan/rule.h                      |   4 +
 src/analysis/scan/scanner-int.h               |   2 +
 src/analysis/scan/scanner.c                   | 180 +++++++-
 src/analysis/scan/scanner.h                   |  15 +-
 src/analysis/scan/tokens.l                    |  40 +-
 src/common/szstr.h                            |  28 +-
 src/core/core.c                               |  11 +
 src/glibext/comparison-int.h                  |   5 +-
 src/glibext/comparison.c                      |  58 ++-
 src/rost.c                                    |  22 +-
 tests/analysis/scan/booleans.py               |  98 ++++
 tests/analysis/scan/common.py                 |  52 +++
 tests/analysis/scan/examples.py               |  70 +++
 tests/analysis/scan/expr.py                   | 169 -------
 tests/analysis/scan/exprs.py                  | 122 -----
 tests/analysis/scan/func.py                   |  16 -
 tests/analysis/scan/functions.py              | 104 +++++
 tests/analysis/scan/grammar.py                | 327 +++++--------
 tests/analysis/scan/matches.py                |  27 ++
 tests/analysis/scan/options.py                |  16 -
 tests/analysis/scan/pyapi.py                  |  58 +++
 tests/analysis/scan/sets.py                   | 118 +++++
 105 files changed, 9298 insertions(+), 3083 deletions(-)
 create mode 100644 src/analysis/scan/exprs/arithmetic-int.h
 create mode 100644 src/analysis/scan/exprs/arithmetic.c
 create mode 100644 src/analysis/scan/exprs/arithmetic.h
 delete mode 100644 src/analysis/scan/exprs/arithmop-int.h
 delete mode 100644 src/analysis/scan/exprs/arithmop.c
 delete mode 100644 src/analysis/scan/exprs/arithmop.h
 delete mode 100644 src/analysis/scan/exprs/boolop-int.h
 delete mode 100644 src/analysis/scan/exprs/boolop.c
 delete mode 100644 src/analysis/scan/exprs/boolop.h
 create mode 100644 src/analysis/scan/exprs/counter-int.h
 create mode 100644 src/analysis/scan/exprs/counter.c
 create mode 100644 src/analysis/scan/exprs/counter.h
 create mode 100644 src/analysis/scan/exprs/intersect-int.h
 create mode 100644 src/analysis/scan/exprs/intersect.c
 create mode 100644 src/analysis/scan/exprs/intersect.h
 create mode 100644 src/analysis/scan/exprs/logical-int.h
 create mode 100644 src/analysis/scan/exprs/logical.c
 create mode 100644 src/analysis/scan/exprs/logical.h
 create mode 100644 src/analysis/scan/exprs/range-int.h
 create mode 100644 src/analysis/scan/exprs/range.c
 create mode 100644 src/analysis/scan/exprs/range.h
 create mode 100644 src/analysis/scan/exprs/relational-int.h
 create mode 100644 src/analysis/scan/exprs/relational.c
 create mode 100644 src/analysis/scan/exprs/relational.h
 delete mode 100644 src/analysis/scan/exprs/relop-int.h
 delete mode 100644 src/analysis/scan/exprs/relop.c
 delete mode 100644 src/analysis/scan/exprs/relop.h
 create mode 100644 src/analysis/scan/exprs/set-int.h
 create mode 100644 src/analysis/scan/exprs/set.c
 create mode 100644 src/analysis/scan/exprs/set.h
 create mode 100644 src/analysis/scan/items/console/Makefile.am
 create mode 100644 src/analysis/scan/items/console/log.c
 create mode 100644 src/analysis/scan/items/console/log.h
 create mode 100644 src/analysis/scan/items/count.c
 create mode 100644 src/analysis/scan/items/count.h
 create mode 100644 src/analysis/scan/items/magic/Makefile.am
 create mode 100644 src/analysis/scan/items/magic/cookie.c
 create mode 100644 src/analysis/scan/items/magic/cookie.h
 create mode 100644 src/analysis/scan/items/magic/mime-encoding.c
 create mode 100644 src/analysis/scan/items/magic/mime-encoding.h
 create mode 100644 src/analysis/scan/items/magic/mime-type.c
 create mode 100644 src/analysis/scan/items/magic/mime-type.h
 create mode 100644 src/analysis/scan/items/magic/type.c
 create mode 100644 src/analysis/scan/items/magic/type.h
 create mode 100644 src/analysis/scan/items/time/Makefile.am
 create mode 100644 src/analysis/scan/items/time/make.c
 create mode 100644 src/analysis/scan/items/time/make.h
 create mode 100644 src/analysis/scan/items/time/now.c
 create mode 100644 src/analysis/scan/items/time/now.h
 create mode 100644 tests/analysis/scan/booleans.py
 create mode 100644 tests/analysis/scan/common.py
 create mode 100644 tests/analysis/scan/examples.py
 delete mode 100644 tests/analysis/scan/expr.py
 delete mode 100644 tests/analysis/scan/exprs.py
 delete mode 100644 tests/analysis/scan/func.py
 create mode 100644 tests/analysis/scan/functions.py
 create mode 100644 tests/analysis/scan/matches.py
 delete mode 100644 tests/analysis/scan/options.py
 create mode 100644 tests/analysis/scan/pyapi.py
 create mode 100644 tests/analysis/scan/sets.py

diff --git a/configure.ac b/configure.ac
index 6b6da96..165cb40 100644
--- a/configure.ac
+++ b/configure.ac
@@ -232,6 +232,10 @@ AC_ARG_ENABLE([curl-support],
               AS_HELP_STRING([--disable-curl-support], [disable cURL support [default=no]]),
               [], [enable_curl_support=yes])
 
+AC_ARG_ENABLE([magic-support],
+              AS_HELP_STRING([--disable-magic-support], [disable magic number recognition [default=no]]),
+              [], [enable_magic_support=yes])
+
 AC_ARG_ENABLE([python-bindings],
               AS_HELP_STRING([--disable-python-bindings], [disable Python bindings [default=no]]),
               [], [enable_python_bindings=yes])
@@ -503,6 +507,35 @@ AC_SUBST(LIBYAML_CFLAGS)
 AC_SUBST(LIBYAML_LIBS)
 
 
+#--- Checks for libmagic
+
+AM_CONDITIONAL([BUILD_MAGIC_SUPPORT], [test "x$enable_magic_support" = "xyes"])
+
+if test "x$BUILD_MAGIC_SUPPORT_TRUE" = "x"; then
+   AC_DEFINE(HAVE_MAGIC_SUPPORT, 1,
+             [Define to 1 if the magic support is available and enabled.])
+fi
+
+
+PKG_CHECK_MODULES(LIBMAGIC,libmagic >= 5.44,[libmagic_found=yes],[libmagic_found=no])
+
+if test "$libmagic_found" = "yes"; then
+   libmagic_version=`pkg-config libmagic --modversion`
+else
+   libmagic_version='-'
+fi
+
+
+if test "x$enable_magic_support" = "xyes"; then
+
+   AC_SUBST(LIBMAGIC_CFLAGS)
+   AC_SUBST(LIBMAGIC_LIBS)
+
+   true # empty if/then body not allowed
+
+fi
+
+
 #--- Checks for Python
 
 if test "x$enable_debug" = "xyes"; then
@@ -760,6 +793,7 @@ echo The small, fast and reliable database engine. : $libsqlite_version
 echo The cryptography and SSL/TLS toolkit......... : $libssl_version
 echo The client URL library....................... : $libcurl_version
 echo The YAML support library..................... : $libyaml_version
+echo The magic number recognition library......... : $libmagic_version
 
 echo
 echo Available Python programming language........ : $python3_version
@@ -781,6 +815,12 @@ else
    disable_curl_support="yes"
 fi
 
+if test "x$enable_magic_support" = "xyes"; then
+   disable_magic_support="no"
+else
+   disable_magic_support="yes"
+fi
+
 if test "x$enable_python_bindings" = "xyes"; then
    disable_python_bindings="no"
 else
@@ -792,6 +832,7 @@ echo Print debugging messages..................... : $enable_debug
 echo Consider local resources..................... : $with_local_resources
 echo Disable GTK support.......................... : $disable_gtk_support
 echo Disable cURL support......................... : $disable_curl_support
+echo Disable Magic support........................ : $disable_magic_support
 echo Disable Python bindings...................... : $disable_python_bindings
 echo Build a Python binary distribution........... : $build_python_package
 
diff --git a/plugins/kaitai/parsers/enum.c b/plugins/kaitai/parsers/enum.c
index 267aaba..27e5660 100644
--- a/plugins/kaitai/parsers/enum.c
+++ b/plugins/kaitai/parsers/enum.c
@@ -351,7 +351,7 @@ static int compare_enum_values_by_sized_label(const sized_string_t *l, const enu
 {
     int result;                             /* Bilan à retourner           */
 
-    result = szstrcmp(l, (*b)->label);
+    result = strncmp(l->data, (*b)->label, l->len);     // FIXME
 
     return result;
 
diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c
index 26089d3..128a788 100644
--- a/plugins/kaitai/parsers/struct.c
+++ b/plugins/kaitai/parsers/struct.c
@@ -578,7 +578,7 @@ GKaitaiEnum *g_kaitai_structure_get_enum(const GKaitaiStruct *kstruct, const siz
     {
         other = g_kaitai_enum_get_name(kstruct->enums[i]);
 
-        if (szstrcmp(name, other) == 0)
+        if (strncmp(name->data, other, name->len) == 0) // FIXME
         {
             result = kstruct->enums[i];
             g_object_ref(G_OBJECT(result));
diff --git a/plugins/pychrysalide/analysis/scan/scanner.c b/plugins/pychrysalide/analysis/scan/scanner.c
index bf5a5f5..befbc80 100644
--- a/plugins/pychrysalide/analysis/scan/scanner.c
+++ b/plugins/pychrysalide/analysis/scan/scanner.c
@@ -188,6 +188,51 @@ static PyObject *py_content_scanner_analyze(PyObject *self, PyObject *args)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique le chemin d'un éventuel fichier de source.           *
+*                                                                             *
+*  Retour      : Chemin d'un éventuel fichier de définitions ou NULL.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_content_scanner_get_filename(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GContentScanner *scanner;               /* Analyseur à consulter       */
+    const char *filename;                   /* Chemin d'accès à transmettre*/
+
+#define CONTENT_SCANNER_FILENAME_ATTRIB PYTHON_GET_DEF_FULL     \
+(                                                               \
+    filename, py_content_scanner,                               \
+    "Provide the access path to the source file of the rules'"  \
+    " definition, or *None* if these rules have not been loaded"\
+    " from memory."                                             \
+)
+
+    scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+    filename = g_content_scanner_get_filename(scanner);
+
+    if (filename != NULL)
+        result = PyUnicode_FromString(filename);
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -206,6 +251,7 @@ PyTypeObject *get_python_content_scanner_type(void)
     };
 
     static PyGetSetDef py_content_scanner_getseters[] = {
+        CONTENT_SCANNER_FILENAME_ATTRIB,
         { NULL }
     };
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 1fe76bc..233fc10 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,6 +66,12 @@ libchrysacore_la_LDFLAGS += $(LIBCURL_LIBS)
 
 endif
 
+if BUILD_MAGIC_SUPPORT
+
+libchrysacore_la_LDFLAGS += $(LIBMAGIC_LIBS)
+
+endif
+
 
 
 ############################################################
diff --git a/src/analysis/scan/context-int.h b/src/analysis/scan/context-int.h
index 94302bf..3a971b8 100644
--- a/src/analysis/scan/context-int.h
+++ b/src/analysis/scan/context-int.h
@@ -29,9 +29,12 @@
 
 
 #include "expr.h"
+#include "../../common/fnv1a.h"
 
 
 
+#define ALLOCATION_STEP 10
+
 /* Mémorisation des correspondances partielles */
 typedef struct _atom_match_tracker_t
 {
@@ -41,12 +44,22 @@ typedef struct _atom_match_tracker_t
 
 } atom_match_tracker_t;
 
-#define ALLOCATION_STEP 10
+/* Mémorisation des correspondances complètes, par motif */
+typedef struct _full_match_tracker_t
+{
+    GSearchPattern *pattern;                /* Motif commun aux trouvailles*/
+
+    GScanMatch **matches;                   /* Correspondances confirmées  */
+    size_t allocated;                       /* Taille du talbeau préparé   */
+    size_t used;                            /* Nombre d'éléments présents  */
+
+} full_match_tracker_t;
 
 /* Condition définissant une règle de correspondance */
 typedef struct _rule_condition_t
 {
     char *name;                             /* Désignation de la règle     */
+    fnv64_t name_hash;                      /* Empreinte de la désignation */
 
     GScanExpression *expr;                  /* Condition de correspondance */
     bool final_reduced;                     /* Réduction finale tentée ?   */
@@ -66,9 +79,8 @@ struct _GScanContext
 
     atom_match_tracker_t *atom_trackers;    /* Correspondances partielles  */
 
-    GScanMatch **full_matches;              /* Correspondances confirmées  */
-    size_t full_allocated;                  /* Taille du talbeau préparé   */
-    size_t full_used;                       /* Nombre d'éléments présents  */
+    full_match_tracker_t **full_trackers;   /* Correspondances confirmées  */
+    size_t full_count;                      /* Quantité de correspondances */
 
     rule_condition_t *conditions;           /* Ensemble de règles suivies  */
     size_t cond_count;                      /* Quantité de ces conditions  */
diff --git a/src/analysis/scan/context.c b/src/analysis/scan/context.c
index c19b76c..1f9c38e 100644
--- a/src/analysis/scan/context.c
+++ b/src/analysis/scan/context.c
@@ -25,11 +25,36 @@
 
 
 #include <assert.h>
+#include <malloc.h>
+#include <stdlib.h>
 #include <string.h>
 
 
 #include "context-int.h"
 #include "exprs/literal.h"
+#include "../../common/sort.h"
+
+
+
+
+
+/* ------------------- ADMINISTRATION DES CORRESPONDANCES TOTALES ------------------- */
+
+
+/* Initialise un suivi de trouvailles pour un premier motif. */
+static full_match_tracker_t *create_full_match_tracker(GSearchPattern *);
+
+/* Termine le suivi de trouvailles pour un motif. */
+static void delete_full_match_tracker(full_match_tracker_t *);
+
+/* Etablit la comparaison entre deux structures de suivi. */
+static int compare_full_match_trackers(const full_match_tracker_t **, const full_match_tracker_t **);
+
+/* Note l'existence d'une nouvelle correspondance pour un motif. */
+static void add_match_to_full_match_tracker(full_match_tracker_t *, GScanMatch *);
+
+
+
 
 
 
@@ -47,6 +72,131 @@ static void g_scan_context_finalize(GScanContext *);
 
 
 
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                     ADMINISTRATION DES CORRESPONDANCES TOTALES                     */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = motif de recherche trouvé.                         *
+*                                                                             *
+*  Description : Initialise un suivi de trouvailles pour un premier motif.    *
+*                                                                             *
+*  Retour      : Structure de suivi mise en place.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static full_match_tracker_t *create_full_match_tracker(GSearchPattern *pattern)
+{
+    full_match_tracker_t *result;           /* Structure à retourner       */
+
+    result = malloc(sizeof(full_match_tracker_t));
+
+    result->pattern = pattern;
+    g_object_ref(G_OBJECT(pattern));
+
+    result->matches = malloc(ALLOCATION_STEP * sizeof(GScanMatch *));
+    result->allocated = ALLOCATION_STEP;
+    result->used = 0;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = structure de gestion à manipuler.                  *
+*                                                                             *
+*  Description : Termine le suivi de trouvailles pour un motif.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void delete_full_match_tracker(full_match_tracker_t *tracker)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    g_object_unref(G_OBJECT(tracker->pattern));
+
+    for (i = 0; i < tracker->used; i++)
+        g_object_unref(G_OBJECT(tracker->matches[i]));
+
+    free(tracker->matches);
+
+    free(tracker);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = première structure de suivi à consulter.                 *
+*                b = seconde structure de suivi à consulter.                  *
+*                                                                             *
+*  Description : Etablit la comparaison entre deux structures de suivi.       *
+*                                                                             *
+*  Retour      : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b).                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int compare_full_match_trackers(const full_match_tracker_t **a, const full_match_tracker_t **b)
+{
+    int result;                             /* Bilan à renvoyer            */
+
+    result = sort_unsigned_long((unsigned long)(*a)->pattern, (unsigned long)(*b)->pattern);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : tracker = structure de gestion à manipuler.                  *
+*                match   = correspondance complète établie.                   *
+*                                                                             *
+*  Description : Note l'existence d'une nouvelle correspondance pour un motif.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void add_match_to_full_match_tracker(full_match_tracker_t *tracker, GScanMatch *match)
+{
+    if (tracker->used == tracker->allocated)
+    {
+        tracker->allocated += ALLOCATION_STEP;
+        tracker->matches = realloc(tracker->matches, tracker->allocated * sizeof(GScanMatch *));
+    }
+
+    tracker->matches[tracker->used++] = match;
+    g_object_ref(G_OBJECT(match));
+
+}
+
+
+
+
+
+
+
+
+
 /* Indique le type défini pour un contexte de suivi d'analyse. */
 G_DEFINE_TYPE(GScanContext, g_scan_context, G_TYPE_OBJECT);
 
@@ -97,9 +247,8 @@ static void g_scan_context_init(GScanContext *context)
 
     context->atom_trackers = NULL;
 
-    context->full_matches = NULL;
-    context->full_allocated = 0;
-    context->full_used = 0;
+    context->full_trackers = NULL;
+    context->full_count = 0;
 
     context->conditions = NULL;
     context->cond_count = 0;
@@ -127,8 +276,12 @@ static void g_scan_context_dispose(GScanContext *context)
 
     g_clear_object(&context->content);
 
-    for (i = 0; i < context->full_used; i++)
-        g_clear_object(&context->full_matches[i]);
+    for (i = 0; i < context->full_count; i++)
+        if (context->full_trackers[i] != NULL)
+        {
+            delete_full_match_tracker(context->full_trackers[i]);
+            context->full_trackers[i] = NULL;
+        }
 
     for (i = 0; i < context->cond_count; i++)
         g_clear_object(&context->conditions[i].expr);
@@ -170,8 +323,8 @@ static void g_scan_context_finalize(GScanContext *context)
 
     }
 
-    if (context->full_matches != NULL)
-        free(context->full_matches);
+    if (context->full_trackers != NULL)
+        free(context->full_trackers);
 
     if (context->conditions != NULL)
     {
@@ -387,14 +540,75 @@ const phys_t *g_scan_context_get_atom_matches(const GScanContext *context, patid
 
 void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match)
 {
-    if (context->full_used == context->full_allocated)
+    GSearchPattern *pattern;                /* Clef d'un suivi             */
+    full_match_tracker_t key;               /* Modèle d'identification     */
+    full_match_tracker_t **found;           /* Structure à actualiser      */
+    full_match_tracker_t *tracker;          /* Nouveau suivi à intégrer    */
+
+    pattern = g_scan_match_get_source(match);
+
+    key.pattern = pattern;
+
+    found = bsearch((full_match_tracker_t *[]) { &key }, context->full_trackers, context->full_count,
+                    sizeof(full_match_tracker_t *), (__compar_fn_t)compare_full_match_trackers);
+
+    if (found == NULL)
     {
-        context->full_allocated += ALLOCATION_STEP;
-        context->full_matches = realloc(context->full_matches, context->full_allocated * sizeof(GScanMatch *));
+        tracker = create_full_match_tracker(pattern);
+
+        context->full_trackers = qinsert(context->full_trackers, &context->full_count,
+                                         sizeof(full_match_tracker_t *),
+                                         (__compar_fn_t)compare_full_match_trackers, &tracker);
+
     }
+    else
+        tracker = *found;
 
-    context->full_matches[context->full_used++] = match;
-    g_object_ref(G_OBJECT(match));
+    add_match_to_full_match_tracker(tracker, match);
+
+    g_object_unref(G_OBJECT(pattern));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : context = instance à mettre à jour.                          *
+*                pattern = motif dont des correspondances sont à retrouver.   *
+*                count   = quantité de correspondances enregistrées. [OUT]    *
+*                                                                             *
+*  Description : Fournit la liste de toutes les correspondances d'un motif.   *
+*                                                                             *
+*  Retour      : Liste courante de correspondances établies.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const GScanMatch **g_scan_context_get_full_matches(const GScanContext *context, const GSearchPattern *pattern, size_t *count)
+{
+    GScanMatch **result;                    /* Correspondance à renvoyer   */
+    full_match_tracker_t key;               /* Modèle d'identification     */
+    full_match_tracker_t **found;           /* Structure à actualiser      */
+
+    key.pattern = pattern;
+
+    found = bsearch((full_match_tracker_t *[]) { &key }, context->full_trackers, context->full_count,
+                    sizeof(full_match_tracker_t *), (__compar_fn_t)compare_full_match_trackers);
+
+    if (found == NULL)
+    {
+        result = NULL;
+        count = 0;
+    }
+
+    else
+    {
+        result = (*found)->matches;
+        *count = (*found)->used;
+    }
+
+    return result;
 
 }
 
@@ -411,12 +625,25 @@ void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match
 *                                                                             *
 ******************************************************************************/
 
-void g_scan_context_display(const GScanContext *context)
+void g_scan_context_display(GScanContext *context)
 {
     size_t i;                               /* Boucle de parcours          */
+    const rule_condition_t *cond;           /* Conditions de orrespondance */
 
+    /*
+      FIXME : ordre
     for (i = 0; i < context->full_used; i++)
         g_scan_match_display(context->full_matches[i]);
+    */
+
+    for (i = 0; i < context->cond_count; i++)
+    {
+        cond = &context->conditions[i];
+
+        if (g_scan_context_has_match_for_rule(context, cond->name))
+            fprintf(stderr, "Rule '%s' has matched!\n", cond->name);
+
+    }
 
 }
 
@@ -445,7 +672,7 @@ bool g_scan_context_set_rule_condition(GScanContext *context, const char *name,
 
     /* Recherche d'antécédent */
 
-    for (i = 0; context->cond_count; i++)
+    for (i = 0; i < context->cond_count; i++)
         if (strcmp(name, context->conditions[i].name) == 0)
         {
             result = false;
@@ -461,8 +688,10 @@ bool g_scan_context_set_rule_condition(GScanContext *context, const char *name,
         new = &context->conditions[context->cond_count - 1];
 
         new->name = strdup(name);
+        new->name_hash = fnv_64a_hash(name);
 
-        new->expr = g_scan_expression_duplicate(expr);
+        new->expr = expr;//g_scan_expression_duplicate(expr);
+        g_object_ref(G_OBJECT(expr)); // FIXME => REMME dup()
         new->final_reduced = false;
 
     }
@@ -477,6 +706,50 @@ bool g_scan_context_set_rule_condition(GScanContext *context, const char *name,
 *  Paramètres  : context = mémoire de résultats d'analyse à consulter.        *
 *                name    = désignation de la règle ciblée.                    *
 *                                                                             *
+*  Description : Indique si un nom donné correspond à une règle.              *
+*                                                                             *
+*  Retour      : Bilan de la présence d'une règle désignée.                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_context_has_rule_for_name(const GScanContext *context, const char *name)
+{
+    bool result;                            /* Bilan à retourner           */
+    fnv64_t hash;                           /* Empreinte du nom à retrouver*/
+    size_t i;                               /* Boucle de parcours          */
+    const rule_condition_t *cond;           /* Condition connue du contexte*/
+
+    result = false;
+
+    hash = fnv_64a_hash(name);
+
+    for (i = 0; i < context->cond_count; i++)
+    {
+        cond = context->conditions + i;
+
+        if (cond->name_hash != hash)
+            continue;
+
+        if (strcmp(cond->name, name) == 0)
+        {
+            result = true;
+            break;
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : context = mémoire de résultats d'analyse à consulter.        *
+*                name    = désignation de la règle ciblée.                    *
+*                                                                             *
 *  Description : Indique si une correspondance globale a pu être établie.     *
 *                                                                             *
 *  Retour      : Bilan final d'une analyse (false par défaut).                *
@@ -513,21 +786,27 @@ bool g_scan_context_has_match_for_rule(GScanContext *context, const char *name)
 
     if (!cond->final_reduced)
     {
-        cond->final_reduced = g_scan_expression_reduce(cond->expr, context, NULL, &new);
+        valid = g_scan_expression_reduce(cond->expr, context, NULL, &new);
+        if (!valid || new == NULL) goto exit;
 
-        if (cond->final_reduced && new != NULL)
-        {
-            g_object_unref(G_OBJECT(cond->expr));
-            cond->expr = new;
-        }
+        g_object_unref(G_OBJECT(cond->expr));
+        cond->expr = new;
+
+        valid = g_scan_expression_reduce_to_boolean(cond->expr, context, NULL, &new);
+        if (!valid || new == NULL) goto exit;
+
+        g_object_unref(G_OBJECT(cond->expr));
+        cond->expr = new;
+
+        cond->final_reduced = true;
 
     }
 
     /* Tentative de récupération d'un bilan final */
 
-    if (G_IS_LITERAL_EXPRESSION(cond->expr))
+    if (cond->final_reduced)
     {
-        valid = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(cond->expr), &result);
+        valid = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(cond->expr), &result);
 
         if (!valid)
         {
diff --git a/src/analysis/scan/context.h b/src/analysis/scan/context.h
index 92522f8..563a53e 100644
--- a/src/analysis/scan/context.h
+++ b/src/analysis/scan/context.h
@@ -86,12 +86,18 @@ const phys_t *g_scan_context_get_atom_matches(const GScanContext *, patid_t, siz
 /* Enregistre une correspondance complète avec un contenu. */
 void g_scan_context_register_full_match(GScanContext *, GScanMatch *);
 
+/* Fournit la liste de toutes les correspondances d'un motif. */
+const GScanMatch **g_scan_context_get_full_matches(const GScanContext *, const GSearchPattern *, size_t *);
+
 /* Affiche les correspondances identifiées. */
-void g_scan_context_display(const GScanContext *);
+void g_scan_context_display(GScanContext *);
 
 /* Intègre une condition de correspondance pour règle. */
 bool g_scan_context_set_rule_condition(GScanContext *, const char *, const GScanExpression *);
 
+/* Indique si un nom donné correspond à une règle. */
+bool g_scan_context_has_rule_for_name(const GScanContext *, const char *);
+
 /* Indique si une correspondance globale a pu être établie. */
 bool g_scan_context_has_match_for_rule(GScanContext *, const char *);
 
diff --git a/src/analysis/scan/core.c b/src/analysis/scan/core.c
index aef9abd..d940ab5 100644
--- a/src/analysis/scan/core.c
+++ b/src/analysis/scan/core.c
@@ -24,8 +24,20 @@
 #include "core.h"
 
 
+#include <config.h>
+
+
+#include "items/count.h"
 #include "items/datasize.h"
 #include "items/uint.h"
+#include "items/console/log.h"
+#ifdef HAVE_MAGIC_SUPPORT
+#   include "items/magic/type.h"
+#   include "items/magic/mime-encoding.h"
+#   include "items/magic/mime-type.h"
+#endif
+#include "items/time/make.h"
+#include "items/time/now.h"
 
 
 
@@ -43,25 +55,83 @@
 
 bool populate_main_scan_namespace(GScanNamespace *space)
 {
-    bool result;
+    bool result;                            /* Bilan à retourner           */
+    GScanNamespace *ns;                     /* Nouvel espace de noms       */
 
     result = true;
 
-#define REGISTER_FUNC(s, f)                                                 \
-    ({                                                                      \
-        bool __result;                                                      \
-        __result = g_scan_namespace_register_item(s, G_REGISTERED_ITEM(f)); \
-        g_object_unref(G_OBJECT(f));                                        \
-        __result;                                                           \
+#define REGISTER_FUNC(s, f)                                 \
+    ({                                                      \
+        bool __result;                                      \
+        __result = g_scan_namespace_register_item(s, f);    \
+        g_object_unref(G_OBJECT(f));                        \
+        __result;                                           \
     })
 
-    if (result) result = REGISTER_FUNC(space, g_datasize_function_new());
-    //if (result) result = REGISTER_FUNC(space, g_datasize_function_new(), "filesize"); /* Alias */
+    if (result) result = REGISTER_FUNC(space, g_scan_count_function_new());
+    if (result) result = REGISTER_FUNC(space, g_scan_datasize_function_new());
+
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_8_BITS_SIGNED, SRE_LITTLE));
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_8_BITS_UNSIGNED, SRE_LITTLE));
+
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_SIGNED, SRE_LITTLE));
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_SIGNED, SRE_BIG));
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_UNSIGNED, SRE_LITTLE));
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_UNSIGNED, SRE_BIG));
+
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_SIGNED, SRE_LITTLE));
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_SIGNED, SRE_BIG));
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_UNSIGNED, SRE_LITTLE));
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_UNSIGNED, SRE_BIG));
+
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_SIGNED, SRE_LITTLE));
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_SIGNED, SRE_BIG));
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_UNSIGNED, SRE_LITTLE));
+    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_UNSIGNED, SRE_BIG));
+
+    /* Console */
+
+    if (result)
+    {
+        ns = g_scan_namespace_new("console");
+        result = g_scan_namespace_register_item(space, G_REGISTERED_ITEM(ns));
+
+        if (result) result = REGISTER_FUNC(ns, g_scan_console_log_function_new());
+
+        g_object_unref(G_OBJECT(ns));
+
+    }
+
+    /* Magic */
+
+#ifdef HAVE_MAGIC_SUPPORT
+    if (result)
+    {
+        ns = g_scan_namespace_new("magic");
+        result = g_scan_namespace_register_item(space, G_REGISTERED_ITEM(ns));
+
+        if (result) result = REGISTER_FUNC(ns, g_scan_magic_type_function_new());
+        if (result) result = REGISTER_FUNC(ns, g_scan_mime_encoding_function_new());
+        if (result) result = REGISTER_FUNC(ns, g_scan_mime_type_function_new());
+
+        g_object_unref(G_OBJECT(ns));
+
+    }
+#endif
+
+    /* Time */
+
+    if (result)
+    {
+        ns = g_scan_namespace_new("time");
+        result = g_scan_namespace_register_item(space, G_REGISTERED_ITEM(ns));
+
+        if (result) result = REGISTER_FUNC(ns, g_scan_time_make_function_new());
+        if (result) result = REGISTER_FUNC(ns, g_scan_time_now_function_new());
+
+        g_object_unref(G_OBJECT(ns));
 
-    if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_8_BITS_UNSIGNED));
-    if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_16_BITS_UNSIGNED));
-    if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_32_BITS_UNSIGNED));
-    if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_64_BITS_UNSIGNED));
+    }
 
     return result;
 
diff --git a/src/analysis/scan/expr-int.h b/src/analysis/scan/expr-int.h
index dbfea6e..48668b5 100644
--- a/src/analysis/scan/expr-int.h
+++ b/src/analysis/scan/expr-int.h
@@ -39,16 +39,28 @@
 typedef bool (* compare_expr_rich_fc) (const GScanExpression *, const GScanExpression *, RichCmpOperation, bool *);
 
 /* Vérifie la validité d'une expression. */
-typedef bool (* check_expr_validity_fc) (const GScanExpression *);
+typedef bool (* check_expr_validity_fc) (const GScanExpression *);    // REMME ?
 
 /* Reproduit une expression en place dans une nouvelle instance. */
-typedef GScanExpression * (* dup_expr_fc) (const GScanExpression *);
+typedef GScanExpression * (* dup_expr_fc) (const GScanExpression *);    // REMME ?
 
 /* Reproduit une expression en place dans une nouvelle instance. */
 typedef void (* copy_expr_fc) (GScanExpression *, const GScanExpression *);
 
 /* Réduit une expression à une forme plus simple. */
-typedef bool (* reduce_expr_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+typedef ScanReductionState (* reduce_expr_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+typedef bool (* reduce_expr_to_bool_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Dénombre les éléments portés par une expression. */
+typedef bool (* count_scan_expr_fc) (const GScanExpression *, size_t *);
+
+/* Fournit un élément donné issu d'un ensemble constitué. */
+typedef bool (* get_scan_expr_fc) (const GScanExpression *, size_t, GScanExpression **);
+
+/* Réalise l'intersection entre deux ensembles. */
+typedef GScanExpression * (* intersect_scan_expr_fc) (GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *);
 
 
 /* Expression d'évaluation généraliste (instance) */
@@ -56,6 +68,8 @@ struct _GScanExpression
 {
     GObject parent;                         /* A laisser en premier        */
 
+    ScanReductionState state;               /* Etat synthétisé de l'élément*/
+
     ExprValueType value_type;               /* Type de valeur portée       */
 
 };
@@ -67,9 +81,15 @@ struct _GScanExpressionClass
 
     compare_expr_rich_fc cmp_rich;          /* Comparaison de façon précise*/
     check_expr_validity_fc check;           /* Validation de la cohérence  */
-    copy_expr_fc copy;                      /* Reproduction d'expression   */
+    copy_expr_fc copyXXX;                      /* Reproduction d'expression   */
     dup_expr_fc dup;                        /* Reproduction d'expression   */
+
     reduce_expr_fc reduce;                  /* Simplification d'expression */
+    reduce_expr_to_bool_fc reduce_to_bool;  /* Conversion en booléen       */
+
+    count_scan_expr_fc count;               /* Décompte d'éléments         */
+    get_scan_expr_fc get;                   /* Extraction d'un élément     */
+    intersect_scan_expr_fc intersect;       /* Intersection entre ensembles*/
 
 };
 
diff --git a/src/analysis/scan/expr.c b/src/analysis/scan/expr.c
index 52d2c42..808b14f 100644
--- a/src/analysis/scan/expr.c
+++ b/src/analysis/scan/expr.c
@@ -28,6 +28,8 @@
 
 
 #include "expr-int.h"
+#include "exprs/literal.h"
+#include "exprs/set.h"
 
 
 
@@ -52,6 +54,9 @@ static void g_scan_expression_finalize(GScanExpression *);
 /* Reproduit une expression en place dans une nouvelle instance. */
 static void g_scan_expression_copy(GScanExpression *, const GScanExpression *);
 
+/* Réalise l'intersection entre deux ensembles. */
+static GScanExpression *_g_scan_expression_intersect(GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *);
+
 
 
 /* ----------------------- INTERFACE OFFRANT DES COMPARAISONS ----------------------- */
@@ -93,7 +98,8 @@ static void g_scan_expression_class_init(GScanExpressionClass *klass)
     object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_expression_dispose;
     object->finalize = (GObjectFinalizeFunc)g_scan_expression_finalize;
 
-    klass->copy = g_scan_expression_copy;
+    //klass->copy = g_scan_expression_copy;
+    klass->intersect = _g_scan_expression_intersect;
 
 }
 
@@ -112,6 +118,7 @@ static void g_scan_expression_class_init(GScanExpressionClass *klass)
 
 static void g_scan_expression_init(GScanExpression *expr)
 {
+    expr->state = SRS_PENDING;
 
 }
 
@@ -292,7 +299,7 @@ GScanExpression *g_scan_expression_duplicate(const GScanExpression *expr)
 
     class = G_SCAN_EXPRESSION_GET_CLASS(expr);
 
-    class->copy(result, expr);
+    //class->copy(result, expr);
 
     return result;
 
@@ -314,7 +321,200 @@ GScanExpression *g_scan_expression_duplicate(const GScanExpression *expr)
 *                                                                             *
 ******************************************************************************/
 
-bool g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+ScanReductionState g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    GScanExpressionClass *class;            /* Classe à activer            */
+
+    if (expr->state == SRS_REDUCED)
+    {
+        *out = expr;
+        g_object_ref(G_OBJECT(expr));
+    }
+
+    else
+    {
+        *out = NULL;
+
+        class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+        if (class->reduce != NULL)
+        {
+            expr->state = class->reduce(expr, ctx, scope, out);
+
+            if (expr->state != SRS_UNRESOLVABLE && *out == NULL)
+            {
+                *out = expr;
+                g_object_ref(G_OBJECT(expr));
+            }
+
+        }
+
+        else
+            expr->state = SRS_UNRESOLVABLE;
+
+#ifndef NDEBUG
+        if (*out != NULL)
+            assert(expr->state != SRS_UNRESOLVABLE);
+#endif
+
+    }
+
+    assert(expr->state != SRS_PENDING);
+
+
+    return expr->state;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme booléenne.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_expression_reduce_to_boolean(GScanExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    GScanExpression *inter;                 /* Expression intermédiaire    */
+    GScanExpressionClass *class;            /* Classe à activer            */
+
+    *out = NULL;
+
+    result = g_scan_expression_reduce(expr, ctx, scope, &inter);
+    if (!result) goto exit;
+
+    if (inter != NULL)
+    {
+        class = G_SCAN_EXPRESSION_GET_CLASS(inter);
+
+        if (class->reduce_to_bool != NULL)
+            result = class->reduce_to_bool(inter, ctx, scope, out);
+        else
+            result = false;
+
+        g_object_unref(G_OBJECT(inter));
+
+        /* Validation d'un type booléen */
+        if (result && *out != NULL)
+        {
+            if (!G_IS_SCAN_LITERAL_EXPRESSION(*out))
+            {
+                g_clear_object(out);
+                result = false;
+            }
+
+            if (g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(*out)) != LVT_BOOLEAN)
+            {
+                g_clear_object(out);
+                result = false;
+            }
+
+        }
+
+    }
+
+ exit:
+
+#ifndef NDEBUG
+    if (*out != NULL)
+        assert(result);
+#endif
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = expression à consulter.                               *
+*                                                                             *
+*  Description : Détermine si l'expression peut représenter un ensemble.      *
+*                                                                             *
+*  Retour      : Bilan de la consultation.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_expression_handle_set_features(const GScanExpression *expr)
+{
+    bool result;                            /* Bilan à retourner           */
+    GScanExpressionClass *class;            /* Classe à activer            */
+
+    class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+    result = (class->count != NULL);
+
+    assert((result && (class->get != NULL)) || (!result && (class->get == NULL)));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                count = quantité d'éléments déterminée. [OUT]                *
+*                                                                             *
+*  Description : Dénombre les éléments portés par une expression.             *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count)
+{
+    bool result;                            /* Bilan à retourner           */
+    GScanExpressionClass *class;            /* Classe à activer            */
+
+    *count = -1;
+
+    class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+    if (class->count != NULL)
+        result = class->count(expr, count);
+    else
+        result = false;
+
+#ifndef NDEBUG
+    if (*count != -1)
+        assert(result);
+#endif
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                index = indice de l'élément à transférer.                    *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Fournit un élément donné issu d'un ensemble constitué.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_expression_get_item(const GScanExpression *expr, size_t index, GScanExpression **out)
 {
     bool result;                            /* Bilan à retourner           */
     GScanExpressionClass *class;            /* Classe à activer            */
@@ -323,7 +523,17 @@ bool g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanSco
 
     class = G_SCAN_EXPRESSION_GET_CLASS(expr);
 
-    result = class->reduce(expr, ctx, scope, out);
+    if (class->get != NULL)
+    {
+        result = class->get(expr, index, out);
+
+        if (*out != NULL)
+            g_object_ref(G_OBJECT(*out));
+
+    }
+
+    else
+        result = false;
 
 #ifndef NDEBUG
     if (*out != NULL)
@@ -335,6 +545,133 @@ bool g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanSco
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à filtrer.                                *
+*                other = expression utilisée pour le filtrage.                *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                                                                             *
+*  Description : Réalise l'intersection entre deux ensembles.                 *
+*                                                                             *
+*  Retour      : Intersection entre les deux ensembles ou NULL en cas d'échec.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GScanExpression *_g_scan_expression_intersect(GScanExpression *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope)
+{
+    GScanExpression *result;                /* Instance à retourner        */
+    size_t other_count;                     /* Taille du second ensemble   */
+    bool valid;                             /* Bilan de validité           */
+    size_t expr_count;                      /* Taille du premier ensemble  */
+    size_t k;                               /* Boucle de parcours #1       */
+    GComparableItem *comparable;            /* Premier élément à comparer  */
+    size_t i;                               /* Boucle de parcours #2       */
+    GScanExpression *item;                  /* Elément à comparer          */
+    bool status;                            /* Bilan d'une comparaison     */
+
+    result = NULL;
+
+    valid = g_scan_expression_count_items(other, &other_count);
+    if (!valid) goto done;
+
+    /* Intersection entre deux ensembles ? */
+    if (g_scan_expression_handle_set_features(expr))
+    {
+        valid = g_scan_expression_count_items(expr, &expr_count);
+        if (!valid) goto done;
+
+        result = g_scan_generic_set_new();
+
+        for (k = 0; k < expr_count; k++)
+        {
+            valid = g_scan_expression_get_item(expr, k, &item);
+            if (!valid) break;
+
+            comparable = G_COMPARABLE_ITEM(item);
+
+            for (i = 0; i < other_count; i++)
+            {
+                valid = g_scan_expression_get_item(other, i, &item);
+                if (!valid) break;
+
+                valid = g_comparable_item_compare_rich(comparable, G_COMPARABLE_ITEM(item), RCO_EQ, &status);
+
+                if (valid && status)
+                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(result), item);
+
+                g_object_unref(G_OBJECT(item));
+
+            }
+
+            g_object_unref(G_OBJECT(comparable));
+
+        }
+
+    }
+
+    /* Intersection entre un élément et un ensemble */
+    else
+    {
+        comparable = G_COMPARABLE_ITEM(expr);
+
+        for (i = 0; i < other_count && result == NULL; i++)
+        {
+            valid = g_scan_expression_get_item(other, i, &item);
+            if (!valid) break;
+
+            valid = g_comparable_item_compare_rich(comparable, G_COMPARABLE_ITEM(item), RCO_EQ, &status);
+
+            if (valid && status)
+                result = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true });
+
+            g_object_unref(G_OBJECT(item));
+
+        }
+
+        if (result && result == NULL)
+            result = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false });
+
+    }
+
+ done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à filtrer.                                *
+*                other = expression utilisée pour le filtrage.                *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                                                                             *
+*  Description : Réalise l'intersection entre deux ensembles.                 *
+*                                                                             *
+*  Retour      : Intersection entre les deux ensembles ou NULL en cas d'échec.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanExpression *g_scan_expression_intersect(GScanExpression *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope)
+{
+    GScanExpression *result;                /* Instance à retourner        */
+    GScanExpressionClass *class;            /* Classe à activer            */
+
+    class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+    result = class->intersect(expr, other, ctx, scope);
+
+    return result;
+
+}
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                         INTERFACE OFFRANT DES COMPARAISONS                         */
@@ -364,7 +701,14 @@ static bool g_scan_expression_compare_rich(const GScanExpression *item, const GS
     class = G_SCAN_EXPRESSION_GET_CLASS(item);
 
     if (class->cmp_rich != NULL)
-        result = class->cmp_rich(item, other, op, status);
+    {
+        result = (G_TYPE_FROM_INSTANCE(item) == G_TYPE_FROM_INSTANCE(other));   // FIXME : subtype ? cf. literal ?
+
+        if (result)
+            result = class->cmp_rich(item, other, op, status);
+
+    }
+
     else
         result = false;
 
diff --git a/src/analysis/scan/expr.h b/src/analysis/scan/expr.h
index d596222..dd4bc3f 100644
--- a/src/analysis/scan/expr.h
+++ b/src/analysis/scan/expr.h
@@ -64,6 +64,16 @@ typedef enum _ExprValueType
 
 } ExprValueType;
 
+/* Etat de l'expression vis à vis des réductions */
+typedef enum _ScanReductionState
+{
+    SRS_PENDING,                            /* Nature à déterminer         */
+    SRS_REDUCED,                            /* Nature compacte finale      */
+    SRS_WAIT_FOR_SCAN,                      /* Nature vouée à évoluer      */
+    SRS_UNRESOLVABLE,                       /* Nature indéterminable       */
+
+} ScanReductionState;
+
 
 /* Indique le type défini pour une expression de validation. */
 GType g_scan_expression_get_type(void);
@@ -78,7 +88,22 @@ bool g_scan_expression_check_validity(const GScanExpression *);
 GScanExpression *g_scan_expression_duplicate(const GScanExpression *);
 
 /* Réduit une expression à une forme plus simple. */
-bool g_scan_expression_reduce(GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+ScanReductionState g_scan_expression_reduce(GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+bool g_scan_expression_reduce_to_boolean(GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Détermine si l'expression peut représenter un ensemble. */
+bool g_scan_expression_handle_set_features(const GScanExpression *);
+
+/* Dénombre les éléments portés par une expression. */
+bool g_scan_expression_count_items(const GScanExpression *, size_t *);
+
+/* Fournit un élément donné issu d'un ensemble constitué. */
+bool g_scan_expression_get_item(const GScanExpression *, size_t, GScanExpression **);
+
+/* Réalise l'intersection entre deux ensembles. */
+GScanExpression *g_scan_expression_intersect(GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *);
 
 
 
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am
index efe25fc..1266a63 100644
--- a/src/analysis/scan/exprs/Makefile.am
+++ b/src/analysis/scan/exprs/Makefile.am
@@ -5,16 +5,24 @@ noinst_LTLIBRARIES  = libanalysisscanexprs.la
 libanalysisscanexprs_la_SOURCES =			\
 	access-int.h							\
 	access.h access.c						\
-	arithmop-int.h							\
-	arithmop.h arithmop.c					\
-	boolop-int.h							\
-	boolop.h boolop.c						\
+	arithmetic-int.h						\
+	arithmetic.h arithmetic.c				\
 	call-int.h								\
 	call.h call.c							\
+	counter-int.h							\
+	counter.h counter.c						\
+	intersect-int.h							\
+	intersect.h intersect.c					\
 	literal-int.h							\
 	literal.h literal.c						\
-	relop-int.h								\
-	relop.h relop.c							\
+	logical-int.h							\
+	logical.h logical.c						\
+	range-int.h								\
+	range.h range.c							\
+	relational-int.h						\
+	relational.h relational.c				\
+	set-int.h								\
+	set.h set.c								\
 	strop-int.h								\
 	strop.h strop.c
 
diff --git a/src/analysis/scan/exprs/access-int.h b/src/analysis/scan/exprs/access-int.h
index 2212b48..725051c 100644
--- a/src/analysis/scan/exprs/access-int.h
+++ b/src/analysis/scan/exprs/access-int.h
@@ -32,8 +32,11 @@
 
 
 
+/* Reproduit un accès en place dans une nouvelle instance. */
+typedef void (* copy_scan_access_fc) (GScanNamedAccess *, const GScanNamedAccess *);
+
 /* Accès à un élément d'expression sous-jacent (instance) */
-struct _GNamedAccess
+struct _GScanNamedAccess
 {
     GScanExpression parent;                 /* A laisser en premier        */
 
@@ -46,23 +49,25 @@ struct _GNamedAccess
 
     char *target;                           /* Cible dans l'espace         */
 
-    struct _GNamedAccess *next;            /* Evnetuel prochain élément   */
+    struct _GScanNamedAccess *next;         /* Evnetuel prochain élément   */
 
 };
 
 /* Accès à un élément d'expression sous-jacent (classe) */
-struct _GNamedAccessClass
+struct _GScanNamedAccessClass
 {
     GScanExpressionClass parent;            /* A laisser en premier        */
 
+    copy_scan_access_fc copy;               /* Reproduction d'accès        */
+
 };
 
 
 /* Met en place une expression d'accès. */
-bool g_named_access_create(GNamedAccess *, const sized_string_t *);
+bool g_scan_named_access_create(GScanNamedAccess *, const sized_string_t *);
 
-/* Réduit une expression à une forme plus simple. */
-bool _g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
+/* Prépare une réduction en menant une résolution locale. */
+GRegisteredItem *_g_scan_named_access_prepare_reduction(GScanNamedAccess *, GScanContext *, GScanScope *);
 
 
 
diff --git a/src/analysis/scan/exprs/access.c b/src/analysis/scan/exprs/access.c
index ad66f60..1c3a880 100644
--- a/src/analysis/scan/exprs/access.c
+++ b/src/analysis/scan/exprs/access.c
@@ -30,6 +30,7 @@
 
 
 #include "access-int.h"
+#include "literal.h"
 #include "../../../core/global.h"
 
 
@@ -38,27 +39,27 @@
 
 
 /* Initialise la classe des appels de fonction avec arguments. */
-static void g_named_access_class_init(GNamedAccessClass *);
+static void g_scan_named_access_class_init(GScanNamedAccessClass *);
 
 /* Initialise une instance d'appel de fonction avec arguments. */
-static void g_named_access_init(GNamedAccess *);
+static void g_scan_named_access_init(GScanNamedAccess *);
 
 /* Supprime toutes les références externes. */
-static void g_named_access_dispose(GNamedAccess *);
+static void g_scan_named_access_dispose(GScanNamedAccess *);
 
 /* Procède à la libération totale de la mémoire. */
-static void g_named_access_finalize(GNamedAccess *);
+static void g_scan_named_access_finalize(GScanNamedAccess *);
 
+/* Reproduit un accès en place dans une nouvelle instance. */
+static void g_scan_named_access_copy(GScanNamedAccess *, const GScanNamedAccess *);
 
 
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
 
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
 
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_named_access_copy(GNamedAccess *, const GNamedAccess *);
 
 /* Réduit une expression à une forme plus simple. */
-static bool g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_named_access_reduce(GScanNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
 
 
 
@@ -68,7 +69,7 @@ static bool g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *,
 
 
 /* Indique le type défini pour un appel de fonction enregistrée. */
-G_DEFINE_TYPE(GNamedAccess, g_named_access, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanNamedAccess, g_scan_named_access, G_TYPE_SCAN_EXPRESSION);
 
 
 /******************************************************************************
@@ -83,21 +84,22 @@ G_DEFINE_TYPE(GNamedAccess, g_named_access, G_TYPE_SCAN_EXPRESSION);
 *                                                                             *
 ******************************************************************************/
 
-static void g_named_access_class_init(GNamedAccessClass *klass)
+static void g_scan_named_access_class_init(GScanNamedAccessClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GScanExpressionClass *expr;             /* Version de classe parente   */
 
     object = G_OBJECT_CLASS(klass);
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_named_access_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_named_access_finalize;
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_named_access_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_named_access_finalize;
 
     expr = G_SCAN_EXPRESSION_CLASS(klass);
 
     expr->cmp_rich = (compare_expr_rich_fc)NULL;
-    expr->copy = (copy_expr_fc)g_named_access_copy;
-    expr->reduce = (reduce_expr_fc)g_named_access_reduce;
+    expr->reduce = (reduce_expr_fc)g_scan_named_access_reduce;
+
+    klass->copy = g_scan_named_access_copy;
 
 }
 
@@ -114,7 +116,7 @@ static void g_named_access_class_init(GNamedAccessClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_named_access_init(GNamedAccess *access)
+static void g_scan_named_access_init(GScanNamedAccess *access)
 {
     access->any = NULL;
     access->target = NULL;
@@ -136,13 +138,13 @@ static void g_named_access_init(GNamedAccess *access)
 *                                                                             *
 ******************************************************************************/
 
-static void g_named_access_dispose(GNamedAccess *access)
+static void g_scan_named_access_dispose(GScanNamedAccess *access)
 {
     g_clear_object(&access->any);
 
     g_clear_object(&access->next);
 
-    G_OBJECT_CLASS(g_named_access_parent_class)->dispose(G_OBJECT(access));
+    G_OBJECT_CLASS(g_scan_named_access_parent_class)->dispose(G_OBJECT(access));
 
 }
 
@@ -159,12 +161,12 @@ static void g_named_access_dispose(GNamedAccess *access)
 *                                                                             *
 ******************************************************************************/
 
-static void g_named_access_finalize(GNamedAccess *access)
+static void g_scan_named_access_finalize(GScanNamedAccess *access)
 {
     if (access->target != NULL)
         free(access->target);
 
-    G_OBJECT_CLASS(g_named_access_parent_class)->finalize(G_OBJECT(access));
+    G_OBJECT_CLASS(g_scan_named_access_parent_class)->finalize(G_OBJECT(access));
 
 }
 
@@ -181,13 +183,13 @@ static void g_named_access_finalize(GNamedAccess *access)
 *                                                                             *
 ******************************************************************************/
 
-GScanExpression *g_named_access_new(const sized_string_t *target)
+GScanExpression *g_scan_named_access_new(const sized_string_t *target)
 {
     GScanExpression *result;                /* Structure à retourner       */
 
-    result = g_object_new(G_TYPE_NAMED_ACCESS, NULL);
+    result = g_object_new(G_TYPE_SCAN_NAMED_ACCESS, NULL);
 
-    if (!g_named_access_create(G_NAMED_ACCESS(result), target))
+    if (!g_scan_named_access_create(G_SCAN_NAMED_ACCESS(result), target))
         g_clear_object(&result);
 
     return result;
@@ -208,16 +210,14 @@ GScanExpression *g_named_access_new(const sized_string_t *target)
 *                                                                             *
 ******************************************************************************/
 
-bool g_named_access_create(GNamedAccess *access, const sized_string_t *target)
+bool g_scan_named_access_create(GScanNamedAccess *access, const sized_string_t *target)
 {
     bool result;                            /* Bilan à retourner           */
 
-    result = g_scan_expression_create(G_SCAN_EXPRESSION(access), EVT_PENDING);
-    if (!result) goto exit;
-
-    access->target = strndup(target->data, target->len);
+    result = true;
 
- exit:
+    if (target != NULL)
+        access->target = strndup(target->data, target->len);
 
     return result;
 
@@ -226,10 +226,10 @@ bool g_named_access_create(GNamedAccess *access, const sized_string_t *target)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : access = expression d'appel à actualiser.                    *
-*                base   = zone de recherche pour la résolution à venir.       *
+*  Paramètres  : dest = emplacement d'enregistrement à constituer. [OUT]      *
+*                src  = expression source à copier.                           *
 *                                                                             *
-*  Description : Définit une base de recherche pour la cible d'accès.         *
+*  Description : Reproduit un accès en place dans une nouvelle instance.      *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -237,55 +237,74 @@ bool g_named_access_create(GNamedAccess *access, const sized_string_t *target)
 *                                                                             *
 ******************************************************************************/
 
-void g_named_access_set_base(GNamedAccess *access, GRegisteredItem *base)
+static void g_scan_named_access_copy(GScanNamedAccess *dest, const GScanNamedAccess *src)
 {
-    g_clear_object(&access->base);
+    /**
+     * Les champs suivants sont voués à être remplacés ou supprimés.
+     *
+     * On évite donc une instanciation inutile.
+     */
 
-    access->base = base;
-    g_object_ref(G_OBJECT(base));
+    /*
+    if (src->any != NULL)
+    {
+        dest->any = src->any;
+        g_object_ref(src->any);
+    }
+    */
+
+    if (src->target != NULL)
+        dest->target = strdup(src->target);
+
+    if (src->next != NULL)
+    {
+        dest->next = src->next;
+        g_object_ref(src->next);
+    }
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : access = expression d'appel à compléter.                     *
-*                next   = expression d'appel suivante dans la chaîne.         *
+*  Paramètres  : accès    = expression d'accès à copier.                      *
+*                resolved = nouvelle base à imposer.                          *
 *                                                                             *
-*  Description : Complète la chaine d'accès à des expressions.                *
+*  Description : Reproduit un accès en place dans une nouvelle instance.      *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Nouvelle instance d'expression d'accès.                      *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_named_access_attach_next(GNamedAccess *access, GNamedAccess *next)
+GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *access, GRegisteredItem *resolved)
 {
-    if (access->next != NULL)
-        g_named_access_attach_next(access->next, next);
+    GScanExpression *result;                /* Instance copiée à retourner */
+    GType type;                             /* Type d'objet à copier       */
+    GScanNamedAccessClass *class;           /* Classe à activer            */
 
-    else
-    {
-        access->next = next;
-        g_object_ref(G_OBJECT(next));
-    }
+    type = G_TYPE_FROM_INSTANCE(access);
 
-}
+    result = g_object_new(type, NULL);
 
+    class = G_SCAN_NAMED_ACCESS_GET_CLASS(access);
 
+    class->copy(G_SCAN_NAMED_ACCESS(result), access);
 
-/* ---------------------------------------------------------------------------------- */
-/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
-/* ---------------------------------------------------------------------------------- */
+    g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(result), resolved);
+
+    return result;
+
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : dest = emplacement d'enregistrement à constituer. [OUT]      *
-*                src  = expression source à copier.                           *
+*  Paramètres  : access = expression d'appel à actualiser.                    *
+*                base   = zone de recherche pour la résolution à venir.       *
 *                                                                             *
-*  Description : Reproduit une expression en place dans une nouvelle instance.*
+*  Description : Définit une base de recherche pour la cible d'accès.         *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -293,27 +312,47 @@ void g_named_access_attach_next(GNamedAccess *access, GNamedAccess *next)
 *                                                                             *
 ******************************************************************************/
 
-static void g_named_access_copy(GNamedAccess *dest, const GNamedAccess *src)
+void g_scan_named_access_set_base(GScanNamedAccess *access, GRegisteredItem *base)
 {
-    GScanExpressionClass *class;            /* Classe parente à solliciter */
+    g_clear_object(&access->base);
 
-    class = G_SCAN_EXPRESSION_CLASS(g_named_access_parent_class);
+    access->base = base;
+    g_object_ref(G_OBJECT(base));
 
-    class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+}
 
-    if (src->any != NULL)
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : access = expression d'appel à compléter.                     *
+*                next   = expression d'appel suivante dans la chaîne.         *
+*                                                                             *
+*  Description : Complète la chaine d'accès à des expressions.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_named_access_attach_next(GScanNamedAccess *access, GScanNamedAccess *next)
+{
+    if (access->next != NULL)
+        g_scan_named_access_attach_next(access->next, next);
+
+    else
     {
-        dest->any = src->any;
-        g_object_ref(src->any);
+        access->next = next;
+        g_object_ref(G_OBJECT(next));
     }
 
-    if (src->target != NULL)
-        dest->target = strdup(src->target);
+}
 
-    if (src->next != NULL)
-        dest->next = G_NAMED_ACCESS(g_scan_expression_duplicate(G_SCAN_EXPRESSION(src->next)));
 
-}
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
 
 
 /******************************************************************************
@@ -321,24 +360,21 @@ static void g_named_access_copy(GNamedAccess *dest, const GNamedAccess *src)
 *  Paramètres  : expr  = expression à consulter.                              *
 *                ctx   = contexte de suivi de l'analyse courante.             *
 *                scope = portée courante des variables locales.               *
-*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
 *                                                                             *
-*  Description : Réduit une expression à une forme plus simple.               *
+*  Description : Prépare une réduction en menant une résolution locale.       *
 *                                                                             *
-*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*  Retour      : Elément résolu avec les moyens du bord ou NULL si échec.     *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+GRegisteredItem *_g_scan_named_access_prepare_reduction(GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope)
 {
-    bool result;                            /* Bilan à retourner           */
+    GRegisteredItem *result;                /* Etat synthétisé à retourner */
     GRegisteredItem *base;                  /* Base de recherche courante  */
-    GRegisteredItem *resolved;              /* Cible concrète obtenue      */
-    GNamedAccess *new;                      /* Copie mise en place         */
 
-    result = true;
+    result = NULL;
 
     if (expr->target != NULL)
     {
@@ -350,24 +386,7 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s
         else
             base = G_REGISTERED_ITEM(get_rost_root_namespace());
 
-        result = g_registered_item_resolve(base, expr->target, ctx, scope, &resolved);
-
-        g_object_unref(G_OBJECT(base));
-
-        if (result && resolved != NULL)
-        {
-            new = G_NAMED_ACCESS(g_scan_expression_duplicate(G_SCAN_EXPRESSION(expr)));
-
-            g_clear_object(&new->base);
-
-            free(new->target);
-            new->target = NULL;
-
-            new->resolved = resolved;
-
-            *out = G_SCAN_EXPRESSION(new);
-
-        }
+        g_registered_item_resolve(base, expr->target, ctx, scope, &result);
 
     }
 
@@ -379,8 +398,8 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s
     {
         assert(expr->resolved != NULL);
 
-        *out = G_SCAN_EXPRESSION(expr);
-        g_object_ref(G_OBJECT(*out));
+        result = expr->resolved;
+        g_object_ref(G_OBJECT(result));
 
     }
 
@@ -404,25 +423,18 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s
 *                                                                             *
 ******************************************************************************/
 
-static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_named_access_reduce(GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
 {
-    bool result;                            /* Bilan à retourner           */
-    GNamedAccess *new;                      /* Eventuel étage suivant      */
-    GScanExpression *final;                 /* Expression d'évaluation     */
+    ScanReductionState result;              /* Etat synthétisé à retourner */
+    GRegisteredItem *resolved;              /* Cible concrète obtenue      */
     GScanExpression *new_next;              /* Nouvelle version du suivant */
+    bool status;                            /* Bilan d'une autre règle     */
 
-    result = _g_named_access_reduce(expr, ctx, scope, out);
+    resolved = _g_scan_named_access_prepare_reduction(expr, ctx, scope);
 
-    if (result && *out != NULL)
+    if (resolved != NULL)
     {
-        assert(G_IS_NAMED_ACCESS(*out));
-
-        new = G_NAMED_ACCESS(*out);
-        *out = NULL;
-
-        assert(new->target == NULL);
-        assert(G_IS_NAMED_ACCESS(new));
-        assert(G_IS_REGISTERED_ITEM(new->resolved));
+        result = SRS_PENDING;
 
         /**
          * Si l'élément résolu se trouve en fin de chaîne, alors cet élément
@@ -430,15 +442,11 @@ static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanSc
          * Le produit de cette réduction finale bénéficie d'une promotion et
          * représente à lui seul la réduction produite pour la chaîne.
          */
-        if (new->next == NULL)
+        if (expr->next == NULL)
         {
-            result = g_registered_item_reduce(new->resolved, ctx, scope, &final);
+            status = g_registered_item_reduce(resolved, ctx, scope, out);
 
-            if (result && final != NULL)
-            {
-                g_clear_object(out);
-                *out = final;
-            }
+            result = (status ? SRS_REDUCED : SRS_UNRESOLVABLE);
 
         }
 
@@ -448,21 +456,34 @@ static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanSc
          */
         else
         {
-            new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next));
-            assert(G_IS_NAMED_ACCESS(new_next));
-
-            g_named_access_set_base(G_NAMED_ACCESS(new_next), new->resolved);
-
-            g_clear_object(out);
+            new_next = g_scan_named_access_duplicate(expr->next, resolved);
 
             result = g_scan_expression_reduce(new_next, ctx, scope, out);
 
-            if (result && *out == NULL)
-                *out = new_next;
+            g_object_unref(G_OBJECT(new_next));
 
         }
 
-        g_object_unref(G_OBJECT(new));
+        g_object_unref(G_OBJECT(resolved));
+
+    }
+
+    /**
+     * Si le nom fournit le correspond à aucun élément de la grammaire,
+     * des recherches sont menées ailleurs.
+     */
+    else
+    {
+        result = SRS_UNRESOLVABLE;
+
+        if (g_scan_context_has_rule_for_name(ctx, expr->target))
+        {
+            status = g_scan_context_has_match_for_rule(ctx, expr->target);
+
+            *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+            result = SRS_REDUCED;
+
+        }
 
     }
 
diff --git a/src/analysis/scan/exprs/access.h b/src/analysis/scan/exprs/access.h
index a04adc7..7c007a9 100644
--- a/src/analysis/scan/exprs/access.h
+++ b/src/analysis/scan/exprs/access.h
@@ -31,32 +31,35 @@
 
 
 
-#define G_TYPE_NAMED_ACCESS            g_named_access_get_type()
-#define G_NAMED_ACCESS(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_NAMED_ACCESS, GNamedAccess))
-#define G_IS_NAMED_ACCESS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_NAMED_ACCESS))
-#define G_NAMED_ACCESS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_NAMED_ACCESS, GNamedAccessClass))
-#define G_IS_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_NAMED_ACCESS))
-#define G_NAMED_ACCESS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_NAMED_ACCESS, GNamedAccessClass))
+#define G_TYPE_SCAN_NAMED_ACCESS            g_scan_named_access_get_type()
+#define G_SCAN_NAMED_ACCESS(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccess))
+#define G_IS_SCAN_NAMED_ACCESS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_NAMED_ACCESS))
+#define G_SCAN_NAMED_ACCESS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccessClass))
+#define G_IS_SCAN_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_NAMED_ACCESS))
+#define G_SCAN_NAMED_ACCESS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccessClass))
 
 
 /* Accès à un élément d'expression sous-jacent (instance) */
-typedef struct _GNamedAccess GNamedAccess;
+typedef struct _GScanNamedAccess GScanNamedAccess;
 
 /* Accès à un élément d'expression sous-jacent (classe) */
-typedef struct _GNamedAccessClass GNamedAccessClass;
+typedef struct _GScanNamedAccessClass GScanNamedAccessClass;
 
 
 /* Indique le type défini pour un appel de fonction enregistrée. */
-GType g_named_access_get_type(void);
+GType g_scan_named_access_get_type(void);
 
 /* Organise un accès à un élément d'expression sous-jacent. */
-GScanExpression *g_named_access_new(const sized_string_t *);
+GScanExpression *g_scan_named_access_new(const sized_string_t *);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *, GRegisteredItem *);
 
 /* Définit une base de recherche pour la cible d'accès. */
-void g_named_access_set_base(GNamedAccess *, GRegisteredItem *);
+void g_scan_named_access_set_base(GScanNamedAccess *, GRegisteredItem *);
 
 /* Complète la chaine d'accès à des expressions. */
-void g_named_access_attach_next(GNamedAccess *, GNamedAccess *);
+void g_scan_named_access_attach_next(GScanNamedAccess *, GScanNamedAccess *);
 
 
 
diff --git a/src/analysis/scan/exprs/arithmetic-int.h b/src/analysis/scan/exprs/arithmetic-int.h
new file mode 100644
index 0000000..c5010b0
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmetic-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmetic-int.h - prototypes internes pour la gestion des opérations arithmétiques
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H
+#define _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H
+
+
+#include "arithmetic.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération arithmétique impliquant deux opérandes (instance) */
+struct _GScanArithmeticOperation
+{
+    GScanExpression parent;                 /* A laisser en premier        */
+
+    ArithmeticExpressionOperator operator;  /* Type d'opération menée      */
+
+    GScanExpression *left;                  /* Expression impactée #1      */
+    GScanExpression *right;                 /* Expression impactée #2      */
+
+};
+
+/* Opération arithmétique impliquant deux opérandes (classe) */
+struct _GScanArithmeticOperationClass
+{
+    GScanExpressionClass parent;            /* A laisser en premier        */
+
+};
+
+
+/* Met en place une opération arithmétique entre expressions. */
+bool g_scan_arithmetic_operation_create(GScanArithmeticOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H */
diff --git a/src/analysis/scan/exprs/arithmetic.c b/src/analysis/scan/exprs/arithmetic.c
new file mode 100644
index 0000000..0c01d2a
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmetic.c
@@ -0,0 +1,638 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmetic.c - gestion des opérations arithmétiques
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "arithmetic.h"
+
+
+#include <assert.h>
+
+
+#include "arithmetic-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations arithmétiques. */
+static void g_scan_arithmetic_operation_class_init(GScanArithmeticOperationClass *);
+
+/* Initialise une instance d'opération arithmétique. */
+static void g_scan_arithmetic_operation_init(GScanArithmeticOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_arithmetic_operation_dispose(GScanArithmeticOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_arithmetic_operation_finalize(GScanArithmeticOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_scan_arithmetic_operation_compare_rich(const GScanArithmeticOperation *, const GScanArithmeticOperation *, RichCmpOperation, bool *);
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_arithmetic_operation_reduce(GScanArithmeticOperation *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+G_DEFINE_TYPE(GScanArithmeticOperation, g_scan_arithmetic_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des opérations arithmétiques.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_class_init(GScanArithmeticOperationClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanExpressionClass *expr;             /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_arithmetic_operation_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_arithmetic_operation_finalize;
+
+    expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+    expr->cmp_rich = (compare_expr_rich_fc)g_scan_arithmetic_operation_compare_rich;
+    expr->reduce = (reduce_expr_fc)g_scan_arithmetic_operation_reduce;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance à initialiser.                                 *
+*                                                                             *
+*  Description : Initialise une instance d'opération arithmétique.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_init(GScanArithmeticOperation *op)
+{
+    op->left = NULL;
+    op->right = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance d'objet GLib à traiter.                        *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_dispose(GScanArithmeticOperation *op)
+{
+    g_clear_object(&op->left);
+    g_clear_object(&op->right);
+
+    G_OBJECT_CLASS(g_scan_arithmetic_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance d'objet GLib à traiter.                        *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_finalize(GScanArithmeticOperation *op)
+{
+    G_OBJECT_CLASS(g_scan_arithmetic_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : operator = type d'opération arithmétique à représenter.      *
+*                left     = premier opérande concerné.                        *
+*                right    = éventuel second opérande impliqué ou NULL.        *
+*                                                                             *
+*  Description : Organise une opération arithmétique entre expressions.       *
+*                                                                             *
+*  Retour      : Fonction mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanExpression *g_scan_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_ARITHMETIC_OPERATION, NULL);
+
+    if (!g_scan_arithmetic_operation_create(G_SCAN_ARITHMETIC_OPERATION(result), operator, left, right))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op       = instance à initialiser pleinement.                *
+*                operator = type d'opération booléenne à représenter.         *
+*                left     = premier opérande concerné.                        *
+*                right    = éventuel second opérande impliqué ou NULL.        *
+*                                                                             *
+*  Description : Met en place une opération arithmétique entre expressions.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_arithmetic_operation_create(GScanArithmeticOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    op->operator = operator;
+
+    op->left = left;
+    g_object_ref(G_OBJECT(op->left));
+
+    op->right = right;
+    g_object_ref(G_OBJECT(op->right));
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item   = premier objet à consulter pour une comparaison.     *
+*                other  = second objet à consulter pour une comparaison.      *
+*                op     = opération de comparaison à réaliser.                *
+*                status = bilan des opérations de comparaison. [OUT]          *
+*                                                                             *
+*  Description : Réalise une comparaison entre objets selon un critère précis.*
+*                                                                             *
+*  Retour      : true si la comparaison a pu être effectuée, false sinon.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_arithmetic_operation_compare_rich(const GScanArithmeticOperation *item, const GScanArithmeticOperation *other, RichCmpOperation op, bool *status)
+{
+    bool result;                            /* Etat à retourner            */
+
+    result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_ARITHMETIC_OPERATION);
+    if (!result) goto done;
+
+    if (item->operator != other->operator)
+    {
+        result = compare_rich_integer_values_unsigned(item->operator, other->operator, op);
+        goto done;
+    }
+
+    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left),
+                                            G_COMPARABLE_ITEM(other->left),
+                                            op, status);
+    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
+                                            G_COMPARABLE_ITEM(other->right),
+                                            op, status);
+
+ done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static ScanReductionState g_scan_arithmetic_operation_reduce(GScanArithmeticOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    ScanReductionState result;              /* Etat synthétisé à retourner */
+    GScanExpression *new_left;              /* Expression réduite (gauche) */
+    GScanExpression *new_right;             /* Expression réduite (droite) */
+    ScanReductionState state_left;          /* Etat synthétisé #1          */
+    ScanReductionState state_right;         /* Etat synthétisé #2          */
+    GScanLiteralExpression *op_left;        /* Opérande gauche final       */
+    GScanLiteralExpression *op_right;       /* Opérande droite final       */
+    LiteralValueType vtype_left;            /* Type de valeur portée #1    */
+    LiteralValueType vtype_right;           /* Type de valeur portée #2    */
+    long long val_1_s;                      /* Première valeur à traiter   */
+    unsigned long long val_1_u;             /* Première valeur à traiter   */
+    long long val_2_s;                      /* Seconde valeur à traiter    */
+    unsigned long long val_2_u;             /* Seconde valeur à traiter    */
+    LiteralValueType state_final;           /* Nature de la valeur finale  */
+    long long reduced_s;                    /* Valeur réduite finale       */
+    unsigned long long reduced_u;           /* Valeur réduite finale       */
+
+    /* Réduction des éléments considérés */
+
+    new_left = NULL;
+    new_right = NULL;
+
+    state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+    if (state_left == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+    if (state_right == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    /* Construction d'une réduction locale ? */
+
+    if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
+    {
+        /* Récupération de l'opérande de gauche */
+
+        op_left = G_SCAN_LITERAL_EXPRESSION(new_left);
+        vtype_left = g_scan_literal_expression_get_value_type(op_left);
+
+        if (vtype_left == LVT_SIGNED_INTEGER)
+        {
+            if (!g_scan_literal_expression_get_signed_integer_value(op_left, &val_1_s))
+            {
+                result = SRS_UNRESOLVABLE;
+                goto exit;
+            }
+        }
+        else if (vtype_left == LVT_UNSIGNED_INTEGER)
+        {
+            if (!g_scan_literal_expression_get_unsigned_integer_value(op_left, &val_1_u))
+            {
+                result = SRS_UNRESOLVABLE;
+                goto exit;
+            }
+        }
+        else
+        {
+            result = SRS_UNRESOLVABLE;
+            goto exit;
+        }
+
+        /* Récupération de l'opérande de droite */
+
+        op_right = G_SCAN_LITERAL_EXPRESSION(new_right);
+        vtype_right = g_scan_literal_expression_get_value_type(op_right);
+
+        if (vtype_right == LVT_SIGNED_INTEGER)
+        {
+            if (!g_scan_literal_expression_get_signed_integer_value(op_right, &val_2_s))
+            {
+                result = SRS_UNRESOLVABLE;
+                goto exit;
+            }
+        }
+        else if (vtype_right == LVT_UNSIGNED_INTEGER)
+        {
+            if (!g_scan_literal_expression_get_unsigned_integer_value(op_right, &val_2_u))
+            {
+                result = SRS_UNRESOLVABLE;
+                goto exit;
+            }
+        }
+        else
+        {
+            result = SRS_UNRESOLVABLE;
+            goto exit;
+        }
+
+        /* Partie des calculs */
+
+        result = SRS_REDUCED;
+
+        switch (expr->operator)
+        {
+            case AEO_PLUS:
+                if (vtype_left == LVT_SIGNED_INTEGER)
+                {
+                    if (vtype_right == LVT_SIGNED_INTEGER)
+                    {
+                        state_final = LVT_SIGNED_INTEGER;
+                        reduced_s = val_1_s + val_2_s;
+                    }
+                    else
+                    {
+                        assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+                        if ((long long)val_2_u > val_1_s)
+                        {
+                            state_final = LVT_UNSIGNED_INTEGER;
+                            reduced_u = val_1_s + (long long)val_2_u;
+                        }
+                        else
+                        {
+                            state_final = LVT_SIGNED_INTEGER;
+                            reduced_s = val_1_s + (long long)val_2_u;
+                        }
+
+                    }
+                }
+                else
+                {
+                    assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+                    if (vtype_right == LVT_SIGNED_INTEGER)
+                    {
+                        if ((long long)val_1_u > val_2_s)
+                        {
+                            state_final = LVT_UNSIGNED_INTEGER;
+                            reduced_u = (long long)val_1_u + val_2_s;
+                        }
+                        else
+                        {
+                            state_final = LVT_SIGNED_INTEGER;
+                            reduced_s = (long long)val_1_u + val_2_s;
+                        }
+
+                    }
+                    else
+                    {
+                        assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+                        state_final = LVT_UNSIGNED_INTEGER;
+                        reduced_u = val_1_u + val_2_u;
+
+                    }
+                }
+                break;
+
+            case AEO_MINUS:
+                if (vtype_left == LVT_SIGNED_INTEGER)
+                {
+                    if (vtype_right == LVT_SIGNED_INTEGER)
+                    {
+                        if (val_2_s < val_1_s)
+                        {
+                            state_final = LVT_UNSIGNED_INTEGER;
+                            reduced_u = val_1_s - val_2_s;
+                        }
+                        else
+                        {
+                            state_final = LVT_SIGNED_INTEGER;
+                            reduced_s = val_1_s - val_2_s;
+                        }
+
+                    }
+                    else
+                    {
+                        assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+                        state_final = LVT_SIGNED_INTEGER;
+                        reduced_s = val_1_s - (long long)val_2_u;
+
+                    }
+                }
+                else
+                {
+                    assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+                    if (vtype_right == LVT_SIGNED_INTEGER)
+                    {
+                        state_final = LVT_UNSIGNED_INTEGER;
+                        reduced_u = (long long)val_1_u - val_2_s;
+                    }
+                    else
+                    {
+                        assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+                        if (val_1_u > val_2_u)
+                        {
+                            state_final = LVT_UNSIGNED_INTEGER;
+                            reduced_u = val_1_u - val_2_u;
+                        }
+                        else
+                        {
+                            state_final = LVT_SIGNED_INTEGER;
+                            reduced_s = val_1_u - val_2_u;
+                        }
+
+                    }
+                }
+                break;
+
+            case AEO_MUL:
+                if (vtype_left == LVT_SIGNED_INTEGER)
+                {
+                    if (vtype_right == LVT_SIGNED_INTEGER)
+                    {
+                        state_final = LVT_UNSIGNED_INTEGER;
+                        reduced_u = val_1_s * val_2_s;
+                    }
+                    else
+                    {
+                        assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+                        state_final = LVT_SIGNED_INTEGER;
+                        reduced_s = val_1_s * (long long)val_2_u;
+
+                    }
+                }
+                else
+                {
+                    assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+                    if (vtype_right == LVT_SIGNED_INTEGER)
+                    {
+                        state_final = LVT_SIGNED_INTEGER;
+                        reduced_s = (long long)val_1_u * val_2_s;
+                    }
+                    else
+                    {
+                        assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+                        state_final = LVT_UNSIGNED_INTEGER;
+                        reduced_u = val_1_u * val_2_u;
+
+                    }
+                }
+                break;
+
+            case AEO_DIV:
+                if ((vtype_right == LVT_SIGNED_INTEGER && val_2_s == 0)
+                    || (vtype_right == LVT_UNSIGNED_INTEGER && val_2_u == 0))
+                {
+                    result = SRS_UNRESOLVABLE;
+                    break;
+                }
+
+                if (vtype_left == LVT_SIGNED_INTEGER)
+                {
+                    if (vtype_right == LVT_SIGNED_INTEGER)
+                    {
+                        state_final = LVT_UNSIGNED_INTEGER;
+                        reduced_u = val_1_s / val_2_s;
+                    }
+                    else
+                    {
+                        assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+                        state_final = LVT_SIGNED_INTEGER;
+                        reduced_s = val_1_s / (long long)val_2_u;
+
+                    }
+                }
+                else
+                {
+                    assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+                    if (vtype_right == LVT_SIGNED_INTEGER)
+                    {
+                        state_final = LVT_SIGNED_INTEGER;
+                        reduced_s = (long long)val_1_u / val_2_s;
+                    }
+                    else
+                    {
+                        assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+                        state_final = LVT_UNSIGNED_INTEGER;
+                        reduced_u = val_1_u / val_2_u;
+
+                    }
+                }
+                break;
+
+            case AEO_MOD:
+                result = SRS_UNRESOLVABLE;
+                /* FIXME 
+                result = (val_2 != 0);
+                if (result)
+                    reduced = val_1 % val_2;
+                */
+                break;
+
+        }
+
+        if (result == SRS_REDUCED)
+        {
+            if (state_final == LVT_SIGNED_INTEGER)
+                *out = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &reduced_s);
+            else
+            {
+                assert(state_final == LVT_UNSIGNED_INTEGER);
+                *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &reduced_u);
+            }
+
+        }
+
+    }
+
+    /* Mise à jour de la progression ? */
+
+    else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
+    {
+        if (new_left != expr->left || new_right != expr->right)
+            *out = g_scan_arithmetic_operation_new(expr->operator, new_left, new_right);
+
+        result = SRS_WAIT_FOR_SCAN;
+
+    }
+
+    /* Cas des situations où les expressions ne sont pas exploitables (!) */
+    else
+    {
+        assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+        result = SRS_UNRESOLVABLE;
+
+    }
+
+    /* Sortie propre */
+
+ exit:
+
+    g_clear_object(&new_left);
+    g_clear_object(&new_right);
+
+    return result;
+
+}
diff --git a/src/analysis/scan/exprs/arithmetic.h b/src/analysis/scan/exprs/arithmetic.h
new file mode 100644
index 0000000..8a1e844
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmetic.h
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmetic.h - prototypes pour la gestion des opérations arithmétiques
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H
+#define _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_ARITHMETIC_OPERATION            g_scan_arithmetic_operation_get_type()
+#define G_SCAN_ARITHMETIC_OPERATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperation))
+#define G_IS_SCAN_ARITHMETIC_OPERATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION))
+#define G_SCAN_ARITHMETIC_OPERATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperationClass))
+#define G_IS_SCAN_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_ARITHMETIC_OPERATION))
+#define G_SCAN_ARITHMETIC_OPERATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperationClass))
+
+
+/* Opération arithmétique impliquant deux opérandes (instance) */
+typedef struct _GScanArithmeticOperation GScanArithmeticOperation;
+
+/* Opération arithmétique impliquant deux opérandes (classe) */
+typedef struct _GScanArithmeticOperationClass GScanArithmeticOperationClass;
+
+
+/* Type d'opération arithmétique */
+typedef enum _ArithmeticExpressionOperator
+{
+    AEO_PLUS,                               /* Opération binaire "+"       */
+    AEO_MINUS,                              /* Opération binaire "-"       */
+    AEO_MUL,                                /* Opération binaire "*"       */
+    AEO_DIV,                                /* Opération binaire "\"       */
+    AEO_MOD,                                /* Opération binaire "%"       */
+
+} ArithmeticExpressionOperator;
+
+
+/* Indique le type défini pour une opération arithmétique entre expressions. */
+GType g_scan_arithmetic_operation_get_type(void);
+
+/* Organise une opération arithmétique entre expressions. */
+GScanExpression *g_scan_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H */
diff --git a/src/analysis/scan/exprs/arithmop-int.h b/src/analysis/scan/exprs/arithmop-int.h
deleted file mode 100644
index 031de84..0000000
--- a/src/analysis/scan/exprs/arithmop-int.h
+++ /dev/null
@@ -1,60 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * arithmop-int.h - prototypes internes pour la gestion des opérations arithmétiques
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H
-#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H
-
-
-#include "arithmop.h"
-
-
-#include "../expr-int.h"
-
-
-
-/* Opération arithmétique impliquant deux opérandes (instance) */
-struct _GArithmOperation
-{
-    GScanExpression parent;                 /* A laisser en premier        */
-
-    ArithmeticExpressionOperator operator;  /* Type d'opération menée      */
-
-    GScanExpression *left;                  /* Expression impactée #1      */
-    GScanExpression *right;                 /* Expression impactée #2      */
-
-};
-
-/* Opération arithmétique impliquant deux opérandes (classe) */
-struct _GArithmOperationClass
-{
-    GScanExpressionClass parent;            /* A laisser en premier        */
-
-};
-
-
-/* Met en place une opération arithmétique entre expressions. */
-bool g_arithmetic_operation_create(GArithmOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
-
-
-
-#endif  /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H */
diff --git a/src/analysis/scan/exprs/arithmop.c b/src/analysis/scan/exprs/arithmop.c
deleted file mode 100644
index 5f9e3f1..0000000
--- a/src/analysis/scan/exprs/arithmop.c
+++ /dev/null
@@ -1,436 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * arithmop.c - gestion des opérations arithmétiques
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "arithmop.h"
-
-
-#include "arithmop-int.h"
-#include "literal.h"
-
-
-
-/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
-
-
-/* Initialise la classe des opérations arithmétiques. */
-static void g_arithmetic_operation_class_init(GArithmOperationClass *);
-
-/* Initialise une instance d'opération arithmétique. */
-static void g_arithmetic_operation_init(GArithmOperation *);
-
-/* Supprime toutes les références externes. */
-static void g_arithmetic_operation_dispose(GArithmOperation *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_arithmetic_operation_finalize(GArithmOperation *);
-
-
-
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-
-
-/* Réalise une comparaison entre objets selon un critère précis. */
-static bool g_arithmetic_operation_compare_rich(const GArithmOperation *, const GArithmOperation *, RichCmpOperation, bool *);
-
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_arithmetic_operation_copy(GArithmOperation *, const GArithmOperation *);
-
-/* Réduit une expression à une forme plus simple. */
-static bool g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, GScanScope *, GScanExpression **);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour une opération de relation entre expressions. */
-G_DEFINE_TYPE(GArithmOperation, g_arithmetic_operation, G_TYPE_SCAN_EXPRESSION);
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : klass = classe à initialiser.                                *
-*                                                                             *
-*  Description : Initialise la classe des opérations arithmétiques.           *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_arithmetic_operation_class_init(GArithmOperationClass *klass)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-    GScanExpressionClass *expr;             /* Version de classe parente   */
-
-    object = G_OBJECT_CLASS(klass);
-
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_arithmetic_operation_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_arithmetic_operation_finalize;
-
-    expr = G_SCAN_EXPRESSION_CLASS(klass);
-
-    expr->cmp_rich = (compare_expr_rich_fc)g_arithmetic_operation_compare_rich;
-    expr->copy = (copy_expr_fc)g_arithmetic_operation_copy;
-    expr->reduce = (reduce_expr_fc)g_arithmetic_operation_reduce;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op = instance à initialiser.                                 *
-*                                                                             *
-*  Description : Initialise une instance d'opération arithmétique.            *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_arithmetic_operation_init(GArithmOperation *op)
-{
-    op->left = NULL;
-    op->right = NULL;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op = instance d'objet GLib à traiter.                        *
-*                                                                             *
-*  Description : Supprime toutes les références externes.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_arithmetic_operation_dispose(GArithmOperation *op)
-{
-    g_clear_object(&op->left);
-    g_clear_object(&op->right);
-
-    G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->dispose(G_OBJECT(op));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op = instance d'objet GLib à traiter.                        *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_arithmetic_operation_finalize(GArithmOperation *op)
-{
-    G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->finalize(G_OBJECT(op));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : operator = type d'opération arithmétique à représenter.      *
-*                left     = premier opérande concerné.                        *
-*                right    = éventuel second opérande impliqué ou NULL.        *
-*                                                                             *
-*  Description : Organise une opération arithmétique entre expressions.       *
-*                                                                             *
-*  Retour      : Fonction mise en place.                                      *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
-{
-    GScanExpression *result;                /* Structure à retourner       */
-
-    result = g_object_new(G_TYPE_ARITHMETIC_OPERATION, NULL);
-
-    if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, left, right))
-        g_clear_object(&result);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op       = instance à initialiser pleinement.                *
-*                operator = type d'opération booléenne à représenter.         *
-*                left     = premier opérande concerné.                        *
-*                right    = éventuel second opérande impliqué ou NULL.        *
-*                                                                             *
-*  Description : Met en place une opération arithmétique entre expressions.   *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
-{
-    bool result;                            /* Bilan à retourner           */
-    ExprValueType vtype;                    /* Type de valeur portée       */
-
-    result = false;
-
-    vtype = g_scan_expression_get_value_type(left);
-
-    if (vtype != EVT_INTEGER && vtype != EVT_PENDING)
-        goto exit;
-
-    vtype = g_scan_expression_get_value_type(right);
-
-    if (vtype != EVT_INTEGER && vtype != EVT_PENDING)
-        goto exit;
-
-    if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_INTEGER))
-        goto exit;
-
-    op->operator = operator;
-
-    op->left = left;
-    g_object_ref(G_OBJECT(op->left));
-
-    op->right = right;
-    g_object_ref(G_OBJECT(op->right));
-
-    result = true;
-
- exit:
-
-    return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : item   = premier objet à consulter pour une comparaison.     *
-*                other  = second objet à consulter pour une comparaison.      *
-*                op     = opération de comparaison à réaliser.                *
-*                status = bilan des opérations de comparaison. [OUT]          *
-*                                                                             *
-*  Description : Réalise une comparaison entre objets selon un critère précis.*
-*                                                                             *
-*  Retour      : true si la comparaison a pu être effectuée, false sinon.     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, const GArithmOperation *other, RichCmpOperation op, bool *status)
-{
-    bool result;                            /* Etat à retourner            */
-
-    result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_ARITHMETIC_OPERATION);
-    if (!result) goto done;
-
-    if (item->operator != other->operator)
-    {
-        result = compare_rich_integer_values(item->operator, other->operator, op);
-        goto done;
-    }
-
-    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
-    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
-
-    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left),
-                                            G_COMPARABLE_ITEM(other->left),
-                                            op, status);
-    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
-
-    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
-                                            G_COMPARABLE_ITEM(other->right),
-                                            op, status);
-
- done:
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : dest = emplacement d'enregistrement à constituer. [OUT]      *
-*                src  = expression source à copier.                           *
-*                                                                             *
-*  Description : Reproduit une expression en place dans une nouvelle instance.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOperation *src)
-{
-    GScanExpressionClass *class;            /* Classe parente à solliciter */
-
-    class = G_SCAN_EXPRESSION_CLASS(g_arithmetic_operation_parent_class);
-
-    class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
-    dest->operator = src->operator;
-
-    dest->left = g_scan_expression_duplicate(src->left);
-    dest->right = g_scan_expression_duplicate(src->right);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr  = expression à consulter.                              *
-*                ctx   = contexte de suivi de l'analyse courante.             *
-*                scope = portée courante des variables locales.               *
-*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
-*                                                                             *
-*  Description : Réduit une expression à une forme plus simple.               *
-*                                                                             *
-*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool g_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
-{
-    bool result;                            /* Bilan à retourner           */
-    GScanExpression *new_left;              /* Expression réduite (gauche) */
-    GScanExpression *new_right;             /* Expression réduite (droite) */
-    GLiteralExpression *op_left;            /* Opérande gauche final       */
-    GLiteralExpression *op_right;           /* Opérande droite final       */
-    unsigned long long val_1;               /* Première valeur à traiter   */
-    unsigned long long val_2;               /* Seconde valeur à traiter    */
-    unsigned long long reduced;             /* Valeur réduite finale       */
-
-    /* Réduction des éléments considérés */
-
-    new_left = NULL;
-    new_right = NULL;
-
-    result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
-    if (!result) goto exit;
-
-    result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
-    if (!result) goto exit;
-
-    /* Construction d'une réduction locale ? */
-
-    if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
-    {
-        op_left = G_LITERAL_EXPRESSION(new_left);
-        op_right = G_LITERAL_EXPRESSION(new_right);
-
-        result = g_literal_expression_get_integer_value(op_left, &val_1);
-        if (!result) goto exit;
-
-        result = g_literal_expression_get_integer_value(op_right, &val_2);
-        if (!result) goto exit;
-
-        switch (expr->operator)
-        {
-            case AEO_PLUS:
-                reduced = val_1 + val_2;
-                break;
-
-            case AEO_MINUS:
-                reduced = val_1 - val_2;
-                break;
-
-            case AEO_MUL:
-                reduced = val_1 * val_2;
-                break;
-
-            case AEO_DIV:
-                result = (val_2 != 0);
-                if (result)
-                    reduced = val_1 / val_2;
-                break;
-
-            case AEO_MOD:
-                result = (val_2 != 0);
-                if (result)
-                    reduced = val_1 % val_2;
-                break;
-
-        }
-
-        if (result)
-            *out = g_literal_expression_new(EVT_INTEGER, &reduced);
-
-    }
-
-    /* Mise à jour de la progression ? */
-
-    else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
-    {
-        if (new_left == NULL)
-        {
-            new_left = expr->left;
-            g_object_ref(G_OBJECT(new_left));
-        }
-
-        if (new_right == NULL)
-        {
-            new_right = expr->right;
-            g_object_ref(G_OBJECT(new_right));
-        }
-
-        *out = g_arithmetic_operation_new(expr->operator, new_left, new_right);
-
-    }
-
- exit:
-
-    g_clear_object(&new_left);
-    g_clear_object(&new_right);
-
-    return result;
-
-}
diff --git a/src/analysis/scan/exprs/arithmop.h b/src/analysis/scan/exprs/arithmop.h
deleted file mode 100644
index dcc8bf8..0000000
--- a/src/analysis/scan/exprs/arithmop.h
+++ /dev/null
@@ -1,67 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * arithmop.h - prototypes pour la gestion des opérations arithmétiques
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMOP_H
-#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_H
-
-
-#include "../expr.h"
-
-
-
-#define G_TYPE_ARITHMETIC_OPERATION            g_arithmetic_operation_get_type()
-#define G_ARITHMETIC_OPERATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperation))
-#define G_IS_ARITHMETIC_OPERATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARITHMETIC_OPERATION))
-#define G_ARITHMETIC_OPERATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass))
-#define G_IS_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARITHMETIC_OPERATION))
-#define G_ARITHMETIC_OPERATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass))
-
-
-/* Opération arithmétique impliquant deux opérandes (instance) */
-typedef struct _GArithmOperation GArithmOperation;
-
-/* Opération arithmétique impliquant deux opérandes (classe) */
-typedef struct _GArithmOperationClass GArithmOperationClass;
-
-
-/* Type d'opération arithmétique */
-typedef enum _ArithmeticExpressionOperator
-{
-    AEO_PLUS,                               /* Opération binaire "+"       */
-    AEO_MINUS,                              /* Opération binaire "-"       */
-    AEO_MUL,                                /* Opération binaire "*"       */
-    AEO_DIV,                                /* Opération binaire "\"       */
-    AEO_MOD,                                /* Opération binaire "%"       */
-
-} ArithmeticExpressionOperator;
-
-
-/* Indique le type défini pour une opération arithmétique entre expressions. */
-GType g_arithmetic_operation_get_type(void);
-
-/* Organise une opération arithmétique entre expressions. */
-GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
-
-
-
-#endif  /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_H */
diff --git a/src/analysis/scan/exprs/boolop-int.h b/src/analysis/scan/exprs/boolop-int.h
deleted file mode 100644
index c381cfe..0000000
--- a/src/analysis/scan/exprs/boolop-int.h
+++ /dev/null
@@ -1,60 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * boolop-int.h - prototypes internes pour la gestion des opérations booléennes
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H
-#define _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H
-
-
-#include "boolop.h"
-
-
-#include "../expr-int.h"
-
-
-
-/* Opération booléenne avec un ou deux opérandes (instance) */
-struct _GBoolOperation
-{
-    GScanExpression parent;                 /* A laisser en premier        */
-
-    BooleanOperationType type;              /* Type d'opération menée      */
-
-    GScanExpression *first;                 /* Expression impactée #1      */
-    GScanExpression *second;                /* Expression impactée #2      */
-
-};
-
-/* Opération booléenne avec un ou deux opérandes (classe) */
-struct _GBoolOperationClass
-{
-    GScanExpressionClass parent;            /* A laisser en premier        */
-
-};
-
-
-/* Met en place une expression d'opération booléenne. */
-bool g_boolean_operation_create(GBoolOperation *, BooleanOperationType, GScanExpression *, GScanExpression *);
-
-
-
-#endif  /* _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H */
diff --git a/src/analysis/scan/exprs/boolop.c b/src/analysis/scan/exprs/boolop.c
deleted file mode 100644
index f6a80dd..0000000
--- a/src/analysis/scan/exprs/boolop.c
+++ /dev/null
@@ -1,479 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * boolop.c - gestion des opérations booléennes
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "boolop.h"
-
-
-#include <assert.h>
-
-
-#include "boolop-int.h"
-#include "literal.h"
-
-
-
-/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
-
-
-/* Initialise la classe des opérations booléennes. */
-static void g_boolean_operation_class_init(GBoolOperationClass *);
-
-/* Initialise une instance d'opération booléenne. */
-static void g_boolean_operation_init(GBoolOperation *);
-
-/* Supprime toutes les références externes. */
-static void g_boolean_operation_dispose(GBoolOperation *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_boolean_operation_finalize(GBoolOperation *);
-
-
-
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-
-
-/* Réalise une comparaison entre objets selon un critère précis. */
-static bool g_boolean_operation_compare_rich(const GBoolOperation *, const GBoolOperation *, RichCmpOperation, bool *);
-
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_boolean_operation_copy(GBoolOperation *, const GBoolOperation *);
-
-/* Réduit une expression à une forme plus simple. */
-static bool g_boolean_operation_reduce(GBoolOperation *, GScanContext *, GScanScope *, GScanExpression **);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour une opération booléenne sur expression(s). */
-G_DEFINE_TYPE(GBoolOperation, g_boolean_operation, G_TYPE_SCAN_EXPRESSION);
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : klass = classe à initialiser.                                *
-*                                                                             *
-*  Description : Initialise la classe des opérations booléennes.              *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_boolean_operation_class_init(GBoolOperationClass *klass)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-    GScanExpressionClass *expr;             /* Version de classe parente   */
-
-    object = G_OBJECT_CLASS(klass);
-
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_boolean_operation_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_boolean_operation_finalize;
-
-    expr = G_SCAN_EXPRESSION_CLASS(klass);
-
-    expr->cmp_rich = (compare_expr_rich_fc)g_boolean_operation_compare_rich;
-    expr->copy = (copy_expr_fc)g_boolean_operation_copy;
-    expr->reduce = (reduce_expr_fc)g_boolean_operation_reduce;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op = instance à initialiser.                                 *
-*                                                                             *
-*  Description : Initialise une instance d'opération booléenne.               *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_boolean_operation_init(GBoolOperation *op)
-{
-    op->first = NULL;
-    op->second = NULL;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op = instance d'objet GLib à traiter.                        *
-*                                                                             *
-*  Description : Supprime toutes les références externes.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_boolean_operation_dispose(GBoolOperation *op)
-{
-    g_clear_object(&op->first);
-    g_clear_object(&op->second);
-
-    G_OBJECT_CLASS(g_boolean_operation_parent_class)->dispose(G_OBJECT(op));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op = instance d'objet GLib à traiter.                        *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_boolean_operation_finalize(GBoolOperation *op)
-{
-    G_OBJECT_CLASS(g_boolean_operation_parent_class)->finalize(G_OBJECT(op));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : type   = type d'opération booléenne à représenter.           *
-*                first  = premier opérande concerné.                          *
-*                second = éventuel second opérande impliqué ou NULL.          *
-*                                                                             *
-*  Description : Organise un appel de fonction avec ses arguments.            *
-*                                                                             *
-*  Retour      : Fonction mise en place.                                      *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GScanExpression *g_boolean_operation_new(BooleanOperationType type, GScanExpression *first, GScanExpression *second)
-{
-    GScanExpression *result;                /* Structure à retourner       */
-
-    result = g_object_new(G_TYPE_BOOLEAN_OPERATION, NULL);
-
-    if (!g_boolean_operation_create(G_BOOLEAN_OPERATION(result), type, first, second))
-        g_clear_object(&result);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr   = instance à initialiser pleinement.                  *
-*                type   = type d'opération booléenne à représenter.           *
-*                first  = premier opérande concerné.                          *
-*                second = éventuel second opérande impliqué ou NULL.          *
-*                                                                             *
-*  Description : Met en place une expression d'opération booléenne.           *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = false;
-
-    if (g_scan_expression_get_value_type(first) != EVT_BOOLEAN)
-        goto exit;
-
-    if (g_scan_expression_get_value_type(second) != EVT_BOOLEAN)
-        goto exit;
-
-    if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN))
-        goto exit;
-
-    op->type = type;
-
-    switch (type)
-    {
-        case BOT_AND:
-        case BOT_OR:
-            op->first = first;
-            g_object_ref(G_OBJECT(op->first));
-
-            op->second = second;
-            g_object_ref(G_OBJECT(op->second));
-
-            result = true;
-            break;
-
-        case BOT_NOT:
-            op->first = first;
-            g_object_ref(G_OBJECT(op->first));
-
-            result = (second == NULL);
-            assert(second != NULL);
-            break;
-
-    }
-
- exit:
-
-    return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : item   = premier objet à consulter pour une comparaison.     *
-*                other  = second objet à consulter pour une comparaison.      *
-*                op     = opération de comparaison à réaliser.                *
-*                status = bilan des opérations de comparaison. [OUT]          *
-*                                                                             *
-*  Description : Réalise une comparaison entre objets selon un critère précis.*
-*                                                                             *
-*  Retour      : true si la comparaison a pu être effectuée, false sinon.     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const GBoolOperation *other, RichCmpOperation op, bool *status)
-{
-    bool result;                            /* Etat à retourner            */
-
-    result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_BOOLEAN_OPERATION);
-    if (!result) goto done;
-
-    if (item->type != other->type)
-    {
-        *status = compare_rich_integer_values(item->type, other->type, op);
-        goto done;
-    }
-
-    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
-    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
-
-    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first),
-                                            G_COMPARABLE_ITEM(other->first),
-                                            op, status);
-    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
-
-    if (item->second == NULL)
-    {
-        assert(other->second == NULL);
-
-        switch (op)
-        {
-            case RCO_LT:
-            case RCO_NE:
-            case RCO_GT:
-                *status = false;
-                break;
-
-            case RCO_LE:
-            case RCO_EQ:
-            case RCO_GE:
-                *status = true;
-                break;
-
-        }
-
-    }
-
-    else
-        result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second),
-                                                G_COMPARABLE_ITEM(other->second),
-                                                op, status);
-
- done:
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : dest = emplacement d'enregistrement à constituer. [OUT]      *
-*                src  = expression source à copier.                           *
-*                                                                             *
-*  Description : Reproduit une expression en place dans une nouvelle instance.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_boolean_operation_copy(GBoolOperation *dest, const GBoolOperation *src)
-{
-    GScanExpressionClass *class;            /* Classe parente à solliciter */
-
-    class = G_SCAN_EXPRESSION_CLASS(g_boolean_operation_parent_class);
-
-    class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
-    dest->type = src->type;
-
-    dest->first = g_scan_expression_duplicate(src->first);
-
-    if (src->second != NULL)
-        dest->second = g_scan_expression_duplicate(src->second);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr  = expression à consulter.                              *
-*                ctx   = contexte de suivi de l'analyse courante.             *
-*                scope = portée courante des variables locales.               *
-*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
-*                                                                             *
-*  Description : Réduit une expression à une forme plus simple.               *
-*                                                                             *
-*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
-{
-    bool result;                            /* Bilan à retourner           */
-    GScanExpression *new_first;             /* Expression réduite (gauche) */
-    GScanExpression *new_second;            /* Expression réduite (droite) */
-    bool values[2];                         /* Valeurs des éléments portés */
-    bool valid[2];                          /* Validité de ces valeurs     */
-
-    /* Réduction des éléments considérés */
-
-    new_first = NULL;
-    new_second = NULL;
-
-    result = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
-    if (!result) goto exit;
-
-    if (expr->second == NULL)
-        new_second = NULL;
-    else
-    {
-        result = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
-        if (!result) goto exit;
-    }
-
-    /* Construction d'une réduction locale ? */
-
-    valid[0] = G_IS_LITERAL_EXPRESSION(new_first);
-
-    if (valid[0])
-        valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_first), &values[0]);
-
-    valid[1] = G_IS_LITERAL_EXPRESSION(new_second);
-
-    if (valid[1])
-        valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_second), &values[1]);
-
-    switch (expr->type)
-    {
-        case BOT_AND:
-            if (valid[0] && valid[1])
-                *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] });
-
-            else if (valid[0] && !values[0])
-                *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
-
-            else if (valid[1] && !values[1])
-                *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
-
-            break;
-
-        case BOT_OR:
-            if (valid[0] && valid[1])
-                *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] });
-
-            else if (valid[0] && values[0])
-                *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true });
-
-            else if (valid[1] && values[1])
-                *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true });
-
-            break;
-
-        case BOT_NOT:
-            if (valid[0])
-                *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[0] });
-            break;
-
-    }
-
-    /* Mise à jour de la progression ? */
-
-    if (*out == NULL)
-    {
-        if ((new_first != NULL && new_first != expr->first) || (new_second != NULL && new_second != expr->second))
-        {
-            if (new_first == NULL)
-            {
-                new_first = expr->first;
-                g_object_ref(G_OBJECT(new_first));
-            }
-
-            if (new_second == NULL)
-            {
-                new_second = expr->second;
-                g_object_ref(G_OBJECT(new_second));
-            }
-
-            *out = g_boolean_operation_new(expr->type, new_first, new_second);
-
-        }
-
-    }
-
- exit:
-
-    g_clear_object(&new_first);
-    g_clear_object(&new_second);
-
-    return result;
-
-}
diff --git a/src/analysis/scan/exprs/boolop.h b/src/analysis/scan/exprs/boolop.h
deleted file mode 100644
index 4add5a1..0000000
--- a/src/analysis/scan/exprs/boolop.h
+++ /dev/null
@@ -1,65 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * boolop.h - prototypes pour la gestion des opérations booléennes
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _ANALYSIS_SCAN_EXPRS_BOOLOP_H
-#define _ANALYSIS_SCAN_EXPRS_BOOLOP_H
-
-
-#include "../expr.h"
-
-
-
-#define G_TYPE_BOOLEAN_OPERATION            g_boolean_operation_get_type()
-#define G_BOOLEAN_OPERATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperation))
-#define G_IS_BOOLEAN_OPERATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BOOLEAN_OPERATION))
-#define G_BOOLEAN_OPERATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass))
-#define G_IS_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BOOLEAN_OPERATION))
-#define G_BOOLEAN_OPERATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass))
-
-
-/* Opération booléenne avec un ou deux opérandes (instance) */
-typedef struct _GBoolOperation GBoolOperation;
-
-/* Opération booléenne avec un ou deux opérandes (classe) */
-typedef struct _GBoolOperationClass GBoolOperationClass;
-
-
-/* Types d'opérations booléennes supportées */
-typedef enum _BooleanOperationType
-{
-    BOT_AND,                                /* Opérateur binaire "and"     */
-    BOT_OR,                                 /* Opérateur binaire "or"      */
-    BOT_NOT,                                /* Opérateur unaire "not"      */
-
-} BooleanOperationType;
-
-
-/* Indique le type défini pour une opération booléenne sur expression(s). */
-GType g_boolean_operation_get_type(void);
-
-/* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_boolean_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *);
-
-
-
-#endif  /* _ANALYSIS_SCAN_EXPRS_BOOLOP_H */
diff --git a/src/analysis/scan/exprs/call-int.h b/src/analysis/scan/exprs/call-int.h
index 631a25b..9646b95 100644
--- a/src/analysis/scan/exprs/call-int.h
+++ b/src/analysis/scan/exprs/call-int.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * call-int.h - prototypes internes pour l'organisation d'un appel à un élément de scan enregistré
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -33,9 +33,9 @@
 
 
 /* Exécution d'une fonction auxiliaire d'analyse (instance) */
-struct _GPendingCall
+struct _GScanPendingCall
 {
-    GNamedAccess parent;                    /* A laisser en premier        */
+    GScanNamedAccess parent;                /* A laisser en premier        */
 
     GScanExpression **args;                 /* Arguments d'appel fournis   */
     size_t count;                           /* Quantité de ces arguments   */
@@ -43,15 +43,15 @@ struct _GPendingCall
 };
 
 /* Exécution d'une fonction auxiliaire d'analyse (classe) */
-struct _GPendingCallClass
+struct _GScanPendingCallClass
 {
-    GNamedAccessClass parent;               /* A laisser en premier        */
+    GScanNamedAccessClass parent;           /* A laisser en premier        */
 
 };
 
 
 /* Met en place une expression d'appel. */
-bool g_pending_call_create(GPendingCall *, const sized_string_t *, GScanExpression **, size_t);
+bool g_scan_pending_call_create(GScanPendingCall *, const sized_string_t *, GScanExpression **, size_t);
 
 
 
diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c
index dde627c..2fd1ff1 100644
--- a/src/analysis/scan/exprs/call.c
+++ b/src/analysis/scan/exprs/call.c
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * call.c - organisation d'un appel à un élément de scan enregistré
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -38,27 +38,27 @@
 
 
 /* Initialise la classe des appels de fonction avec arguments. */
-static void g_pending_call_class_init(GPendingCallClass *);
+static void g_scan_pending_call_class_init(GScanPendingCallClass *);
 
 /* Initialise une instance d'appel de fonction avec arguments. */
-static void g_pending_call_init(GPendingCall *);
+static void g_scan_pending_call_init(GScanPendingCall *);
 
 /* Supprime toutes les références externes. */
-static void g_pending_call_dispose(GPendingCall *);
+static void g_scan_pending_call_dispose(GScanPendingCall *);
 
 /* Procède à la libération totale de la mémoire. */
-static void g_pending_call_finalize(GPendingCall *);
+static void g_scan_pending_call_finalize(GScanPendingCall *);
 
 
 
 /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
 
 
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_pending_call_copy(GPendingCall *, const GPendingCall *);
-
 /* Réduit une expression à une forme plus simple. */
-static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_pending_call_reduce(GScanPendingCall *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+static void g_scan_pending_call_copy(GScanPendingCall *, const GScanPendingCall *);
 
 
 
@@ -68,7 +68,7 @@ static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *,
 
 
 /* Indique le type défini pour un appel de fonction enregistrée. */
-G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS);
+G_DEFINE_TYPE(GScanPendingCall, g_scan_pending_call, G_TYPE_SCAN_NAMED_ACCESS);
 
 
 /******************************************************************************
@@ -83,21 +83,25 @@ G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS);
 *                                                                             *
 ******************************************************************************/
 
-static void g_pending_call_class_init(GPendingCallClass *klass)
+static void g_scan_pending_call_class_init(GScanPendingCallClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GScanExpressionClass *expr;             /* Version de classe parente   */
+    GScanNamedAccessClass *access;          /* Autre version de la classe  */
 
     object = G_OBJECT_CLASS(klass);
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_pending_call_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_pending_call_finalize;
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pending_call_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_pending_call_finalize;
 
     expr = G_SCAN_EXPRESSION_CLASS(klass);
 
     expr->cmp_rich = (compare_expr_rich_fc)NULL;
-    expr->copy = (copy_expr_fc)g_pending_call_copy;
-    expr->reduce = (reduce_expr_fc)g_pending_call_reduce;
+    expr->reduce = (reduce_expr_fc)g_scan_pending_call_reduce;
+
+    access = G_SCAN_NAMED_ACCESS_CLASS(klass);
+
+    access->copy = (copy_scan_access_fc)g_scan_pending_call_copy;
 
 }
 
@@ -114,7 +118,7 @@ static void g_pending_call_class_init(GPendingCallClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_pending_call_init(GPendingCall *call)
+static void g_scan_pending_call_init(GScanPendingCall *call)
 {
     call->args = NULL;
     call->count = 0;
@@ -134,14 +138,14 @@ static void g_pending_call_init(GPendingCall *call)
 *                                                                             *
 ******************************************************************************/
 
-static void g_pending_call_dispose(GPendingCall *call)
+static void g_scan_pending_call_dispose(GScanPendingCall *call)
 {
     size_t i;                               /* Boucle de parcours          */
 
     for (i = 0; i < call->count; i++)
         g_clear_object(&call->args[i]);
 
-    G_OBJECT_CLASS(g_pending_call_parent_class)->dispose(G_OBJECT(call));
+    G_OBJECT_CLASS(g_scan_pending_call_parent_class)->dispose(G_OBJECT(call));
 
 }
 
@@ -158,12 +162,12 @@ static void g_pending_call_dispose(GPendingCall *call)
 *                                                                             *
 ******************************************************************************/
 
-static void g_pending_call_finalize(GPendingCall *call)
+static void g_scan_pending_call_finalize(GScanPendingCall *call)
 {
     if (call->args != NULL)
         free(call->args);
 
-    G_OBJECT_CLASS(g_pending_call_parent_class)->finalize(G_OBJECT(call));
+    G_OBJECT_CLASS(g_scan_pending_call_parent_class)->finalize(G_OBJECT(call));
 
 }
 
@@ -182,13 +186,13 @@ static void g_pending_call_finalize(GPendingCall *call)
 *                                                                             *
 ******************************************************************************/
 
-GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpression **args, size_t count)
+GScanExpression *g_scan_pending_call_new(const sized_string_t *target, GScanExpression **args, size_t count)
 {
     GScanExpression *result;                /* Structure à retourner       */
 
-    result = g_object_new(G_TYPE_PENDING_CALL, NULL);
+    result = g_object_new(G_TYPE_SCAN_PENDING_CALL, NULL);
 
-    if (!g_pending_call_create(G_PENDING_CALL(result), target, args, count))
+    if (!g_scan_pending_call_create(G_SCAN_PENDING_CALL(result), target, args, count))
         g_clear_object(&result);
 
     return result;
@@ -211,12 +215,12 @@ GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpressio
 *                                                                             *
 ******************************************************************************/
 
-bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count)
+bool g_scan_pending_call_create(GScanPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count)
 {
     bool result;                            /* Bilan à retourner           */
     size_t i;                               /* Boucle de parcours          */
 
-    result = g_named_access_create(G_NAMED_ACCESS(call), target);
+    result = g_scan_named_access_create(G_SCAN_NAMED_ACCESS(call), target);
     if (!result) goto exit;
 
     call->args = malloc(count * sizeof(GScanExpression *));
@@ -243,37 +247,6 @@ bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GSc
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : dest = emplacement d'enregistrement à constituer. [OUT]      *
-*                src  = expression source à copier.                           *
-*                                                                             *
-*  Description : Reproduit une expression en place dans une nouvelle instance.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_pending_call_copy(GPendingCall *dest, const GPendingCall *src)
-{
-    GScanExpressionClass *class;            /* Classe parente à solliciter */
-    size_t i;                               /* Boucle de parcours          */
-
-    class = G_SCAN_EXPRESSION_CLASS(g_pending_call_parent_class);
-
-    class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
-    dest->args = malloc(src->count * sizeof(GScanExpression *));
-    dest->count = src->count;
-
-    for (i = 0; i < src->count; i++)
-        dest->args[i] = g_scan_expression_duplicate(src->args[i]);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : expr  = expression à consulter.                              *
 *                ctx   = contexte de suivi de l'analyse courante.             *
 *                scope = portée courante des variables locales.               *
@@ -287,89 +260,196 @@ static void g_pending_call_copy(GPendingCall *dest, const GPendingCall *src)
 *                                                                             *
 ******************************************************************************/
 
-static bool g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_pending_call_reduce(GScanPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
 {
-    bool result;                            /* Bilan à retourner           */
-    GNamedAccess *new;                      /* Eventuel étage suivant      */
-    GPendingCall *new_call;                 /* Version en appel            */
-    size_t i;                               /* Boucle de parcours          */
+    ScanReductionState result;              /* Etat synthétisé à retourner */
+    GScanNamedAccess *access;               /* Autre vision de l'expression*/
+    GRegisteredItem *resolved;              /* Cible concrète obtenue      */
+    size_t i;                               /* Boucle de parcours #1       */
     GScanExpression *arg;                   /* Argument réduit à échanger  */
-    GObject *final;                         /* Expression ou élément ?     */
+    GScanExpression *new;                   /* Nouvelle réduction obtenue  */
+    ScanReductionState state;               /* Etat synthétisé d'un élément*/
+    size_t k;                               /* Boucle de parcours #2       */
+    GScanExpression **new_args;             /* Nouvelle séquence d'args.   */
     GScanExpression *new_next;              /* Nouvelle version du suivant */
+    GObject *final;                         /* Expression ou élément ?     */
+    bool valid;                             /* Validité de l'élément       */
 
-    result = _g_named_access_reduce(G_NAMED_ACCESS(expr), ctx, scope, out);
+    access = G_SCAN_NAMED_ACCESS(expr);
 
-    if (result && *out != NULL)
-    {
-        assert(G_IS_NAMED_ACCESS(*out));
+    resolved = _g_scan_named_access_prepare_reduction(access, ctx, scope);
+
+    if (resolved == NULL)
+        result = SRS_UNRESOLVABLE;
 
-        new = G_NAMED_ACCESS(*out);
-        *out = NULL;
+    else
+    {
+        result = SRS_PENDING;
 
-        assert(new->target == NULL);
-        assert(G_IS_PENDING_CALL(new));
-        assert(G_IS_REGISTERED_ITEM(new->resolved));
+        /* Actualisation nécessaire des arguments ? */
 
-        new_call = G_PENDING_CALL(new);
+        new_args = NULL;
 
-        for (i = 0; i < new_call->count; i++)
+        for (i = 0; i < expr->count; i++)
         {
-            result = g_scan_expression_reduce(new_call->args[i], ctx, scope, &arg);
-            if (!result) goto exit;
+            arg = expr->args[i];
 
-            if (arg != NULL)
+            state = g_scan_expression_reduce(arg, ctx, scope, &new);
+            if (state == SRS_UNRESOLVABLE)
             {
-                g_object_unref(G_OBJECT(new_call->args[i]));
-                new_call->args[i] = arg;
+                result = SRS_UNRESOLVABLE;
+                break;
             }
 
+            if (state == SRS_WAIT_FOR_SCAN)
+                result = SRS_WAIT_FOR_SCAN;
+
+            if (new != arg)
+            {
+                if (new_args == NULL)
+                {
+                    new_args = calloc(expr->count, sizeof(GScanExpression *));
+
+                    for (k = 0; k < i; k++)
+                    {
+                        new_args[k] = expr->args[i];
+                        g_object_ref(G_OBJECT(new_args[k]));
+                    }
+
+                }
+
+                new_args[i] = new;
+
+            }
+
+            else
+            {
+                if (new_args != NULL)
+                    new_args[i] = new;
+            }
 
         }
 
-        result = g_registered_item_run_call(new->resolved,
-                                            new_call->args,
-                                            new_call->count,
-                                            ctx, scope, &final);
+        /* Suite des traitements */
 
-        if (result && final != NULL)
+        if (result == SRS_WAIT_FOR_SCAN)
         {
             /**
-             * Si le produit de l'appel à la fonction est une expression d'évaluation
-             * classique, alors ce produit constitue la réduction finale de la chaîne.
-             *
-             * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne.
+             * Si changement il y a eu...
              */
-            if (!G_IS_REGISTERED_ITEM(final))
+            if (new_args != NULL)
             {
-                assert(new->next == NULL);
-                *out = G_SCAN_EXPRESSION(final);
+                *out = g_scan_pending_call_new(NULL, new_args, expr->count);
+
+                /**
+                 * Fonctionnement équivalent de :
+                 *    g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(*out), resolved);
+                 */
+                G_SCAN_NAMED_ACCESS(*out)->resolved = resolved;
+                g_object_ref(G_OBJECT(resolved));
+
+                if (G_SCAN_NAMED_ACCESS(expr)->next != NULL)
+                    g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS(*out), G_SCAN_NAMED_ACCESS(expr)->next);
+
             }
+
+        }
+
+        else if (result == SRS_PENDING)
+        {
+            if (new_args == NULL)
+                valid = g_registered_item_run_call(resolved,
+                                                   expr->args,
+                                                   expr->count,
+                                                   ctx, scope, &final);
             else
-            {
-                assert(new->next != NULL);
+                valid = g_registered_item_run_call(resolved,
+                                                   new_args,
+                                                   expr->count,
+                                                   ctx, scope, &final);
 
-                new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next));
-                assert(G_IS_NAMED_ACCESS(new_next));
+            if (valid && final != NULL)
+            {
+                /**
+                 * Si le produit de l'appel à la fonction est une expression d'évaluation
+                 * classique, alors ce produit constitue la réduction finale de la chaîne.
+                 *
+                 * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne.
+                 */
+                if (!G_IS_REGISTERED_ITEM(final))
+                {
+                    assert(access->next == NULL);
 
-                g_named_access_set_base(G_NAMED_ACCESS(new_next), G_REGISTERED_ITEM(final));
+                    *out = G_SCAN_EXPRESSION(final);
 
-                result = g_scan_expression_reduce(new_next, ctx, scope, out);
+                    result = SRS_REDUCED;
 
-                if (result && *out == NULL)
-                    *out = new_next;
+                }
                 else
+                {
+                    assert(access->next != NULL);
+
+                    new_next = g_scan_named_access_duplicate(access->next, resolved);
+
+                    result = g_scan_expression_reduce(new_next, ctx, scope, out);
+
                     g_object_unref(G_OBJECT(new_next));
 
+                }
+
             }
 
+            else
+                result = SRS_UNRESOLVABLE;
+
         }
 
- exit:
+        /* Libération locale des arguments reconstruits */
 
-        g_object_unref(G_OBJECT(new));
+        if (new_args != NULL)
+        {
+            for (i = 0; i < expr->count; i++)
+                g_clear_object(&new_args[i]);
+        }
+
+        g_object_unref(G_OBJECT(resolved));
 
     }
 
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : dest = emplacement d'enregistrement à constituer. [OUT]      *
+*                src  = expression source à copier.                           *
+*                                                                             *
+*  Description : Reproduit un accès en place dans une nouvelle instance.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_pending_call_copy(GScanPendingCall *dest, const GScanPendingCall *src)
+{
+    GScanNamedAccessClass *class;           /* Classe parente à solliciter */
+    size_t i;                               /* Boucle de parcours          */
+
+    class = G_SCAN_NAMED_ACCESS_CLASS(g_scan_pending_call_parent_class);
+
+    class->copy(G_SCAN_NAMED_ACCESS(dest), G_SCAN_NAMED_ACCESS(src));
+
+    dest->args = malloc(src->count * sizeof(GScanExpression *));
+    dest->count = src->count;
+
+    for (i = 0; i < src->count; i++)
+    {
+        dest->args[i] = src->args[i];
+        g_object_ref(G_OBJECT(src->args[i]));
+    }
+
+}
diff --git a/src/analysis/scan/exprs/call.h b/src/analysis/scan/exprs/call.h
index c344036..c4d8964 100644
--- a/src/analysis/scan/exprs/call.h
+++ b/src/analysis/scan/exprs/call.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * call.h - prototypes pour l'organisation d'un appel à un élément de scan enregistré
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -30,26 +30,26 @@
 
 
 
-#define G_TYPE_PENDING_CALL            g_pending_call_get_type()
-#define G_PENDING_CALL(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PENDING_CALL, GPendingCall))
-#define G_IS_PENDING_CALL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PENDING_CALL))
-#define G_PENDING_CALL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PENDING_CALL, GPendingCallClass))
-#define G_IS_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PENDING_CALL))
-#define G_PENDING_CALL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PENDING_CALL, GPendingCallClass))
+#define G_TYPE_SCAN_PENDING_CALL            g_scan_pending_call_get_type()
+#define G_SCAN_PENDING_CALL(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PENDING_CALL, GScanPendingCall))
+#define G_IS_SCAN_PENDING_CALL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PENDING_CALL))
+#define G_SCAN_PENDING_CALL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PENDING_CALL, GScanPendingCallClass))
+#define G_IS_SCAN_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PENDING_CALL))
+#define G_SCAN_PENDING_CALL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PENDING_CALL, GScanPendingCallClass))
 
 
 /* Exécution d'une fonction auxiliaire d'analyse (instance) */
-typedef struct _GPendingCall GPendingCall;
+typedef struct _GScanPendingCall GScanPendingCall;
 
 /* Exécution d'une fonction auxiliaire d'analyse (classe) */
-typedef struct _GPendingCallClass GPendingCallClass;
+typedef struct _GScanPendingCallClass GScanPendingCallClass;
 
 
 /* Indique le type défini pour un appel de fonction enregistrée. */
-GType g_pending_call_get_type(void);
+GType g_scan_pending_call_get_type(void);
 
 /* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_pending_call_new(const sized_string_t *, GScanExpression **, size_t);
+GScanExpression *g_scan_pending_call_new(const sized_string_t *, GScanExpression **, size_t);
 
 
 
diff --git a/src/analysis/scan/exprs/counter-int.h b/src/analysis/scan/exprs/counter-int.h
new file mode 100644
index 0000000..8c5e56b
--- /dev/null
+++ b/src/analysis/scan/exprs/counter-int.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter-int.h - prototypes internes pour le décompte de correspondances identifiées dans du contenu 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_COUNTER_INT_H
+#define _ANALYSIS_SCAN_EXPRS_COUNTER_INT_H
+
+
+#include "counter.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Décompte des identifications de motifs (instance) */
+struct _GScanMatchCounter
+{
+    GScanExpression parent;                 /* A laisser en premier        */
+
+    GSearchPattern *pattern;                /* Motif associé               */
+
+};
+
+/* Décompte des identifications de motifs (classe) */
+struct _GScanMatchCounterClass
+{
+    GScanExpressionClass parent;            /* A laisser en premier        */
+
+};
+
+
+/* Met en place un compteur de correspondances. */
+bool g_scan_match_counter_create(GScanMatchCounter *, GSearchPattern *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_COUNTER_INT_H */
diff --git a/src/analysis/scan/exprs/counter.c b/src/analysis/scan/exprs/counter.c
new file mode 100644
index 0000000..290fd02
--- /dev/null
+++ b/src/analysis/scan/exprs/counter.c
@@ -0,0 +1,248 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter.c - décompte de correspondances identifiées dans du contenu 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "counter.h"
+
+
+#include "counter-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INSTANCIATION D'UNE FORME DE CONDITION --------------------- */
+
+
+/* Initialise la classe des opérations booléennes. */
+static void g_scan_match_counter_class_init(GScanMatchCounterClass *);
+
+/* Initialise une instance d'opération booléenne. */
+static void g_scan_match_counter_init(GScanMatchCounter *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_match_counter_dispose(GScanMatchCounter *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_match_counter_finalize(GScanMatchCounter *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_match_counter_reduce(GScanMatchCounter *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       INSTANCIATION D'UNE FORME DE CONDITION                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */
+G_DEFINE_TYPE(GScanMatchCounter, g_scan_match_counter, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des opérations booléennes.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_match_counter_class_init(GScanMatchCounterClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanExpressionClass *expr;             /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_match_counter_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_match_counter_finalize;
+
+    expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+    expr->cmp_rich = (compare_expr_rich_fc)NULL;
+    expr->reduce = (reduce_expr_fc)g_scan_match_counter_reduce;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance à initialiser.                                 *
+*                                                                             *
+*  Description : Initialise une instance d'opération booléenne.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_match_counter_init(GScanMatchCounter *counter)
+{
+    counter->pattern = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance d'objet GLib à traiter.                        *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_match_counter_dispose(GScanMatchCounter *counter)
+{
+    g_clear_object(&counter->pattern);
+
+    G_OBJECT_CLASS(g_scan_match_counter_parent_class)->dispose(G_OBJECT(counter));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance d'objet GLib à traiter.                        *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_match_counter_finalize(GScanMatchCounter *counter)
+{
+    G_OBJECT_CLASS(g_scan_match_counter_parent_class)->finalize(G_OBJECT(counter));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = motif à impliquer.                                 *
+*                                                                             *
+*  Description : Met en place un décompte de correspondances obtenues.        *
+*                                                                             *
+*  Retour      : Expression mise en place.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanExpression *g_scan_match_counter_new(GSearchPattern *pattern)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_MATCH_COUNTER, NULL);
+
+    if (!g_scan_match_counter_create(G_SCAN_MATCH_COUNTER(result), pattern))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : counter = instance à initialiser pleinement.                 *
+*                pattern = motif à impliquer.                                 *
+*                                                                             *
+*  Description : Met en place un compteur de correspondances.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_match_counter_create(GScanMatchCounter *counter, GSearchPattern *pattern)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    counter->pattern = pattern;
+    g_object_ref(G_OBJECT(pattern));
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_match_counter_reduce(GScanMatchCounter *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t count;                           /* Quantité de correspondances */
+    const GScanMatch **matches;             /* Correspondances établies    */
+
+
+    matches = g_scan_context_get_full_matches(ctx, expr->pattern, &count);
+
+
+    printf("matches: %zu\n", count);
+
+
+    *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ count });
+    result = true;
+
+
+    return result;
+
+}
diff --git a/src/analysis/scan/exprs/counter.h b/src/analysis/scan/exprs/counter.h
new file mode 100644
index 0000000..c90953e
--- /dev/null
+++ b/src/analysis/scan/exprs/counter.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter.h - prototypes pour le décompte de correspondances identifiées dans du contenu 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_COUNTER_H
+#define _ANALYSIS_SCAN_EXPRS_COUNTER_H
+
+
+#include <glib-object.h>
+
+
+#include "../expr.h"
+#include "../pattern.h"
+
+
+
+#define G_TYPE_SCAN_MATCH_COUNTER            g_scan_match_counter_get_type()
+#define G_SCAN_MATCH_COUNTER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounter))
+#define G_IS_SCAN_MATCH_COUNTER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MATCH_COUNTER))
+#define G_SCAN_MATCH_COUNTER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounterClass))
+#define G_IS_SCAN_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MATCH_COUNTER))
+#define G_SCAN_MATCH_COUNTER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounterClass))
+
+
+/* Décompte des identifications de motifs (instance) */
+typedef struct _GScanMatchCounter GScanMatchCounter;
+
+/* Décompte des identifications de motifs (classe) */
+typedef struct _GScanMatchCounterClass GScanMatchCounterClass;
+
+
+/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */
+GType g_scan_match_counter_get_type(void);
+
+/* Met en place un décompte de correspondances obtenues. */
+GScanExpression *g_scan_match_counter_new(GSearchPattern *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_COUNTER_H */
diff --git a/src/analysis/scan/exprs/intersect-int.h b/src/analysis/scan/exprs/intersect-int.h
new file mode 100644
index 0000000..83e4251
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect-int.h - prototypes internes pour l'intersection d'ensembles aux types indentiques
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H
+#define _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H
+
+
+#include "intersect.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération d'intersection entre deux ensembles (instance) */
+struct _GScanSetsIntersection
+{
+    GScanExpression parent;                 /* A laisser en premier        */
+
+    GScanExpression *first;                 /* Expression impactée #1      */
+    GScanExpression *second;                /* Expression impactée #2      */
+
+};
+
+/* Opération d'intersection entre deux ensembles (classe) */
+struct _GScanSetsIntersectionClass
+{
+    GScanExpressionClass parent;            /* A laisser en premier        */
+
+};
+
+
+/* Met en place une expression d'opération booléenne. */
+bool g_scan_sets_intersection_create(GScanSetsIntersection *, GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H */
diff --git a/src/analysis/scan/exprs/intersect.c b/src/analysis/scan/exprs/intersect.c
new file mode 100644
index 0000000..f0660e0
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect.c
@@ -0,0 +1,290 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect.c - intersection d'ensembles aux types indentiques
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "intersect.h"
+
+
+#include <assert.h>
+
+
+#include "intersect-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des intersections entre deux ensembles. */
+static void g_scan_sets_intersection_class_init(GScanSetsIntersectionClass *);
+
+/* Initialise une instance d'intersection entre deux ensembles. */
+static void g_scan_sets_intersection_init(GScanSetsIntersection *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_sets_intersection_dispose(GScanSetsIntersection *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_sets_intersection_finalize(GScanSetsIntersection *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_sets_intersection_reduce(GScanSetsIntersection *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une intersection entre deux ensembles. */
+G_DEFINE_TYPE(GScanSetsIntersection, g_scan_sets_intersection, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des intersections entre deux ensembles. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_sets_intersection_class_init(GScanSetsIntersectionClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanExpressionClass *expr;             /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sets_intersection_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_sets_intersection_finalize;
+
+    expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+    expr->reduce = (reduce_expr_fc)g_scan_sets_intersection_reduce;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance à initialiser.                                 *
+*                                                                             *
+*  Description : Initialise une instance d'intersection entre deux ensembles. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_sets_intersection_init(GScanSetsIntersection *inter)
+{
+    inter->first = NULL;
+    inter->second = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inter = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_sets_intersection_dispose(GScanSetsIntersection *inter)
+{
+    g_clear_object(&inter->first);
+    g_clear_object(&inter->second);
+
+    G_OBJECT_CLASS(g_scan_sets_intersection_parent_class)->dispose(G_OBJECT(inter));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inter = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_sets_intersection_finalize(GScanSetsIntersection *inter)
+{
+    G_OBJECT_CLASS(g_scan_sets_intersection_parent_class)->finalize(G_OBJECT(inter));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type   = type d'opération booléenne à représenter.           *
+*                first  = premier élément concerné.                           *
+*                second = second élément concerné.                            *
+*                                                                             *
+*  Description : Organise une intersection entre deux ensembles.              *
+*                                                                             *
+*  Retour      : Expression mise en place.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanExpression *g_scan_sets_intersection_new(GScanExpression *first, GScanExpression *second)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_SETS_INTERSECTION, NULL);
+
+    if (!g_scan_sets_intersection_create(G_SCAN_SETS_INTERSECTION(result), first, second))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : inter  = instance à initialiser pleinement.                  *
+*                first  = premier élément concerné.                           *
+*                second = second élément concerné.                            *
+*                                                                             *
+*  Description : Met en place une expression d'opération booléenne.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_sets_intersection_create(GScanSetsIntersection *inter, GScanExpression *first, GScanExpression *second)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    inter->first = first;
+    g_object_ref(G_OBJECT(first));
+
+    inter->second = second;
+    g_object_ref(G_OBJECT(second));
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static ScanReductionState g_scan_sets_intersection_reduce(GScanSetsIntersection *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    ScanReductionState result;              /* Etat synthétisé à retourner */
+    GScanExpression *new_first;             /* Nouvelle réduction #1       */
+    GScanExpression *new_second;            /* Nouvelle réduction #2       */
+    ScanReductionState state_first;         /* Etat synthétisé #1          */
+    ScanReductionState state_second;        /* Etat synthétisé #2          */
+
+    new_first = NULL;
+    new_second = NULL;
+
+    state_first = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
+    if (state_first == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    state_second = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
+    if (state_second == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    if (state_first == SRS_WAIT_FOR_SCAN || state_second == SRS_WAIT_FOR_SCAN)
+    {
+        if (new_first != expr->first || new_second != expr->second)
+            *out = g_scan_sets_intersection_new(new_first, new_second);
+
+        result = SRS_WAIT_FOR_SCAN;
+
+    }
+
+    else
+    {
+        assert(state_first == SRS_REDUCED && state_second == SRS_REDUCED);
+
+        *out = g_scan_expression_intersect(new_first, new_second, ctx, scope);
+
+        result = (*out != NULL ? SRS_REDUCED : SRS_UNRESOLVABLE);
+
+    }
+
+ exit:
+
+    g_clear_object(&new_first);
+    g_clear_object(&new_second);
+
+    return result;
+
+}
diff --git a/src/analysis/scan/exprs/intersect.h b/src/analysis/scan/exprs/intersect.h
new file mode 100644
index 0000000..56efdff
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect.h - prototypes pour l'intersection d'ensembles aux types indentiques
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_INTERSECT_H
+#define _ANALYSIS_SCAN_EXPRS_INTERSECT_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_SETS_INTERSECTION            g_scan_sets_intersection_get_type()
+#define G_SCAN_SETS_INTERSECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersection))
+#define G_IS_SCAN_SETS_INTERSECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SETS_INTERSECTION))
+#define G_SCAN_SETS_INTERSECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersectionClass))
+#define G_IS_SCAN_SETS_INTERSECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SETS_INTERSECTION))
+#define G_SCAN_SETS_INTERSECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersectionClass))
+
+
+/* Opération d'intersection entre deux ensembles (instance) */
+typedef struct _GScanSetsIntersection GScanSetsIntersection;
+
+/* Opération d'intersection entre deux ensembles (classe) */
+typedef struct _GScanSetsIntersectionClass GScanSetsIntersectionClass;
+
+
+/* Indique le type défini pour une intersection entre deux ensembles. */
+GType g_scan_sets_intersection_get_type(void);
+
+/* Organise une intersection entre deux ensembles. */
+GScanExpression *g_scan_sets_intersection_new(GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_INTERSECT_H */
diff --git a/src/analysis/scan/exprs/literal-int.h b/src/analysis/scan/exprs/literal-int.h
index 875b3de..b0a0ec5 100644
--- a/src/analysis/scan/exprs/literal-int.h
+++ b/src/analysis/scan/exprs/literal-int.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * literal-int.h - prototypes internes pour la représentation d'une valeur concrète
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -28,24 +28,22 @@
 #include "literal.h"
 
 
-#include <stdbool.h>
-
-
 #include "../expr-int.h"
 
 
 
 /* Expression portant une valeur concrète (instance) */
-struct _GLiteralExpression
+struct _GScanLiteralExpression
 {
     GScanExpression parent;                 /* A laisser en premier        */
 
-    ExprValueType value_type;               /* Type de valeur portée       */
+    LiteralValueType value_type;            /* Type de valeur portée       */
 
     union
     {
         bool boolean;                       /* Valeur booléenne            */
-        unsigned long long integer;         /* Valeur entière 64 bits      */
+        long long s_integer;                /* Valeur entière 64 bits      */
+        unsigned long long u_integer;       /* Valeur entière 64 bits      */
         sized_string_t string;              /* Chaîne de caractères        */
         struct
         {
@@ -58,7 +56,7 @@ struct _GLiteralExpression
 };
 
 /* Expression portant une valeur concrète (classe) */
-struct _GLiteralExpressionClass
+struct _GScanLiteralExpressionClass
 {
     GScanExpressionClass parent;            /* A laisser en premier        */
 
@@ -66,7 +64,7 @@ struct _GLiteralExpressionClass
 
 
 /* Met en place une expression de valeur concrête. */
-bool g_literal_expression_create(GLiteralExpression *, ExprValueType, ...);
+bool g_scan_literal_expression_create(GScanLiteralExpression *, LiteralValueType, ...);
 
 
 
diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c
index 119b871..e468382 100644
--- a/src/analysis/scan/exprs/literal.c
+++ b/src/analysis/scan/exprs/literal.c
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * literal.c - représentation d'une valeur concrète
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -37,16 +37,16 @@
 
 
 /* Initialise la classe des expressions de valeur concrète. */
-static void g_literal_expression_class_init(GLiteralExpressionClass *);
+static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *);
 
 /* Initialise une instance d'expression de valeur concrète. */
-static void g_literal_expression_init(GLiteralExpression *);
+static void g_scan_literal_expression_init(GScanLiteralExpression *);
 
 /* Supprime toutes les références externes. */
-static void g_literal_expression_dispose(GLiteralExpression *);
+static void g_scan_literal_expression_dispose(GScanLiteralExpression *);
 
 /* Procède à la libération totale de la mémoire. */
-static void g_literal_expression_finalize(GLiteralExpression *);
+static void g_scan_literal_expression_finalize(GScanLiteralExpression *);
 
 
 
@@ -54,13 +54,13 @@ static void g_literal_expression_finalize(GLiteralExpression *);
 
 
 /* Réalise une comparaison entre objets selon un critère précis. */
-static bool g_literal_expression_compare_rich(const GLiteralExpression *, const GLiteralExpression *, RichCmpOperation, bool *);
+static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression *, const GScanLiteralExpression *, RichCmpOperation, bool *);
 
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_literal_expression_copy(GLiteralExpression *, const GLiteralExpression *);
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **);
 
-/* Réduit une expression à une forme plus simple. */
-static bool g_literal_expression_reduce(GLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **);
+/* Dénombre les éléments portés par une expression. */
+static bool g_scan_literal_expression_count(const GScanLiteralExpression *, size_t *);
 
 
 
@@ -70,7 +70,7 @@ static bool g_literal_expression_reduce(GLiteralExpression *, GScanContext *, GS
 
 
 /* Indique le type défini pour un appel de fonction enregistrée. */
-G_DEFINE_TYPE(GLiteralExpression, g_literal_expression, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanLiteralExpression, g_scan_literal_expression, G_TYPE_SCAN_EXPRESSION);
 
 
 /******************************************************************************
@@ -85,21 +85,21 @@ G_DEFINE_TYPE(GLiteralExpression, g_literal_expression, G_TYPE_SCAN_EXPRESSION);
 *                                                                             *
 ******************************************************************************/
 
-static void g_literal_expression_class_init(GLiteralExpressionClass *klass)
+static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GScanExpressionClass *expr;             /* Version de classe parente   */
 
     object = G_OBJECT_CLASS(klass);
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_literal_expression_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_literal_expression_finalize;
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_literal_expression_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_literal_expression_finalize;
 
     expr = G_SCAN_EXPRESSION_CLASS(klass);
 
-    expr->cmp_rich = (compare_expr_rich_fc)g_literal_expression_compare_rich;
-    expr->copy = (copy_expr_fc)g_literal_expression_copy;
-    expr->reduce = (reduce_expr_fc)g_literal_expression_reduce;
+    expr->cmp_rich = (compare_expr_rich_fc)g_scan_literal_expression_compare_rich;
+    expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_literal_expression_reduce_to_boolean;
+    expr->count = (count_scan_expr_fc)g_scan_literal_expression_count;
 
 }
 
@@ -116,8 +116,9 @@ static void g_literal_expression_class_init(GLiteralExpressionClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_literal_expression_init(GLiteralExpression *expr)
+static void g_scan_literal_expression_init(GScanLiteralExpression *expr)
 {
+    G_SCAN_EXPRESSION(expr)->state = SRS_REDUCED;
 
 }
 
@@ -134,9 +135,9 @@ static void g_literal_expression_init(GLiteralExpression *expr)
 *                                                                             *
 ******************************************************************************/
 
-static void g_literal_expression_dispose(GLiteralExpression *expr)
+static void g_scan_literal_expression_dispose(GScanLiteralExpression *expr)
 {
-    G_OBJECT_CLASS(g_literal_expression_parent_class)->dispose(G_OBJECT(expr));
+    G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->dispose(G_OBJECT(expr));
 
 }
 
@@ -153,9 +154,9 @@ static void g_literal_expression_dispose(GLiteralExpression *expr)
 *                                                                             *
 ******************************************************************************/
 
-static void g_literal_expression_finalize(GLiteralExpression *expr)
+static void g_scan_literal_expression_finalize(GScanLiteralExpression *expr)
 {
-    G_OBJECT_CLASS(g_literal_expression_parent_class)->finalize(G_OBJECT(expr));
+    G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->finalize(G_OBJECT(expr));
 
 }
 
@@ -167,25 +168,25 @@ static void g_literal_expression_finalize(GLiteralExpression *expr)
 *                                                                             *
 *  Description : Organise un appel de fonction avec ses arguments.            *
 *                                                                             *
-*  Retour      : Fonction mise en place.                                      *
+*  Retour      : Expression mise en place.                                    *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GScanExpression *g_literal_expression_new(ExprValueType vtype, ...)
+GScanExpression *g_scan_literal_expression_new(LiteralValueType vtype, ...)
 {
     GScanExpression *result;                /* Structure à retourner       */
     va_list ap;                             /* Liste d'arguements          */
     void *ptr;                              /* Vision générique de valeur  */
 
-    result = g_object_new(G_TYPE_LITERAL_EXPRESSION, NULL);
+    result = g_object_new(G_TYPE_SCAN_LITERAL_EXPRESSION, NULL);
 
     va_start(ap, vtype);
 
     ptr = va_arg(ap, void *);
 
-    if (!g_literal_expression_create(G_LITERAL_EXPRESSION(result), vtype, ptr))
+    if (!g_scan_literal_expression_create(G_SCAN_LITERAL_EXPRESSION(result), vtype, ptr))
         g_clear_object(&result);
 
     va_end(ap);
@@ -209,12 +210,13 @@ GScanExpression *g_literal_expression_new(ExprValueType vtype, ...)
 *                                                                             *
 ******************************************************************************/
 
-bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, ...)
+bool g_scan_literal_expression_create(GScanLiteralExpression *expr, LiteralValueType vtype, ...)
 {
     bool result;                            /* Bilan à retourner           */
     va_list ap;                             /* Liste d'arguements          */
     const bool *boolean;                    /* Valeur booléenne            */
-    const unsigned long long *integer;      /* Valeur entière 64 bits      */
+    const long long *s_integer;             /* Valeur entière 64 bits #1   */
+    const unsigned long long *u_integer;    /* Valeur entière 64 bits #2   */
     const sized_string_t *string;           /* Chaîne de caractères        */
     const char *raw;                        /* Chaîne de caractères brute  */
     size_t len;                             /* Taille de la chaîne         */
@@ -223,89 +225,115 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype,
     char *tmp;                              /* Zone de travail temporaire  */
     int ret;                                /* Bilan d'une opération       */
 
-    result = g_scan_expression_create(G_SCAN_EXPRESSION(expr), vtype);
+    va_start(ap, vtype);
 
-    if (result)
+    switch (vtype)
     {
-        va_start(ap, vtype);
+        case LVT_BOOLEAN:
+            boolean = va_arg(ap, const bool *);
+            expr->value.boolean = *boolean;
+            result = true;
+            break;
 
-        switch (vtype)
-        {
-            case EVT_BOOLEAN:
-                boolean = va_arg(ap, const bool *);
-                expr->value.boolean = *boolean;
-                break;
+        case LVT_SIGNED_INTEGER:
+            s_integer = va_arg(ap, const long long *);
+            expr->value.s_integer = *s_integer;
+            result = true;
+            break;
 
-            case EVT_INTEGER:
-                integer = va_arg(ap, const unsigned long long *);
-                expr->value.integer = *integer;
-                break;
+        case LVT_UNSIGNED_INTEGER:
+            u_integer = va_arg(ap, const unsigned long long *);
+            expr->value.u_integer = *u_integer;
+            result = true;
+            break;
+
+        case LVT_STRING:
+            string = va_arg(ap, const sized_string_t *);
+            szstrdup(&expr->value.string, string);
+            result = true;
+            break;
 
-            case EVT_STRING:
-                string = va_arg(ap, const sized_string_t *);
-                szstrdup(&expr->value.string, string);
-                break;
+        case LVT_REG_EXPR:
+            raw = va_arg(ap, const char *);
+            len = strlen(raw);
 
-            case EVT_REG_EXPR:
-                raw = va_arg(ap, const char *);
-                len = strlen(raw);
+            result = (len > 2 && raw[0] == '/');
 
-                result = (len > 2 && raw[0] == '/');
+            cflags = REG_EXTENDED | REG_NOSUB;
 
-                cflags = REG_EXTENDED | REG_NOSUB;
+            for (i = 0; i < 2 && result; i++)
+            {
+                result = (len > 2);
 
-                for (i = 0; i < 2 && result; i++)
+                if (raw[len - 1] == 'i')
                 {
-                    result = (len > 2);
+                    cflags |= REG_ICASE;
+                    len -= 1;
+                }
 
-                    if (raw[len - 1] == 'i')
-                    {
-                        cflags |= REG_ICASE;
-                        len -= 1;
-                    }
+                else if (raw[len - 1] == 's')
+                {
+                    cflags |= REG_NEWLINE;
+                    len -= 1;
+                }
 
-                    else if (raw[len - 1] == 's')
-                    {
-                        cflags |= REG_NEWLINE;
-                        len -= 1;
-                    }
+                else if (raw[len - 1] == '/')
+                    break;
 
-                    else if (raw[len - 1] == '/')
-                        break;
+            }
 
-                }
+            if (result)
+                result = (raw[len - 1] == '/');
 
-                if (result)
-                    result = (raw[len - 1] == '/');
+            if (result)
+            {
+                assert(len > 2);
+
+                tmp = strndup(&raw[1], len - 2);
+                ret = regcomp(&expr->value.preg, tmp, cflags);
+                free(tmp);
+
+                result = (ret == 0);
 
                 if (result)
-                {
-                    assert(len > 2);
+                    expr->value.regex = strdup(raw);
+
+            }
+
+            break;
 
-                    tmp = strndup(&raw[1], len - 2);
-                    ret = regcomp(&expr->value.preg, tmp, cflags);
-                    free(tmp);
+        default:
+            result = false;
+            break;
 
-                    result = (ret == 0);
+        }
 
-                    if (result)
-                        expr->value.regex = strdup(raw);
+    va_end(ap);
 
-                }
+    expr->value_type = vtype;
 
-                break;
+    return result;
 
-            default:
-                result = false;
-                break;
+}
 
-        }
 
-        va_end(ap);
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr = expression à consulter.                               *
+*                                                                             *
+*  Description : Indique le type de valeur portée par une expression.         *
+*                                                                             *
+*  Retour      : Type de valeur associée à l'expression.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    }
+LiteralValueType g_scan_literal_expression_get_value_type(const GScanLiteralExpression *expr)
+{
+    LiteralValueType result;                /* Type à retourner            */
 
-    expr->value_type = vtype;
+    result = expr->value_type;
 
     return result;
 
@@ -314,7 +342,7 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype,
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : item  = premier objet à consulter pour une comparaison.      *
+*  Paramètres  : expr  = premier objet à consulter pour une comparaison.      *
 *                value = valeur portée portée par l'expression. [OUT]         *
 *                                                                             *
 *  Description : Indique la valeur portée par une expression booléenne.       *
@@ -325,14 +353,41 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype,
 *                                                                             *
 ******************************************************************************/
 
-bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool *value)
+bool g_scan_literal_expression_get_boolean_value(const GScanLiteralExpression *expr, bool *value)
+{
+    bool result;                            /* Etat à retourner            */
+
+    result = (expr->value_type == LVT_BOOLEAN);
+
+    if (result)
+        *value = expr->value.boolean;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = premier objet à consulter pour une comparaison.      *
+*                value = valeur portée portée par l'expression. [OUT]         *
+*                                                                             *
+*  Description : Indique la valeur portée par une expression d'entier.        *
+*                                                                             *
+*  Retour      : true si l'expression est de type entier, false sinon.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_literal_expression_get_signed_integer_value(const GScanLiteralExpression *expr, long long *value)
 {
     bool result;                            /* Etat à retourner            */
 
-    result = (item->value_type == EVT_BOOLEAN);
+    result = (expr->value_type == LVT_SIGNED_INTEGER);
 
     if (result)
-        *value = item->value.boolean;
+        *value = expr->value.u_integer;
 
     return result;
 
@@ -341,7 +396,7 @@ bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : item  = premier objet à consulter pour une comparaison.      *
+*  Paramètres  : expr  = premier objet à consulter pour une comparaison.      *
 *                value = valeur portée portée par l'expression. [OUT]         *
 *                                                                             *
 *  Description : Indique la valeur portée par une expression d'entier.        *
@@ -352,14 +407,14 @@ bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool
 *                                                                             *
 ******************************************************************************/
 
-bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsigned long long *value)
+bool g_scan_literal_expression_get_unsigned_integer_value(const GScanLiteralExpression *expr, unsigned long long *value)
 {
     bool result;                            /* Etat à retourner            */
 
-    result = (item->value_type == EVT_INTEGER);
+    result = (expr->value_type == LVT_UNSIGNED_INTEGER);
 
     if (result)
-        *value = item->value.integer;
+        *value = expr->value.u_integer;
 
     return result;
 
@@ -368,7 +423,7 @@ bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsi
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : item  = premier objet à consulter pour une comparaison.      *
+*  Paramètres  : expr  = premier objet à consulter pour une comparaison.      *
 *                value = valeur portée portée par l'expression. [OUT]         *
 *                                                                             *
 *  Description : Indique la valeur portée par une expression de chaîne.       *
@@ -379,14 +434,14 @@ bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsi
 *                                                                             *
 ******************************************************************************/
 
-bool g_literal_expression_get_string_value(const GLiteralExpression *item, const sized_string_t **value)
+bool g_scan_literal_expression_get_string_value(const GScanLiteralExpression *expr, const sized_string_t **value)
 {
     bool result;                            /* Etat à retourner            */
 
-    result = (item->value_type == EVT_STRING);
+    result = (expr->value_type == LVT_STRING);
 
     if (result)
-        *value = &item->value.string;
+        *value = &expr->value.string;
 
     return result;
 
@@ -395,7 +450,7 @@ bool g_literal_expression_get_string_value(const GLiteralExpression *item, const
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : item  = premier objet à consulter pour une comparaison.      *
+*  Paramètres  : expr  = premier objet à consulter pour une comparaison.      *
 *                value = valeur portée portée par l'expression. [OUT]         *
 *                                                                             *
 *  Description : Indique la valeur portée par une expression rationnelle.     *
@@ -406,14 +461,14 @@ bool g_literal_expression_get_string_value(const GLiteralExpression *item, const
 *                                                                             *
 ******************************************************************************/
 
-bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const regex_t **value)
+bool g_scan_literal_expression_get_regex_value(const GScanLiteralExpression *expr, const regex_t **value)
 {
     bool result;                            /* Etat à retourner            */
 
-    result = (item->value_type == EVT_REG_EXPR);
+    result = (expr->value_type == LVT_REG_EXPR);
 
     if (result)
-        *value = &item->value.preg;
+        *value = &expr->value.preg;
 
     return result;
 
@@ -428,7 +483,7 @@ bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : item   = premier objet à consulter pour une comparaison.     *
+*  Paramètres  : expr   = premier objet à consulter pour une comparaison.     *
 *                other  = second objet à consulter pour une comparaison.      *
 *                op     = opération de comparaison à réaliser.                *
 *                status = bilan des opérations de comparaison. [OUT]          *
@@ -441,32 +496,32 @@ bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const
 *                                                                             *
 ******************************************************************************/
 
-static bool g_literal_expression_compare_rich(const GLiteralExpression *item, const GLiteralExpression *other, RichCmpOperation op, bool *status)
+static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression *expr, const GScanLiteralExpression *other, RichCmpOperation op, bool *status)
 {
     bool result;                            /* Etat à retourner            */
     int cmp;                                /* Bilan intermédiaire         */
 
-    result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_LITERAL_EXPRESSION);
+    result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_LITERAL_EXPRESSION);
     if (!result) goto done;
 
-    if (item->value_type != other->value_type)
+    if (expr->value_type != other->value_type)
     {
-        *status = compare_rich_integer_values(item->value_type, other->value_type, op);
+        *status = compare_rich_integer_values_unsigned(expr->value_type, other->value_type, op);
         goto done;
     }
 
-    switch (item->value_type)
+    switch (expr->value_type)
     {
-        case EVT_BOOLEAN:
+        case LVT_BOOLEAN:
             switch (op)
             {
                 case RCO_EQ:
-                    *status = (item->value.boolean == other->value.boolean);
+                    *status = (expr->value.boolean == other->value.boolean);
                     result = true;
                     break;
 
                 case RCO_NE:
-                    *status = (item->value.boolean != other->value.boolean);
+                    *status = (expr->value.boolean != other->value.boolean);
                     result = true;
                     break;
 
@@ -477,20 +532,25 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co
             };
             break;
 
-        case EVT_INTEGER:
-            *status = compare_rich_integer_values(item->value.integer, other->value.integer, op);
+        case LVT_SIGNED_INTEGER:
+            *status = compare_rich_integer_values_signed(expr->value.s_integer, other->value.s_integer, op);
             result = true;
             break;
 
-        case EVT_STRING:
-            cmp = szstrcmp(&item->value.string, &other->value.string);
-            *status = compare_rich_integer_values(cmp, 0, op);
+        case LVT_UNSIGNED_INTEGER:
+            *status = compare_rich_integer_values_unsigned(expr->value.u_integer, other->value.u_integer, op);
             result = true;
             break;
 
-        case EVT_REG_EXPR:
-            cmp = strcmp(item->value.regex, other->value.regex);
-            *status = compare_rich_integer_values(cmp, 0, op);
+        case LVT_STRING:
+            cmp = szstrcmp(&expr->value.string, &other->value.string);
+            *status = compare_rich_integer_values_signed(cmp, 0, op);
+            result = true;
+            break;
+
+        case LVT_REG_EXPR:
+            cmp = strcmp(expr->value.regex, other->value.regex);
+            *status = compare_rich_integer_values_signed(cmp, 0, op);
             result = true;
             break;
 
@@ -509,62 +569,63 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : dest = emplacement d'enregistrement à constituer. [OUT]      *
-*                src  = expression source à copier.                           *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
 *                                                                             *
-*  Description : Reproduit une expression en place dans une nouvelle instance.*
+*  Description : Réduit une expression à une forme booléenne.                 *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_literal_expression_copy(GLiteralExpression *dest, const GLiteralExpression *src)
+static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
 {
-    GScanExpressionClass *class;            /* Classe parente à solliciter */
-
-    class = G_SCAN_EXPRESSION_CLASS(g_literal_expression_parent_class);
-
-    class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
-    dest->value_type = src->value_type;
+    bool result;                            /* Bilan à retourner           */
 
-    switch (src->value_type)
+    switch (expr->value_type)
     {
-        case EVT_BOOLEAN:
-            dest->value.boolean = src->value.boolean;
+        case LVT_BOOLEAN:
+            *out = G_SCAN_EXPRESSION(expr);
+            g_object_ref(G_OBJECT(expr));
+            result = true;
             break;
 
-        case EVT_INTEGER:
-            dest->value.integer = src->value.integer;
+        case LVT_SIGNED_INTEGER:
+            *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.s_integer != 0 });
+            result = true;
             break;
 
-        case EVT_STRING:
-            szstrdup(&dest->value.string, &src->value.string);
+        case LVT_UNSIGNED_INTEGER:
+            *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.u_integer != 0 });
+            result = true;
             break;
 
-        case EVT_REG_EXPR:
-            /*ptr = &expr->value.regex*//* FIXME */;
+        case LVT_STRING:
+            *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.string.len > 0 });
+            result = true;
             break;
 
         default:
-            assert(false);
+            result = false;
             break;
 
     }
 
+    return result;
+
 }
 
 
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : expr  = expression à consulter.                              *
-*                ctx   = contexte de suivi de l'analyse courante.             *
-*                scope = portée courante des variables locales.               *
-*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                count = quantité d'éléments déterminée. [OUT]                *
 *                                                                             *
-*  Description : Réduit une expression à une forme plus simple.               *
+*  Description : Dénombre les éléments portés par une expression.             *
 *                                                                             *
 *  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
 *                                                                             *
@@ -572,14 +633,22 @@ static void g_literal_expression_copy(GLiteralExpression *dest, const GLiteralEx
 *                                                                             *
 ******************************************************************************/
 
-static bool g_literal_expression_reduce(GLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static bool g_scan_literal_expression_count(const GScanLiteralExpression *expr, size_t *count)
 {
     bool result;                            /* Bilan à retourner           */
 
-    result = true;
+    switch (expr->value_type)
+    {
+        case LVT_STRING:
+            *count = expr->value.string.len;
+            result = true;
+            break;
+
+        default:
+            result = false;
+            break;
 
-    *out = G_SCAN_EXPRESSION(expr);
-    g_object_ref(G_OBJECT(expr));
+    }
 
     return result;
 
diff --git a/src/analysis/scan/exprs/literal.h b/src/analysis/scan/exprs/literal.h
index 7120c07..9352baf 100644
--- a/src/analysis/scan/exprs/literal.h
+++ b/src/analysis/scan/exprs/literal.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * literal.h - prototypes pour la représentation d'une valeur concrète
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -26,6 +26,7 @@
 
 
 #include <regex.h>
+#include <stdbool.h>
 
 
 #include "../expr.h"
@@ -33,38 +34,56 @@
 
 
 
-#define G_TYPE_LITERAL_EXPRESSION            g_literal_expression_get_type()
-#define G_LITERAL_EXPRESSION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpression))
-#define G_IS_LITERAL_EXPRESSION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LITERAL_EXPRESSION))
-#define G_LITERAL_EXPRESSION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass))
-#define G_IS_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LITERAL_EXPRESSION))
-#define G_LITERAL_EXPRESSION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass))
+#define G_TYPE_SCAN_LITERAL_EXPRESSION            g_scan_literal_expression_get_type()
+#define G_SCAN_LITERAL_EXPRESSION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpression))
+#define G_IS_SCAN_LITERAL_EXPRESSION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_LITERAL_EXPRESSION))
+#define G_SCAN_LITERAL_EXPRESSION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpressionClass))
+#define G_IS_SCAN_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_LITERAL_EXPRESSION))
+#define G_SCAN_LITERAL_EXPRESSION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpressionClass))
 
 
 /* Expression portant une valeur concrète (instance) */
-typedef struct _GLiteralExpression GLiteralExpression;
+typedef struct _GScanLiteralExpression GScanLiteralExpression;
 
 /* Expression portant une valeur concrète (classe) */
-typedef struct _GLiteralExpressionClass GLiteralExpressionClass;
+typedef struct _GScanLiteralExpressionClass GScanLiteralExpressionClass;
+
+
+/* Types naturel équivalant à l'expression */
+typedef enum _LiteralValueType
+{
+    LVT_BOOLEAN,                            /* Valeur booléenne            */
+    LVT_SIGNED_INTEGER,                     /* Nombre entier 64 bits #1    */
+    LVT_UNSIGNED_INTEGER,                   /* Nombre entier 64 bits #2    */
+    LVT_STRING,                             /* Chaîne de caractères        */
+    LVT_REG_EXPR,                           /* Expression rationnelle      */
+
+} LiteralValueType;
 
 
 /* Indique le type défini pour un appel de fonction enregistrée. */
-GType g_literal_expression_get_type(void);
+GType g_scan_literal_expression_get_type(void);
 
 /* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_literal_expression_new(ExprValueType, ...);
+GScanExpression *g_scan_literal_expression_new(LiteralValueType, ...);
+
+/* Indique le type de valeur portée par une expression. */
+LiteralValueType g_scan_literal_expression_get_value_type(const GScanLiteralExpression *);
 
 /* Indique la valeur portée par une expression booléenne. */
-bool g_literal_expression_get_boolean_value(const GLiteralExpression *, bool *);
+bool g_scan_literal_expression_get_boolean_value(const GScanLiteralExpression *, bool *);
+
+/* Indique la valeur portée par une expression d'entier. */
+bool g_scan_literal_expression_get_signed_integer_value(const GScanLiteralExpression *, long long *);
 
 /* Indique la valeur portée par une expression d'entier. */
-bool g_literal_expression_get_integer_value(const GLiteralExpression *, unsigned long long *);
+bool g_scan_literal_expression_get_unsigned_integer_value(const GScanLiteralExpression *, unsigned long long *);
 
 /* Indique la valeur portée par une expression de chaîne. */
-bool g_literal_expression_get_string_value(const GLiteralExpression *, const sized_string_t **);
+bool g_scan_literal_expression_get_string_value(const GScanLiteralExpression *, const sized_string_t **);
 
 /* Indique la valeur portée par une expression rationnelle. */
-bool g_literal_expression_get_regex_value(const GLiteralExpression *, const regex_t **);
+bool g_scan_literal_expression_get_regex_value(const GScanLiteralExpression *, const regex_t **);
 
 
 
diff --git a/src/analysis/scan/exprs/logical-int.h b/src/analysis/scan/exprs/logical-int.h
new file mode 100644
index 0000000..6df55d0
--- /dev/null
+++ b/src/analysis/scan/exprs/logical-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logical-int.h - prototypes internes pour la gestion des opérations booléennes
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H
+
+
+#include "logical.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération booléenne avec un ou deux opérandes (instance) */
+struct _GScanLogicalOperation
+{
+    GScanExpression parent;                 /* A laisser en premier        */
+
+    BooleanOperationType type;              /* Type d'opération menée      */
+
+    GScanExpression *first;                 /* Expression impactée #1      */
+    GScanExpression *second;                /* Expression impactée #2      */
+
+};
+
+/* Opération booléenne avec un ou deux opérandes (classe) */
+struct _GScanLogicalOperationClass
+{
+    GScanExpressionClass parent;            /* A laisser en premier        */
+
+};
+
+
+/* Met en place une expression d'opération booléenne. */
+bool g_scan_logical_operation_create(GScanLogicalOperation *, BooleanOperationType, GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H */
diff --git a/src/analysis/scan/exprs/logical.c b/src/analysis/scan/exprs/logical.c
new file mode 100644
index 0000000..4c82b1e
--- /dev/null
+++ b/src/analysis/scan/exprs/logical.c
@@ -0,0 +1,508 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logical.c - gestion des opérations booléennes
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "logical.h"
+
+
+#include <assert.h>
+
+
+#include "logical-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations booléennes. */
+static void g_scan_logical_operation_class_init(GScanLogicalOperationClass *);
+
+/* Initialise une instance d'opération booléenne. */
+static void g_scan_logical_operation_init(GScanLogicalOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_logical_operation_dispose(GScanLogicalOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_logical_operation_finalize(GScanLogicalOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_scan_logical_operation_compare_rich(const GScanLogicalOperation *, const GScanLogicalOperation *, RichCmpOperation, bool *);
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_logical_operation_reduce(GScanLogicalOperation *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération booléenne sur expression(s). */
+G_DEFINE_TYPE(GScanLogicalOperation, g_scan_logical_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des opérations booléennes.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_logical_operation_class_init(GScanLogicalOperationClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanExpressionClass *expr;             /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_logical_operation_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_logical_operation_finalize;
+
+    expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+    expr->cmp_rich = (compare_expr_rich_fc)g_scan_logical_operation_compare_rich;
+    expr->reduce = (reduce_expr_fc)g_scan_logical_operation_reduce;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance à initialiser.                                 *
+*                                                                             *
+*  Description : Initialise une instance d'opération booléenne.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_logical_operation_init(GScanLogicalOperation *op)
+{
+    op->first = NULL;
+    op->second = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance d'objet GLib à traiter.                        *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_logical_operation_dispose(GScanLogicalOperation *op)
+{
+    g_clear_object(&op->first);
+    g_clear_object(&op->second);
+
+    G_OBJECT_CLASS(g_scan_logical_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance d'objet GLib à traiter.                        *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_logical_operation_finalize(GScanLogicalOperation *op)
+{
+    G_OBJECT_CLASS(g_scan_logical_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type   = type d'opération booléenne à représenter.           *
+*                first  = premier opérande concerné.                          *
+*                second = éventuel second opérande impliqué ou NULL.          *
+*                                                                             *
+*  Description : Organise un appel de fonction avec ses arguments.            *
+*                                                                             *
+*  Retour      : Fonction mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanExpression *g_scan_logical_operation_new(BooleanOperationType type, GScanExpression *first, GScanExpression *second)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_BOOLEAN_OPERATION, NULL);
+
+    if (!g_scan_logical_operation_create(G_SCAN_LOGICAL_OPERATION(result), type, first, second))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr   = instance à initialiser pleinement.                  *
+*                type   = type d'opération booléenne à représenter.           *
+*                first  = premier opérande concerné.                          *
+*                second = éventuel second opérande impliqué ou NULL.          *
+*                                                                             *
+*  Description : Met en place une expression d'opération booléenne.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_logical_operation_create(GScanLogicalOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    op->type = type;
+
+    switch (type)
+    {
+        case BOT_AND:
+        case BOT_OR:
+            op->first = first;
+            g_object_ref(G_OBJECT(op->first));
+
+            op->second = second;
+            g_object_ref(G_OBJECT(op->second));
+
+            result = true;
+            break;
+
+        case BOT_NOT:
+            op->first = first;
+            g_object_ref(G_OBJECT(op->first));
+
+            result = (second == NULL);
+            assert(second != NULL);
+            break;
+
+        default:
+            result = false;
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item   = premier objet à consulter pour une comparaison.     *
+*                other  = second objet à consulter pour une comparaison.      *
+*                op     = opération de comparaison à réaliser.                *
+*                status = bilan des opérations de comparaison. [OUT]          *
+*                                                                             *
+*  Description : Réalise une comparaison entre objets selon un critère précis.*
+*                                                                             *
+*  Retour      : true si la comparaison a pu être effectuée, false sinon.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_logical_operation_compare_rich(const GScanLogicalOperation *item, const GScanLogicalOperation *other, RichCmpOperation op, bool *status)
+{
+    bool result;                            /* Etat à retourner            */
+
+    result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_BOOLEAN_OPERATION);
+    if (!result) goto done;
+
+    if (item->type != other->type)
+    {
+        *status = compare_rich_integer_values_unsigned(item->type, other->type, op);
+        goto done;
+    }
+
+    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first),
+                                            G_COMPARABLE_ITEM(other->first),
+                                            op, status);
+    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+    if (item->second == NULL)
+    {
+        assert(other->second == NULL);
+
+        switch (op)
+        {
+            case RCO_LT:
+            case RCO_NE:
+            case RCO_GT:
+                *status = false;
+                break;
+
+            case RCO_LE:
+            case RCO_EQ:
+            case RCO_GE:
+                *status = true;
+                break;
+
+        }
+
+    }
+
+    else
+        result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second),
+                                                G_COMPARABLE_ITEM(other->second),
+                                                op, status);
+
+ done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static ScanReductionState g_scan_logical_operation_reduce(GScanLogicalOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    ScanReductionState result;              /* Etat synthétisé à retourner */
+    GScanExpression *new_first;             /* Expression réduite (gauche) */
+    ScanReductionState state[2];            /* Bilan de sous-réductons     */
+    GScanExpression *new_second;            /* Expression réduite (droite) */
+    GScanExpression *bool_operands[2];      /* Expressions booléennes      */
+    bool values[2];                         /* Valeurs des éléments portés */
+    bool valid[2];                          /* Validité de ces valeurs     */
+
+    /* Réduction des éléments considérés */
+
+    state[0] = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
+
+    if (expr->second != NULL)
+        state[1] = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
+    else
+    {
+        new_second = NULL;
+        state[1] = SRS_REDUCED;
+    }
+
+    /* Récupération des valeurs booléennes */
+
+    if (new_first != NULL)
+    {
+        valid[0] = g_scan_expression_reduce_to_boolean(new_first, ctx, scope, &bool_operands[0]);
+
+        if (valid[0])
+            valid[0] = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(bool_operands[0]),
+                                                                   &values[0]);
+        else
+            bool_operands[0] = NULL;
+
+    }
+    else
+    {
+        bool_operands[0] = NULL;
+        valid[0] = false;
+    }
+
+    if (new_second != NULL)
+    {
+        valid[1] = g_scan_expression_reduce_to_boolean(new_second, ctx, scope, &bool_operands[1]);
+
+        if (valid[1])
+            valid[1] = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(bool_operands[1]),
+                                                                   &values[1]);
+        else
+            bool_operands[1] = NULL;
+
+    }
+    else
+    {
+        bool_operands[1] = NULL;
+        valid[1] = false;
+    }
+
+    /* Construction d'une réduction locale ? */
+
+    switch (expr->type)
+    {
+        case BOT_AND:
+            if (valid[0] && valid[1])
+            {
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { values[0] && values[1] });
+                result = SRS_REDUCED;
+            }
+
+            else if (valid[0] && !values[0])
+            {
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false });
+                result = SRS_REDUCED;
+            }
+
+            else if (valid[1] && !values[1])
+            {
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false });
+                result = SRS_REDUCED;
+            }
+
+            else
+            {
+                if (state[0] == SRS_UNRESOLVABLE || state[1] == SRS_UNRESOLVABLE)
+                    result = SRS_UNRESOLVABLE;
+                else
+                {
+                    assert(state[0] == SRS_WAIT_FOR_SCAN || state[1] == SRS_WAIT_FOR_SCAN);
+                    result = SRS_WAIT_FOR_SCAN;
+                }
+            }
+
+            break;
+
+        case BOT_OR:
+            if (valid[0] && valid[1])
+            {
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { values[0] || values[1] });
+                result = SRS_REDUCED;
+            }
+
+            else if (valid[0] && values[0])
+            {
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true });
+                result = SRS_REDUCED;
+            }
+
+            else if (valid[1] && values[1])
+            {
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true });
+                result = SRS_REDUCED;
+            }
+
+            else
+            {
+                if (state[0] == SRS_UNRESOLVABLE || state[1] == SRS_UNRESOLVABLE)
+                    result = SRS_UNRESOLVABLE;
+                else
+                {
+                    assert(state[0] == SRS_WAIT_FOR_SCAN || state[1] == SRS_WAIT_FOR_SCAN);
+                    result = SRS_WAIT_FOR_SCAN;
+                }
+            }
+
+            break;
+
+        case BOT_NOT:
+            if (valid[0])
+            {
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { !values[0] });
+                result = SRS_REDUCED;
+            }
+
+            else
+            {
+                if (state[0] == SRS_UNRESOLVABLE)
+                    result = SRS_UNRESOLVABLE;
+                else
+                {
+                    assert(state[0] == SRS_WAIT_FOR_SCAN);
+                    result = SRS_WAIT_FOR_SCAN;
+                }
+            }
+
+            break;
+
+    }
+
+    /* Mise à jour de la progression ? */
+
+    if (result == SRS_WAIT_FOR_SCAN)
+    {
+        if (new_first != expr->first || new_second != expr->second)
+        {
+            assert(new_first != NULL);
+            assert(new_second != NULL || expr->second == NULL);
+
+            *out = g_scan_logical_operation_new(expr->type, new_first, new_second);
+
+        }
+
+    }
+
+    /* Sortie propre */
+
+    g_clear_object(&bool_operands[0]);
+    g_clear_object(&bool_operands[1]);
+
+    g_clear_object(&new_first);
+    g_clear_object(&new_second);
+
+    return result;
+
+}
diff --git a/src/analysis/scan/exprs/logical.h b/src/analysis/scan/exprs/logical.h
new file mode 100644
index 0000000..e98bf11
--- /dev/null
+++ b/src/analysis/scan/exprs/logical.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logical.h - prototypes pour la gestion des opérations booléennes
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_LOGICAL_H
+#define _ANALYSIS_SCAN_EXPRS_LOGICAL_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_BOOLEAN_OPERATION            g_scan_logical_operation_get_type()
+#define G_SCAN_LOGICAL_OPERATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperation))
+#define G_IS_BOOLEAN_OPERATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BOOLEAN_OPERATION))
+#define G_SCAN_LOGICAL_OPERATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperationClass))
+#define G_IS_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BOOLEAN_OPERATION))
+#define G_SCAN_LOGICAL_OPERATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperationClass))
+
+
+/* Opération booléenne avec un ou deux opérandes (instance) */
+typedef struct _GScanLogicalOperation GScanLogicalOperation;
+
+/* Opération booléenne avec un ou deux opérandes (classe) */
+typedef struct _GScanLogicalOperationClass GScanLogicalOperationClass;
+
+
+/* Types d'opérations booléennes supportées */
+typedef enum _BooleanOperationType
+{
+    BOT_AND,                                /* Opérateur binaire "and"     */
+    BOT_OR,                                 /* Opérateur binaire "or"      */
+    BOT_NOT,                                /* Opérateur unaire "not"      */
+
+} BooleanOperationType;
+
+
+/* Indique le type défini pour une opération booléenne sur expression(s). */
+GType g_scan_logical_operation_get_type(void);
+
+/* Organise un appel de fonction avec ses arguments. */
+GScanExpression *g_scan_logical_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_LOGICAL_H */
diff --git a/src/analysis/scan/exprs/range-int.h b/src/analysis/scan/exprs/range-int.h
new file mode 100644
index 0000000..6257874
--- /dev/null
+++ b/src/analysis/scan/exprs/range-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range-int.h - prototypes internes pour la représentation compacte d'un éventail de valeurs
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_RANGE_INT_H
+#define _ANALYSIS_SCAN_EXPRS_RANGE_INT_H
+
+
+#include "range.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Représentation compacte d'un éventail de valeurs (instance) */
+struct _GScanCompactRange
+{
+    GScanExpression parent;                 /* A laisser en premier        */
+
+    GScanExpression *start;                 /* Point de départ             */
+    GScanExpression *end;                   /* Point d'arrivée             */
+
+};
+
+/* Représentation compacte d'un éventail de valeurs (classe) */
+struct _GScanCompactRangeClass
+{
+    GScanExpressionClass parent;            /* A laisser en premier        */
+
+};
+
+
+/* Met en place une réprésentation d'un éventail de valeurs. */
+bool g_scan_compact_range_create(GScanCompactRange *, GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_RANGE_INT_H */
diff --git a/src/analysis/scan/exprs/range.c b/src/analysis/scan/exprs/range.c
new file mode 100644
index 0000000..f97b15e
--- /dev/null
+++ b/src/analysis/scan/exprs/range.c
@@ -0,0 +1,352 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range.c - représentation compacte d'un éventail de valeurs
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "range.h"
+
+
+#include "literal.h"
+#include "range-int.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des éventail de valeurs. */
+static void g_scan_compact_range_class_init(GScanCompactRangeClass *);
+
+/* Initialise une instance d'éventail de valeurs. */
+static void g_scan_compact_range_init(GScanCompactRange *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_compact_range_dispose(GScanCompactRange *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_compact_range_finalize(GScanCompactRange *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_compact_range_reduce(GScanCompactRange *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_compact_range_reduce_to_boolean(GScanCompactRange *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réalise l'intersection entre deux ensembles. */
+static GScanExpression *g_scan_compact_range_intersect(GScanCompactRange *expr, const GScanExpression *, GScanContext *, GScanScope *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une représentation compacte d'un éventail de valeurs. */
+G_DEFINE_TYPE(GScanCompactRange, g_scan_compact_range, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des éventail de valeurs.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_compact_range_class_init(GScanCompactRangeClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanExpressionClass *expr;             /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_compact_range_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_compact_range_finalize;
+
+    expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+    expr->reduce = (reduce_expr_fc)g_scan_compact_range_reduce;
+    expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_compact_range_reduce_to_boolean;
+    expr->intersect = (intersect_scan_expr_fc)g_scan_compact_range_intersect;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : range = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une instance d'éventail de valeurs.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_compact_range_init(GScanCompactRange *range)
+{
+    range->start = NULL;
+    range->end = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : range = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_compact_range_dispose(GScanCompactRange *range)
+{
+    g_clear_object(&range->start);
+    g_clear_object(&range->end);
+
+    G_OBJECT_CLASS(g_scan_compact_range_parent_class)->dispose(G_OBJECT(range));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : range = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_compact_range_finalize(GScanCompactRange *range)
+{
+    G_OBJECT_CLASS(g_scan_compact_range_parent_class)->finalize(G_OBJECT(range));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : start = point de départ de la plage de valeurs.              *
+*                end   = point d'arrivée de la plage de valeurs.              *
+*                                                                             *
+*  Description : Organise une réprésentation d'un éventail de valeurs.        *
+*                                                                             *
+*  Retour      : Expression mise en place.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanExpression *g_scan_compact_range_new(GScanExpression *start, GScanExpression *end)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_COMPACT_RANGE, NULL);
+
+    if (!g_scan_compact_range_create(G_SCAN_COMPACT_RANGE(result), start, end))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : range = instance à initialiser pleinement.                   *
+*                start = point de départ de la plage de valeurs.              *
+*                end   = point d'arrivée de la plage de valeurs.              *
+*                                                                             *
+*  Description : Met en place une réprésentation d'un éventail de valeurs.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_compact_range_create(GScanCompactRange *range, GScanExpression *start, GScanExpression *end)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    range->start = start;
+    g_object_ref(G_OBJECT(start));
+
+    range->end = end;
+    g_object_ref(G_OBJECT(end));
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static ScanReductionState g_scan_compact_range_reduce(GScanCompactRange *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    ScanReductionState result;              /* Etat synthétisé à retourner */
+    GScanExpression *new_start;             /* Nouvelle réduction #1       */
+    GScanExpression *new_end;               /* Nouvelle réduction #2       */
+    ScanReductionState state_start;         /* Etat synthétisé #1          */
+    ScanReductionState state_end;           /* Etat synthétisé #2          */
+
+    new_start = NULL;
+    new_end = NULL;
+
+    state_start = g_scan_expression_reduce(expr->start, ctx, scope, &new_start);
+    if (state_start == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    state_end = g_scan_expression_reduce(expr->end, ctx, scope, &new_end);
+    if (state_end == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    if (state_start == SRS_WAIT_FOR_SCAN || state_end == SRS_WAIT_FOR_SCAN)
+        result = SRS_WAIT_FOR_SCAN;
+    else
+        result = SRS_REDUCED;
+
+    if (new_start != expr->start || new_end != expr->end)
+        *out = g_scan_compact_range_new(new_start, new_end);
+
+ exit:
+
+    g_clear_object(&new_start);
+    g_clear_object(&new_end);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme booléenne.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_compact_range_reduce_to_boolean(GScanCompactRange *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    bool status;                            /* Bilan d'une comparaison     */
+
+    result = G_IS_SCAN_LITERAL_EXPRESSION(expr->start) && G_IS_SCAN_LITERAL_EXPRESSION(expr->end);
+    if (!result) goto exit;
+
+    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(expr->start),
+                                            G_COMPARABLE_ITEM(expr->end),
+                                            RCO_LE, &status);
+    if (!result) goto exit;
+
+    *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à filtrer.                                *
+*                other = expression utilisée pour le filtrage.                *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                                                                             *
+*  Description : Réalise l'intersection entre deux ensembles.                 *
+*                                                                             *
+*  Retour      : Intersection entre les deux ensembles ou NULL en cas d'échec.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GScanExpression *g_scan_compact_range_intersect(GScanCompactRange *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope)
+{
+    GScanExpression *result;                /* Instance à retourner        */
+
+
+
+
+    result = true;  // TODO
+
+
+
+
+    return result;
+
+}
diff --git a/src/analysis/scan/exprs/range.h b/src/analysis/scan/exprs/range.h
new file mode 100644
index 0000000..4b7ad04
--- /dev/null
+++ b/src/analysis/scan/exprs/range.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range.h - prototypes pour la représentation compacte d'un éventail de valeurs
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_SET_H
+#define _ANALYSIS_SCAN_EXPRS_SET_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_COMPACT_RANGE            g_scan_compact_range_get_type()
+#define G_SCAN_COMPACT_RANGE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRange))
+#define G_IS_SCAN_COMPACT_RANGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_COMPACT_RANGE))
+#define G_SCAN_COMPACT_RANGE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRangeClass))
+#define G_IS_SCAN_COMPACT_RANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_COMPACT_RANGE))
+#define G_SCAN_COMPACT_RANGE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRangeClass))
+
+
+/* Représentation compacte d'un éventail de valeurs (instance) */
+typedef struct _GScanCompactRange GScanCompactRange;
+
+/* Représentation compacte d'un éventail de valeurs (classe) */
+typedef struct _GScanCompactRangeClass GScanCompactRangeClass;
+
+
+/* Indique le type défini pour une représentation compacte d'un éventail de valeurs. */
+GType g_scan_compact_range_get_type(void);
+
+/* Organise une réprésentation d'un éventail de valeurs. */
+GScanExpression *g_scan_compact_range_new(GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_SET_H */
diff --git a/src/analysis/scan/exprs/relational-int.h b/src/analysis/scan/exprs/relational-int.h
new file mode 100644
index 0000000..813b89d
--- /dev/null
+++ b/src/analysis/scan/exprs/relational-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relational-int.h - prototypes internes pour la gestion des opérations relationnelles
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H
+
+
+#include "relational.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération relationnelle impliquant deux opérandes (instance) */
+struct _GScanRelationalOperation
+{
+    GScanExpression parent;                 /* A laisser en premier        */
+
+    RichCmpOperation rel_type;              /* Type de relation étudiée    */
+
+    GScanExpression *left;                  /* Expression impactée #1      */
+    GScanExpression *right;                 /* Expression impactée #2      */
+
+};
+
+/* Opération relationnelle impliquant deux opérandes (classe) */
+struct _GScanRelationalOperationClass
+{
+    GScanExpressionClass parent;            /* A laisser en premier        */
+
+};
+
+
+/* Met en place une opération relationnelle entre expressions. */
+bool g_scan_relational_operation_create(GScanRelationalOperation *, RichCmpOperation, GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H */
diff --git a/src/analysis/scan/exprs/relational.c b/src/analysis/scan/exprs/relational.c
new file mode 100644
index 0000000..b56b599
--- /dev/null
+++ b/src/analysis/scan/exprs/relational.c
@@ -0,0 +1,408 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relational.c - gestion des opérations relationnelles
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "relational.h"
+
+
+#include <assert.h>
+
+
+#include "relational-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations de relations. */
+static void g_scan_relational_operation_class_init(GScanRelationalOperationClass *);
+
+/* Initialise une instance d'opération de relation. */
+static void g_scan_relational_operation_init(GScanRelationalOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_relational_operation_dispose(GScanRelationalOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_relational_operation_finalize(GScanRelationalOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_scan_relational_operation_compare_rich(const GScanRelationalOperation *, const GScanRelationalOperation *, RichCmpOperation, bool *);
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_relational_operation_reduce(GScanRelationalOperation *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+G_DEFINE_TYPE(GScanRelationalOperation, g_scan_relational_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des opérations de relations.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_relational_operation_class_init(GScanRelationalOperationClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanExpressionClass *expr;             /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_relational_operation_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_relational_operation_finalize;
+
+    expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+    expr->cmp_rich = (compare_expr_rich_fc)g_scan_relational_operation_compare_rich;
+    expr->reduce = (reduce_expr_fc)g_scan_relational_operation_reduce;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance à initialiser.                                 *
+*                                                                             *
+*  Description : Initialise une instance d'opération de relation.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_relational_operation_init(GScanRelationalOperation *op)
+{
+    op->left = NULL;
+    op->right = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance d'objet GLib à traiter.                        *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_relational_operation_dispose(GScanRelationalOperation *op)
+{
+    g_clear_object(&op->left);
+    g_clear_object(&op->right);
+
+    G_OBJECT_CLASS(g_scan_relational_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op = instance d'objet GLib à traiter.                        *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_relational_operation_finalize(GScanRelationalOperation *op)
+{
+    G_OBJECT_CLASS(g_scan_relational_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type  = type d'opération booléenne à représenter.            *
+*                left  = premier opérande concerné.                           *
+*                right = éventuel second opérande impliqué ou NULL.           *
+*                                                                             *
+*  Description : Organise une opération relationnelle entre expressions.      *
+*                                                                             *
+*  Retour      : Fonction mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanExpression *g_scan_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_RELATIONAL_OPERATION, NULL);
+
+    if (!g_scan_relational_operation_create(G_SCAN_RELATIONAL_OPERATION(result), type, left, right))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : op    = instance à initialiser pleinement.                   *
+*                type  = type d'opération booléenne à représenter.            *
+*                left  = premier opérande concerné.                           *
+*                right = éventuel second opérande impliqué ou NULL.           *
+*                                                                             *
+*  Description : Met en place une opération relationnelle entre expressions.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_relational_operation_create(GScanRelationalOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    op->rel_type = type;
+
+    op->left = left;
+    g_object_ref(G_OBJECT(op->left));
+
+    op->right = right;
+    g_object_ref(G_OBJECT(op->right));
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item   = premier objet à consulter pour une comparaison.     *
+*                other  = second objet à consulter pour une comparaison.      *
+*                op     = opération de comparaison à réaliser.                *
+*                status = bilan des opérations de comparaison. [OUT]          *
+*                                                                             *
+*  Description : Réalise une comparaison entre objets selon un critère précis.*
+*                                                                             *
+*  Retour      : true si la comparaison a pu être effectuée, false sinon.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_relational_operation_compare_rich(const GScanRelationalOperation *item, const GScanRelationalOperation *other, RichCmpOperation op, bool *status)
+{
+    bool result;                            /* Etat à retourner            */
+
+    result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_RELATIONAL_OPERATION);
+    if (!result) goto done;
+
+    if (item->rel_type != other->rel_type)
+    {
+        *status = compare_rich_integer_values_unsigned(item->rel_type, other->rel_type, op);
+        goto done;
+    }
+
+    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left),
+                                            G_COMPARABLE_ITEM(other->left),
+                                            op, status);
+    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
+                                            G_COMPARABLE_ITEM(other->right),
+                                            op, status);
+
+ done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static ScanReductionState g_scan_relational_operation_reduce(GScanRelationalOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    ScanReductionState result;              /* Etat synthétisé à retourner */
+    GScanExpression *new_left;              /* Expression réduite (gauche) */
+    GScanExpression *new_right;             /* Expression réduite (droite) */
+    ScanReductionState state_left;          /* Etat synthétisé #1          */
+    ScanReductionState state_right;         /* Etat synthétisé #2          */
+    LiteralValueType vtype_left;            /* Type de valeur portée #1    */
+    LiteralValueType vtype_right;           /* Type de valeur portée #2    */
+    GScanExpression *casted;                /* Nouvelle forme en booléen   */
+    bool status;                            /* Bilan d'une comparaison     */
+    bool valid;                             /* Validité de ce bilan obtenu */
+
+    /* Réduction des éléments considérés */
+
+    new_left = NULL;
+    new_right = NULL;
+
+    state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+    if (state_left == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+    if (state_right == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    /* Transtypage vers des booléens imposé ? */
+
+    if (expr->rel_type == RCO_EQ || expr->rel_type == RCO_NE)
+    {
+        if (G_IS_SCAN_LITERAL_EXPRESSION(new_left))
+        {
+            vtype_left = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(new_left));
+
+            if (vtype_left == LVT_BOOLEAN)
+            {
+                if (g_scan_expression_reduce_to_boolean(new_right, ctx, scope, &casted))
+                {
+                    g_object_unref(G_OBJECT(new_right));
+                    new_right = casted;
+                }
+            }
+
+        }
+
+        if (G_IS_SCAN_LITERAL_EXPRESSION(new_right))
+        {
+            vtype_right = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(new_right));
+
+            if (vtype_right == LVT_BOOLEAN)
+            {
+                if (g_scan_expression_reduce_to_boolean(new_left, ctx, scope, &casted))
+                {
+                    g_object_unref(G_OBJECT(new_left));
+                    new_left = casted;
+                }
+            }
+
+        }
+
+    }
+
+    /* Construction d'une réduction locale ? */
+
+    if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
+    {
+        valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(new_left),
+                                               G_COMPARABLE_ITEM(new_right),
+                                               expr->rel_type, &status);
+
+        if (valid)
+        {
+            *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { status });
+            result = SRS_REDUCED;
+        }
+        else
+            result = SRS_UNRESOLVABLE;
+
+    }
+
+    /* Mise à jour de la progression ? */
+
+    else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
+    {
+        if (new_left != expr->left || new_right != expr->right)
+            *out = g_scan_relational_operation_new(expr->rel_type, new_left, new_right);
+
+        result = SRS_WAIT_FOR_SCAN;
+
+    }
+
+    /* Cas des situations où les expressions ne sont pas exploitables (!) */
+    else
+    {
+        assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+        result = SRS_UNRESOLVABLE;
+
+    }
+
+    /* Sortie propre */
+
+ exit:
+
+    g_clear_object(&new_left);
+    g_clear_object(&new_right);
+
+    return result;
+
+}
diff --git a/src/analysis/scan/exprs/relational.h b/src/analysis/scan/exprs/relational.h
new file mode 100644
index 0000000..10d58a6
--- /dev/null
+++ b/src/analysis/scan/exprs/relational.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relational.h - prototypes pour la gestion des opérations relationnelles
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_RELATIONAL_H
+#define _ANALYSIS_SCAN_EXPRS_RELATIONAL_H
+
+
+#include "../expr.h"
+#include "../../../glibext/comparison.h"
+
+
+
+#define G_TYPE_SCAN_RELATIONAL_OPERATION            g_scan_relational_operation_get_type()
+#define G_SCAN_RELATIONAL_OPERATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperation))
+#define G_IS_SCAN_RELATIONAL_OPERATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_RELATIONAL_OPERATION))
+#define G_SCAN_RELATIONAL_OPERATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperationClass))
+#define G_IS_SCAN_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_RELATIONAL_OPERATION))
+#define G_SCAN_RELATIONAL_OPERATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperationClass))
+
+
+/* Opération relationnelle impliquant deux opérandes (instance) */
+typedef struct _GScanRelationalOperation GScanRelationalOperation;
+
+/* Opération relationnelle impliquant deux opérandes (classe) */
+typedef struct _GScanRelationalOperationClass GScanRelationalOperationClass;
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+GType g_scan_relational_operation_get_type(void);
+
+/* Organise une opération relationnelle entre expressions. */
+GScanExpression *g_scan_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_RELATIONAL_H */
diff --git a/src/analysis/scan/exprs/relop-int.h b/src/analysis/scan/exprs/relop-int.h
deleted file mode 100644
index 3adbcf0..0000000
--- a/src/analysis/scan/exprs/relop-int.h
+++ /dev/null
@@ -1,60 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * relop-int.h - prototypes internes pour la gestion des opérations relationnelles
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _ANALYSIS_SCAN_EXPRS_RELOP_INT_H
-#define _ANALYSIS_SCAN_EXPRS_RELOP_INT_H
-
-
-#include "relop.h"
-
-
-#include "../expr-int.h"
-
-
-
-/* Opération relationnelle impliquant deux opérandes (instance) */
-struct _GRelOperation
-{
-    GScanExpression parent;                 /* A laisser en premier        */
-
-    RichCmpOperation rel_type;              /* Type de relation étudiée    */
-
-    GScanExpression *left;                  /* Expression impactée #1      */
-    GScanExpression *right;                 /* Expression impactée #2      */
-
-};
-
-/* Opération relationnelle impliquant deux opérandes (classe) */
-struct _GRelOperationClass
-{
-    GScanExpressionClass parent;            /* A laisser en premier        */
-
-};
-
-
-/* Met en place une opération relationnelle entre expressions. */
-bool g_relational_operation_create(GRelOperation *, RichCmpOperation, GScanExpression *, GScanExpression *);
-
-
-
-#endif  /* _ANALYSIS_SCAN_EXPRS_RELOP_INT_H */
diff --git a/src/analysis/scan/exprs/relop.c b/src/analysis/scan/exprs/relop.c
deleted file mode 100644
index 7dc6864..0000000
--- a/src/analysis/scan/exprs/relop.c
+++ /dev/null
@@ -1,392 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * relop.c - gestion des opérations relationnelles
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "relop.h"
-
-
-#include "relop-int.h"
-#include "literal.h"
-
-
-
-/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
-
-
-/* Initialise la classe des opérations de relations. */
-static void g_relational_operation_class_init(GRelOperationClass *);
-
-/* Initialise une instance d'opération de relation. */
-static void g_relational_operation_init(GRelOperation *);
-
-/* Supprime toutes les références externes. */
-static void g_relational_operation_dispose(GRelOperation *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_relational_operation_finalize(GRelOperation *);
-
-
-
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-
-
-/* Réalise une comparaison entre objets selon un critère précis. */
-static bool g_relational_operation_compare_rich(const GRelOperation *, const GRelOperation *, RichCmpOperation, bool *);
-
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_relational_operation_copy(GRelOperation *, const GRelOperation *);
-
-/* Réduit une expression à une forme plus simple. */
-static bool g_relational_operation_reduce(GRelOperation *, GScanContext *, GScanScope *, GScanExpression **);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour une opération de relation entre expressions. */
-G_DEFINE_TYPE(GRelOperation, g_relational_operation, G_TYPE_SCAN_EXPRESSION);
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : klass = classe à initialiser.                                *
-*                                                                             *
-*  Description : Initialise la classe des opérations de relations.            *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_relational_operation_class_init(GRelOperationClass *klass)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-    GScanExpressionClass *expr;             /* Version de classe parente   */
-
-    object = G_OBJECT_CLASS(klass);
-
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_relational_operation_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_relational_operation_finalize;
-
-    expr = G_SCAN_EXPRESSION_CLASS(klass);
-
-    expr->cmp_rich = (compare_expr_rich_fc)g_relational_operation_compare_rich;
-    expr->copy = (copy_expr_fc)g_relational_operation_copy;
-    expr->reduce = (reduce_expr_fc)g_relational_operation_reduce;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op = instance à initialiser.                                 *
-*                                                                             *
-*  Description : Initialise une instance d'opération de relation.             *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_relational_operation_init(GRelOperation *op)
-{
-    op->left = NULL;
-    op->right = NULL;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op = instance d'objet GLib à traiter.                        *
-*                                                                             *
-*  Description : Supprime toutes les références externes.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_relational_operation_dispose(GRelOperation *op)
-{
-    g_clear_object(&op->left);
-    g_clear_object(&op->right);
-
-    G_OBJECT_CLASS(g_relational_operation_parent_class)->dispose(G_OBJECT(op));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op = instance d'objet GLib à traiter.                        *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_relational_operation_finalize(GRelOperation *op)
-{
-    G_OBJECT_CLASS(g_relational_operation_parent_class)->finalize(G_OBJECT(op));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : type  = type d'opération booléenne à représenter.            *
-*                left  = premier opérande concerné.                           *
-*                right = éventuel second opérande impliqué ou NULL.           *
-*                                                                             *
-*  Description : Organise une opération relationnelle entre expressions.      *
-*                                                                             *
-*  Retour      : Fonction mise en place.                                      *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right)
-{
-    GScanExpression *result;                /* Structure à retourner       */
-
-    result = g_object_new(G_TYPE_RELATIONAL_OPERATION, NULL);
-
-    if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, left, right))
-        g_clear_object(&result);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : op    = instance à initialiser pleinement.                   *
-*                type  = type d'opération booléenne à représenter.            *
-*                left  = premier opérande concerné.                           *
-*                right = éventuel second opérande impliqué ou NULL.           *
-*                                                                             *
-*  Description : Met en place une opération relationnelle entre expressions.  *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = false;
-
-    if (g_scan_expression_get_value_type(left) != g_scan_expression_get_value_type(left))
-        goto exit;
-
-    if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN))
-        goto exit;
-
-    op->rel_type = type;
-
-    op->left = left;
-    g_object_ref(G_OBJECT(op->left));
-
-    op->right = right;
-    g_object_ref(G_OBJECT(op->right));
-
-    result = true;
-
- exit:
-
-    return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : item   = premier objet à consulter pour une comparaison.     *
-*                other  = second objet à consulter pour une comparaison.      *
-*                op     = opération de comparaison à réaliser.                *
-*                status = bilan des opérations de comparaison. [OUT]          *
-*                                                                             *
-*  Description : Réalise une comparaison entre objets selon un critère précis.*
-*                                                                             *
-*  Retour      : true si la comparaison a pu être effectuée, false sinon.     *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool g_relational_operation_compare_rich(const GRelOperation *item, const GRelOperation *other, RichCmpOperation op, bool *status)
-{
-    bool result;                            /* Etat à retourner            */
-
-    result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_RELATIONAL_OPERATION);
-    if (!result) goto done;
-
-    if (item->rel_type != other->rel_type)
-    {
-        *status = compare_rich_integer_values(item->rel_type, other->rel_type, op);
-        goto done;
-    }
-
-    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
-    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
-
-    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left),
-                                            G_COMPARABLE_ITEM(other->left),
-                                            op, status);
-    if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
-
-    result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
-                                            G_COMPARABLE_ITEM(other->right),
-                                            op, status);
-
- done:
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : dest = emplacement d'enregistrement à constituer. [OUT]      *
-*                src  = expression source à copier.                           *
-*                                                                             *
-*  Description : Reproduit une expression en place dans une nouvelle instance.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_relational_operation_copy(GRelOperation *dest, const GRelOperation *src)
-{
-    GScanExpressionClass *class;            /* Classe parente à solliciter */
-
-    class = G_SCAN_EXPRESSION_CLASS(g_relational_operation_parent_class);
-
-    class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
-    dest->rel_type = src->rel_type;
-
-    dest->left = g_scan_expression_duplicate(src->left);
-    dest->right = g_scan_expression_duplicate(src->right);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : expr  = expression à consulter.                              *
-*                ctx   = contexte de suivi de l'analyse courante.             *
-*                scope = portée courante des variables locales.               *
-*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
-*                                                                             *
-*  Description : Réduit une expression à une forme plus simple.               *
-*                                                                             *
-*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
-{
-    bool result;                            /* Bilan à retourner           */
-    GScanExpression *new_left;              /* Expression réduite (gauche) */
-    GScanExpression *new_right;             /* Expression réduite (droite) */
-    bool status;                            /* Bilan d'une comparaison     */
-    bool valid;                             /* Validité de ce bilan obtenu */
-
-    /* Réduction des éléments considérés */
-
-    new_left = NULL;
-    new_right = NULL;
-
-    result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
-    if (!result) goto exit;
-
-    result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
-    if (!result) goto exit;
-
-    /* Construction d'une réduction locale ? */
-
-    if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
-    {
-        valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(new_left),
-                                               G_COMPARABLE_ITEM(new_right),
-                                               expr->rel_type, &status);
-
-        if (valid)
-            *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status });
-
-    }
-
-    /* Mise à jour de la progression ? */
-
-    else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
-    {
-        if (new_left == NULL)
-        {
-            new_left = expr->left;
-            g_object_ref(G_OBJECT(new_left));
-        }
-
-        if (new_right == NULL)
-        {
-            new_right = expr->right;
-            g_object_ref(G_OBJECT(new_right));
-        }
-
-        *out = g_relational_operation_new(expr->rel_type, new_left, new_right);
-
-    }
-
- exit:
-
-    g_clear_object(&new_left);
-    g_clear_object(&new_right);
-
-    return result;
-
-}
diff --git a/src/analysis/scan/exprs/relop.h b/src/analysis/scan/exprs/relop.h
deleted file mode 100644
index ecbc8ef..0000000
--- a/src/analysis/scan/exprs/relop.h
+++ /dev/null
@@ -1,56 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * relop.h - prototypes pour la gestion des opérations relationnelles
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _ANALYSIS_SCAN_EXPRS_RELOP_H
-#define _ANALYSIS_SCAN_EXPRS_RELOP_H
-
-
-#include "../expr.h"
-#include "../../../glibext/comparison.h"
-
-
-
-#define G_TYPE_RELATIONAL_OPERATION            g_relational_operation_get_type()
-#define G_RELATIONAL_OPERATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperation))
-#define G_IS_RELATIONAL_OPERATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RELATIONAL_OPERATION))
-#define G_RELATIONAL_OPERATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass))
-#define G_IS_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RELATIONAL_OPERATION))
-#define G_RELATIONAL_OPERATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass))
-
-
-/* Opération relationnelle impliquant deux opérandes (instance) */
-typedef struct _GRelOperation GRelOperation;
-
-/* Opération relationnelle impliquant deux opérandes (classe) */
-typedef struct _GRelOperationClass GRelOperationClass;
-
-
-/* Indique le type défini pour une opération de relation entre expressions. */
-GType g_relational_operation_get_type(void);
-
-/* Organise une opération relationnelle entre expressions. */
-GScanExpression *g_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *);
-
-
-
-#endif  /* _ANALYSIS_SCAN_EXPRS_RELOP_H */
diff --git a/src/analysis/scan/exprs/set-int.h b/src/analysis/scan/exprs/set-int.h
new file mode 100644
index 0000000..ebb4380
--- /dev/null
+++ b/src/analysis/scan/exprs/set-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * set-int.h - prototypes internes pour la base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_SET_INT_H
+#define _ANALYSIS_SCAN_EXPRS_SET_INT_H
+
+
+#include "set.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (instance) */
+struct _GScanGenericSet
+{
+    GScanExpression parent;                 /* A laisser en premier        */
+
+    GScanExpression **items;                /* Liste d'éléments embarqués  */
+    size_t count;                           /* Quantité de ces éléments    */
+
+};
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (classe) */
+struct _GScanGenericSetClass
+{
+    GScanExpressionClass parent;            /* A laisser en premier        */
+
+};
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_SET_INT_H */
diff --git a/src/analysis/scan/exprs/set.c b/src/analysis/scan/exprs/set.c
new file mode 100644
index 0000000..0a93ced
--- /dev/null
+++ b/src/analysis/scan/exprs/set.c
@@ -0,0 +1,379 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * set.c - base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "set.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "literal.h"
+#include "set-int.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des bases d'ensembles d'éléments. */
+static void g_scan_generic_set_class_init(GScanGenericSetClass *);
+
+/* Initialise une instance de base d'ensemble d'éléments. */
+static void g_scan_generic_set_init(GScanGenericSet *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_generic_set_dispose(GScanGenericSet *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_generic_set_finalize(GScanGenericSet *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_generic_set_reduce(GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Dénombre les éléments portés par une expression. */
+static bool g_scan_generic_set_count_items(const GScanGenericSet *, size_t *);
+
+/* Fournit un élément donné issu d'un ensemble constitué. */
+static bool g_scan_generic_set_get_item(const GScanGenericSet *, size_t, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une base d'ensembles d'éléments homogènes ou hétérogènes. */
+G_DEFINE_TYPE(GScanGenericSet, g_scan_generic_set, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des bases d'ensembles d'éléments.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_generic_set_class_init(GScanGenericSetClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanExpressionClass *expr;             /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_generic_set_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_generic_set_finalize;
+
+    expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+    expr->reduce = (reduce_expr_fc)g_scan_generic_set_reduce;
+    expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_generic_set_reduce_to_boolean;
+    expr->count = (count_scan_expr_fc)g_scan_generic_set_count_items;
+    expr->get = (get_scan_expr_fc)g_scan_generic_set_get_item;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : set = instance à initialiser.                                *
+*                                                                             *
+*  Description : Initialise une instance de base d'ensemble d'éléments.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_generic_set_init(GScanGenericSet *set)
+{
+    set->items = NULL;
+    set->count = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : set = instance d'objet GLib à traiter.                       *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_generic_set_dispose(GScanGenericSet *set)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < set->count; i++)
+        g_clear_object(&set->items[i]);
+
+    G_OBJECT_CLASS(g_scan_generic_set_parent_class)->dispose(G_OBJECT(set));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : set = instance d'objet GLib à traiter.                       *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_generic_set_finalize(GScanGenericSet *set)
+{
+    if (set->items != NULL)
+        free(set->items);
+
+    G_OBJECT_CLASS(g_scan_generic_set_parent_class)->finalize(G_OBJECT(set));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Met en place un ensemble d'éléments homogènes ou hétérogènes.*
+*                                                                             *
+*  Retour      : Expression mise en place.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanExpression *g_scan_generic_set_new(void)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_GENERIC_SET, NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : set  = ensemble à compléter.                                 *
+*                item = nouvel élément à intégrer.                            *
+*                                                                             *
+*  Description : Ajoute un nouvel élément à un ensemble.                      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_generic_set_add_item(GScanGenericSet *set, GScanExpression *item)
+{
+    set->items = realloc(set->items, ++set->count * sizeof(GScanExpression *));
+
+    set->items[set->count - 1] = item;
+    g_object_ref(G_OBJECT(item));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static ScanReductionState g_scan_generic_set_reduce(GScanGenericSet *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    ScanReductionState result;              /* Etat synthétisé à retourner */
+    size_t i;                               /* Boucle de parcours #1       */
+    GScanExpression *item;                  /* Elément en cours d'analyse  */
+    GScanExpression *new;                   /* Nouvelle réduction obtenue  */
+    ScanReductionState state;               /* Etat synthétisé d'un élément*/
+    size_t k;                               /* Boucle de parcours #2       */
+
+    result = SRS_REDUCED;
+
+    for (i = 0; i < expr->count; i++)
+    {
+        item = expr->items[i];
+
+        state = g_scan_expression_reduce(item, ctx, scope, &new);
+        if (state == SRS_UNRESOLVABLE)
+        {
+            result = SRS_UNRESOLVABLE;
+            g_clear_object(out);
+            break;
+        }
+
+        if (state == SRS_WAIT_FOR_SCAN)
+            result = SRS_WAIT_FOR_SCAN;
+
+        if (new != item)
+        {
+            if (*out == NULL)
+            {
+                *out = g_scan_generic_set_new();
+
+                for (k = 0; k < i; k++)
+                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), expr->items[k]);
+
+            }
+
+            g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), new);
+
+        }
+
+        else
+        {
+            if (*out != NULL)
+                g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), item);
+        }
+
+        g_object_unref(G_OBJECT(new));
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme booléenne.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->count > 0 });
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                count = quantité d'éléments déterminée. [OUT]                *
+*                                                                             *
+*  Description : Dénombre les éléments portés par une expression.             *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, size_t *count)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    *count = expr->count;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                index = indice de l'élément à transférer.                    *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Fournit un élément donné issu d'un ensemble constitué.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_generic_set_get_item(const GScanGenericSet *expr, size_t index, GScanExpression **out)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = (index < expr->count);
+
+    if (result)
+        *out = expr->items[index];
+
+    return result;
+
+}
diff --git a/src/analysis/scan/exprs/set.h b/src/analysis/scan/exprs/set.h
new file mode 100644
index 0000000..f857ce9
--- /dev/null
+++ b/src/analysis/scan/exprs/set.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * set.h - prototypes pour la base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_SET_H
+#define _ANALYSIS_SCAN_EXPRS_SET_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_GENERIC_SET            g_scan_generic_set_get_type()
+#define G_SCAN_GENERIC_SET(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_GENERIC_SET, GScanGenericSet))
+#define G_IS_SCAN_GENERIC_SET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_GENERIC_SET))
+#define G_SCAN_GENERIC_SET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_GENERIC_SET, GScanGenericSetClass))
+#define G_IS_SCAN_GENERIC_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_GENERIC_SET))
+#define G_SCAN_GENERIC_SET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_GENERIC_SET, GScanGenericSetClass))
+
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (instance) */
+typedef struct _GScanGenericSet GScanGenericSet;
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (classe) */
+typedef struct _GScanGenericSetClass GScanGenericSetClass;
+
+
+/* Indique le type défini pour une base d'ensembles d'éléments homogènes ou hétérogènes. */
+GType g_scan_generic_set_get_type(void);
+
+/* Met en place un ensemble d'éléments homogènes ou hétérogènes. */
+GScanExpression *g_scan_generic_set_new(void);
+
+/* Ajoute un nouvel élément à un ensemble. */
+void g_scan_generic_set_add_item(GScanGenericSet *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_SET_H */
diff --git a/src/analysis/scan/exprs/strop-int.h b/src/analysis/scan/exprs/strop-int.h
index 234ae8f..c2b40cf 100644
--- a/src/analysis/scan/exprs/strop-int.h
+++ b/src/analysis/scan/exprs/strop-int.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * strop-int.h - prototypes internes pour la gestion des opérations booléennes
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -34,7 +34,7 @@
 
 
 /* Opération booléenne avec un ou deux opérandes (instance) */
-struct _GStringOperation
+struct _GScanStringOperation
 {
     GScanExpression parent;                 /* A laisser en premier        */
 
@@ -47,7 +47,7 @@ struct _GStringOperation
 };
 
 /* Opération booléenne avec un ou deux opérandes (classe) */
-struct _GStringOperationClass
+struct _GScanStringOperationClass
 {
     GScanExpressionClass parent;            /* A laisser en premier        */
 
@@ -55,7 +55,7 @@ struct _GStringOperationClass
 
 
 /* Met en place une expression d'opération traite une chaîne. */
-bool g_string_operation_create(GStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool);
+bool g_scan_string_operation_create(GScanStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool);
 
 
 
diff --git a/src/analysis/scan/exprs/strop.c b/src/analysis/scan/exprs/strop.c
index 145e8da..c7c2878 100644
--- a/src/analysis/scan/exprs/strop.c
+++ b/src/analysis/scan/exprs/strop.c
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * strop.c - gestion des opérations booléennes
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -38,27 +38,24 @@
 
 
 /* Initialise la classe des opérations visant des chaînes. */
-static void g_string_operation_class_init(GStringOperationClass *);
+static void g_scan_string_operation_class_init(GScanStringOperationClass *);
 
 /* Initialise une instance d'opération visant une chaîne. */
-static void g_string_operation_init(GStringOperation *);
+static void g_scan_string_operation_init(GScanStringOperation *);
 
 /* Supprime toutes les références externes. */
-static void g_string_operation_dispose(GStringOperation *);
+static void g_scan_string_operation_dispose(GScanStringOperation *);
 
 /* Procède à la libération totale de la mémoire. */
-static void g_string_operation_finalize(GStringOperation *);
+static void g_scan_string_operation_finalize(GScanStringOperation *);
 
 
 
 /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
 
 
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_string_operation_copy(GStringOperation *, const GStringOperation *);
-
 /* Réduit une expression à une forme plus simple. */
-static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_string_operation_reduce(GScanStringOperation *, GScanContext *, GScanScope *, GScanExpression **);
 
 
 
@@ -68,7 +65,7 @@ static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanS
 
 
 /* Indique le type défini pour une opération traitant une chaîne de caractères. */
-G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanStringOperation, g_scan_string_operation, G_TYPE_SCAN_EXPRESSION);
 
 
 /******************************************************************************
@@ -83,21 +80,20 @@ G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION);
 *                                                                             *
 ******************************************************************************/
 
-static void g_string_operation_class_init(GStringOperationClass *klass)
+static void g_scan_string_operation_class_init(GScanStringOperationClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GScanExpressionClass *expr;             /* Version de classe parente   */
 
     object = G_OBJECT_CLASS(klass);
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_string_operation_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_string_operation_finalize;
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_string_operation_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_string_operation_finalize;
 
     expr = G_SCAN_EXPRESSION_CLASS(klass);
 
     expr->cmp_rich = (compare_expr_rich_fc)NULL;
-    expr->copy = (copy_expr_fc)g_string_operation_copy;
-    expr->reduce = (reduce_expr_fc)g_string_operation_reduce;
+    expr->reduce = (reduce_expr_fc)g_scan_string_operation_reduce;
 
 }
 
@@ -114,7 +110,7 @@ static void g_string_operation_class_init(GStringOperationClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_string_operation_init(GStringOperation *op)
+static void g_scan_string_operation_init(GScanStringOperation *op)
 {
     op->left = NULL;
     op->right = NULL;
@@ -134,12 +130,12 @@ static void g_string_operation_init(GStringOperation *op)
 *                                                                             *
 ******************************************************************************/
 
-static void g_string_operation_dispose(GStringOperation *op)
+static void g_scan_string_operation_dispose(GScanStringOperation *op)
 {
     g_clear_object(&op->left);
     g_clear_object(&op->right);
 
-    G_OBJECT_CLASS(g_string_operation_parent_class)->dispose(G_OBJECT(op));
+    G_OBJECT_CLASS(g_scan_string_operation_parent_class)->dispose(G_OBJECT(op));
 
 }
 
@@ -156,9 +152,9 @@ static void g_string_operation_dispose(GStringOperation *op)
 *                                                                             *
 ******************************************************************************/
 
-static void g_string_operation_finalize(GStringOperation *op)
+static void g_scan_string_operation_finalize(GScanStringOperation *op)
 {
-    G_OBJECT_CLASS(g_string_operation_parent_class)->finalize(G_OBJECT(op));
+    G_OBJECT_CLASS(g_scan_string_operation_parent_class)->finalize(G_OBJECT(op));
 
 }
 
@@ -178,13 +174,13 @@ static void g_string_operation_finalize(GStringOperation *op)
 *                                                                             *
 ******************************************************************************/
 
-GScanExpression *g_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive)
+GScanExpression *g_scan_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive)
 {
     GScanExpression *result;                /* Structure à retourner       */
 
-    result = g_object_new(G_TYPE_STRING_OPERATION, NULL);
+    result = g_object_new(G_TYPE_SCAN_STRING_OPERATION, NULL);
 
-    if (!g_string_operation_create(G_STRING_OPERATION(result), type, first, second, sensitive))
+    if (!g_scan_string_operation_create(G_SCAN_STRING_OPERATION(result), type, first, second, sensitive))
         g_clear_object(&result);
 
     return result;
@@ -198,7 +194,7 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio
 *                type      = type d'opération booléenne à représenter.        *
 *                left      = premier opérande concerné.                       *
 *                right     = éventuel second opérande impliqué ou NULL.       *
-*                sensitive = détermine la prise en compte de la casse.       *
+*                sensitive = détermine la prise en compte de la casse.        *
 *                                                                             *
 *  Description : Met en place une expression d'opération traite une chaîne.   *
 *                                                                             *
@@ -208,22 +204,11 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio
 *                                                                             *
 ******************************************************************************/
 
-bool g_string_operation_create(GStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive)
+bool g_scan_string_operation_create(GScanStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive)
 {
     bool result;                            /* Bilan à retourner           */
-    ExprValueType vtype;                    /* Type de valeur portée       */
-
-    result = false;
-
-    vtype = g_scan_expression_get_value_type(left);
-
-    if (vtype != EVT_STRING && vtype != EVT_PENDING)
-        goto exit;
-
-    vtype = g_scan_expression_get_value_type(right);
 
-    if (vtype != EVT_STRING && vtype != EVT_REG_EXPR && vtype != EVT_PENDING)
-        goto exit;
+    result = true;
 
     op->type = type;
 
@@ -251,10 +236,6 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G
     op->right = right;
     g_object_ref(G_OBJECT(op->right));
 
-    result = true;
-
- exit:
-
     return result;
 
 }
@@ -268,36 +249,6 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : dest = emplacement d'enregistrement à constituer. [OUT]      *
-*                src  = expression source à copier.                           *
-*                                                                             *
-*  Description : Reproduit une expression en place dans une nouvelle instance.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_string_operation_copy(GStringOperation *dest, const GStringOperation *src)
-{
-    GScanExpressionClass *class;            /* Classe parente à solliciter */
-
-    class = G_SCAN_EXPRESSION_CLASS(g_string_operation_parent_class);
-
-    class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
-    dest->type = src->type;
-    dest->case_sensitive = src->case_sensitive;
-
-    dest->left = g_scan_expression_duplicate(src->left);
-    dest->right = g_scan_expression_duplicate(src->right);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : expr  = expression à consulter.                              *
 *                ctx   = contexte de suivi de l'analyse courante.             *
 *                scope = portée courante des variables locales.               *
@@ -311,47 +262,65 @@ static void g_string_operation_copy(GStringOperation *dest, const GStringOperati
 *                                                                             *
 ******************************************************************************/
 
-static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_string_operation_reduce(GScanStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
 {
-    bool result;                            /* Bilan à retourner           */
+    ScanReductionState result;              /* Etat synthétisé à retourner */
     GScanExpression *new_left;              /* Expression réduite (gauche) */
     GScanExpression *new_right;             /* Expression réduite (droite) */
-    GLiteralExpression *op_left;            /* Opérande gauche final       */
-    GLiteralExpression *op_right;           /* Opérande droite final       */
+    ScanReductionState state_left;          /* Etat synthétisé #1          */
+    ScanReductionState state_right;         /* Etat synthétisé #2          */
+    GScanLiteralExpression *op_left;        /* Opérande gauche final       */
+    GScanLiteralExpression *op_right;       /* Opérande droite final       */
     const sized_string_t *strings[2];       /* Chaînes en jeu              */
     const void *found;                      /* Présence d'une bribe ?      */
     bool status;                            /* Bilan de comparaison #1     */
+    int ret;                                /* Bilan de comparaison #2     */
     size_t offset;                          /* Point de départ d'analyse   */
     const regex_t *preg;                    /* Expression rationnelle      */
-    int ret;                                /* Bilan de comparaison #2     */
 
     /* Réduction des éléments considérés */
 
     new_left = NULL;
     new_right = NULL;
 
-    result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
-    if (!result) goto exit;
+    state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+    if (state_left == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
 
-    result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
-    if (!result) goto exit;
+    state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+    if (state_right == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
 
     /* Construction d'une réduction locale ? */
 
-    if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
+    if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
     {
-        op_left = G_LITERAL_EXPRESSION(new_left);
-        op_right = G_LITERAL_EXPRESSION(new_right);
+        op_left = G_SCAN_LITERAL_EXPRESSION(new_left);
+        op_right = G_SCAN_LITERAL_EXPRESSION(new_right);
+
+        if (!g_scan_literal_expression_get_string_value(op_left, &strings[0]))
+        {
+            result = SRS_UNRESOLVABLE;
+            goto exit;
+        }
 
-        result = g_literal_expression_get_string_value(op_left, &strings[0]);
-        if (!result) goto exit;
+        result = SRS_REDUCED;
 
         switch (expr->type)
         {
             case SOT_CONTAINS:
 
-                result = g_literal_expression_get_string_value(op_right, &strings[1]);
-                if (!result) goto exit;
+                if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+                {
+                    result = SRS_UNRESOLVABLE;
+                    goto exit;
+                }
 
                 if (expr->case_sensitive)
                     found = memmem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len);
@@ -359,13 +328,16 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
                 else
                     found = memcasemem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len);
 
-                result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { found != NULL });
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { found != NULL });
                 break;
 
             case SOT_STARTSWITH:
 
-                result = g_literal_expression_get_string_value(op_right, &strings[1]);
-                if (!result) goto exit;
+                if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+                {
+                    result = SRS_UNRESOLVABLE;
+                    goto exit;
+                }
 
                 if (strings[0]->len < strings[1]->len)
                     status = false;
@@ -381,13 +353,16 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
 
                 }
 
-                result = g_literal_expression_new(EVT_BOOLEAN, &status);
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
                 break;
 
             case SOT_ENDSWITH:
 
-                result = g_literal_expression_get_string_value(op_right, &strings[1]);
-                if (!result) goto exit;
+                if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+                {
+                    result = SRS_UNRESOLVABLE;
+                    goto exit;
+                }
 
                 if (strings[0]->len < strings[1]->len)
                     status = false;
@@ -405,23 +380,29 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
 
                 }
 
-                result = g_literal_expression_new(EVT_BOOLEAN, &status);
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
                 break;
 
             case SOT_MATCHES:
 
-                result = g_literal_expression_get_regex_value(op_right, &preg);
-                if (!result) goto exit;
+                if (!g_scan_literal_expression_get_regex_value(op_right, &preg))
+                {
+                    result = SRS_UNRESOLVABLE;
+                    goto exit;
+                }
 
                 ret = regexec(preg, strings[0]->data, 0, NULL, 0);
 
-                *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH });
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { ret != REG_NOMATCH });
                 break;
 
             case SOT_IEQUALS:
 
-                result = g_literal_expression_get_string_value(op_right, &strings[1]);
-                if (!result) goto exit;
+                if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+                {
+                    result = SRS_UNRESOLVABLE;
+                    goto exit;
+                }
 
                 if (strings[0]->len != strings[1]->len)
                     status = false;
@@ -432,7 +413,7 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
                     status = (ret == 0);
                 }
 
-                result = g_literal_expression_new(EVT_BOOLEAN, &status);
+                *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
                 break;
 
         }
@@ -441,24 +422,26 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
 
     /* Mise à jour de la progression ? */
 
-    else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
+    else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
     {
-        if (new_left == NULL)
-        {
-            new_left = expr->left;
-            g_object_ref(G_OBJECT(new_left));
-        }
+        if (new_left != expr->left || new_right != expr->right)
+            *out = g_scan_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive);
 
-        if (new_right == NULL)
-        {
-            new_right = expr->right;
-            g_object_ref(G_OBJECT(new_right));
-        }
+        result = SRS_WAIT_FOR_SCAN;
 
-        *out = g_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive);
+    }
+
+    /* Cas des situations où les expressions ne sont pas exploitables (!) */
+    else
+    {
+        assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+        result = SRS_UNRESOLVABLE;
 
     }
 
+    /* Sortie propre */
+
  exit:
 
     g_clear_object(&new_left);
diff --git a/src/analysis/scan/exprs/strop.h b/src/analysis/scan/exprs/strop.h
index c7c0813..0a32269 100644
--- a/src/analysis/scan/exprs/strop.h
+++ b/src/analysis/scan/exprs/strop.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * strop.h - prototypes pour la gestion des opérations booléennes
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -29,19 +29,19 @@
 
 
 
-#define G_TYPE_STRING_OPERATION            g_string_operation_get_type()
-#define G_STRING_OPERATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_STRING_OPERATION, GStringOperation))
-#define G_IS_STRING_OPERATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_STRING_OPERATION))
-#define G_STRING_OPERATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STRING_OPERATION, GStringOperationClass))
-#define G_IS_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STRING_OPERATION))
-#define G_STRING_OPERATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STRING_OPERATION, GStringOperationClass))
+#define G_TYPE_SCAN_STRING_OPERATION            g_scan_string_operation_get_type()
+#define G_SCAN_STRING_OPERATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperation))
+#define G_IS_SCAN_STRING_OPERATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_STRING_OPERATION))
+#define G_SCAN_STRING_OPERATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperationClass))
+#define G_IS_SCAN_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_STRING_OPERATION))
+#define G_SCAN_STRING_OPERATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperationClass))
 
 
 /* Opération booléenne avec un ou deux opérandes (instance) */
-typedef struct _GStringOperation GStringOperation;
+typedef struct _GScanStringOperation GScanStringOperation;
 
 /* Opération booléenne avec un ou deux opérandes (classe) */
-typedef struct _GStringOperationClass GStringOperationClass;
+typedef struct _GScanStringOperationClass GScanStringOperationClass;
 
 
 /* Types d'opérations booléennes supportées */
@@ -57,10 +57,10 @@ typedef enum _StringOperationType
 
 
 /* Indique le type défini pour une opération traitant une chaîne de caractères. */
-GType g_string_operation_get_type(void);
+GType g_scan_string_operation_get_type(void);
 
 /* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool);
+GScanExpression *g_scan_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool);
 
 
 
diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y
index 525c5d1..19a4257 100644
--- a/src/analysis/scan/grammar.y
+++ b/src/analysis/scan/grammar.y
@@ -18,12 +18,15 @@ typedef void *yyscan_t;
 
 #include "scanner.h"
 #include "exprs/access.h"
-#include "exprs/arithmop.h"
-#include "exprs/boolop.h"
+#include "exprs/arithmetic.h"
 #include "exprs/call.h"
+#include "exprs/counter.h"
+#include "exprs/intersect.h"
 #include "exprs/literal.h"
+#include "exprs/logical.h"
+#include "exprs/set.h"
+#include "exprs/relational.h"
 #include "exprs/strop.h"
-#include "exprs/relop.h"
 #include "patterns/tokens/plain.h"
 
 
@@ -48,13 +51,12 @@ typedef void *yyscan_t;
 
     unsigned long long unsigned_integer;    /* Valeur entière #1           */
     signed long long signed_integer;        /* Valeur entière #2           */
-    double floating_number;                 /* Valeur à virgule flottante  */
+    //double floating_number;                 /* Valeur à virgule flottante  */
     sized_string_t sized_cstring;           /* Chaîne de caractères        */
-    char byte;                              /* Octet unique                */
+    //char byte;                              /* Octet unique                */
 
 
 
-    unsigned long long integer;             /* Valeur entière              */
 
 
     GScanRule *rule;                        /* Nouvelle règle à intégrer   */
@@ -89,11 +91,17 @@ YY_DECL;
 }
 
 
+%token INCLUDE          "include"
+
 %token RAW_RULE
 %token RULE_NAME
 
 %token STRINGS CONDITION
 %token IDENTIFIER
+%token BYTES_ID
+%token BYTES_ID_COUNTER
+%token BYTES_ID_LOCATION
+%token BYTES_ID_LENGTH
 %token NAME
 
 %token BRACE_IN BRACE_OUT ASSIGN COLON
@@ -104,7 +112,8 @@ YY_DECL;
 
 %token TRUE_            "true"
 %token FALSE_           "false"
-%token INTEGER
+%token SIGNED_INTEGER
+%token UNSIGNED_INTEGER
 %token STRING
 
 %token KB MB GB
@@ -132,7 +141,7 @@ YY_DECL;
 %token PLUS             "+"
 %token MINUS            "-"
 %token MUL              "*"
-%token DIV              "\\"
+%token DIV              "/"
 %token MOD              "%"
 
 %token PAREN_O          "("
@@ -145,16 +154,18 @@ YY_DECL;
 %token ALL              "all"
 %token OF               "of"
 %token THEM             "them"
+%token IN               "in"
 
 
 %type <sized_cstring> RULE_NAME
 
 
-%type <sized_cstring> IDENTIFIER
+%type <sized_cstring> IDENTIFIER BYTES_ID_COUNTER
 %type <sized_cstring> NAME
 
 
-%type <integer> INTEGER
+%type <signed_integer> SIGNED_INTEGER
+%type <unsigned_integer> UNSIGNED_INTEGER
 %type <sized_cstring> STRING
 
 %type <rule> rule
@@ -162,16 +173,19 @@ YY_DECL;
 %type <sized_cstring> PLAIN_STRING
 %type <pattern> MASKED_STRING
 
-%type <expr> cexpression
+%type <expr> cexpression _cexpression
+%type <expr> pattern_match
 %type <expr> literal
 %type <expr> item_chain
 %type <args_list> call_args
-%type <expr> bool_expr
-%type <expr> rel_expr
-%type <expr> str_expr
+%type <expr> logical_expr
+%type <expr> relational_expr
+%type <expr> string_op
 %type <expr> arithm_expr
 %type <expr> set_counter
-
+%type <expr> set
+%type <expr> set_items
+%type <expr> intersection
 
 
 %left OR
@@ -181,11 +195,11 @@ YY_DECL;
 %left LT LE GT GE
 %left PLUS MINUS
 %left MUL DIV MOD
+%left IN
 %right NOT
 
 
 
-
 %destructor { printf("-------- Discarding symbol %p.\n", $$); } <rule>
 
 
@@ -207,12 +221,24 @@ YY_DECL;
 
 
 rules : /* empty */
+      | external rules
       | rule rules { g_content_scanner_add_rule(scanner, $1); }
 
         //rule : RAW_RULE RULE_NAME { printf("RULE %s\n", $2); } RAW_BLOCK { printf("BLOCK: %s\n", $4); }
 
+
+external : "include" STRING
+         {
+             bool __status;
+             __status = g_content_scanner_include_resource(scanner, $2.data);
+             if (!__status)
+                 YYERROR;
+         }
+
+
 rule : RAW_RULE RULE_NAME
      {
+         //printf("--------built rule '%s'\n", $2.data);
          *built_rule = g_scan_rule_new($2.data);
          $<rule>$ = *built_rule;
      }
@@ -220,6 +246,7 @@ rule : RAW_RULE RULE_NAME
      {
          $$ = $<rule>3;
          //printf("RULE %s -> %p\n", $2, $$);
+         //printf("end of rule\n");
      } 
 
 
@@ -274,16 +301,18 @@ string_decl : IDENTIFIER ASSIGN PLAIN_STRING
             }
             ;
 
-condition : /* empty */
-          | CONDITION COLON cexpression
-          {
-              g_scan_rule_set_match_condition(*built_rule, $3);
-              g_object_ref(G_OBJECT($3));
-          }
-          ;
+      condition : /* empty */
+                | CONDITION COLON cexpression
+                {
+                    g_scan_rule_set_match_condition(*built_rule, $3);
+                    g_object_unref(G_OBJECT($3));
+                }
+                ;
 
-cexpression : IDENTIFIER
-            {
+    cexpression : _cexpression { $$ = $1; if ($$ == NULL) { printf("ERROR !!!\n"); YYERROR; } }
+
+   _cexpression : IDENTIFIER
+                {
                 printf("named var: %s\n", "$1");
                 /*
                    GSearchPattern *__pat;
@@ -297,112 +326,223 @@ cexpression : IDENTIFIER
                        g_object_unref(G_OBJECT(__pat));
                    }
                 */
-            }
-            | literal { $$ = $1; }
-            | item_chain { $$ = $1; }
-            | bool_expr { $$ = $1; }
-            | rel_expr { $$ = $1; }
-            | str_expr { $$ = $1; }
-            | arithm_expr { $$ = $1; }
-            | set_counter { $$ = $1; }
-            | "(" cexpression ")" { $$ = $2; }
+                }
+                | literal { $$ = $1; }
+                | pattern_match { $$ = $1; }
+                | item_chain { $$ = $1; }
+                | logical_expr { $$ = $1; }
+                | relational_expr { $$ = $1; }
+                | string_op { $$ = $1; }
+                | arithm_expr { $$ = $1; }
+                | set_counter { $$ = $1; }
+                | set { $$ = $1; }
+                | intersection { $$ = $1; }
+                | "(" cexpression ")" { $$ = $2; }
+                ;
+
+  pattern_match : BYTES_ID_COUNTER
+                {
+                    GSearchPattern *__pat;
+                    __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+                    $$ = g_scan_match_counter_new(__pat);
+                    g_object_unref(G_OBJECT(__pat));
+                }
+                ;
+
+        literal : "true"
+                {
+                    $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true });
+                }
+                | "false"
+                {
+                    $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ false });
+                }
+                | SIGNED_INTEGER
+                {
+                    $$ = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &$1);
+                }
+                | UNSIGNED_INTEGER
+                {
+                    $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &$1);
+                }
+                | UNSIGNED_INTEGER KB
+                {
+                 unsigned long long __converted;
+                 __converted = $1 * 1024;
+                    $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &__converted);
+                }
+                | UNSIGNED_INTEGER MB
+                {
+                 unsigned long long __converted;
+                 __converted = $1 * 1048576;
+                    $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &__converted);
+                }
+                | UNSIGNED_INTEGER GB
+                {
+                 unsigned long long __converted;
+                 __converted = $1 * 1073741824;
+                    $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &__converted);
+                }
+                | STRING
+                {
+                    $$ = g_scan_literal_expression_new(LVT_STRING, &$1);
+                }
+                ;
+
+     item_chain : NAME { $$ = g_scan_named_access_new(&$1); }
+                | NAME "(" ")" { $$ = g_scan_pending_call_new(&$1, NULL, 0); }
+                | NAME "(" call_args ")"
+                {
+                    size_t __i;
+                    $$ = g_scan_pending_call_new(&$1, $3.args, $3.count);
+                    for (__i = 0; __i < $3.count; __i++)
+                        g_object_unref(G_OBJECT($3.args[__i]));
+                    free($3.args);
+                }
+                | item_chain "." NAME
+                {
+                    GScanExpression *__next;
+                    __next = g_scan_named_access_new(&$3);
+                    g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next));
+                    $$ = $1;
+                }
+                | item_chain "." NAME "(" ")"
+                {
+                    GScanExpression *__next;
+                    __next = g_scan_pending_call_new(&$3, NULL, 0);
+                    g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next));
+                    $$ = $1;
+                }
+                | item_chain "." NAME "(" call_args ")"
+                {
+                    GScanExpression *__next;
+                    size_t __i;
+                    __next = g_scan_pending_call_new(&$3, $5.args, $5.count);
+                    for (__i = 0; __i < $5.count; __i++)
+                        g_object_unref(G_OBJECT($5.args[__i]));
+                    free($5.args);
+                    g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next));
+                    $$ = $1;
+                }
+                ;
+
+      call_args : cexpression
+                {
+                    $$.count = 1;
+                    $$.args = malloc(sizeof(GScanExpression *));
+                    $$.args[0] = $1;
+                }
+                | call_args "," cexpression
+                {
+                    $1.count++;
+                    $1.args = realloc($1.args, $1.count * sizeof(GScanExpression *));
+                    $1.args[$1.count - 1] = $3;
+                    $$ = $1;
+                }
+                ;
+
+   logical_expr : cexpression "and" cexpression { $$ = g_scan_logical_operation_new(BOT_AND, $1, $3); }
+                | cexpression "or" cexpression  { $$ = g_scan_logical_operation_new(BOT_OR, $1, $3); }
+                | "not" "(" cexpression ")"     { $$ = g_scan_logical_operation_new(BOT_NOT, $3, NULL); }
+                ;
+
+relational_expr : cexpression "<" cexpression  { $$ = g_scan_relational_operation_new(RCO_LT, $1, $3); }
+                | cexpression "<=" cexpression { $$ = g_scan_relational_operation_new(RCO_LE, $1, $3); }
+                | cexpression "==" cexpression { $$ = g_scan_relational_operation_new(RCO_EQ, $1, $3); }
+                | cexpression "!=" cexpression { $$ = g_scan_relational_operation_new(RCO_NE, $1, $3); }
+                | cexpression ">" cexpression  { $$ = g_scan_relational_operation_new(RCO_GT, $1, $3); }
+                | cexpression ">=" cexpression { $$ = g_scan_relational_operation_new(RCO_GE, $1, $3); }
+                ;
+
+      string_op : cexpression "contains" cexpression
+                {
+                    $$ = g_scan_string_operation_new(SOT_CONTAINS, $1, $3, true);
+                }
+                | cexpression "startswith" cexpression
+                {
+                    $$ = g_scan_string_operation_new(SOT_STARTSWITH, $1, $3, true);
+                }
+                | cexpression "endswith" cexpression
+                {
+                    $$ = g_scan_string_operation_new(SOT_ENDSWITH, $1, $3, true);
+                }
+                | cexpression "matches" cexpression
+                {
+                    $$ = g_scan_string_operation_new(SOT_MATCHES, $1, $3, true);
+                }
+                | cexpression "icontains" cexpression
+                {
+                    $$ = g_scan_string_operation_new(SOT_CONTAINS, $1, $3, false);
+                }
+                | cexpression "istartswith" cexpression
+                {
+                    $$ = g_scan_string_operation_new(SOT_STARTSWITH, $1, $3, false);
+                }
+                | cexpression "iendswith" cexpression
+                {
+                    $$ = g_scan_string_operation_new(SOT_ENDSWITH, $1, $3, false);
+                }
+                | cexpression "iequals" cexpression
+                {
+                    $$ = g_scan_string_operation_new(SOT_IEQUALS, $1, $3, false);
+                }
+                ;
+
+    arithm_expr : cexpression "+" cexpression  { $$ = g_scan_arithmetic_operation_new(AEO_PLUS, $1, $3); }
+                | cexpression "-" cexpression  { $$ = g_scan_arithmetic_operation_new(AEO_MINUS, $1, $3); }
+                | cexpression "*" cexpression  { $$ = g_scan_arithmetic_operation_new(AEO_MUL, $1, $3); }
+                | cexpression "/" cexpression { $$ = g_scan_arithmetic_operation_new(AEO_DIV, $1, $3); }
+                | cexpression "%" cexpression  { $$ = g_scan_arithmetic_operation_new(AEO_MOD, $1, $3); }
+                ;
+
+set_counter : "none" "of" "them"  { $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true }); }
+            | "any" "of" "them"  { $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true }); }
+            | "all" "of" "them"  { $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true }); }
             ;
 
-literal : "true" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
-        | "false" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ false }); }
-        | INTEGER { $$ = g_literal_expression_new(EVT_INTEGER, &$1); }
-        | INTEGER KB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1024 }); }
-        | INTEGER MB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1048576 }); }
-        | INTEGER GB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1073741824 }); }
-        | STRING { $$ = g_literal_expression_new(EVT_STRING, &$1); }
-        ;
 
-item_chain : NAME { $$ = g_named_access_new(&$1); }
-         | NAME "(" ")" { $$ = g_pending_call_new(&$1, NULL, 0); }
-         | NAME "(" call_args ")"
-         {
-             size_t __i;
-             $$ = g_pending_call_new(&$1, $3.args, $3.count);
-             for (__i = 0; __i < $3.count; __i++)
-                 g_object_unref(G_OBJECT($3.args[__i]));
-             free($3.args);
-         }
-         | item_chain "." NAME
-         {
-             GScanExpression *__next;
-             __next = g_named_access_new(&$3);
-             g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next));
-             $$ = $1;
-         }
-         | item_chain "." NAME "(" ")"
-         {
-             GScanExpression *__next;
-             __next = g_pending_call_new(&$3, NULL, 0);
-             g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next));
-             $$ = $1;
-         }
-         | item_chain "." NAME "(" call_args ")"
-         {
-             GScanExpression *__next;
-             size_t __i;
-             __next = g_pending_call_new(&$3, $5.args, $5.count);
-             for (__i = 0; __i < $5.count; __i++)
-                 g_object_unref(G_OBJECT($5.args[__i]));
-             free($5.args);
-             g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next));
-             $$ = $1;
-         }
-         ;
-
-call_args : cexpression
-          {
-              $$.count = 1;
-              $$.args = malloc(sizeof(GScanExpression *));
-              $$.args[0] = $1;
-          }
-          | call_args "," cexpression
-          {
-              $1.count++;
-              $1.args = realloc($1.args, $1.count * sizeof(GScanExpression *));
-              $1.args[$1.count - 1] = $3;
-              $$ = $1;
-          }
-          ;
-
-bool_expr : cexpression "and" cexpression { $$ = g_boolean_operation_new(BOT_AND, $1, $3); }
-          | cexpression "or" cexpression  { $$ = g_boolean_operation_new(BOT_OR, $1, $3); }
-          | "not" "(" cexpression ")"     { $$ = g_boolean_operation_new(BOT_NOT, $3, NULL); }
-          ;
-
-rel_expr : cexpression "<" cexpression  { $$ = g_relational_operation_new(RCO_LT, $1, $3); }
-         | cexpression "<=" cexpression { $$ = g_relational_operation_new(RCO_LE, $1, $3); }
-         | cexpression "==" cexpression { $$ = g_relational_operation_new(RCO_EQ, $1, $3); }
-         | cexpression "!=" cexpression { $$ = g_relational_operation_new(RCO_NE, $1, $3); }
-         | cexpression ">" cexpression  { $$ = g_relational_operation_new(RCO_GT, $1, $3); }
-         | cexpression ">=" cexpression { $$ = g_relational_operation_new(RCO_GT, $1, $3); }
-         ;
-
-str_expr : cexpression "contains" cexpression    { $$ = g_string_operation_new(SOT_CONTAINS, $1, $3, true); }
-         | cexpression "startswith" cexpression  { $$ = g_string_operation_new(SOT_STARTSWITH, $1, $3, true); }
-         | cexpression "endswith" cexpression    { $$ = g_string_operation_new(SOT_ENDSWITH, $1, $3, true); }
-         | cexpression "matches" cexpression     { $$ = g_string_operation_new(SOT_MATCHES, $1, $3, true); }
-         | cexpression "icontains" cexpression   { $$ = g_string_operation_new(SOT_CONTAINS, $1, $3, false); }
-         | cexpression "istartswith" cexpression { $$ = g_string_operation_new(SOT_STARTSWITH, $1, $3, false); }
-         | cexpression "iendswith" cexpression   { $$ = g_string_operation_new(SOT_ENDSWITH, $1, $3, false); }
-         | cexpression "iequals" cexpression     { $$ = g_string_operation_new(SOT_IEQUALS, $1, $3, false); }
-         ;
-
-arithm_expr : cexpression "+" cexpression  { $$ = g_arithmetic_operation_new(AEO_PLUS, $1, $3); }
-            | cexpression "-" cexpression  { $$ = g_arithmetic_operation_new(AEO_MINUS, $1, $3); }
-            | cexpression "*" cexpression  { $$ = g_arithmetic_operation_new(AEO_MUL, $1, $3); }
-            | cexpression "\\" cexpression { $$ = g_arithmetic_operation_new(AEO_DIV, $1, $3); }
-            | cexpression "%" cexpression  { $$ = g_arithmetic_operation_new(AEO_MOD, $1, $3); }
-            ;
+            set : "(" ")"
+                {
+                    $$ = g_scan_generic_set_new();
+                }
+                | "(" cexpression "," ")"
+                {
+                    $$ = g_scan_generic_set_new();
+                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $2);
+                    g_object_unref(G_OBJECT($2));
+                }
+                | "(" set_items ")"
+                {
+                    $$ = $2;
+                }
+                ;
+
+      set_items : cexpression "," cexpression
+                {
+                    $$ = g_scan_generic_set_new();
+                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $1);
+                    g_object_unref(G_OBJECT($1));
+                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3);
+                    g_object_unref(G_OBJECT($3));
+                }
+                | set_items "," cexpression
+                {
+                    $$ = $1;
+                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3);
+                    g_object_unref(G_OBJECT($3));
+                }
+                ;
+
+   intersection : cexpression "in" cexpression
+                {
+                    $$ = g_scan_sets_intersection_new($1, $3);
+                    g_object_unref(G_OBJECT($1));
+                    g_object_unref(G_OBJECT($3));
+                }
+                ;
+
+
 
-set_counter : "none" "of" "them"  { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
-            | "any" "of" "them"  { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
-            | "all" "of" "them"  { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
-            ;
 
 %%
 
diff --git a/src/analysis/scan/items/Makefile.am b/src/analysis/scan/items/Makefile.am
index 3a6bb62..ce39cad 100644
--- a/src/analysis/scan/items/Makefile.am
+++ b/src/analysis/scan/items/Makefile.am
@@ -2,14 +2,32 @@
 noinst_LTLIBRARIES  = libanalysisscanitems.la
 
 
+if BUILD_MAGIC_SUPPORT
+
+MAGIC_LIBADD = magic/libanalysisscanitemsmagic.la
+
+MAGIC_SUBDIRS = magic
+
+endif
+
+
 libanalysisscanitems_la_SOURCES =			\
+	count.h count.c							\
 	datasize.h datasize.c					\
 	uint-int.h								\
 	uint.h uint.c
 
+libanalysisscanitems_la_LIBADD = 			\
+	console/libanalysisscanitemsconsole.la	\
+	$(MAGIC_LIBADD)							\
+	time/libanalysisscanitemstime.la
+
 libanalysisscanitems_la_CFLAGS = $(LIBGOBJ_CFLAGS)
 
 
 devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
 
 dev_HEADERS = $(libanalysisscanitems_la_SOURCES:%c=)
+
+
+SUBDIRS = console $(MAGIC_SUBDIRS) time
diff --git a/src/analysis/scan/items/console/Makefile.am b/src/analysis/scan/items/console/Makefile.am
new file mode 100644
index 0000000..4433789
--- /dev/null
+++ b/src/analysis/scan/items/console/Makefile.am
@@ -0,0 +1,13 @@
+
+noinst_LTLIBRARIES  = libanalysisscanitemsconsole.la
+
+
+libanalysisscanitemsconsole_la_SOURCES =	\
+	log.h log.c
+
+libanalysisscanitemsconsole_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanitemsconsole_la_SOURCES:%c=)
diff --git a/src/analysis/scan/items/console/log.c b/src/analysis/scan/items/console/log.c
new file mode 100644
index 0000000..f4031c7
--- /dev/null
+++ b/src/analysis/scan/items/console/log.c
@@ -0,0 +1,303 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log.c - affichage de message à partir des conditions d'une règle
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "log.h"
+
+
+#include <ctype.h>
+
+
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des affichages de messages. */
+static void g_scan_console_log_function_class_init(GScanConsoleLogFunctionClass *);
+
+/* Initialise une instance d'affichage de message. */
+static void g_scan_console_log_function_init(GScanConsoleLogFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_console_log_function_dispose(GScanConsoleLogFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_console_log_function_finalize(GScanConsoleLogFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_console_log_function_get_name(const GScanConsoleLogFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_console_log_function_run_call(GScanConsoleLogFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un afficheur de messages arbitraires. */
+G_DEFINE_TYPE(GScanConsoleLogFunction, g_scan_console_log_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des affichages de messages.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_console_log_function_class_init(GScanConsoleLogFunctionClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GRegisteredItemClass *registered;       /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_console_log_function_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_console_log_function_finalize;
+
+    registered = G_REGISTERED_ITEM_CLASS(klass);
+
+    registered->get_name = (get_registered_item_name_fc)g_scan_console_log_function_get_name;
+    registered->run_call = (run_registered_item_call_fc)g_scan_console_log_function_run_call;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance d'affichage de message.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_console_log_function_init(GScanConsoleLogFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_console_log_function_dispose(GScanConsoleLogFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_console_log_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_console_log_function_finalize(GScanConsoleLogFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_console_log_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Constitue une fonction d'affichage de messages quelconques.  *
+*                                                                             *
+*  Retour      : Fonction mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanConsoleLogFunction *g_scan_console_log_function_new(void)
+{
+    GScanConsoleLogFunction *result;              /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, NULL);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = élément d'appel à consulter.                          *
+*                                                                             *
+*  Description : Indique le nom associé à une expression d'évaluation.        *
+*                                                                             *
+*  Retour      : Désignation humaine de l'expression d'évaluation.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_console_log_function_get_name(const GScanConsoleLogFunction *item)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("log");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = élément d'appel à consulter.                         *
+*                args  = liste d'éventuels arguments fournis.                 *
+*                count = taille de cette liste.                               *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la résolution opérée. [OUT] *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_console_log_function_run_call(GScanConsoleLogFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours #1       */
+    LiteralValueType vtype;                 /* Type de valeur portée       */
+    GScanLiteralExpression *literal;        /* Version plus accessible     */
+    bool boolean;                           /* Valeur booléenne            */
+    long long sinteger;                     /* Valeur entière signée   */
+    unsigned long long uinteger;            /* Valeur entière non signée   */
+    const sized_string_t *string;           /* Description du chaîne       */
+    size_t k;                               /* Boucle de parcours #2       */
+
+    result = true;
+
+    if (count == 0)
+        goto done;
+
+    for (i = 0; i < count && result; i++)
+        result = G_IS_SCAN_LITERAL_EXPRESSION(args[i]);
+
+    if (!result)
+        goto done;
+
+    for (i = 0; i < count; i++)
+    {
+        literal = G_SCAN_LITERAL_EXPRESSION(args[i]);
+
+        vtype = g_scan_literal_expression_get_value_type(literal);
+
+        switch (vtype)
+        {
+            case LVT_BOOLEAN:
+                result = g_scan_literal_expression_get_boolean_value(literal, &boolean);
+                if (result)
+                    fprintf(stderr, "%s", boolean ? "true" : "false");
+                break;
+
+            case LVT_SIGNED_INTEGER:
+                result = g_scan_literal_expression_get_signed_integer_value(literal, &sinteger);
+                if (result)
+                    fprintf(stderr, "0x%llx", sinteger);
+                break;
+
+            case LVT_UNSIGNED_INTEGER:
+                result = g_scan_literal_expression_get_unsigned_integer_value(literal, &uinteger);
+                if (result)
+                    fprintf(stderr, "0x%llx", uinteger);
+                break;
+
+            case LVT_STRING:
+                result = g_scan_literal_expression_get_string_value(literal, &string);
+                for (k = 0; k < string->len; k++)
+                {
+                    if (isprint(string->data[k]))
+                        fprintf(stderr, "%c", string->data[k]);
+                    else
+                        fprintf(stderr, "\\x%02hhx", string->data[k]);
+                }
+                break;
+
+            default:
+                break;
+
+        }
+
+    }
+
+    fprintf(stderr, "\n");
+
+ done:
+
+    if (result)
+        *out = G_OBJECT(g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ result }));
+
+    return result;
+
+}
diff --git a/src/analysis/scan/items/console/log.h b/src/analysis/scan/items/console/log.h
new file mode 100644
index 0000000..3e72ad8
--- /dev/null
+++ b/src/analysis/scan/items/console/log.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log.h - prototypes pour l'affichage de message à partir des conditions d'une règle
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_ITEMS_CONSOLE_LOG_H
+#define _ANALYSIS_SCAN_ITEMS_CONSOLE_LOG_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_CONSOLE_LOG_FUNCTION            g_scan_console_log_function_get_type()
+#define G_SCAN_CONSOLE_LOG_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, GScanConsoleLogFunction))
+#define G_IS_SCAN_CONSOLE_LOG_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION))
+#define G_SCAN_CONSOLE_LOG_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, GScanConsoleLogFunctionClass))
+#define G_IS_SCAN_CONSOLE_LOG_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION))
+#define G_SCAN_CONSOLE_LOG_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, GScanConsoleLogFunctionClass))
+
+
+/* Mesure de la quantité de données scannées (instance) */
+typedef GRegisteredItem GScanConsoleLogFunction;
+
+/* Mesure de la quantité de données scannées (classe) */
+typedef GRegisteredItemClass GScanConsoleLogFunctionClass;
+
+
+/* Indique le type défini pour un afficheur de messages arbitraires. */
+GType g_scan_console_log_function_get_type(void);
+
+/* Constitue une fonction d'affichage de messages quelconques. */
+GScanConsoleLogFunction *g_scan_console_log_function_new(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_ITEMS_CONSOLE_LOG_H */
diff --git a/src/analysis/scan/items/count.c b/src/analysis/scan/items/count.c
new file mode 100644
index 0000000..d87d33b
--- /dev/null
+++ b/src/analysis/scan/items/count.c
@@ -0,0 +1,244 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * count.c - récupération de la taille du contenu scanné
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "count.h"
+
+
+#include "../item-int.h"
+#include "../exprs/arithmetic.h"
+#include "../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des décomptes d'ensemble homogène. */
+static void g_scan_count_function_class_init(GScanCountFunctionClass *);
+
+/* Initialise une instance de décompte d'ensemble homogène. */
+static void g_scan_count_function_init(GScanCountFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_count_function_dispose(GScanCountFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_count_function_finalize(GScanCountFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_count_function_get_name(const GScanCountFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_count_function_run_call(GScanCountFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un décompte d'ensemble. */
+G_DEFINE_TYPE(GScanCountFunction, g_scan_count_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des décomptes d'ensemble homogène.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_count_function_class_init(GScanCountFunctionClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GRegisteredItemClass *registered;       /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_count_function_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_count_function_finalize;
+
+    registered = G_REGISTERED_ITEM_CLASS(klass);
+
+    registered->get_name = (get_registered_item_name_fc)g_scan_count_function_get_name;
+    registered->run_call = (run_registered_item_call_fc)g_scan_count_function_run_call;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance de décompte d'ensemble homogène.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_count_function_init(GScanCountFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_count_function_dispose(GScanCountFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_count_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_count_function_finalize(GScanCountFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_count_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Constitue une fonction de décompte d'éléments d'un ensemble. *
+*                                                                             *
+*  Retour      : Fonction mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRegisteredItem *g_scan_count_function_new(void)
+{
+    GScanCountFunction *result;              /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_COUNT_FUNCTION, NULL);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = élément d'appel à consulter.                          *
+*                                                                             *
+*  Description : Indique le nom associé à une expression d'évaluation.        *
+*                                                                             *
+*  Retour      : Désignation humaine de l'expression d'évaluation.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_count_function_get_name(const GScanCountFunction *item)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("count");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = élément d'appel à consulter.                         *
+*                args  = liste d'éventuels arguments fournis.                 *
+*                count = taille de cette liste.                               *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la résolution opérée. [OUT] *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_count_function_run_call(GScanCountFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t value;                           /* Nouveau décompte            */
+
+    if (count != 1)
+        result = false;
+
+    else
+    {
+        result = g_scan_expression_count_items(args[0], &value);
+
+        if (result)
+            *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ value }));
+
+    }
+
+    return result;
+
+}
diff --git a/src/analysis/scan/items/count.h b/src/analysis/scan/items/count.h
new file mode 100644
index 0000000..2429e40
--- /dev/null
+++ b/src/analysis/scan/items/count.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * count.h - prototypes pour la récupération de la taille du contenu scanné
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_ITEMS_COUNT_H
+#define _ANALYSIS_SCAN_ITEMS_COUNT_H
+
+
+#include <glib-object.h>
+
+
+#include "../item.h"
+
+
+
+#define G_TYPE_SCAN_COUNT_FUNCTION            g_scan_count_function_get_type()
+#define G_SCAN_COUNT_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_COUNT_FUNCTION, GScanCountFunction))
+#define G_IS_SCAN_COUNT_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_COUNT_FUNCTION))
+#define G_SCAN_COUNT_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_COUNT_FUNCTION, GScanCountFunctionClass))
+#define G_IS_SCAN_COUNT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_COUNT_FUNCTION))
+#define G_SCAN_COUNT_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_COUNT_FUNCTION, GScanCountFunctionClass))
+
+
+/* Mesure de la quantité de données scannées (instance) */
+typedef GRegisteredItem GScanCountFunction;
+
+/* Mesure de la quantité de données scannées (classe) */
+typedef GRegisteredItemClass GScanCountFunctionClass;
+
+
+/* Indique le type défini pour un décompte d'ensemble. */
+GType g_scan_count_function_get_type(void);
+
+/* Constitue une fonction de décompte d'éléments d'un ensemble. */
+GRegisteredItem *g_scan_count_function_new(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_ITEMS_COUNT_H */
diff --git a/src/analysis/scan/items/datasize.c b/src/analysis/scan/items/datasize.c
index 618d0c3..55e2d3b 100644
--- a/src/analysis/scan/items/datasize.c
+++ b/src/analysis/scan/items/datasize.c
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * datasize.c - récupération de la taille du contenu scanné
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -33,16 +33,16 @@
 
 
 /* Initialise la classe des mesures de quantité de données. */
-static void g_datasize_function_class_init(GDatasizeFunctionClass *);
+static void g_scan_datasize_function_class_init(GScanDatasizeFunctionClass *);
 
 /* Initialise une instance de mesure de quantité de données. */
-static void g_datasize_function_init(GDatasizeFunction *);
+static void g_scan_datasize_function_init(GScanDatasizeFunction *);
 
 /* Supprime toutes les références externes. */
-static void g_datasize_function_dispose(GDatasizeFunction *);
+static void g_scan_datasize_function_dispose(GScanDatasizeFunction *);
 
 /* Procède à la libération totale de la mémoire. */
-static void g_datasize_function_finalize(GDatasizeFunction *);
+static void g_scan_datasize_function_finalize(GScanDatasizeFunction *);
 
 
 
@@ -50,13 +50,13 @@ static void g_datasize_function_finalize(GDatasizeFunction *);
 
 
 /* Indique le nom associé à une expression d'évaluation. */
-static char *g_datasize_function_get_name(const GDatasizeFunction *);
+static char *g_scan_datasize_function_get_name(const GScanDatasizeFunction *);
 
 /* Réduit une expression à une forme plus simple. */
-static bool g_datasize_function_reduce(GDatasizeFunction *, GScanContext *, GScanScope *, GScanExpression **);
+static bool g_scan_datasize_function_reduce(GScanDatasizeFunction *, GScanContext *, GScanScope *, GScanExpression **);
 
 /* Réduit une expression à une forme plus simple. */
-static bool g_datasize_function_run_call(GDatasizeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+static bool g_scan_datasize_function_run_call(GScanDatasizeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
 
 
 
@@ -66,7 +66,7 @@ static bool g_datasize_function_run_call(GDatasizeFunction *, GScanExpression **
 
 
 /* Indique le type défini pour une mesure de quantité de données scannées. */
-G_DEFINE_TYPE(GDatasizeFunction, g_datasize_function, G_TYPE_REGISTERED_ITEM);
+G_DEFINE_TYPE(GScanDatasizeFunction, g_scan_datasize_function, G_TYPE_REGISTERED_ITEM);
 
 
 /******************************************************************************
@@ -81,21 +81,21 @@ G_DEFINE_TYPE(GDatasizeFunction, g_datasize_function, G_TYPE_REGISTERED_ITEM);
 *                                                                             *
 ******************************************************************************/
 
-static void g_datasize_function_class_init(GDatasizeFunctionClass *klass)
+static void g_scan_datasize_function_class_init(GScanDatasizeFunctionClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GRegisteredItemClass *registered;       /* Version de classe parente   */
 
     object = G_OBJECT_CLASS(klass);
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_datasize_function_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_datasize_function_finalize;
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_datasize_function_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_datasize_function_finalize;
 
     registered = G_REGISTERED_ITEM_CLASS(klass);
 
-    registered->get_name = (get_registered_item_name_fc)g_datasize_function_get_name;
-    registered->reduce = (reduce_registered_item_fc)g_datasize_function_reduce;
-    registered->run_call = (run_registered_item_call_fc)g_datasize_function_run_call;
+    registered->get_name = (get_registered_item_name_fc)g_scan_datasize_function_get_name;
+    registered->reduce = (reduce_registered_item_fc)g_scan_datasize_function_reduce;
+    registered->run_call = (run_registered_item_call_fc)g_scan_datasize_function_run_call;
 
 }
 
@@ -112,7 +112,7 @@ static void g_datasize_function_class_init(GDatasizeFunctionClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_datasize_function_init(GDatasizeFunction *func)
+static void g_scan_datasize_function_init(GScanDatasizeFunction *func)
 {
 
 }
@@ -130,9 +130,9 @@ static void g_datasize_function_init(GDatasizeFunction *func)
 *                                                                             *
 ******************************************************************************/
 
-static void g_datasize_function_dispose(GDatasizeFunction *func)
+static void g_scan_datasize_function_dispose(GScanDatasizeFunction *func)
 {
-    G_OBJECT_CLASS(g_datasize_function_parent_class)->dispose(G_OBJECT(func));
+    G_OBJECT_CLASS(g_scan_datasize_function_parent_class)->dispose(G_OBJECT(func));
 
 }
 
@@ -149,9 +149,9 @@ static void g_datasize_function_dispose(GDatasizeFunction *func)
 *                                                                             *
 ******************************************************************************/
 
-static void g_datasize_function_finalize(GDatasizeFunction *func)
+static void g_scan_datasize_function_finalize(GScanDatasizeFunction *func)
 {
-    G_OBJECT_CLASS(g_datasize_function_parent_class)->finalize(G_OBJECT(func));
+    G_OBJECT_CLASS(g_scan_datasize_function_parent_class)->finalize(G_OBJECT(func));
 
 }
 
@@ -168,11 +168,11 @@ static void g_datasize_function_finalize(GDatasizeFunction *func)
 *                                                                             *
 ******************************************************************************/
 
-GDatasizeFunction *g_datasize_function_new(void)
+GRegisteredItem *g_scan_datasize_function_new(void)
 {
-    GDatasizeFunction *result;              /* Structure à retourner       */
+    GScanDatasizeFunction *result;              /* Structure à retourner       */
 
-    result = g_object_new(G_TYPE_DATASIZE_FUNCTION, NULL);
+    result = g_object_new(G_TYPE_SCAN_DATASIZE_FUNCTION, NULL);
 
     return result;
 
@@ -197,7 +197,7 @@ GDatasizeFunction *g_datasize_function_new(void)
 *                                                                             *
 ******************************************************************************/
 
-static char *g_datasize_function_get_name(const GDatasizeFunction *item)
+static char *g_scan_datasize_function_get_name(const GScanDatasizeFunction *item)
 {
     char *result;                           /* Désignation à retourner     */
 
@@ -223,7 +223,7 @@ static char *g_datasize_function_get_name(const GDatasizeFunction *item)
 *                                                                             *
 ******************************************************************************/
 
-static bool g_datasize_function_reduce(GDatasizeFunction *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static bool g_scan_datasize_function_reduce(GScanDatasizeFunction *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
 {
     bool result;                            /* Bilan à retourner           */
     GBinContent *content;                   /* Contenu à manipuler         */
@@ -235,7 +235,7 @@ static bool g_datasize_function_reduce(GDatasizeFunction *item, GScanContext *ct
 
     size = g_binary_content_compute_size(content);
 
-    *out = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ size });
+    *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ size });
 
     g_object_unref(G_OBJECT(content));
 
@@ -261,11 +261,11 @@ static bool g_datasize_function_reduce(GDatasizeFunction *item, GScanContext *ct
 *                                                                             *
 ******************************************************************************/
 
-static bool g_datasize_function_run_call(GDatasizeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+static bool g_scan_datasize_function_run_call(GScanDatasizeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
 {
     bool result;                            /* Bilan à retourner           */
 
-    result = g_datasize_function_reduce(item, ctx, scope, (GScanExpression **)out);
+    result = g_scan_datasize_function_reduce(item, ctx, scope, (GScanExpression **)out);
 
     return result;
 
diff --git a/src/analysis/scan/items/datasize.h b/src/analysis/scan/items/datasize.h
index bd8e185..476df2d 100644
--- a/src/analysis/scan/items/datasize.h
+++ b/src/analysis/scan/items/datasize.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * datasize.h - prototypes pour la récupération de la taille du contenu scanné
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -32,26 +32,26 @@
 
 
 
-#define G_TYPE_DATASIZE_FUNCTION            g_datasize_function_get_type()
-#define G_DATASIZE_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunction))
-#define G_IS_DATASIZE_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DATASIZE_FUNCTION))
-#define G_DATASIZE_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunctionClass))
-#define G_IS_DATASIZE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DATASIZE_FUNCTION))
-#define G_DATASIZE_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunctionClass))
+#define G_TYPE_SCAN_DATASIZE_FUNCTION            g_scan_datasize_function_get_type()
+#define G_SCAN_DATASIZE_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_DATASIZE_FUNCTION, GScanDatasizeFunction))
+#define G_IS_SCAN_DATASIZE_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_DATASIZE_FUNCTION))
+#define G_SCAN_DATASIZE_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_DATASIZE_FUNCTION, GScanDatasizeFunctionClass))
+#define G_IS_SCAN_DATASIZE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_DATASIZE_FUNCTION))
+#define G_SCAN_DATASIZE_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_DATASIZE_FUNCTION, GScanDatasizeFunctionClass))
 
 
 /* Mesure de la quantité de données scannées (instance) */
-typedef GRegisteredItem GDatasizeFunction;
+typedef GRegisteredItem GScanDatasizeFunction;
 
 /* Mesure de la quantité de données scannées (classe) */
-typedef GRegisteredItemClass GDatasizeFunctionClass;
+typedef GRegisteredItemClass GScanDatasizeFunctionClass;
 
 
 /* Indique le type défini pour une mesure de quantité de données scannées. */
-GType g_datasize_function_get_type(void);
+GType g_scan_datasize_function_get_type(void);
 
 /* Constitue une fonction de récupération de taille de données. */
-GDatasizeFunction *g_datasize_function_new(void);
+GRegisteredItem *g_scan_datasize_function_new(void);
 
 
 
diff --git a/src/analysis/scan/items/magic/Makefile.am b/src/analysis/scan/items/magic/Makefile.am
new file mode 100644
index 0000000..1d741ff
--- /dev/null
+++ b/src/analysis/scan/items/magic/Makefile.am
@@ -0,0 +1,16 @@
+
+noinst_LTLIBRARIES  = libanalysisscanitemsmagic.la
+
+
+libanalysisscanitemsmagic_la_SOURCES =		\
+	cookie.h cookie.c						\
+	mime-encoding.h mime-encoding.c			\
+	mime-type.h mime-type.c					\
+	type.h type.c
+
+libanalysisscanitemsmagic_la_CFLAGS = $(LIBGOBJ_CFLAGS) $(LIBMAGIC_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanitemsmagic_la_SOURCES:%c=)
diff --git a/src/analysis/scan/items/magic/cookie.c b/src/analysis/scan/items/magic/cookie.c
new file mode 100644
index 0000000..41f26a0
--- /dev/null
+++ b/src/analysis/scan/items/magic/cookie.c
@@ -0,0 +1,122 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cookie.c - chargement des motifs de reconnaissance de contenus
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "cookie.h"
+
+
+#include <assert.h>
+
+
+#include <i18n.h>
+
+
+#include "../../../../core/logs.h"
+
+
+
+/* Référence des bibliothèques de reconnaissance */
+static magic_t __magic_cookie = 0;
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Charge les motifs de reconnaissance de contenus.             *
+*                                                                             *
+*  Retour      : Bilan de l'opération de chargemement.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool init_magic_cookie(void)
+{
+    bool result;                            /* Bilan à retourner           */
+    int ret;                                /* Bilan d'une opération       */
+
+    __magic_cookie = magic_open(0);
+
+    ret = magic_load(__magic_cookie, NULL);
+    result = (ret != -1);
+
+    if (!result)
+        log_variadic_message(LMT_EXT_ERROR, _("cannot load magic database: %s"), magic_error(__magic_cookie));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Décharge les motifs de reconnaissance de contenus.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void exit_magic_cookie(void)
+{
+    magic_close(__magic_cookie);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : flags = forme de reconnaissance à préparer.                  *
+*                                                                             *
+*  Description : Fournit la référence aux mécanismes de reconnaissance.       *
+*                                                                             *
+*  Retour      : Cookie prêt à emploi.                                        * 
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+magic_t get_magic_cookie(int flags)
+{
+    magic_t result;                         /* Référence à retourner       */
+#ifndef NDEBUG
+    int ret;                                /* Bilan de la préparation     */
+#endif
+
+    result = __magic_cookie;
+    assert(result != 0);
+
+#ifndef NDEBUG
+    ret = magic_setflags(result, flags);
+    assert(ret != -1);
+#else
+    magic_setflags(result, flags);
+#endif
+
+    return result;
+
+}
diff --git a/src/analysis/scan/items/magic/cookie.h b/src/analysis/scan/items/magic/cookie.h
new file mode 100644
index 0000000..0ee2274
--- /dev/null
+++ b/src/analysis/scan/items/magic/cookie.h
@@ -0,0 +1,44 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cookie.h - prototypes pour le chargement des motifs de reconnaissance de contenus
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_ITEMS_MAGIC_COOKIE_H
+#define _ANALYSIS_SCAN_ITEMS_MAGIC_COOKIE_H
+
+
+#include <magic.h>
+#include <stdbool.h>
+
+
+
+/* Charge les motifs de reconnaissance de contenus. */
+bool init_magic_cookie(void);
+
+/* Décharge les motifs de reconnaissance de contenus. */
+void exit_magic_cookie(void);
+
+/* Fournit la référence aux mécanismes de reconnaissance. */
+magic_t get_magic_cookie(int);
+
+
+
+#endif  /* _ANALYSIS_SCAN_ITEMS_MAGIC_COOKIE_H */
diff --git a/src/analysis/scan/items/magic/mime-encoding.c b/src/analysis/scan/items/magic/mime-encoding.c
new file mode 100644
index 0000000..935515d
--- /dev/null
+++ b/src/analysis/scan/items/magic/mime-encoding.c
@@ -0,0 +1,270 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * mime-encoding.c - reconnaissance de l'encodage d'un contenu
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "mime-encoding.h"
+
+
+#include "cookie.h"
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des reconnaissances de contenus. */
+static void g_scan_mime_encoding_function_class_init(GScanMimeEncodingFunctionClass *);
+
+/* Initialise une instance de reconnaissance de contenus. */
+static void g_scan_mime_encoding_function_init(GScanMimeEncodingFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_mime_encoding_function_dispose(GScanMimeEncodingFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_mime_encoding_function_finalize(GScanMimeEncodingFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_mime_encoding_function_get_name(const GScanMimeEncodingFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_mime_encoding_function_run_call(GScanMimeEncodingFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une reconnaissance d'encodages de contenus. */
+G_DEFINE_TYPE(GScanMimeEncodingFunction, g_scan_mime_encoding_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des reconnaissances de contenus.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_mime_encoding_function_class_init(GScanMimeEncodingFunctionClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GRegisteredItemClass *registered;       /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_mime_encoding_function_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_mime_encoding_function_finalize;
+
+    registered = G_REGISTERED_ITEM_CLASS(klass);
+
+    registered->get_name = (get_registered_item_name_fc)g_scan_mime_encoding_function_get_name;
+    registered->run_call = (run_registered_item_call_fc)g_scan_mime_encoding_function_run_call;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance de reconnaissance de contenus.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_mime_encoding_function_init(GScanMimeEncodingFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_mime_encoding_function_dispose(GScanMimeEncodingFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_mime_encoding_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_mime_encoding_function_finalize(GScanMimeEncodingFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_mime_encoding_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Constitue une fonction de cernement d'encodages de contenus. *
+*                                                                             *
+*  Retour      : Fonction mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRegisteredItem *g_scan_mime_encoding_function_new(void)
+{
+    GRegisteredItem *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_MIME_ENCODING_FUNCTION, NULL);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = élément d'appel à consulter.                          *
+*                                                                             *
+*  Description : Indique le nom associé à une expression d'évaluation.        *
+*                                                                             *
+*  Retour      : Désignation humaine de l'expression d'évaluation.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_mime_encoding_function_get_name(const GScanMimeEncodingFunction *item)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("mime_encoding");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = élément d'appel à consulter.                         *
+*                args  = liste d'éventuels arguments fournis.                 *
+*                count = taille de cette liste.                               *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la résolution opérée. [OUT] *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_mime_encoding_function_run_call(GScanMimeEncodingFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    magic_t cookie;                         /* Référence des bibliothèques */
+    GBinContent *content;                   /* Contenu à manipuler         */
+    vmpa2t pos;                             /* Tête de lecture             */
+    phys_t size;                            /* Quantité de données dispos. */
+    const bin_t *data;                      /* Accès à des données         */
+    const char *desc;                       /* Description du contenu      */
+    sized_string_t string;                  /* Description à diffuser      */
+
+    result = (count == 0);
+    if (!result) goto exit;
+
+    cookie = get_magic_cookie(MAGIC_MIME_ENCODING);
+
+    content = g_scan_context_get_content(ctx);
+
+    g_binary_content_compute_start_pos(content, &pos);
+
+    size = g_binary_content_compute_size(content);
+
+    data = g_binary_content_get_raw_access(content, &pos, size);
+
+    desc = magic_buffer(cookie, data, size);
+
+    if (desc != NULL)
+    {
+        string.data = (char *)desc;
+        string.len = strlen(desc);
+    }
+    else
+    {
+        string.data = "";
+        string.len = 0;
+    }
+
+    *out = G_OBJECT(g_scan_literal_expression_new(LVT_STRING, &string));
+
+    g_object_unref(G_OBJECT(content));
+
+ exit:
+
+    return result;
+
+}
diff --git a/src/analysis/scan/items/magic/mime-encoding.h b/src/analysis/scan/items/magic/mime-encoding.h
new file mode 100644
index 0000000..9349d55
--- /dev/null
+++ b/src/analysis/scan/items/magic/mime-encoding.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * mime-encoding.h - prototypes pour la reconnaissance de l'encodage d'un contenu
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_ENCODING_H
+#define _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_ENCODING_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_MIME_ENCODING_FUNCTION            g_scan_mime_encoding_function_get_type()
+#define G_SCAN_MIME_ENCODING_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MIME_ENCODING_FUNCTION, GScanMimeEncodingFunction))
+#define G_IS_SCAN_MIME_ENCODING_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MIME_ENCODING_FUNCTION))
+#define G_SCAN_MIME_ENCODING_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MIME_ENCODING_FUNCTION, GScanMimeEncodingFunctionClass))
+#define G_IS_SCAN_MIME_ENCODING_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MIME_ENCODING_FUNCTION))
+#define G_SCAN_MIME_ENCODING_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MIME_ENCODING_FUNCTION, GScanMimeEncodingFunctionClass))
+
+
+/* Reconnaissance d'encodages de contenus (instance) */
+typedef GRegisteredItem GScanMimeEncodingFunction;
+
+/* Reconnaissance d'encodages de contenus (classe) */
+typedef GRegisteredItemClass GScanMimeEncodingFunctionClass;
+
+
+/* Indique le type défini pour une reconnaissance d'encodages de contenus. */
+GType g_scan_mime_encoding_function_get_type(void);
+
+/* Constitue une fonction de cernement d'encodages de contenus. */
+GRegisteredItem *g_scan_mime_encoding_function_new(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_ENCODING_H */
diff --git a/src/analysis/scan/items/magic/mime-type.c b/src/analysis/scan/items/magic/mime-type.c
new file mode 100644
index 0000000..95e441d
--- /dev/null
+++ b/src/analysis/scan/items/magic/mime-type.c
@@ -0,0 +1,270 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.c - reconnaissance du type MIME d'un contenu
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "mime-type.h"
+
+
+#include "cookie.h"
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des reconnaissances de contenus. */
+static void g_scan_mime_type_function_class_init(GScanMimeTypeFunctionClass *);
+
+/* Initialise une instance de reconnaissance de contenus. */
+static void g_scan_mime_type_function_init(GScanMimeTypeFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_mime_type_function_dispose(GScanMimeTypeFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_mime_type_function_finalize(GScanMimeTypeFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_mime_type_function_get_name(const GScanMimeTypeFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_mime_type_function_run_call(GScanMimeTypeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une reconnaissance de types de contenus. */
+G_DEFINE_TYPE(GScanMimeTypeFunction, g_scan_mime_type_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des reconnaissances de contenus.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_mime_type_function_class_init(GScanMimeTypeFunctionClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GRegisteredItemClass *registered;       /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_mime_type_function_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_mime_type_function_finalize;
+
+    registered = G_REGISTERED_ITEM_CLASS(klass);
+
+    registered->get_name = (get_registered_item_name_fc)g_scan_mime_type_function_get_name;
+    registered->run_call = (run_registered_item_call_fc)g_scan_mime_type_function_run_call;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance de reconnaissance de contenus.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_mime_type_function_init(GScanMimeTypeFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_mime_type_function_dispose(GScanMimeTypeFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_mime_type_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_mime_type_function_finalize(GScanMimeTypeFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_mime_type_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Constitue une fonction d'identification de types de contenus.*
+*                                                                             *
+*  Retour      : Fonction mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRegisteredItem *g_scan_mime_type_function_new(void)
+{
+    GRegisteredItem *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_MIME_TYPE_FUNCTION, NULL);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = élément d'appel à consulter.                          *
+*                                                                             *
+*  Description : Indique le nom associé à une expression d'évaluation.        *
+*                                                                             *
+*  Retour      : Désignation humaine de l'expression d'évaluation.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_mime_type_function_get_name(const GScanMimeTypeFunction *item)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("mime_type");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = élément d'appel à consulter.                         *
+*                args  = liste d'éventuels arguments fournis.                 *
+*                count = taille de cette liste.                               *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la résolution opérée. [OUT] *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_mime_type_function_run_call(GScanMimeTypeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    magic_t cookie;                         /* Référence des bibliothèques */
+    GBinContent *content;                   /* Contenu à manipuler         */
+    vmpa2t pos;                             /* Tête de lecture             */
+    phys_t size;                            /* Quantité de données dispos. */
+    const bin_t *data;                      /* Accès à des données         */
+    const char *desc;                       /* Description du contenu      */
+    sized_string_t string;                  /* Description à diffuser      */
+
+    result = (count == 0);
+    if (!result) goto exit;
+
+    cookie = get_magic_cookie(MAGIC_MIME_TYPE);
+
+    content = g_scan_context_get_content(ctx);
+
+    g_binary_content_compute_start_pos(content, &pos);
+
+    size = g_binary_content_compute_size(content);
+
+    data = g_binary_content_get_raw_access(content, &pos, size);
+
+    desc = magic_buffer(cookie, data, size);
+
+    if (desc != NULL)
+    {
+        string.data = (char *)desc;
+        string.len = strlen(desc);
+    }
+    else
+    {
+        string.data = "";
+        string.len = 0;
+    }
+
+    *out = G_OBJECT(g_scan_literal_expression_new(LVT_STRING, &string));
+
+    g_object_unref(G_OBJECT(content));
+
+ exit:
+
+    return result;
+
+}
diff --git a/src/analysis/scan/items/magic/mime-type.h b/src/analysis/scan/items/magic/mime-type.h
new file mode 100644
index 0000000..e02ce0f
--- /dev/null
+++ b/src/analysis/scan/items/magic/mime-type.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * mime-type.h - prototypes pour la reconnaissance du type MIME d'un contenu
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_TYPE_H
+#define _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_TYPE_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_MIME_TYPE_FUNCTION            g_scan_mime_type_function_get_type()
+#define G_SCAN_MIME_TYPE_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MIME_TYPE_FUNCTION, GScanMimeTypeFunction))
+#define G_IS_SCAN_MIME_TYPE_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MIME_TYPE_FUNCTION))
+#define G_SCAN_MIME_TYPE_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MIME_TYPE_FUNCTION, GScanMimeTypeFunctionClass))
+#define G_IS_SCAN_MIME_TYPE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MIME_TYPE_FUNCTION))
+#define G_SCAN_MIME_TYPE_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MIME_TYPE_FUNCTION, GScanMimeTypeFunctionClass))
+
+
+/* Reconnaissance de types de contenus (instance) */
+typedef GRegisteredItem GScanMimeTypeFunction;
+
+/* Reconnaissance de types de contenus (classe) */
+typedef GRegisteredItemClass GScanMimeTypeFunctionClass;
+
+
+/* Indique le type défini pour une reconnaissance de types de contenus. */
+GType g_scan_mime_type_function_get_type(void);
+
+/* Constitue une fonction d'identification de types de contenus. */
+GRegisteredItem *g_scan_mime_type_function_new(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_TYPE_H */
diff --git a/src/analysis/scan/items/magic/type.c b/src/analysis/scan/items/magic/type.c
new file mode 100644
index 0000000..f87c34a
--- /dev/null
+++ b/src/analysis/scan/items/magic/type.c
@@ -0,0 +1,270 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.c - reconnaissance du type d'un contenu
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "type.h"
+
+
+#include "cookie.h"
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des reconnaissances de contenus. */
+static void g_scan_magic_type_function_class_init(GScanMagicTypeFunctionClass *);
+
+/* Initialise une instance de reconnaissance de contenus. */
+static void g_scan_magic_type_function_init(GScanMagicTypeFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_magic_type_function_dispose(GScanMagicTypeFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_magic_type_function_finalize(GScanMagicTypeFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_magic_type_function_get_name(const GScanMagicTypeFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_magic_type_function_run_call(GScanMagicTypeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une reconnaissance de types de contenus. */
+G_DEFINE_TYPE(GScanMagicTypeFunction, g_scan_magic_type_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des reconnaissances de contenus.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_magic_type_function_class_init(GScanMagicTypeFunctionClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GRegisteredItemClass *registered;       /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_magic_type_function_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_magic_type_function_finalize;
+
+    registered = G_REGISTERED_ITEM_CLASS(klass);
+
+    registered->get_name = (get_registered_item_name_fc)g_scan_magic_type_function_get_name;
+    registered->run_call = (run_registered_item_call_fc)g_scan_magic_type_function_run_call;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance de reconnaissance de contenus.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_magic_type_function_init(GScanMagicTypeFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_magic_type_function_dispose(GScanMagicTypeFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_magic_type_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_magic_type_function_finalize(GScanMagicTypeFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_magic_type_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Constitue une fonction d'identification de types de contenus.*
+*                                                                             *
+*  Retour      : Fonction mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRegisteredItem *g_scan_magic_type_function_new(void)
+{
+    GRegisteredItem *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, NULL);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = élément d'appel à consulter.                          *
+*                                                                             *
+*  Description : Indique le nom associé à une expression d'évaluation.        *
+*                                                                             *
+*  Retour      : Désignation humaine de l'expression d'évaluation.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_magic_type_function_get_name(const GScanMagicTypeFunction *item)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("type");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = élément d'appel à consulter.                         *
+*                args  = liste d'éventuels arguments fournis.                 *
+*                count = taille de cette liste.                               *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la résolution opérée. [OUT] *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_magic_type_function_run_call(GScanMagicTypeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    magic_t cookie;                         /* Référence des bibliothèques */
+    GBinContent *content;                   /* Contenu à manipuler         */
+    vmpa2t pos;                             /* Tête de lecture             */
+    phys_t size;                            /* Quantité de données dispos. */
+    const bin_t *data;                      /* Accès à des données         */
+    const char *desc;                       /* Description du contenu      */
+    sized_string_t string;                  /* Description à diffuser      */
+
+    result = (count == 0);
+    if (!result) goto exit;
+
+    cookie = get_magic_cookie(MAGIC_NONE);
+
+    content = g_scan_context_get_content(ctx);
+
+    g_binary_content_compute_start_pos(content, &pos);
+
+    size = g_binary_content_compute_size(content);
+
+    data = g_binary_content_get_raw_access(content, &pos, size);
+
+    desc = magic_buffer(cookie, data, size);
+
+    if (desc != NULL)
+    {
+        string.data = (char *)desc;
+        string.len = strlen(desc);
+    }
+    else
+    {
+        string.data = "";
+        string.len = 0;
+    }
+
+    *out = G_OBJECT(g_scan_literal_expression_new(LVT_STRING, &string));
+
+    g_object_unref(G_OBJECT(content));
+
+ exit:
+
+    return result;
+
+}
diff --git a/src/analysis/scan/items/magic/type.h b/src/analysis/scan/items/magic/type.h
new file mode 100644
index 0000000..bfad213
--- /dev/null
+++ b/src/analysis/scan/items/magic/type.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.h - prototypes pour la reconnaissance du type d'un contenu
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_ITEMS_MAGIC_TYPE_H
+#define _ANALYSIS_SCAN_ITEMS_MAGIC_TYPE_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_MAGIC_TYPE_FUNCTION            g_scan_magic_type_function_get_type()
+#define G_SCAN_MAGIC_TYPE_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, GScanMagicTypeFunction))
+#define G_IS_SCAN_MAGIC_TYPE_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION))
+#define G_SCAN_MAGIC_TYPE_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, GScanMagicTypeFunctionClass))
+#define G_IS_SCAN_MAGIC_TYPE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION))
+#define G_SCAN_MAGIC_TYPE_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, GScanMagicTypeFunctionClass))
+
+
+/* Reconnaissance de types de contenus (instance) */
+typedef GRegisteredItem GScanMagicTypeFunction;
+
+/* Reconnaissance de types de contenus (classe) */
+typedef GRegisteredItemClass GScanMagicTypeFunctionClass;
+
+
+/* Indique le type défini pour une reconnaissance de types de contenus. */
+GType g_scan_magic_type_function_get_type(void);
+
+/* Constitue une fonction d'identification de types de contenus. */
+GRegisteredItem *g_scan_magic_type_function_new(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_ITEMS_MAGIC_TYPE_H */
diff --git a/src/analysis/scan/items/time/Makefile.am b/src/analysis/scan/items/time/Makefile.am
new file mode 100644
index 0000000..e5330be
--- /dev/null
+++ b/src/analysis/scan/items/time/Makefile.am
@@ -0,0 +1,14 @@
+
+noinst_LTLIBRARIES  = libanalysisscanitemstime.la
+
+
+libanalysisscanitemstime_la_SOURCES =		\
+	make.h make.c							\
+	now.h now.c
+
+libanalysisscanitemstime_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanitemstime_la_SOURCES:%c=)
diff --git a/src/analysis/scan/items/time/make.c b/src/analysis/scan/items/time/make.c
new file mode 100644
index 0000000..477a77c
--- /dev/null
+++ b/src/analysis/scan/items/time/make.c
@@ -0,0 +1,350 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * make.c - construction de volume de secondes à partir d'une date
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "make.h"
+
+
+#include <assert.h>
+#include <time.h>
+
+
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des conversions de dates en secondes. */
+static void g_scan_time_make_function_class_init(GScanTimeMakeFunctionClass *);
+
+/* Initialise une instance de convertisseur de date en secondes. */
+static void g_scan_time_make_function_init(GScanTimeMakeFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_time_make_function_dispose(GScanTimeMakeFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_time_make_function_finalize(GScanTimeMakeFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_time_make_function_get_name(const GScanTimeMakeFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_time_make_function_run_call(GScanTimeMakeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une conversion de date en nombre de secondes. */
+G_DEFINE_TYPE(GScanTimeMakeFunction, g_scan_time_make_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des conversions de dates en secondes.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_time_make_function_class_init(GScanTimeMakeFunctionClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GRegisteredItemClass *registered;       /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_time_make_function_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_time_make_function_finalize;
+
+    registered = G_REGISTERED_ITEM_CLASS(klass);
+
+    registered->get_name = (get_registered_item_name_fc)g_scan_time_make_function_get_name;
+    registered->run_call = (run_registered_item_call_fc)g_scan_time_make_function_run_call;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance de convertisseur de date en secondes.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_time_make_function_init(GScanTimeMakeFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_time_make_function_dispose(GScanTimeMakeFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_time_make_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_time_make_function_finalize(GScanTimeMakeFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_time_make_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Constitue une fonction de décompte du temps écoulé.          *
+*                                                                             *
+*  Retour      : Fonction mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRegisteredItem *g_scan_time_make_function_new(void)
+{
+    GRegisteredItem *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_TIME_MAKE_FUNCTION, NULL);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = élément d'appel à consulter.                          *
+*                                                                             *
+*  Description : Indique le nom associé à une expression d'évaluation.        *
+*                                                                             *
+*  Retour      : Désignation humaine de l'expression d'évaluation.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_time_make_function_get_name(const GScanTimeMakeFunction *item)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("make");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = élément d'appel à consulter.                         *
+*                args  = liste d'éventuels arguments fournis.                 *
+*                count = taille de cette liste.                               *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la résolution opérée. [OUT] *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_time_make_function_run_call(GScanTimeMakeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    bool status;                            /* Possibilité de construction */
+    size_t i;                               /* Boucle de parcours          */
+    LiteralValueType vtype;                 /* Type de valeur portée       */
+    struct tm date;                         /* Date à mettre en place      */
+    unsigned long long value;               /* Valeur entière à utiliser   */
+    time_t computed;                        /* Nombre de secondes déterminé*/
+
+    /* Validation des arguments */
+
+    result = (count == 3 || count == 6);
+    if (!result) goto exit;
+
+    status = true;
+
+    for (i = 0; i < count && status; i++)
+    {
+        status = G_IS_SCAN_LITERAL_EXPRESSION(args[i]);
+        if (!status) break;
+
+        vtype = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(args[i]));
+
+        status = (vtype == LVT_UNSIGNED_INTEGER);
+        if (!status) break;
+
+    }
+
+    if (!status) goto exit;
+
+    /* Lecture des arguments */
+
+    memset(&date, 0, sizeof(struct tm));
+
+    status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[0]), &value);
+    assert(status);
+    if (!status) goto exit;
+
+    if (value < 1900)
+    {
+        result = false;
+        goto exit;
+    }
+
+    date.tm_year = value - 1900;
+
+    status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[1]), &value);
+    assert(status);
+    if (!status) goto exit;
+
+    if (value > 12)
+    {
+        result = false;
+        goto exit;
+    }
+
+    date.tm_mon = value - 1;
+
+    status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[2]), &value);
+    assert(status);
+    if (!status) goto exit;
+
+    if (value < 1 || value > 31)
+    {
+        result = false;
+        goto exit;
+    }
+
+    date.tm_mday = value;
+
+    if (count == 6)
+    {
+        status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[3]), &value);
+        assert(status);
+        if (!status) goto exit;
+
+        if (value >= 24)
+        {
+            result = false;
+            goto exit;
+        }
+
+        date.tm_hour = value;
+
+        status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[4]), &value);
+        assert(status);
+        if (!status) goto exit;
+
+        if (value >= 60)
+        {
+            result = false;
+            goto exit;
+        }
+
+        date.tm_min = value;
+
+        status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[5]), &value);
+        assert(status);
+        if (!status) goto exit;
+
+        if (value >= 60)
+        {
+            result = false;
+            goto exit;
+        }
+
+        date.tm_sec = value;
+
+    }
+
+    /* Construction de la valeur finale */
+
+    computed = timegm(&date);
+
+    if (computed != (time_t)-1)
+        *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ computed }));
+
+ exit:
+
+    return result;
+
+}
diff --git a/src/analysis/scan/items/time/make.h b/src/analysis/scan/items/time/make.h
new file mode 100644
index 0000000..958a392
--- /dev/null
+++ b/src/analysis/scan/items/time/make.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * make.h - prototypes pour une construction de volume de secondes à partir d'une date
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_ITEMS_TIME_MAKE_H
+#define _ANALYSIS_SCAN_ITEMS_TIME_MAKE_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_TIME_MAKE_FUNCTION            g_scan_time_make_function_get_type()
+#define G_SCAN_TIME_MAKE_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TIME_MAKE_FUNCTION, GScanTimeMakeFunction))
+#define G_IS_SCAN_TIME_MAKE_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TIME_MAKE_FUNCTION))
+#define G_SCAN_TIME_MAKE_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TIME_MAKE_FUNCTION, GScanTimeMakeFunctionClass))
+#define G_IS_SCAN_TIME_MAKE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TIME_MAKE_FUNCTION))
+#define G_SCAN_TIME_MAKE_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TIME_MAKE_FUNCTION, GScanTimeMakeFunctionClass))
+
+
+/* Convertisseur de date en nombre de secondes depuis le 01/01/1970 (instance) */
+typedef GRegisteredItem GScanTimeMakeFunction;
+
+/* Convertisseur de date en nombre de secondes depuis le 01/01/1970 (classe) */
+typedef GRegisteredItemClass GScanTimeMakeFunctionClass;
+
+
+/* Indique le type défini pour une conversion de date en nombre de secondes. */
+GType g_scan_time_make_function_get_type(void);
+
+/* Constitue une fonction de décompte du temps écoulé. */
+GRegisteredItem *g_scan_time_make_function_new(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_ITEMS_TIME_MAKE_H */
diff --git a/src/analysis/scan/items/time/now.c b/src/analysis/scan/items/time/now.c
new file mode 100644
index 0000000..16c4aef
--- /dev/null
+++ b/src/analysis/scan/items/time/now.c
@@ -0,0 +1,243 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * now.c - décompte du temps écoulé depuis Epoch
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "now.h"
+
+
+#include <time.h>
+
+
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des décomptes de temps écoulé. */
+static void g_scan_time_now_function_class_init(GScanTimeNowFunctionClass *);
+
+/* Initialise une instance de décompte de temps écoulé. */
+static void g_scan_time_now_function_init(GScanTimeNowFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_time_now_function_dispose(GScanTimeNowFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_time_now_function_finalize(GScanTimeNowFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_time_now_function_get_name(const GScanTimeNowFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_time_now_function_run_call(GScanTimeNowFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un décompte de secondes écoulées depuis le 01/01/1970. */
+G_DEFINE_TYPE(GScanTimeNowFunction, g_scan_time_now_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des décomptes de temps écoulé.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_time_now_function_class_init(GScanTimeNowFunctionClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GRegisteredItemClass *registered;       /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_time_now_function_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_time_now_function_finalize;
+
+    registered = G_REGISTERED_ITEM_CLASS(klass);
+
+    registered->get_name = (get_registered_item_name_fc)g_scan_time_now_function_get_name;
+    registered->run_call = (run_registered_item_call_fc)g_scan_time_now_function_run_call;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance de décompte de temps écoulé.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_time_now_function_init(GScanTimeNowFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_time_now_function_dispose(GScanTimeNowFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_time_now_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : func = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_time_now_function_finalize(GScanTimeNowFunction *func)
+{
+    G_OBJECT_CLASS(g_scan_time_now_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Constitue une fonction de décompte du temps écoulé.          *
+*                                                                             *
+*  Retour      : Fonction mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRegisteredItem *g_scan_time_now_function_new(void)
+{
+    GRegisteredItem *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_TIME_NOW_FUNCTION, NULL);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = élément d'appel à consulter.                          *
+*                                                                             *
+*  Description : Indique le nom associé à une expression d'évaluation.        *
+*                                                                             *
+*  Retour      : Désignation humaine de l'expression d'évaluation.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_time_now_function_get_name(const GScanTimeNowFunction *item)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("now");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = élément d'appel à consulter.                         *
+*                args  = liste d'éventuels arguments fournis.                 *
+*                count = taille de cette liste.                               *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la résolution opérée. [OUT] *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_time_now_function_run_call(GScanTimeNowFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    time_t now;                             /* Date relative courante      */
+
+    result = (count == 0);
+    if (!result) goto exit;
+
+    now = time(NULL);
+
+    *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ now }));
+
+ exit:
+
+    return result;
+
+}
diff --git a/src/analysis/scan/items/time/now.h b/src/analysis/scan/items/time/now.h
new file mode 100644
index 0000000..6b3faa2
--- /dev/null
+++ b/src/analysis/scan/items/time/now.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * now.h - prototypes pour le décompte du temps écoulé depuis Epoch
+ *
+ * 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_ITEMS_TIME_NOW_H
+#define _ANALYSIS_SCAN_ITEMS_TIME_NOW_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_TIME_NOW_FUNCTION            g_scan_time_now_function_get_type()
+#define G_SCAN_TIME_NOW_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TIME_NOW_FUNCTION, GScanTimeNowFunction))
+#define G_IS_SCAN_TIME_NOW_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TIME_NOW_FUNCTION))
+#define G_SCAN_TIME_NOW_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TIME_NOW_FUNCTION, GScanTimeNowFunctionClass))
+#define G_IS_SCAN_TIME_NOW_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TIME_NOW_FUNCTION))
+#define G_SCAN_TIME_NOW_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TIME_NOW_FUNCTION, GScanTimeNowFunctionClass))
+
+
+/* Décompte du nombre de seccondes écoulées depuis le 01/01/1970 (instance) */
+typedef GRegisteredItem GScanTimeNowFunction;
+
+/* Décompte du nombre de seccondes écoulées depuis le 01/01/1970 (classe) */
+typedef GRegisteredItemClass GScanTimeNowFunctionClass;
+
+
+/* Indique le type défini pour un décompte de secondes écoulées depuis le 01/01/1970. */
+GType g_scan_time_now_function_get_type(void);
+
+/* Constitue une fonction de décompte du temps écoulé. */
+GRegisteredItem *g_scan_time_now_function_new(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_ITEMS_TIME_NOW_H */
diff --git a/src/analysis/scan/items/uint-int.h b/src/analysis/scan/items/uint-int.h
index 1fa83c5..972d7a0 100644
--- a/src/analysis/scan/items/uint-int.h
+++ b/src/analysis/scan/items/uint-int.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * uint-int.h - prototypes internes pour la lecture d'un mot à partir de données binaires
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -33,7 +33,7 @@
 
 
 /* Fonction conduisant à la lecture d'un mot (instance) */
-struct _GUintFunction
+struct _GScanUintFunction
 {
     GRegisteredItem parent;                 /* A laisser en premier        */
 
@@ -43,7 +43,7 @@ struct _GUintFunction
 };
 
 /* Fonction conduisant à la lecture d'un mot (classe) */
-struct _GUintFunctionClass
+struct _GScanUintFunctionClass
 {
     GRegisteredItemClass parent;            /* A laisser en premier        */
 
@@ -51,7 +51,7 @@ struct _GUintFunctionClass
 
 
 /* Met en place un nouvelle fonction de lecture d'entiers. */
-bool g_uint_function_create(GUintFunction *, MemoryDataSize);
+bool g_scan_uint_function_create(GScanUintFunction *, MemoryDataSize, SourceEndian);
 
 
 
diff --git a/src/analysis/scan/items/uint.c b/src/analysis/scan/items/uint.c
index 4fea494..66c7fa9 100644
--- a/src/analysis/scan/items/uint.c
+++ b/src/analysis/scan/items/uint.c
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * uint.c - lecture d'un mot à partir de données binaires
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -29,6 +29,7 @@
 
 #include "uint-int.h"
 #include "../exprs/literal.h"
+#include "../../../common/extstr.h"
 
 
 
@@ -36,16 +37,16 @@
 
 
 /* Initialise la classe des lectures de valeurs entières. */
-static void g_uint_function_class_init(GUintFunctionClass *);
+static void g_scan_uint_function_class_init(GScanUintFunctionClass *);
 
 /* Initialise une instance de lecture de valeur entière. */
-static void g_uint_function_init(GUintFunction *);
+static void g_scan_uint_function_init(GScanUintFunction *);
 
 /* Supprime toutes les références externes. */
-static void g_uint_function_dispose(GUintFunction *);
+static void g_scan_uint_function_dispose(GScanUintFunction *);
 
 /* Procède à la libération totale de la mémoire. */
-static void g_uint_function_finalize(GUintFunction *);
+static void g_scan_uint_function_finalize(GScanUintFunction *);
 
 
 
@@ -53,10 +54,10 @@ static void g_uint_function_finalize(GUintFunction *);
 
 
 /* Indique le nom associé à une expression d'évaluation. */
-static char *g_uint_function_get_name(const GUintFunction *);
+static char *g_scan_uint_function_get_name(const GScanUintFunction *);
 
 /* Réduit une expression à une forme plus simple. */
-static bool g_uint_function_run_call(GUintFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+static bool g_scan_uint_function_run_call(GScanUintFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
 
 
 
@@ -66,7 +67,7 @@ static bool g_uint_function_run_call(GUintFunction *, GScanExpression **, size_t
 
 
 /* Indique le type défini pour une lecture de mot à partir de données binaires. */
-G_DEFINE_TYPE(GUintFunction, g_uint_function, G_TYPE_REGISTERED_ITEM);
+G_DEFINE_TYPE(GScanUintFunction, g_scan_uint_function, G_TYPE_REGISTERED_ITEM);
 
 
 /******************************************************************************
@@ -81,20 +82,20 @@ G_DEFINE_TYPE(GUintFunction, g_uint_function, G_TYPE_REGISTERED_ITEM);
 *                                                                             *
 ******************************************************************************/
 
-static void g_uint_function_class_init(GUintFunctionClass *klass)
+static void g_scan_uint_function_class_init(GScanUintFunctionClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GRegisteredItemClass *registered;       /* Version de classe parente   */
 
     object = G_OBJECT_CLASS(klass);
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_uint_function_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_uint_function_finalize;
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_uint_function_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_uint_function_finalize;
 
     registered = G_REGISTERED_ITEM_CLASS(klass);
 
-    registered->get_name = (get_registered_item_name_fc)g_uint_function_get_name;
-    registered->run_call = (run_registered_item_call_fc)g_uint_function_run_call;
+    registered->get_name = (get_registered_item_name_fc)g_scan_uint_function_get_name;
+    registered->run_call = (run_registered_item_call_fc)g_scan_uint_function_run_call;
 
 }
 
@@ -111,7 +112,7 @@ static void g_uint_function_class_init(GUintFunctionClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_uint_function_init(GUintFunction *func)
+static void g_scan_uint_function_init(GScanUintFunction *func)
 {
     func->size = MDS_UNDEFINED;
     func->endian = SRE_LITTLE;
@@ -131,9 +132,9 @@ static void g_uint_function_init(GUintFunction *func)
 *                                                                             *
 ******************************************************************************/
 
-static void g_uint_function_dispose(GUintFunction *func)
+static void g_scan_uint_function_dispose(GScanUintFunction *func)
 {
-    G_OBJECT_CLASS(g_uint_function_parent_class)->dispose(G_OBJECT(func));
+    G_OBJECT_CLASS(g_scan_uint_function_parent_class)->dispose(G_OBJECT(func));
 
 }
 
@@ -150,9 +151,9 @@ static void g_uint_function_dispose(GUintFunction *func)
 *                                                                             *
 ******************************************************************************/
 
-static void g_uint_function_finalize(GUintFunction *func)
+static void g_scan_uint_function_finalize(GScanUintFunction *func)
 {
-    G_OBJECT_CLASS(g_uint_function_parent_class)->finalize(G_OBJECT(func));
+    G_OBJECT_CLASS(g_scan_uint_function_parent_class)->finalize(G_OBJECT(func));
 
 }
 
@@ -169,13 +170,13 @@ static void g_uint_function_finalize(GUintFunction *func)
 *                                                                             *
 ******************************************************************************/
 
-GUintFunction *g_uint_function_new(MemoryDataSize size)
+GRegisteredItem *g_scan_uint_function_new(MemoryDataSize size, SourceEndian endian)
 {
-    GUintFunction *result;                  /* Structure à retourner       */
+    GRegisteredItem *result;                /* Structure à retourner       */
 
-    result = g_object_new(G_TYPE_UINT_FUNCTION, NULL);
+    result = g_object_new(G_TYPE_SCAN_UINT_FUNCTION, NULL);
 
-    if (!g_uint_function_create(result, size))
+    if (!g_scan_uint_function_create(G_SCAN_UINT_FUNCTION(result), size, endian))
         g_clear_object(&result);
 
     return result;
@@ -196,13 +197,14 @@ GUintFunction *g_uint_function_new(MemoryDataSize size)
 *                                                                             *
 ******************************************************************************/
 
-bool g_uint_function_create(GUintFunction *func, MemoryDataSize size)
+bool g_scan_uint_function_create(GScanUintFunction *func, MemoryDataSize size, SourceEndian endian)
 {
     bool result;                            /* Bilan à retourner           */
 
     result = true;
 
     func->size = size;
+    func->endian = endian;
 
     return result;
 
@@ -227,26 +229,26 @@ bool g_uint_function_create(GUintFunction *func, MemoryDataSize size)
 *                                                                             *
 ******************************************************************************/
 
-static char *g_uint_function_get_name(const GUintFunction *item)
+static char *g_scan_uint_function_get_name(const GScanUintFunction *item)
 {
     char *result;                           /* Désignation à retourner     */
 
-    switch (item->size)
+    switch (item->size & ~MDS_SIGN)
     {
         case MDS_8_BITS_UNSIGNED:
-            result = strdup("uint8");
+            result = strdup("int8");
             break;
 
         case MDS_16_BITS_UNSIGNED:
-            result = strdup("uint16");
+            result = strdup("int16");
             break;
 
         case MDS_32_BITS_UNSIGNED:
-            result = strdup("uint32");
+            result = strdup("int32");
             break;
 
         case MDS_64_BITS_UNSIGNED:
-            result = strdup("uint64");
+            result = strdup("int64");
             break;
 
         default:
@@ -256,6 +258,16 @@ static char *g_uint_function_get_name(const GUintFunction *item)
 
     }
 
+    if (result)
+    {
+        if (!MDS_IS_SIGNED(item->size))
+            result = strprep(result, "u");
+
+        if (item->endian == SRE_BIG)
+            result = stradd(result, "be");
+
+    }
+
     return result;
 
 }
@@ -278,21 +290,25 @@ static char *g_uint_function_get_name(const GUintFunction *item)
 *                                                                             *
 ******************************************************************************/
 
-static bool g_uint_function_run_call(GUintFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+static bool g_scan_uint_function_run_call(GScanUintFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
 {
     bool result;                            /* Bilan à retourner           */
     unsigned long long offset;              /* Position du mot ciblé       */
     GBinContent *content;                   /* Contenu à manipuler         */
     vmpa2t pos;                             /* Tête de lecture             */
-    uint8_t val_8;                          /* Valeur entière sur 8 bits   */
-    uint16_t val_16;                        /* Valeur entière sur 16 bits  */
-    uint32_t val_32;                        /* Valeur entière sur 32 bits  */
-    uint64_t val_64;                        /* Valeur entière sur 64 bits  */
-
-    result = (count == 1 && G_IS_LITERAL_EXPRESSION(args[0]));
+    uint8_t val_s8;                          /* Valeur entière sur 8 bits   */
+    uint8_t val_u8;                          /* Valeur entière sur 8 bits   */
+    uint16_t val_s16;                        /* Valeur entière sur 16 bits  */
+    uint16_t val_u16;                        /* Valeur entière sur 16 bits  */
+    uint32_t val_s32;                        /* Valeur entière sur 32 bits  */
+    uint32_t val_u32;                        /* Valeur entière sur 32 bits  */
+    uint64_t val_s64;                        /* Valeur entière sur 64 bits  */
+    uint64_t val_u64;                        /* Valeur entière sur 64 bits  */
+
+    result = (count == 1 && G_IS_SCAN_LITERAL_EXPRESSION(args[0]));
     if (!result) goto exit;
 
-    result = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(args[0]), &offset);
+    result = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[0]), &offset);
     if (!result) goto exit;
 
     content = g_scan_context_get_content(ctx);
@@ -302,29 +318,60 @@ static bool g_uint_function_run_call(GUintFunction *item, GScanExpression **args
 
     switch (item->size)
     {
+        case MDS_8_BITS_SIGNED:
+            result = g_binary_content_read_s8(content, &pos, &val_s8);
+            if (result)
+                *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER,
+                                                              (long long []){ val_s8 }));
+            break;
+
         case MDS_8_BITS_UNSIGNED:
-            result = g_binary_content_read_u8(content, &pos, &val_8);
+            result = g_binary_content_read_u8(content, &pos, &val_u8);
             if (result)
-                *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_8 }));
+                *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+                                                              (unsigned long long []){ val_u8 }));
+            break;
+
+        case MDS_16_BITS_SIGNED:
+            result = g_binary_content_read_s16(content, &pos, item->endian, &val_s16);
+            if (result)
+                *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER,
+                                                              (long long []){ val_s16 }));
             break;
 
         case MDS_16_BITS_UNSIGNED:
-            result = g_binary_content_read_u16(content, &pos, item->endian, &val_16);
+            result = g_binary_content_read_u16(content, &pos, item->endian, &val_u16);
             if (result)
-                *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_16 }));
+                *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+                                                              (unsigned long long []){ val_u16 }));
+            break;
+
+        case MDS_32_BITS_SIGNED:
+            result = g_binary_content_read_s32(content, &pos, item->endian, &val_s32);
+            if (result)
+                *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER,
+                                                              (long long []){ val_s32 }));
             break;
 
         case MDS_32_BITS_UNSIGNED:
-            result = g_binary_content_read_u32(content, &pos, item->endian, &val_32);
+            result = g_binary_content_read_u32(content, &pos, item->endian, &val_u32);
             if (result)
-                *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_32 }));
+                *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+                                                              (unsigned long long []){ val_u32 }));
             break;
 
+        case MDS_64_BITS_SIGNED:
+            result = g_binary_content_read_s64(content, &pos, item->endian, &val_s64);
+            if (result)
+                *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER,
+                                                              (long long []){ val_s64 }));
+            break;
 
         case MDS_64_BITS_UNSIGNED:
-            result = g_binary_content_read_u64(content, &pos, item->endian, &val_64);
+            result = g_binary_content_read_u64(content, &pos, item->endian, &val_u64);
             if (result)
-                *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_64 }));
+                *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+                                                              (unsigned long long []){ val_u64 }));
             break;
 
         default:
diff --git a/src/analysis/scan/items/uint.h b/src/analysis/scan/items/uint.h
index 60f2975..abc2231 100644
--- a/src/analysis/scan/items/uint.h
+++ b/src/analysis/scan/items/uint.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * uint.h - prototypes pour la lecture d'un mot à partir de données binaires
  *
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -28,30 +28,31 @@
 #include <glib-object.h>
 
 
+#include "../item.h"
 #include "../../../arch/archbase.h"
 
 
 
-#define G_TYPE_UINT_FUNCTION            g_uint_function_get_type()
-#define G_UINT_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UINT_FUNCTION, GUintFunction))
-#define G_IS_UINT_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UINT_FUNCTION))
-#define G_UINT_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UINT_FUNCTION, GUintFunctionClass))
-#define G_IS_UINT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UINT_FUNCTION))
-#define G_UINT_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UINT_FUNCTION, GUintFunctionClass))
+#define G_TYPE_SCAN_UINT_FUNCTION            g_scan_uint_function_get_type()
+#define G_SCAN_UINT_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_UINT_FUNCTION, GScanUintFunction))
+#define G_IS_SCAN_UINT_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_UINT_FUNCTION))
+#define G_SCAN_UINT_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_UINT_FUNCTION, GScanUintFunctionClass))
+#define G_IS_SCAN_UINT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_UINT_FUNCTION))
+#define G_SCAN_UINT_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_UINT_FUNCTION, GScanUintFunctionClass))
 
 
 /* Fonction conduisant à la lecture d'un mot (instance) */
-typedef struct _GUintFunction GUintFunction;
+typedef struct _GScanUintFunction GScanUintFunction;
 
 /* Fonction conduisant à la lecture d'un mot (classe) */
-typedef struct _GUintFunctionClass GUintFunctionClass;
+typedef struct _GScanUintFunctionClass GScanUintFunctionClass;
 
 
 /* Indique le type défini pour une lecture de mot à partir de données binaires. */
-GType g_uint_function_get_type(void);
+GType g_scan_uint_function_get_type(void);
 
 /* Constitue une fonction de lecture de valeur entière. */
-GUintFunction *g_uint_function_new(MemoryDataSize);
+GRegisteredItem *g_scan_uint_function_new(MemoryDataSize, SourceEndian);
 
 
 
diff --git a/src/analysis/scan/rule-int.h b/src/analysis/scan/rule-int.h
index b43c20b..cc10b08 100644
--- a/src/analysis/scan/rule-int.h
+++ b/src/analysis/scan/rule-int.h
@@ -38,6 +38,7 @@ struct _GScanRule
     GObject parent;                         /* A laisser en premier        */
 
     char *name;                             /* Désignation de la règle     */
+    fnv64_t name_hash;                      /* Empreinte de la désignation */
 
     GSearchPattern **data_locals;           /* Variables de données        */
     size_t data_allocated;                  /* Taille allouée du tableau   */
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c
index bf37585..6ca97ab 100644
--- a/src/analysis/scan/rule.c
+++ b/src/analysis/scan/rule.c
@@ -91,6 +91,7 @@ static void g_scan_rule_class_init(GScanRuleClass *klass)
 static void g_scan_rule_init(GScanRule *rule)
 {
     rule->name = NULL;
+    rule->name_hash = 0;
 
     rule->data_locals = NULL;
     rule->data_allocated = 0;
@@ -168,6 +169,33 @@ GScanRule *g_scan_rule_new(const char *name)
     result = g_object_new(G_TYPE_SCAN_RULE, NULL);
 
     result->name = strdup(name);
+    result->name_hash = fnv_64a_hash(name);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : rule = règle de détection à compléter.                       *
+*                hash = empreinte précalculée associée au nom. [OUT]          *
+*                                                                             *
+*  Description : Indique le nom associé à une règle de détection.             *
+*                                                                             *
+*  Retour      : Désignation humaine associée à la règle.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_scan_rule_get_name(const GScanRule *rule, fnv64_t *hash)
+{
+    const char *result;                     /* Désignation à retourner     */
+
+    result = rule->name;
+
+    *hash = rule->name_hash;
 
     return result;
 
diff --git a/src/analysis/scan/rule.h b/src/analysis/scan/rule.h
index e240da9..12a435c 100644
--- a/src/analysis/scan/rule.h
+++ b/src/analysis/scan/rule.h
@@ -33,6 +33,7 @@
 #include "pattern.h"
 #include "expr.h"
 #include "patterns/backend.h"
+#include "../../common/fnv1a.h"
 
 
 
@@ -57,6 +58,9 @@ GType g_scan_rule_get_type(void);
 /* Crée une règle de détection statique à l'aide de motifs. */
 GScanRule *g_scan_rule_new(const char *);
 
+/* Indique le nom associé à une règle de détection. */
+const char *g_scan_rule_get_name(const GScanRule *, fnv64_t *);
+
 /* Intègre une nouvelle variable locale à une règle. */
 void g_scan_rule_add_local_variable(GScanRule *, GSearchPattern *);
 
diff --git a/src/analysis/scan/scanner-int.h b/src/analysis/scan/scanner-int.h
index 54b4f62..4fcda87 100644
--- a/src/analysis/scan/scanner-int.h
+++ b/src/analysis/scan/scanner-int.h
@@ -37,6 +37,8 @@ struct _GContentScanner
 {
     GObject parent;                         /* A laisser en premier        */
 
+    char *filename;                         /* Eventuel fichier d'origine  */
+
     GScanRule **rules;                      /* Règles de détection         */
     size_t rule_count;                      /* Nombre de ces règles        */
 
diff --git a/src/analysis/scan/scanner.c b/src/analysis/scan/scanner.c
index d52c0fc..ce8d677 100644
--- a/src/analysis/scan/scanner.c
+++ b/src/analysis/scan/scanner.c
@@ -25,11 +25,15 @@
 
 
 #include <assert.h>
+#include <libgen.h>
+#include <malloc.h>
 
 
 #include "decl.h"
 #include "scanner-int.h"
 #include "../contents/file.h"
+#include "../../common/extstr.h"
+#include "../../core/logs.h"
 
 
 
@@ -45,6 +49,9 @@ static void g_content_scanner_dispose(GContentScanner *);
 /* Procède à la libération totale de la mémoire. */
 static void g_content_scanner_finalize(GContentScanner *);
 
+/* Intègre une nouvelle règle de détection. */
+static bool _g_content_scanner_add_rule(GContentScanner *, GScanRule *);
+
 
 
 /* Indique le type défini pour une recherche dans du binaire. */
@@ -89,6 +96,8 @@ static void g_content_scanner_class_init(GContentScannerClass *klass)
 
 static void g_content_scanner_init(GContentScanner *scanner)
 {
+    scanner->filename = NULL;
+
     scanner->rules = NULL;
     scanner->rule_count = 0;
 
@@ -137,6 +146,9 @@ static void g_content_scanner_dispose(GContentScanner *scanner)
 
 static void g_content_scanner_finalize(GContentScanner *scanner)
 {
+    if (scanner->filename != NULL)
+        free(scanner->filename);
+
     if (scanner->rules != NULL)
         free(scanner->rules);
 
@@ -250,6 +262,8 @@ bool g_content_scanner_create_from_file(GContentScanner *scanner, const char *fi
     content = g_file_content_new(filename);
     if (content == NULL) goto no_content;
 
+    scanner->filename = strdup(filename);
+
     size = g_binary_content_compute_size(content);
 
     g_binary_content_compute_start_pos(content, &start);
@@ -268,25 +282,187 @@ bool g_content_scanner_create_from_file(GContentScanner *scanner, const char *fi
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : scanner = scanner de contenus à consulter.                   *
+*                                                                             *
+*  Description : Indique le chemin d'un éventuel fichier de source.           *
+*                                                                             *
+*  Retour      : Chemin d'un éventuel fichier de définitions ou NULL.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_content_scanner_get_filename(const GContentScanner *scanner)
+{
+    const char *result;                     /* Chemin à retourner          */
+
+    result = scanner->filename;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : scanner = gestionnaire de recherche à compléter.             *
+*                path    = chemin vers une définition de règles à intégrer.   *
+*                                                                             *
+*  Description : Inclut les définitions d'un fichier de règles externe.       *
+*                                                                             *
+*  Retour      : Bilan de l'inclusion à retourner.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_content_scanner_include_resource(GContentScanner *scanner, const char *path)
+{
+    bool result;                            /* Bilan à retourner           */
+    GContentScanner *included;              /* Définition à inclure        */
+    char *tmp;                              /* Copie de travail            */
+    char *filename;                         /* Chemin d'accès reconstruit  */
+    size_t i;                               /* Boucle de parcours          */
+    const char *inc_name;                   /* Nom de la nouvelle règle    */
+
+    /* Cas le plus simple : un chemin absolu */
+    if (path[0] == '/')
+        included = g_content_scanner_new_from_file(path);
+
+    /* Chemin relatif à l'emplacement de la définition courante ? */
+    else if (scanner->filename != NULL)
+    {
+        tmp = strdup(scanner->filename);
+
+        filename = strdup(dirname(tmp));
+        filename = stradd(filename, G_DIR_SEPARATOR_S);
+        filename = stradd(filename, path);
+
+        included = g_content_scanner_new_from_file(filename);
+
+        free(filename);
+        free(tmp);
+
+    }
+
+    else
+        included = NULL;
+
+    /* Inclusion des règles chargées */
+
+    result = (included != NULL);
+
+    if (result)
+    {
+        for (i = 0; i < included->rule_count && result; i++)
+        {
+            result = _g_content_scanner_add_rule(scanner, included->rules[i]);
+
+            if (!result)
+            {
+                inc_name = g_scan_rule_get_name(included->rules[i], (fnv64_t []) { 0 });
+
+                log_variadic_message(LMT_ERROR, "Can not import from '%s': rule '%s' already exists!",
+                                     path, inc_name);
+
+            }
+
+        }
+
+        g_object_unref(G_OBJECT(included));
+
+    }
+
+    return result;
+
+
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : scanner = gestionnaire de recherche à compléter.             *
 *                rule    = règle de détection à intégrer.                     *
 *                                                                             *
 *  Description : Intègre une nouvelle règle de détection.                     *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de l'ajout à retourner.                                *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule)
+static bool _g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule)
 {
+    bool result;                            /* Bilan à retourner           */
+    const char *inc_name;                   /* Nom de la nouvelle règle    */
+    fnv64_t inc_hash;                       /* Empreinte de ce nom         */
+    size_t i;                               /* Boucle de parcours          */
+    const char *cur_name;                   /* Nom d'une règle en place    */
+    fnv64_t cur_hash;                       /* Empreinte de ce nom         */
+
+    result = false;
+
+    inc_name = g_scan_rule_get_name(rule, &inc_hash);
+
+    for (i = 0; i < scanner->rule_count; i++)
+    {
+        cur_name = g_scan_rule_get_name(scanner->rules[i], &cur_hash);
+
+        if (inc_hash != cur_hash)
+            continue;
+
+        if (strcmp(inc_name, cur_name) == 0)
+            goto exit_add;
+
+    }
+
+    result = true;
+
     scanner->rules = realloc(scanner->rules, ++scanner->rule_count * sizeof(GScanRule *));
 
     scanner->rules[scanner->rule_count - 1] = rule;
 
     g_object_ref(G_OBJECT(rule));
 
+ exit_add:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : scanner = gestionnaire de recherche à compléter.             *
+*                rule    = règle de détection à intégrer.                     *
+*                                                                             *
+*  Description : Intègre une nouvelle règle de détection.                     *
+*                                                                             *
+*  Retour      : Bilan de l'ajout à retourner.                                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule)
+{
+    bool result;                            /* Bilan à retourner           */
+    const char *inc_name;                   /* Nom de la nouvelle règle    */
+
+    result = _g_content_scanner_add_rule(scanner, rule);
+
+    if (!result)
+    {
+        inc_name = g_scan_rule_get_name(rule, (fnv64_t []) { 0 });
+
+        log_variadic_message(LMT_ERROR, "Can not add rule: '%s' already exists!", inc_name);
+
+    }
+
+    return result;
+
 }
 
 
diff --git a/src/analysis/scan/scanner.h b/src/analysis/scan/scanner.h
index 8a3919a..f838344 100644
--- a/src/analysis/scan/scanner.h
+++ b/src/analysis/scan/scanner.h
@@ -59,19 +59,18 @@ GContentScanner *g_content_scanner_new_from_text(const char *);
 /* Prépare une recherche de motifs dans du contenu binaire. */
 GContentScanner *g_content_scanner_new_from_file(const char *);
 
+/* Indique le chemin d'un éventuel fichier de source. */
+const char *g_content_scanner_get_filename(const GContentScanner *);
+
+/* Inclut les définitions d'un fichier de règles externe. */
+bool g_content_scanner_include_resource(GContentScanner *, const char *);
+
 /* Intègre une nouvelle règle de détection. */
-void g_content_scanner_add_rule(GContentScanner *, GScanRule *);
+bool g_content_scanner_add_rule(GContentScanner *, GScanRule *);
 
 /* Définit l'expression d'une correspondance recherchée. */
 GScanContext *g_content_scanner_analyze(GContentScanner *, GScanOptions *, GBinContent *);
 
 
 
-
-
-/* Lance une analyse d'un élément, fichier ou répertoire. */
-//void g_content_scanner_analyze(GContentScanner *, const char *);
-
-
-
 #endif  /* _ANALYSIS_SCAN_SCANNER_H */
diff --git a/src/analysis/scan/tokens.l b/src/analysis/scan/tokens.l
index b541786..f3dbc79 100644
--- a/src/analysis/scan/tokens.l
+++ b/src/analysis/scan/tokens.l
@@ -82,6 +82,7 @@
 %option yylineno
 %option never-interactive
 
+%x include_path
 
 %x rule_intro
 %x raw_block
@@ -105,6 +106,14 @@
 
 
 
+"include"                       { PUSH_STATE(include_path); return INCLUDE; }
+
+<include_path>"\""              {
+                                    POP_STATE;
+                                    *used = 0;
+                                    PUSH_STATE(strlit);
+                                }
+
 "rule"                          { PUSH_STATE(rule_intro); return RAW_RULE; }
 
 <rule_intro>[A-Za-z0-9_]+       {
@@ -116,8 +125,8 @@
 <rule_intro>[ \t]*              {  }
 <rule_intro>"{"                 { POP_STATE; PUSH_STATE(raw_block); return BRACE_IN; }
 
-<raw_block>"strings"            { PUSH_STATE(strings); PUSH_STATE(wait_for_colon); return STRINGS; }
-<raw_block,strings>"condition"          { PUSH_STATE(condition); PUSH_STATE(wait_for_colon); return CONDITION; }
+<raw_block>"strings"            { POP_STATE; PUSH_STATE(strings); PUSH_STATE(wait_for_colon); return STRINGS; }
+<raw_block,strings>"condition"          { POP_STATE; PUSH_STATE(condition); PUSH_STATE(wait_for_colon); return CONDITION; }
 
 
 
@@ -127,8 +136,11 @@
 <condition>"true"               { return TRUE_; }
 <condition>"false"              { return FALSE_; }
 
-<condition>(0|[1-9][0-9]*)      { yylval->integer = strtoull(yytext, NULL, 10); return INTEGER; }
-<condition>0x[0-9a-f]+          { yylval->integer = strtoull(yytext, NULL, 16); return INTEGER; }
+<condition>-(0|[1-9][0-9]*)     { yylval->signed_integer = strtoll(yytext, NULL, 10); return SIGNED_INTEGER; }
+<condition>-0x[0-9a-f]+         { yylval->signed_integer = strtoll(yytext, NULL, 16); return SIGNED_INTEGER; }
+
+<condition>(0|[1-9][0-9]*)      { yylval->unsigned_integer = strtoull(yytext, NULL, 10); return UNSIGNED_INTEGER; }
+<condition>0x[0-9a-f]+          { yylval->unsigned_integer = strtoull(yytext, NULL, 16); return UNSIGNED_INTEGER; }
 
 <condition>[kK][bB]             { return KB; }
 <condition>[mM][bB]             { return MB; }
@@ -141,8 +153,6 @@
 
 <strlit>"\""                    {
                                     POP_STATE; 
-                                    EXTEND_BUFFER_IF_NEEDED(1);
-                                    (*buf)[(*used)++] = '\0';
                                     yylval->sized_cstring.data = *buf;
                                     yylval->sized_cstring.len = *used;
                                     return STRING;
@@ -195,7 +205,7 @@
 <condition>"+"                  { return PLUS; }
 <condition>"-"                  { return MINUS; }
 <condition>"*"                  { return MUL; }
-<condition>"\\"                 { return DIV; }
+<condition>"/"                  { return DIV; }
 <condition>"%"                  { return MOD; }
 
 <condition>"("                  { return PAREN_O; }
@@ -208,6 +218,7 @@
 <condition>"all"                { return ALL; }
 <condition>"of"                 { return OF; }
 <condition>"them"               { return THEM; }
+<condition>"in"                 { return IN; }
 
 
 <strings,condition>$[A-Za-z0-9_]* {
@@ -215,6 +226,21 @@
                                     yylval->sized_cstring.len = yyleng - 1;
                                     return IDENTIFIER;
                                 }
+
+<condition>$[A-Za-z_][A-Za-z0-9_]* {
+                                    yylval->sized_cstring.data = yytext + 1;
+                                    yylval->sized_cstring.len = yyleng - 1;
+                                    return BYTES_ID;
+                                }
+
+<condition>#[A-Za-z_][A-Za-z0-9_]* {
+                                    yylval->sized_cstring.data = yytext + 1;
+                                    yylval->sized_cstring.len = yyleng - 1;
+                                    return BYTES_ID_COUNTER;
+                                }
+
+
+
 <condition>[A-Za-z_][A-Za-z0-9_]* {
                                     yylval->sized_cstring.data = yytext;
                                     yylval->sized_cstring.len = yyleng;
diff --git a/src/common/szstr.h b/src/common/szstr.h
index 54beb9a..d73e489 100644
--- a/src/common/szstr.h
+++ b/src/common/szstr.h
@@ -29,6 +29,9 @@
 #include <sys/types.h>
 
 
+#include "sort.h"
+
+
 
 /* Structure associant une chaîne et sa taille */
 typedef struct _sized_string_t
@@ -66,9 +69,28 @@ typedef struct _sized_string_t
         }                       \
     }                           \
     while (0)
-            
-#define szstrcmp(ss, rs) \
-    strncmp((ss)->data, (rs)/*->data*/, (ss)->len)
+
+#define szstrcmp(s1, s2)                                            \
+    ({                                                              \
+        int __ret;                                                  \
+        size_t __n;                                                 \
+        __n = (s1)->len < (s2)->len ? (s1)->len : (s2)->len;        \
+        __ret = strncmp((s1)->data, (s2)->data, __n);               \
+        if (__ret == 0)                                             \
+            __ret = sort_unsigned_long_long((s1)->len, (s2)->len);  \
+        __ret;                                                      \
+    })
+
+#define szmemcmp(s1, s2)                                            \
+    ({                                                              \
+        int __ret;                                                  \
+        size_t __n;                                                 \
+        __n = (s1)->len < (s2)->len ? (s1)->len : (s2)->len;        \
+        __ret = memcmp((s1)->data, (s2)->data, __n);                \
+        if (__ret == 0)                                             \
+            __ret = sort_unsigned_long_long((s1)->len, (s2)->len);  \
+        __ret;                                                      \
+    })
 
 
 
diff --git a/src/core/core.c b/src/core/core.c
index 8d4daa7..26469ff 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -41,6 +41,9 @@
 #include "processors.h"
 #include "queue.h"
 #include "../analysis/scan/core.h"
+#ifdef HAVE_MAGIC_SUPPORT
+#   include "../analysis/scan/items/magic/cookie.h"
+#endif
 #include "../common/io.h"
 #include "../common/xdg.h"
 #include "../glibext/linesegment.h"
@@ -102,6 +105,10 @@ bool load_all_core_components(bool cs)
             explorer = g_content_explorer_new();
             set_current_content_explorer(explorer);
 
+#ifdef HAVE_MAGIC_SUPPORT
+            if (result) result = init_magic_cookie();
+#endif
+
             resolver = g_content_resolver_new();
             set_current_content_resolver(resolver);
 
@@ -152,6 +159,10 @@ void unload_all_core_components(bool cs)
 
         set_rost_root_namespace(NULL);
 
+#ifdef HAVE_MAGIC_SUPPORT
+        exit_magic_cookie();
+#endif
+
         set_current_content_resolver(NULL);
 
         set_current_content_explorer(NULL);
diff --git a/src/glibext/comparison-int.h b/src/glibext/comparison-int.h
index efb289a..446f25d 100644
--- a/src/glibext/comparison-int.h
+++ b/src/glibext/comparison-int.h
@@ -48,7 +48,10 @@ typedef GComparableItemIface GComparableItemInterface;
 
 
 /* Réalise une comparaison riche entre valeurs entière. */
-bool compare_rich_integer_values(unsigned long long, unsigned long long, RichCmpOperation);
+bool compare_rich_integer_values_signed(long long, long long, RichCmpOperation);
+
+/* Réalise une comparaison riche entre valeurs entière. */
+bool compare_rich_integer_values_unsigned(unsigned long long, unsigned long long, RichCmpOperation);
 
 
 
diff --git a/src/glibext/comparison.c b/src/glibext/comparison.c
index 463f354..8ce6941 100644
--- a/src/glibext/comparison.c
+++ b/src/glibext/comparison.c
@@ -101,7 +101,63 @@ bool g_comparable_item_compare_rich(const GComparableItem *item, const GComparab
 *                                                                             *
 ******************************************************************************/
 
-bool compare_rich_integer_values(unsigned long long a, unsigned long long b, RichCmpOperation op)
+bool compare_rich_integer_values_signed(long long a, long long b, RichCmpOperation op)
+{
+    bool result;                            /* Bilan  à retourner          */
+
+    switch (op)
+    {
+        case RCO_LT:
+            result = (a < b);
+            break;
+
+        case RCO_LE:
+            result = (a <= b);
+            break;
+
+        case RCO_EQ:
+            result = (a == b);
+            break;
+
+        case RCO_NE:
+            result = (a != b);
+            break;
+
+        case RCO_GT:
+            result = (a > b);
+            break;
+
+        case RCO_GE:
+            result = (a >= b);
+            break;
+
+        default:
+            assert(false);
+            result = false;
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a  = premier élément à consulter pour une comparaison.       *
+*                b  = second objet à consulter pour une comparaison.          *
+*                op = opération de comparaison à réaliser.                    *
+*                                                                             *
+*  Description : Réalise une comparaison riche entre valeurs entière.         *
+*                                                                             *
+*  Retour      : Bilan des opérations de comparaison.                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool compare_rich_integer_values_unsigned(unsigned long long a, unsigned long long b, RichCmpOperation op)
 {
     bool result;                            /* Bilan  à retourner          */
 
diff --git a/src/rost.c b/src/rost.c
index 37ca098..40fe587 100644
--- a/src/rost.c
+++ b/src/rost.c
@@ -275,31 +275,33 @@ int main(int argc, char **argv)
 
     set_log_verbosity(verbosity);
 
-    /*
-    if (!load_all_core_components(false))
+    if (!load_all_core_components(true))
         goto done;
-    */
 
     /* Traitement des recherches */
 
     scanner = g_content_scanner_new_from_file(rules);
 
-    content = g_file_content_new(target);
+    if (scanner != NULL)
+    {
+        content = g_file_content_new(target);
+
+        context = g_content_scanner_analyze(scanner, options, content);
 
-    context = g_content_scanner_analyze(scanner, options, content);
+        g_scan_context_display(context);
 
-    g_scan_context_display(context);
+        g_object_unref(G_OBJECT(context));
+        g_object_unref(G_OBJECT(content));
 
-    g_object_unref(G_OBJECT(context));
-    g_object_unref(G_OBJECT(content));
+        g_object_unref(G_OBJECT(scanner));
 
-    g_object_unref(G_OBJECT(scanner));
+    }
 
     g_object_unref(G_OBJECT(options));
 
     /* Sortie */
 
-    //unload_all_core_components(false);
+    unload_all_core_components(false);
 
 #ifdef TRACK_GOBJECT_LEAKS
     remember_gtypes_for_leaks();
diff --git a/tests/analysis/scan/booleans.py b/tests/analysis/scan/booleans.py
new file mode 100644
index 0000000..aa3c1a3
--- /dev/null
+++ b/tests/analysis/scan/booleans.py
@@ -0,0 +1,98 @@
+
+from common import RostTestClass
+
+
+class TestRostBooleans(RostTestClass):
+    """TestCases for booleans and ROST."""
+
+    def testFinalCondition(self):
+        """Validate the final condition."""
+
+        rule = '''
+rule test {
+
+   condition:
+      false
+
+}
+'''
+
+        self.check_rule_failure(rule)
+
+
+        rule = '''
+rule test {
+
+   condition:
+      true
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+    def testBasicBooleanOperations(self):
+        """Evaluate basic boolean operations."""
+
+        rule = '''
+rule test {
+
+   condition:
+      true and false
+
+}
+'''
+
+        self.check_rule_failure(rule)
+
+
+        rule = '''
+rule test {
+
+   condition:
+      true or false
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+    def testImplicitCast(self):
+        """Imply implicit casts to booleans."""
+
+        rule = '''
+rule test {
+
+   condition:
+      true and 0
+
+}
+'''
+
+        self.check_rule_failure(rule)
+
+
+        rule = '''
+rule test {
+
+   condition:
+      1 or false
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+        rule = '''
+rule test {
+
+   condition:
+      1 or ()
+
+}
+'''
+
+        self.check_rule_success(rule)
diff --git a/tests/analysis/scan/common.py b/tests/analysis/scan/common.py
new file mode 100644
index 0000000..3b52e38
--- /dev/null
+++ b/tests/analysis/scan/common.py
@@ -0,0 +1,52 @@
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.analysis.scan import ContentScanner
+from pychrysalide.analysis.scan import ScanOptions
+from pychrysalide.analysis.scan.patterns.backends import AcismBackend
+
+
+class RostTestClass(ChrysalideTestCase):
+    """TestCase for analysis.scan.ScanExpression."""
+
+    @classmethod
+    def setUpClass(cls):
+
+        super(RostTestClass, cls).setUpClass()
+
+        cls._options = ScanOptions()
+        cls._options.backend_for_data = AcismBackend
+
+        cls._empty_content = MemoryContent(b'')
+
+
+    def _validate_rule_result(self, rule, content, expected):
+        """Check for scan success or failure."""
+
+        scanner = ContentScanner(rule)
+        ctx = scanner.analyze(self._options, content)
+
+        self.assertIsNotNone(ctx)
+
+        if expected:
+            self.assertTrue(ctx.has_match_for_rule('test'))
+        else:
+            self.assertFalse(ctx.has_match_for_rule('test'))
+
+
+    def check_rule_success(self, rule, content = None):
+        """Check for scan success."""
+
+        if content is None:
+            content = self._empty_content
+
+        self._validate_rule_result(rule, content, True)
+
+
+    def check_rule_failure(self, rule, content = None):
+        """Check for scan failure."""
+
+        if content is None:
+            content = self._empty_content
+
+        self._validate_rule_result(rule, content, False)
diff --git a/tests/analysis/scan/examples.py b/tests/analysis/scan/examples.py
new file mode 100644
index 0000000..74b5094
--- /dev/null
+++ b/tests/analysis/scan/examples.py
@@ -0,0 +1,70 @@
+
+from common import RostTestClass
+from pychrysalide.analysis.contents import MemoryContent
+
+
+class TestRostExamples(RostTestClass):
+    """TestCases for the examples provides in the ROST documentation."""
+
+    def testComments(self):
+        """Ensure comments do not bother rule definitions."""
+
+        rule = '''
+/*
+    Multi-line header...
+*/
+
+rule test {    // comment
+
+   /*
+    * Some context
+    */
+
+   condition:  /* List of condition(s) */
+      true     // Dummy condition
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+    def testArithmeticPrecedence(self):
+        """Take care of arithmetic operators precedence."""
+
+        rule = '''
+rule test {  // MulFirst
+
+   condition:
+      1 + 4 * (3 + 2) == 21
+      and
+      (1 + 4) * (3 + 2) == 25
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+    def testUintCast(self):
+        """Process nested integer values from binary content."""
+
+        cnt = MemoryContent(b'\x4d\x5a\x00\x00' + b'\x50\x45\x00\x00' + 52 * b'\x00' + b'\x04\x00\x00\x00')
+
+        rule = '''
+rule test {  // IsPE
+
+    condition:
+
+        // MZ signature at offset 0 and ...
+
+        uint16(0) == 0x5a4d and
+
+        // ... PE signature at offset stored in the MZ header at offset 0x3c
+
+        uint32(uint32(0x3c)) == 0x00004550
+
+}
+'''
+
+        self.check_rule_success(rule, cnt)
diff --git a/tests/analysis/scan/expr.py b/tests/analysis/scan/expr.py
deleted file mode 100644
index dbe8c55..0000000
--- a/tests/analysis/scan/expr.py
+++ /dev/null
@@ -1,169 +0,0 @@
-
-
-from chrysacase import ChrysalideTestCase
-from pychrysalide.analysis.scan import ScanExpression
-from pychrysalide.glibext import ComparableItem
-
-
-class TestScanExpression(ChrysalideTestCase):
-    """TestCase for analysis.scan.ScanExpression."""
-
-
-    def testDirectInstances(self):
-        """Reject direct instances."""
-
-        with self.assertRaisesRegex(RuntimeError, 'pychrysalide.analysis.scan.ScanExpression is an abstract class'):
-
-            e = ScanExpression()
-
-
-    def testBooleanComparison(self):
-        """Compare custom scan expressions."""
-
-        class StrLenExpr(ScanExpression):
-
-            def __init__(self, value):
-                super().__init__(ScanExpression.ExprValueType.STRING)
-                self._value = value
-
-            def _cmp_rich(self, other, op):
-
-                if op == ComparableItem.RichCmpOperation.EQ:
-                    return len(self._value) == len(other._value)
-
-
-        e0 = StrLenExpr('00000000000')
-
-        e1 = StrLenExpr('00000000000')
-
-        e2 = StrLenExpr('000000000000000000000000000')
-
-        self.assertTrue(e0 == e1)
-
-        # !?
-        # Python teste e0 != e1 (non implémenté), puis e1 != e0 (pareil) et en déduit une différence !
-        # self.assertFalse(e0 != e1)
-
-        self.assertFalse(e0 == e2)
-
-        # TypeError: '<' not supported between instances of 'StrLenExpr' and 'StrLenExpr'
-        with self.assertRaisesRegex(TypeError, '\'<\' not supported between instances'):
-            self.assertTrue(e0 < e1)
-
-
-
-
-
-
-    # def testTypeSubclassing(self):
-    #     """Verify the data type subclassing is working."""
-
-    #     class MyType(DataType):
-
-    #         def __init__(self, num):
-    #             super(MyType, self).__init__()
-    #             self._num = num
-
-    #         def _to_string(self, include):
-    #             return '%x' % self._num
-
-    #         def _dup(self):
-    #             return MyType(self._num)
-
-    #     tp = MyType(0x123)
-
-    #     self.assertEqual(str(tp), '123')
-
-    #     tp2 = tp.dup()
-
-    #     self.assertEqual(str(tp), str(tp2))
-
-
-    # def testTypeDefaultProperties(self):
-    #     """Check for default values of some type properties."""
-
-    #     class MyPropType(DataType):
-    #         pass
-
-    #     tp = MyPropType()
-
-    #     self.assertTrue(tp.handle_namespaces)
-
-    #     self.assertFalse(tp.is_pointer)
-
-    #     self.assertFalse(tp.is_reference)
-
-    #     class MyPropType2(DataType):
-
-    #         def _handle_namespaces(self):
-    #             return True
-
-    #         def _is_pointer(self):
-    #             return 123 < 1234
-
-    #         def _is_reference(self):
-    #             return False
-
-    #     tp2 = MyPropType2()
-
-    #     self.assertTrue(tp.handle_namespaces)
-
-    #     self.assertTrue(tp2.is_pointer)
-
-    #     self.assertFalse(tp2.is_reference)
-
-
-    # def testTypeNamespaces(self):
-    #     """Test the type namespace property."""
-
-    #     class MyNSType(DataType):
-
-    #         def __init__(self, name):
-    #             super(MyNSType, self).__init__()
-    #             self._name = name
-
-    #         def _to_string(self, include):
-    #             return self._name
-
-    #     tp = MyNSType('TP')
-    #     ns = MyNSType('NS')
-
-    #     self.assertIsNone(tp.namespace)
-
-    #     tp.namespace = (ns, '.')
-
-    #     self.assertEqual(str(tp), 'NS.TP')
-
-    #     self.assertEqual(tp.namespace, (ns, '.'))
-
-
-    # def testTypeHash(self):
-    #     """Hash a user-defined type."""
-
-    #     class MyUserType(DataType):
-
-    #         def __init__(self, name):
-    #             super(MyUserType, self).__init__()
-    #             self._name = name
-
-    #         def _hash(self):
-    #             return hash(self._name)
-
-    #     tp = MyUserType('random')
-
-    #     self.assertEqual(tp.hash, hash('random') & ((1 << 32) - 1))
-
-    #     class MyOutOfRangeUserType(DataType):
-
-    #         hard_coded_hash = -8752470794866657507
-
-    #         def __init__(self, name):
-    #             super(MyOutOfRangeUserType, self).__init__()
-    #             self._name = name
-
-    #         def _hash(self):
-    #             return self.hard_coded_hash
-
-    #     tp = MyOutOfRangeUserType('out-of-range')
-
-    #     self.assertEqual(tp.hash, MyOutOfRangeUserType.hard_coded_hash & ((1 << 32) - 1))
diff --git a/tests/analysis/scan/exprs.py b/tests/analysis/scan/exprs.py
deleted file mode 100644
index c89dc59..0000000
--- a/tests/analysis/scan/exprs.py
+++ /dev/null
@@ -1,122 +0,0 @@
-
-from chrysacase import ChrysalideTestCase
-from pychrysalide.analysis.contents import MemoryContent
-from pychrysalide.analysis.scan import ContentScanner
-from pychrysalide.analysis.scan import ScanOptions
-from pychrysalide.analysis.scan.patterns.backends import AcismBackend
-
-
-class TestScanExpressions(ChrysalideTestCase):
-    """TestCase for analysis.scan.exprs.*."""
-
-    @classmethod
-    def setUpClass(cls):
-
-        super(TestScanExpressions, cls).setUpClass()
-
-        cls._options = ScanOptions()
-        cls._options.backend_for_data = AcismBackend
-
-
-    def testBasicStringOperations(self):
-        """Evaluate basic string operations."""
-
-        cnt = MemoryContent(b'empty')
-
-        rule = '''
-rule test {
-
-   condition:
-      "123abc456" contains "abc"
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(ctx.has_match_for_rule('test'))
-
-        rule = '''
-rule test {
-
-   condition:
-      "123\t456" contains "\t"
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(ctx.has_match_for_rule('test'))
-
-        rule = '''
-rule test {
-
-   condition:
-      "123-456" startswith "1"
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(ctx.has_match_for_rule('test'))
-
-        rule = '''
-rule test {
-
-   condition:
-      "123-456" startswith "1234"
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertFalse(ctx.has_match_for_rule('test'))
-
-        rule = '''
-rule test {
-
-   condition:
-      "123-456" endswith "6"
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(ctx.has_match_for_rule('test'))
-
-        rule = '''
-rule test {
-
-   condition:
-      "123-456" endswith "3456"
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertFalse(ctx.has_match_for_rule('test'))
-
-        rule = '''
-rule test {
-
-   condition:
-      "ABCD" iequals "AbCd"
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(ctx.has_match_for_rule('test'))
diff --git a/tests/analysis/scan/func.py b/tests/analysis/scan/func.py
deleted file mode 100644
index bd7d0ce..0000000
--- a/tests/analysis/scan/func.py
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-from chrysacase import ChrysalideTestCase
-from pychrysalide.analysis.scan import ScanFunction
-
-
-class TestScanFunction(ChrysalideTestCase):
-    """TestCase for analysis.scan.ScanFunction."""
-
-
-    def testDirectInstances(self):
-        """Reject direct instances."""
-
-        with self.assertRaisesRegex(RuntimeError, 'pychrysalide.analysis.scan.ScanFunction is an abstract class'):
-
-            f = ScanFunction('name')
diff --git a/tests/analysis/scan/functions.py b/tests/analysis/scan/functions.py
new file mode 100644
index 0000000..8553018
--- /dev/null
+++ b/tests/analysis/scan/functions.py
@@ -0,0 +1,104 @@
+
+from common import RostTestClass
+from pychrysalide.analysis.contents import MemoryContent
+
+
+class TestRostFunctions(RostTestClass):
+    """TestCases for the core functions of ROST."""
+
+    # Core
+    # ====
+
+    def testDatasize(self):
+        """Handle the size of the provided data."""
+
+        cnt = MemoryContent(b'\x01\x02\x03\x04')
+
+        cases = [
+            'datasize == 4',
+            'uint16(0) == 0x201 and uint16(datasize - 2) == 0x0403',
+        ]
+
+        for c in cases:
+
+            rule = '''
+rule test {
+
+   condition:
+      %s
+
+}
+''' % c
+
+            self.check_rule_success(rule, cnt)
+
+
+    # Modules
+    # =======
+
+    def testConsole(self):
+        """Ensure logging always returns true."""
+
+        rule = '''
+rule test {
+
+   condition:
+      console.log()
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+    def testMagic(self):
+        """Scan text content with the Magic module."""
+
+        cnt = MemoryContent(b'aaaa')
+
+        cases = [
+            [ 'type', 'ASCII text, with no line terminators' ],
+            [ 'mime_encoding', 'us-ascii' ],
+            [ 'mime_type', 'text/plain' ],
+        ]
+
+        for target, expected in cases:
+
+            rule = '''
+rule test {
+
+   condition:
+      magic.%s() == "%s"
+
+}
+''' % (target, expected)
+
+            self.check_rule_success(rule, cnt)
+
+
+    def testTime(self):
+        """Check current time."""
+
+        # Cf. https://www.epochconverter.com/
+
+        rule = '''
+rule test {
+
+   condition:
+      time.make(2023, 8, 5, 22, 8, 41) == 0x64cec869
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+        rule = '''
+rule test {
+
+   condition:
+      time.now() >= 0x64cec874 and time.now() <= time.now()
+
+}
+'''
+
+        self.check_rule_success(rule)
diff --git a/tests/analysis/scan/grammar.py b/tests/analysis/scan/grammar.py
index 5a2e1d5..8b18f81 100644
--- a/tests/analysis/scan/grammar.py
+++ b/tests/analysis/scan/grammar.py
@@ -1,286 +1,191 @@
 
-from chrysacase import ChrysalideTestCase
-from pychrysalide.analysis.contents import MemoryContent
-from pychrysalide.analysis.scan import ContentScanner
-from pychrysalide.analysis.scan import ScanOptions
-from pychrysalide.analysis.scan.patterns.backends import AcismBackend
+from common import RostTestClass
 
 
-class TestRostGrammar(ChrysalideTestCase):
-    """TestCase for analysis.scan.ScanExpression."""
+class TestRostGrammar(RostTestClass):
+    """TestCases for the ROST grammar."""
 
-    @classmethod
-    def setUpClass(cls):
+    def testRelationalExpressions(self):
+        """Build expressions with relational comparisons."""
 
-        super(TestRostGrammar, cls).setUpClass()
+        cases = [
 
-        cls._options = ScanOptions()
-        cls._options.backend_for_data = AcismBackend
+            # Regular
+            [ '-1', '<=', '2', True ],
+            [ '-1', '<=', '2', True ],
+            [ '"aaa"', '==', '"aaa"', True ],
+            [ '"aaa"', '<', '"aaaa"', True ],
+            [ '""', '<', '"aaaa"', True ],
 
+            # Cast
+            [ 'false', '==', '0', True ],
+            [ 'false', '==', '1', False ],
+            [ 'true', '!=', '0', True ],
+            [ '1', '==', 'true', True ],
+            [ 'false', '==', '()', True ],
+            [ 'true', '==', '(0,)', True ],
 
-    def testComments(self):
-        """Ensure comments do not bother rule definitions."""
+        ]
 
-        cnt = MemoryContent(b'no_real_content')
+        for op1, kwd, op2, expected in cases:
 
-        rule = '''
-/*
-    Multi-line header...
-*/
-
-rule test {    // comment
-
-   /*
-    * Some context
-    */
-
-   condition:  /* List of condition(s) */
-      true     // Dummy condition
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
-
-
-    def testUintCast(self):
-        """Process nested integer values from binary content."""
-
-        cnt = MemoryContent(b'\x4d\x5a\x00\x00' + b'\x50\x45\x00\x00' + 52 * b'\x00' + b'\x04\x00\x00\x00')
-
-        rule = '''
-rule IsPE {
-
-    condition:
-
-        // MZ signature at offset 0 and ...
-
-        uint16(0) == 0x5a4d and
-
-        // ... PE signature at offset stored in the MZ header at offset 0x3c
-
-        uint32(uint32(0x3c)) == 0x00004550
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('IsPE'))
-
-
-    def testBasicBooleanConditions(self):
-        """Evaluate basic boolean conditions."""
-
-        cnt = MemoryContent(b'0123')
-
-        rule = '''
-rule test {
-
-   condition:
-      true and false
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(not(ctx is None))
-        self.assertFalse(ctx.has_match_for_rule('test'))
-
-        rule = '''
+            rule = '''
 rule test {
 
    condition:
-      true or false
+      %s %s %s
 
 }
-'''
+''' % (op1, kwd, op2)
 
-        scanner = ContentScanner(rule)
+            if expected:
+                self.check_rule_success(rule)
+            else:
+                self.check_rule_failure(rule)
 
-        ctx = scanner.analyze(self._options, cnt)
 
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+    def testLogicalOperations(self):
+        """Evaluate some logical operations."""
 
+        cases = [
+            [ 'true and false', False ],
+            [ 'false or false', False ],
+            [ 'true and true or false', True ],
+            [ 'false or true and false', False ],
+            [ '1 or false', True ],
+        ]
 
-    def testArithmeticOpeations(self):
-        """Compute some arithmetic operations."""
+        for cond, expected in cases:
 
-        cnt = MemoryContent(b'0123')
-
-        rule = '''
+            rule = '''
 rule test {
 
    condition:
-      1 + 4 * 3 + 2 == 15
+      %s
 
 }
-'''
-
-        scanner = ContentScanner(rule)
-
-        ctx = scanner.analyze(self._options, cnt)
+''' % (cond)
 
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+            if expected:
+                self.check_rule_success(rule)
+            else:
+                self.check_rule_failure(rule)
 
 
-        rule = '''
-rule test {
+    def testArithmeticOperations(self):
+        """Evaluate some arithmetic operations."""
 
-   condition:
-      (1 + 4) * 3 + 2 == 17
+        cases = [
 
-}
-'''
+            # Clever
+            '1 + 2 == 3',
+            '10 + -3 == 7',
+            '-3 + 10 == 7',
+            '-10 - 1 < 0',
+            '-10 - 1 == -11',
+            '(-10 - 1) == -11',
+            '(-1 - -10) == 9',
+            '-2 * -3 == 6',
+            '-2 * 3 == -6',
 
-        scanner = ContentScanner(rule)
+            # Legacy
+            '1 + 4 * 3 + 2 == 15',
+            '(1 + 4) * 3 + 2 == 17',
+            '1 + 4 * (3 + 2) == 21',
+            '(1 + 4) * (3 + 2) == 25',
 
-        ctx = scanner.analyze(self._options, cnt)
+        ]
 
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+        for c in cases:
 
-
-        rule = '''
+            rule = '''
 rule test {
 
    condition:
-      1 + 4 * (3 + 2) == 21
+      %s
 
 }
-'''
+''' % (c)
 
-        scanner = ContentScanner(rule)
+            self.check_rule_success(rule)
 
-        ctx = scanner.analyze(self._options, cnt)
 
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+    def testBasicStringsOperations(self):
+        """Build expressions with basic strings operations."""
 
+        cases = [
 
-        rule = '''
-rule test {
+            # Clever
+            [ '123---456', 'contains', '---', True ],
+            [ '123---456', 'contains', 'xxx', False ],
+            [ '---123---456', 'startswith', '---', True ],
+            [ '---123---456', 'startswith', 'xxx', False ],
+            [ '123---456---', 'endswith', '---', True ],
+            [ '123---456---', 'endswith', 'xxx', False ],
+            [ 'AAA---BBB', 'icontains', 'aaa', True ],
+            [ 'AAA---BBB', 'icontains', 'xxx', False ],
+            [ 'AAA---BBB', 'istartswith', 'aAa', True ],
+            [ 'AAA---BBB', 'istartswith', 'xxx', False ],
+            [ 'AAA---BBB', 'iendswith', 'bBb', True ],
+            [ 'AAA---BBB', 'iendswith', 'xxx', False ],
+            [ 'AzertY', 'iequals', 'AZERTY', True ],
+            [ 'AzertY', 'iequals', 'AZERTY-', False ],
 
-   condition:
-      (1 + 4) * (3 + 2) == 25
-
-}
-'''
+            # Legacy
+            [ '123\t456', 'contains', '\t', True ],
+            [ '123-456', 'startswith', '1', True ],
+            [ '123-456', 'startswith', '1234', False ],
+            [ '123-456', 'endswith', '6', True ],
+            [ '123-456', 'endswith', '3456', False ],
 
-        scanner = ContentScanner(rule)
+        ]
 
-        ctx = scanner.analyze(self._options, cnt)
+        for op1, kwd, op2, expected in cases:
 
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
-
-
-    def testSizeUnits(self):
-        """Evaluate size units."""
-
-        cnt = MemoryContent(b'0123')
-
-
-        rule = '''
-rule test {
-
-   condition:
-      1KB == 1024
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
-
-
-        rule = '''
+            rule = '''
 rule test {
 
    condition:
-      2MB == 2 * 1024 * 1024
+      "%s" %s "%s"
 
 }
-'''
+''' % (op1, kwd, op2)
 
-        scanner = ContentScanner(rule)
+            if expected:
+                self.check_rule_success(rule)
+            else:
+                self.check_rule_failure(rule)
 
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
-
-
-        rule = '''
-rule test {
-
-   condition:
-      4Kb == (4 * 1024)
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
-
-
-        rule = '''
-rule test {
-
-   condition:
-      1KB <= 1024 and 1024 < 1MB
-
-}
-'''
-
-        scanner = ContentScanner(rule)
-
-        ctx = scanner.analyze(self._options, cnt)
-
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
 
+    def testSizeUnits(self):
+        """Evaluate size units."""
 
-    def testNamespace(self):
-        """Resolve main functions with the root scan namesapce."""
+        cases = [
+            '1KB == 1024',
+            '2MB == 2 * 1024 * 1024',
+            '4Kb == (4 * 1024)',
+            '1KB <= 1024 and 1024 < 1MB',
+        ]
 
-        cnt = MemoryContent(b'\x01\x02\x03\x04')
+        for c in cases:
 
-        rule = '''
+            rule = '''
 rule test {
 
    condition:
-      datasize == 4
+      %s
 
 }
-'''
+''' % (c)
 
-        scanner = ContentScanner(rule)
+            self.check_rule_success(rule)
 
-        ctx = scanner.analyze(self._options, cnt)
 
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
 
 
-        rule = '''
-rule test {
 
-   condition:
-      uint16(0) == 0x201 and uint16(datasize - 2) == 0x0403
 
-}
-'''
+# TODO : test     <haystack> matches <regex>
 
-        scanner = ContentScanner(rule)
 
-        ctx = scanner.analyze(self._options, cnt)
 
-        self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
diff --git a/tests/analysis/scan/matches.py b/tests/analysis/scan/matches.py
new file mode 100644
index 0000000..0d7556e
--- /dev/null
+++ b/tests/analysis/scan/matches.py
@@ -0,0 +1,27 @@
+
+from common import RostTestClass
+from pychrysalide.analysis.contents import MemoryContent
+
+
+class TestRostMatchs(RostTestClass):
+    """TestCases for the ROST pattern matching engine."""
+
+    def testCountMatches(self):
+        """Count matches patterns."""
+
+        cnt = MemoryContent(b'aaa aaa bbb aaa')
+
+        rule = '''
+rule test {
+
+   strings:
+      $a = "aaa"
+      $b = "bbb"
+
+   condition:
+      #a == 3 and #b < 2
+
+}
+'''
+
+        self.check_rule_success(rule, cnt)
diff --git a/tests/analysis/scan/options.py b/tests/analysis/scan/options.py
deleted file mode 100644
index 7617b3a..0000000
--- a/tests/analysis/scan/options.py
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-from chrysacase import ChrysalideTestCase
-from gi._constants import TYPE_INVALID
-from pychrysalide.analysis.scan import ScanOptions
-
-
-class TestScanOptions(ChrysalideTestCase):
-    """TestCase for analysis.scan.ScanOptions."""
-
-    def testEmptyOptions(self):
-        """Check default scan options."""
-
-        ops = ScanOptions()
-
-        self.assertEqual(ops.backend_for_data, TYPE_INVALID)
diff --git a/tests/analysis/scan/pyapi.py b/tests/analysis/scan/pyapi.py
new file mode 100644
index 0000000..1bba44e
--- /dev/null
+++ b/tests/analysis/scan/pyapi.py
@@ -0,0 +1,58 @@
+
+from chrysacase import ChrysalideTestCase
+from gi._constants import TYPE_INVALID
+from pychrysalide.analysis.scan import ScanExpression
+from pychrysalide.analysis.scan import ScanOptions
+from pychrysalide.glibext import ComparableItem
+
+
+class TestRostPythonAPI(ChrysalideTestCase):
+    """TestCase for the ROST Python API."""
+
+    def testEmptyOptions(self):
+        """Check default scan options."""
+
+        ops = ScanOptions()
+
+        self.assertEqual(ops.backend_for_data, TYPE_INVALID)
+
+
+    def testDirectInstancesOfExpression(self):
+        """Reject direct instances of ROST expressions."""
+
+        with self.assertRaisesRegex(RuntimeError, 'pychrysalide.analysis.scan.ScanExpression is an abstract class'):
+
+            e = ScanExpression()
+
+    def testBooleanComparison(self):
+        """Compare custom scan expressions."""
+
+        class StrLenExpr(ScanExpression):
+
+            def __init__(self, value):
+                super().__init__(ScanExpression.ExprValueType.STRING)
+                self._value = value
+
+            def _cmp_rich(self, other, op):
+
+                if op == ComparableItem.RichCmpOperation.EQ:
+                    return len(self._value) == len(other._value)
+
+
+        e0 = StrLenExpr('00000000000')
+
+        e1 = StrLenExpr('00000000000')
+
+        e2 = StrLenExpr('000000000000000000000000000')
+
+        self.assertTrue(e0 == e1)
+
+        # !?
+        # Python teste e0 != e1 (non implémenté), puis e1 != e0 (pareil) et en déduit une différence !
+        # self.assertFalse(e0 != e1)
+
+        self.assertFalse(e0 == e2)
+
+        # TypeError: '<' not supported between instances of 'StrLenExpr' and 'StrLenExpr'
+        with self.assertRaisesRegex(TypeError, '\'<\' not supported between instances'):
+            self.assertTrue(e0 < e1)
diff --git a/tests/analysis/scan/sets.py b/tests/analysis/scan/sets.py
new file mode 100644
index 0000000..1d10fbf
--- /dev/null
+++ b/tests/analysis/scan/sets.py
@@ -0,0 +1,118 @@
+
+from common import RostTestClass
+
+
+class TestRostSets(RostTestClass):
+    """TestCases for sets support in ROST."""
+
+    def testSetsAsBooleans(self):
+        """Convert sets to boolean."""
+
+        rule = '''
+rule test {
+
+   condition:
+      ()
+
+}
+'''
+
+        self.check_rule_failure(rule)
+
+
+        rule = '''
+rule test {
+
+   condition:
+      (1, )
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+        rule = '''
+rule test {
+
+   condition:
+      ("aaa", true, 123)
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+    def testStringAsArray(self):
+        """Handle strings as arrays."""
+
+        rule = '''
+rule test {
+
+   condition:
+      count("aaa")
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+        rule = '''
+rule test {
+
+   condition:
+      count("aaa") == 3
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+    def testSetsIntersections(self):
+        """Perform sets intersections."""
+
+        rule = '''
+rule test {
+
+   condition:
+      ("aaa", "bbb") in ("AAA", "BBB", "aaa")
+
+}
+'''
+
+        self.check_rule_success(rule)
+
+
+        rule = '''
+rule test {
+
+   condition:
+      ("aaa", "bbb") in ("123", )
+
+}
+'''
+
+        self.check_rule_failure(rule)
+
+
+
+
+
+
+
+
+
+
+
+
+
+        # TODO :
+
+        # test : intersection(a, a) == a
+
+        # test : "123" in "0123456789"
+        # test : "123" in "012987"
+
-- 
cgit v0.11.2-87-g4458