From 2424c52c4f3bc44ce5f36348442cfa103e0989c2 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 18 Aug 2023 02:07:39 +0200
Subject: Create some modifiers and handle match properties inside ROST.

---
 configure.ac                                       |   3 +
 plugins/pychrysalide/analysis/scan/Makefile.am     |   1 +
 plugins/pychrysalide/analysis/scan/context.c       |  85 +++
 plugins/pychrysalide/analysis/scan/core.c          | 188 +++++++
 plugins/pychrysalide/analysis/scan/core.h          |  39 ++
 plugins/pychrysalide/analysis/scan/module.c        |   3 +
 plugins/pychrysalide/analysis/scan/options.c       | 156 ++++++
 .../analysis/scan/patterns/Makefile.am             |  10 +-
 .../pychrysalide/analysis/scan/patterns/modifier.c | 324 ++++++++++++
 .../pychrysalide/analysis/scan/patterns/modifier.h |  45 ++
 .../analysis/scan/patterns/modifiers/Makefile.am   |  17 +
 .../analysis/scan/patterns/modifiers/hex.c         | 211 ++++++++
 .../analysis/scan/patterns/modifiers/hex.h         |  45 ++
 .../analysis/scan/patterns/modifiers/list.c        | 320 +++++++++++
 .../analysis/scan/patterns/modifiers/list.h        |  45 ++
 .../analysis/scan/patterns/modifiers/module.c      | 110 ++++
 .../analysis/scan/patterns/modifiers/module.h      |  42 ++
 .../analysis/scan/patterns/modifiers/plain.c       | 211 ++++++++
 .../analysis/scan/patterns/modifiers/plain.h       |  45 ++
 .../analysis/scan/patterns/modifiers/rev.c         | 211 ++++++++
 .../analysis/scan/patterns/modifiers/rev.h         |  45 ++
 .../pychrysalide/analysis/scan/patterns/module.c   |   5 +
 src/analysis/scan/context-int.h                    |   1 +
 src/analysis/scan/context.c                        |  93 ++--
 src/analysis/scan/context.h                        |  11 +-
 src/analysis/scan/core.c                           | 162 ++++++
 src/analysis/scan/core.h                           |  13 +
 src/analysis/scan/expr-int.h                       |   4 +-
 src/analysis/scan/expr.c                           |  20 +-
 src/analysis/scan/expr.h                           |   6 +-
 src/analysis/scan/exprs/Makefile.am                |   4 +
 src/analysis/scan/exprs/counter.c                  |  22 +-
 src/analysis/scan/exprs/handler-int.h              |  58 ++
 src/analysis/scan/exprs/handler.c                  | 402 ++++++++++++++
 src/analysis/scan/exprs/handler.h                  |  66 +++
 src/analysis/scan/exprs/item-int.h                 |  58 ++
 src/analysis/scan/exprs/item.c                     | 346 ++++++++++++
 src/analysis/scan/exprs/item.h                     |  55 ++
 src/analysis/scan/exprs/literal.c                  |   5 +-
 src/analysis/scan/exprs/set.c                      |  10 +-
 src/analysis/scan/grammar.y                        | 559 +++++++++++++++++---
 src/analysis/scan/items/count.c                    |   2 +-
 src/analysis/scan/match-int.h                      |  10 +-
 src/analysis/scan/match.c                          |  92 +++-
 src/analysis/scan/match.h                          |  14 +-
 src/analysis/scan/matches/bytes-int.h              |   6 +-
 src/analysis/scan/matches/bytes.c                  | 270 ++++++++--
 src/analysis/scan/matches/bytes.h                  |  26 +-
 src/analysis/scan/matches/pending.c                | 243 +++++++--
 src/analysis/scan/matches/pending.h                |  32 +-
 src/analysis/scan/options-int.h                    |   2 +
 src/analysis/scan/options.c                        |  86 +++
 src/analysis/scan/options.h                        |  12 +
 src/analysis/scan/pattern-int.h                    |  13 +-
 src/analysis/scan/pattern.c                        | 111 +++-
 src/analysis/scan/pattern.h                        |  18 +-
 src/analysis/scan/patterns/Makefile.am             |   7 +-
 src/analysis/scan/patterns/modifier-int.h          |  59 +++
 src/analysis/scan/patterns/modifier.c              | 181 +++++++
 src/analysis/scan/patterns/modifier.h              |  62 +++
 src/analysis/scan/patterns/modifiers/Makefile.am   |  17 +
 src/analysis/scan/patterns/modifiers/hex.c         | 252 +++++++++
 src/analysis/scan/patterns/modifiers/hex.h         |  58 ++
 src/analysis/scan/patterns/modifiers/list-int.h    |  54 ++
 src/analysis/scan/patterns/modifiers/list.c        | 405 ++++++++++++++
 src/analysis/scan/patterns/modifiers/list.h        |  68 +++
 src/analysis/scan/patterns/modifiers/plain.c       | 245 +++++++++
 src/analysis/scan/patterns/modifiers/plain.h       |  58 ++
 src/analysis/scan/patterns/modifiers/rev.c         | 247 +++++++++
 src/analysis/scan/patterns/modifiers/rev.h         |  58 ++
 src/analysis/scan/patterns/token-int.h             |   6 +
 src/analysis/scan/patterns/token.c                 | 180 ++++++-
 src/analysis/scan/patterns/token.h                 |   1 +
 src/analysis/scan/patterns/tokens/Makefile.am      |  12 +
 src/analysis/scan/patterns/tokens/atom.c           | 364 +++++++++++++
 src/analysis/scan/patterns/tokens/atom.h           |  68 +++
 src/analysis/scan/patterns/tokens/hex-int.h        |  56 ++
 src/analysis/scan/patterns/tokens/hex.c            | 457 ++++++++++++++++
 src/analysis/scan/patterns/tokens/hex.h            |  59 +++
 src/analysis/scan/patterns/tokens/node-int.h       |  58 ++
 src/analysis/scan/patterns/tokens/node.c           | 195 +++++++
 src/analysis/scan/patterns/tokens/node.h           |  77 +++
 .../scan/patterns/tokens/nodes/Makefile.am         |  16 +
 src/analysis/scan/patterns/tokens/nodes/hub-int.h  |  51 ++
 src/analysis/scan/patterns/tokens/nodes/hub.c      | 150 ++++++
 src/analysis/scan/patterns/tokens/nodes/hub.h      |  55 ++
 .../scan/patterns/tokens/nodes/plain-int.h         |  64 +++
 src/analysis/scan/patterns/tokens/nodes/plain.c    | 582 +++++++++++++++++++++
 src/analysis/scan/patterns/tokens/nodes/plain.h    |  70 +++
 src/analysis/scan/patterns/tokens/plain-int.h      |  64 +++
 src/analysis/scan/patterns/tokens/plain.c          | 365 ++++++++-----
 src/analysis/scan/patterns/tokens/plain.h          |  31 +-
 src/analysis/scan/rule-int.h                       |   6 +-
 src/analysis/scan/rule.c                           | 194 ++++++-
 src/analysis/scan/rule.h                           |  13 +
 src/analysis/scan/scanner.c                        | 116 ++++
 src/analysis/scan/scanner.h                        |  13 +
 src/analysis/scan/tokens.l                         | 495 ++++++++++++++----
 src/common/cpp.h                                   |   2 +
 src/common/szstr.h                                 |   6 +
 src/core/core.c                                    |   8 +-
 src/rost.c                                         |  26 +-
 tests/analysis/scan/pyapi.py                       |  33 ++
 tests/analysis/scan/scanning_hex.py                |  26 +
 104 files changed, 10150 insertions(+), 533 deletions(-)
 create mode 100644 plugins/pychrysalide/analysis/scan/core.c
 create mode 100644 plugins/pychrysalide/analysis/scan/core.h
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifier.c
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifier.h
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c
 create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h
 create mode 100644 src/analysis/scan/exprs/handler-int.h
 create mode 100644 src/analysis/scan/exprs/handler.c
 create mode 100644 src/analysis/scan/exprs/handler.h
 create mode 100644 src/analysis/scan/exprs/item-int.h
 create mode 100644 src/analysis/scan/exprs/item.c
 create mode 100644 src/analysis/scan/exprs/item.h
 create mode 100644 src/analysis/scan/patterns/modifier-int.h
 create mode 100644 src/analysis/scan/patterns/modifier.c
 create mode 100644 src/analysis/scan/patterns/modifier.h
 create mode 100644 src/analysis/scan/patterns/modifiers/Makefile.am
 create mode 100644 src/analysis/scan/patterns/modifiers/hex.c
 create mode 100644 src/analysis/scan/patterns/modifiers/hex.h
 create mode 100644 src/analysis/scan/patterns/modifiers/list-int.h
 create mode 100644 src/analysis/scan/patterns/modifiers/list.c
 create mode 100644 src/analysis/scan/patterns/modifiers/list.h
 create mode 100644 src/analysis/scan/patterns/modifiers/plain.c
 create mode 100644 src/analysis/scan/patterns/modifiers/plain.h
 create mode 100644 src/analysis/scan/patterns/modifiers/rev.c
 create mode 100644 src/analysis/scan/patterns/modifiers/rev.h
 create mode 100644 src/analysis/scan/patterns/tokens/atom.c
 create mode 100644 src/analysis/scan/patterns/tokens/atom.h
 create mode 100644 src/analysis/scan/patterns/tokens/hex-int.h
 create mode 100644 src/analysis/scan/patterns/tokens/hex.c
 create mode 100644 src/analysis/scan/patterns/tokens/hex.h
 create mode 100644 src/analysis/scan/patterns/tokens/node-int.h
 create mode 100644 src/analysis/scan/patterns/tokens/node.c
 create mode 100644 src/analysis/scan/patterns/tokens/node.h
 create mode 100644 src/analysis/scan/patterns/tokens/nodes/Makefile.am
 create mode 100644 src/analysis/scan/patterns/tokens/nodes/hub-int.h
 create mode 100644 src/analysis/scan/patterns/tokens/nodes/hub.c
 create mode 100644 src/analysis/scan/patterns/tokens/nodes/hub.h
 create mode 100644 src/analysis/scan/patterns/tokens/nodes/plain-int.h
 create mode 100644 src/analysis/scan/patterns/tokens/nodes/plain.c
 create mode 100644 src/analysis/scan/patterns/tokens/nodes/plain.h
 create mode 100644 src/analysis/scan/patterns/tokens/plain-int.h
 create mode 100644 tests/analysis/scan/scanning_hex.py

diff --git a/configure.ac b/configure.ac
index e9183a2..2f35cbe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -684,6 +684,7 @@ AC_CONFIG_FILES([Makefile
                  plugins/pychrysalide/analysis/scan/Makefile
                  plugins/pychrysalide/analysis/scan/patterns/Makefile
                  plugins/pychrysalide/analysis/scan/patterns/backends/Makefile
+                 plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile
                  plugins/pychrysalide/analysis/storage/Makefile
                  plugins/pychrysalide/analysis/types/Makefile
                  plugins/pychrysalide/arch/Makefile
@@ -734,7 +735,9 @@ AC_CONFIG_FILES([Makefile
                  src/analysis/scan/matches/Makefile
                  src/analysis/scan/patterns/Makefile
                  src/analysis/scan/patterns/backends/Makefile
+                 src/analysis/scan/patterns/modifiers/Makefile
                  src/analysis/scan/patterns/tokens/Makefile
+                 src/analysis/scan/patterns/tokens/nodes/Makefile
                  src/analysis/storage/Makefile
                  src/analysis/types/Makefile
                  src/arch/Makefile
diff --git a/plugins/pychrysalide/analysis/scan/Makefile.am b/plugins/pychrysalide/analysis/scan/Makefile.am
index 565ce82..32bf1e3 100644
--- a/plugins/pychrysalide/analysis/scan/Makefile.am
+++ b/plugins/pychrysalide/analysis/scan/Makefile.am
@@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libpychrysaanalysisscan.la
 libpychrysaanalysisscan_la_SOURCES =		\
 	constants.h constants.c					\
 	context.h context.c						\
+	core.h core.c							\
 	expr.h expr.c							\
 	item.h item.c							\
 	module.h module.c						\
diff --git a/plugins/pychrysalide/analysis/scan/context.c b/plugins/pychrysalide/analysis/scan/context.c
index 524ec46..8f29457 100644
--- a/plugins/pychrysalide/analysis/scan/context.c
+++ b/plugins/pychrysalide/analysis/scan/context.c
@@ -44,9 +44,15 @@ CREATE_DYN_CONSTRUCTOR(scan_context, G_TYPE_SCAN_CONTEXT);
 /* Initialise une instance sur la base du dérivé de GObject. */
 static int py_scan_context_init(PyObject *, PyObject *, PyObject *);
 
+/* Note que la phase d'analyse de contenu est terminée. */
+static PyObject *py_scan_context_mark_scan_as_done(PyObject *, PyObject *);
+
 /* Indique si une correspondance globale a pu être établie. */
 static PyObject *py_scan_context_has_match_for_rule(PyObject *, PyObject *);
 
+/* Indique si la phase d'analyse de contenu est terminée. */
+static PyObject *py_scan_context_is_scan_done(PyObject *, void *);
+
 
 
 /******************************************************************************
@@ -95,6 +101,43 @@ static int py_scan_context_init(PyObject *self, PyObject *args, PyObject *kwds)
 *  Paramètres  : self = classe représentant un format.                        *
 *                args = arguments fournis à l'appel.                          *
 *                                                                             *
+*  Description : Note que la phase d'analyse de contenu est terminée.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_context_mark_scan_as_done(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Contexte de suivi à renvoyer*/
+    GScanContext *context;                  /* Contexte de suivi d'analyse */
+
+#define SCAN_CONTEXT_MARK_SCAN_AS_DONE_METHOD PYTHON_METHOD_DEF \
+(                                                               \
+    mark_scan_as_done, "$self",                                 \
+    METH_NOARGS, py_scan_context,                               \
+    "Note that the analysis operations are finished."           \
+)
+
+    context = G_SCAN_CONTEXT(pygobject_get(self));
+
+    g_scan_context_mark_scan_as_done(context);
+
+    result = Py_None;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = classe représentant un format.                        *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
 *  Description : Indique si une correspondance globale a pu être établie.     *
 *                                                                             *
 *  Retour      : Bilan final d'une analyse (False par défaut).                *
@@ -140,6 +183,46 @@ static PyObject *py_scan_context_has_match_for_rule(PyObject *self, PyObject *ar
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique si la phase d'analyse de contenu est terminée.       *
+*                                                                             *
+*  Retour      : True si la phase de scan est terminée, False sinon.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_context_is_scan_done(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Instance Python à retourner */
+    GScanContext *context;                  /* Contexte de suivi d'analyse */
+    bool status;                            /* Bilan de consultation       */
+
+#define SCAN_CONTEXT_IS_SCAN_DONE_ATTRIB PYTHON_IS_DEF_FULL     \
+(                                                               \
+    scan_done, py_scan_context,                                 \
+    "Tell if the analysis operations are finished.\n"           \
+    "\n"                                                        \
+    "The result is a boolean: *True* if the scan is marked as"  \
+    " done, *False* otherwise."                                 \
+)
+
+    context = G_SCAN_CONTEXT(pygobject_get(self));
+
+    status = g_scan_context_is_scan_done(context);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -153,11 +236,13 @@ static PyObject *py_scan_context_has_match_for_rule(PyObject *self, PyObject *ar
 PyTypeObject *get_python_scan_context_type(void)
 {
     static PyMethodDef py_scan_context_methods[] = {
+        SCAN_CONTEXT_MARK_SCAN_AS_DONE_METHOD,
         SCAN_CONTEXT_HAS_MATCH_FOR_RULE_METHOD,
         { NULL }
     };
 
     static PyGetSetDef py_scan_context_getseters[] = {
+        SCAN_CONTEXT_IS_SCAN_DONE_ATTRIB,
         { NULL }
     };
 
diff --git a/plugins/pychrysalide/analysis/scan/core.c b/plugins/pychrysalide/analysis/scan/core.c
new file mode 100644
index 0000000..f609f7d
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/core.c
@@ -0,0 +1,188 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - équivalent Python du fichier "analysis/scan/core.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "core.h"
+
+
+#include <pygobject.h>
+
+
+#include <analysis/scan/core.h>
+
+
+#include "patterns/modifier.h"
+#include "../../access.h"
+#include "../../helpers.h"
+
+
+
+/* #include <malloc.h> */
+
+/* #include <i18n.h> */
+/* #include <arch/processor.h> */
+/* #include <core/processors.h> */
+
+/* #include "../core.h" */
+
+/* #include "../arch/processor.h" */
+
+
+
+/* Inscrit un modificateur dans la liste des disponibles. */
+static PyObject *py_scan_register_token_modifier(PyObject *, PyObject *);
+
+/* Fournit le modificateur correspondant à un nom. */
+static PyObject *py_scan_find_token_modifiers_for_name(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet Python concerné par l'appel.                    *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Inscrit un modificateur dans la liste des disponibles.       *
+*                                                                             *
+*  Retour      : Bilan des enregistrements effectués : True si nouveauté.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_register_token_modifier(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    PyObject *instance;                     /* Instance Python fournie     */
+    GScanTokenModifier *modifier;           /* Version native              */
+    int ret;                                /* Bilan de lecture des args.  */
+    bool status;                            /* Bilan d'un enregistrement   */
+
+#define SCAN_REGISTER_TOKEN_MODIFIER_METHOD PYTHON_METHOD_DEF           \
+(                                                                       \
+    register_token_modifier, "inst, /",                                 \
+    METH_VARARGS, py_scan,                                              \
+    "Register a token modifier for byte patterns to scan.\n"            \
+    "\n"                                                                \
+    "This instance will be used as singleton and has to be a"           \
+    " subclass of pychrysalide.analysis.scan.patterns.TokenModifier."   \
+)
+
+    ret = PyArg_ParseTuple(args, "O!", get_python_scan_token_modifier_type(), &instance);
+    if (!ret) return NULL;
+
+    modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(instance));
+
+    status = register_scan_token_modifier(modifier);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet Python concerné par l'appel.                    *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Fournit le modificateur correspondant à un nom.              *
+*                                                                             *
+*  Retour      : Instance du modificateur identifié ou None.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_find_token_modifiers_for_name(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    const char *name;                       /* Nom d'appel à rechercher    */
+    int ret;                                /* Bilan de lecture des args.  */
+    GScanTokenModifier *modifier;           /* Instance mise en place      */
+
+#define SCAN_FIND_TOKEN_MODIFIERS_FOR_NAME_METHOD PYTHON_METHOD_DEF \
+(                                                                   \
+    find_token_modifiers_for_name, "name, /",                       \
+    METH_VARARGS, py_scan,                                          \
+    "Provide the registered instance of a pattern modifier linked"  \
+    " to a given *name* provided as a key string.\n"                \
+    "\n"                                                            \
+    "The returned instance is an object inherited from"             \
+    " pychrysalide.analysis.scan.patterns.TokenModifier or *None*"  \
+    " if no instance was found for the provided name."              \
+)
+
+    ret = PyArg_ParseTuple(args, "s", &name);
+    if (!ret) return NULL;
+
+    modifier = find_scan_token_modifiers_for_name(name);
+
+    if (modifier != NULL)
+    {
+        result = pygobject_new(G_OBJECT(modifier));
+        g_object_unref(G_OBJECT(modifier));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Définit une extension du module 'scan' à compléter.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool populate_scan_module_with_core_methods(void)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *module;                       /* Module à recompléter        */
+
+    static PyMethodDef py_core_methods[] = {
+        SCAN_REGISTER_TOKEN_MODIFIER_METHOD,
+        SCAN_FIND_TOKEN_MODIFIERS_FOR_NAME_METHOD,
+        { NULL }
+    };
+
+    module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+    result = register_python_module_methods(module, py_core_methods);
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/core.h b/plugins/pychrysalide/analysis/scan/core.h
new file mode 100644
index 0000000..e283f91
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/core.h
@@ -0,0 +1,39 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour l'équivalent Python du fichier "analysis/scan/core.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_CORE_CORE_H
+#define _PLUGINS_PYCHRYSALIDE_CORE_CORE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit une extension du module 'scan' à compléter. */
+bool populate_scan_module_with_core_methods(void);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_CORE_CORE_H */
diff --git a/plugins/pychrysalide/analysis/scan/module.c b/plugins/pychrysalide/analysis/scan/module.c
index d56e44a..ff19d92 100644
--- a/plugins/pychrysalide/analysis/scan/module.c
+++ b/plugins/pychrysalide/analysis/scan/module.c
@@ -29,6 +29,7 @@
 
 
 #include "context.h"
+#include "core.h"
 #include "expr.h"
 #include "item.h"
 #include "options.h"
@@ -110,6 +111,8 @@ bool populate_analysis_scan_module(void)
     if (result) result = ensure_python_scan_options_is_registered();
     if (result) result = ensure_python_scan_namespace_is_registered();
 
+    if (result) result = populate_scan_module_with_core_methods();
+
     if (result) result = populate_analysis_scan_patterns_module();
 
     assert(result);
diff --git a/plugins/pychrysalide/analysis/scan/options.c b/plugins/pychrysalide/analysis/scan/options.c
index 30c3f18..84c1784 100644
--- a/plugins/pychrysalide/analysis/scan/options.c
+++ b/plugins/pychrysalide/analysis/scan/options.c
@@ -46,6 +46,18 @@ static PyObject *py_scan_options_get_backend_for_data(PyObject *, void *);
 /* Sélectionne un type de moteur d'analyse pour données brutes. */
 static int py_scan_options_set_backend_for_data(PyObject *, PyObject *, void *);
 
+/* Impose le format JSON comme type de sortie. */
+static PyObject *py_scan_options_get_print_json(PyObject *, void *);
+
+/* Mémorise le format JSON comme type de sortie. */
+static int py_scan_options_set_print_json(PyObject *, PyObject *, void *);
+
+/* Indique un besoin d'affichage des correspondances finales. */
+static PyObject *py_scan_options_get_print_strings(PyObject *, void *);
+
+/* Mémorise un besoin d'affichage des correspondances finales. */
+static int py_scan_options_set_print_strings(PyObject *, PyObject *, void *);
+
 /* Indique un besoin de statistiques en fin de compilation. */
 static PyObject *py_scan_options_get_print_stats(PyObject *, void *);
 
@@ -161,6 +173,148 @@ static int py_scan_options_set_backend_for_data(PyObject *self, PyObject *value,
 *  Paramètres  : self    = classe représentant un format Axml.                *
 *                closure = adresse non utilisée ici.                          *
 *                                                                             *
+*  Description : Impose le format JSON comme type de sortie.                  *
+*                                                                             *
+*  Retour      : Etat de l'option visée à conservé.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_print_json(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Liste éventuelle à renvoyer */
+    GScanOptions *options;                  /* Version native              */
+    bool state;                             /* Etat courant à consulter    */
+
+#define SCAN_OPTIONS_PRINT_JSON_ATTRIB PYTHON_GETSET_DEF_FULL   \
+(                                                               \
+    print_json, py_scan_options,                                \
+    "Define if the process summary is output into a JSON"       \
+    " format at the end of the scan or not."                    \
+)
+
+    options = G_SCAN_OPTIONS(pygobject_get(self));
+
+    state = g_scan_options_get_print_json(options);
+
+    result = state ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Mémorise le format JSON comme type de sortie.                *
+*                                                                             *
+*  Retour      : Bilan de l'opération pour Python.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_scan_options_set_print_json(PyObject *self, PyObject *value, void *closure)
+{
+    bool state;                             /* Nouvel état à définir       */
+    GScanOptions *options;                  /* Version native              */
+
+    if (value != Py_True && value != Py_False)
+        return -1;
+
+    state = (value == Py_True);
+
+    options = G_SCAN_OPTIONS(pygobject_get(self));
+
+    g_scan_options_set_print_json(options, state);
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = classe représentant un format Axml.                *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Indique un besoin d'affichage des correspondances finales.   *
+*                                                                             *
+*  Retour      : Etat de l'option visée à conservé.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_print_strings(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Liste éventuelle à renvoyer */
+    GScanOptions *options;                  /* Version native              */
+    bool state;                             /* Etat courant à consulter    */
+
+#define SCAN_OPTIONS_PRINT_STRINGS_ATTRIB PYTHON_GETSET_DEF_FULL    \
+(                                                                   \
+    print_strings, py_scan_options,                                 \
+    "Define if the matching patterns are printed with found"        \
+    " offset at the end of the scan or not."                        \
+)
+
+    options = G_SCAN_OPTIONS(pygobject_get(self));
+
+    state = g_scan_options_get_print_strings(options);
+
+    result = state ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Mémorise un besoin d'affichage des correspondances finales.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération pour Python.                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_scan_options_set_print_strings(PyObject *self, PyObject *value, void *closure)
+{
+    bool state;                             /* Nouvel état à définir       */
+    GScanOptions *options;                  /* Version native              */
+
+    if (value != Py_True && value != Py_False)
+        return -1;
+
+    state = (value == Py_True);
+
+    options = G_SCAN_OPTIONS(pygobject_get(self));
+
+    g_scan_options_set_print_strings(options, state);
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = classe représentant un format Axml.                *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
 *  Description : Indique un besoin de statistiques en fin de compilation.     *
 *                                                                             *
 *  Retour      : Etat de l'option visée à conservé.                           *
@@ -246,6 +400,8 @@ PyTypeObject *get_python_scan_options_type(void)
 
     static PyGetSetDef py_scan_options_getseters[] = {
         SCAN_OPTIONS_BACKEND_FOR_DATA_ATTRIB,
+        SCAN_OPTIONS_PRINT_JSON_ATTRIB,
+        SCAN_OPTIONS_PRINT_STRINGS_ATTRIB,
         SCAN_OPTIONS_PRINT_STATS_ATTRIB,
         { NULL }
     };
diff --git a/plugins/pychrysalide/analysis/scan/patterns/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/Makefile.am
index 612f34b..dd26fa5 100644
--- a/plugins/pychrysalide/analysis/scan/patterns/Makefile.am
+++ b/plugins/pychrysalide/analysis/scan/patterns/Makefile.am
@@ -3,13 +3,15 @@ noinst_LTLIBRARIES = libpychrysaanalysisscanpatterns.la
 
 libpychrysaanalysisscanpatterns_la_SOURCES = \
 	backend.h backend.c						\
+	modifier.h modifier.c					\
 	module.h module.c
 
 libpychrysaanalysisscanpatterns_la_LIBADD = \
-	backends/libpychrysaanalysisscanpatternsbackends.la
+	backends/libpychrysaanalysisscanpatternsbackends.la \
+	modifiers/libpychrysaanalysisscanpatternsmodifiers.la
 
-libpychrysaanalysisscanpatterns_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
-	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+libpychrysaanalysisscanpatterns_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+    $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
 
 
 devdir = $(includedir)/chrysalide/$(subdir)
@@ -17,4 +19,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
 dev_HEADERS = $(libpychrysaanalysisscanpatterns_la_SOURCES:%c=)
 
 
-SUBDIRS = backends
+SUBDIRS = backends modifiers
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifier.c b/plugins/pychrysalide/analysis/scan/patterns/modifier.c
new file mode 100644
index 0000000..4cae011
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifier.c
@@ -0,0 +1,324 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier.c - équivalent Python du fichier "analysis/scan/modifier.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "modifier.h"
+
+
+#include <pygobject.h>
+
+
+#include <analysis/scan/patterns/modifier-int.h>
+
+
+#include "../../../access.h"
+#include "../../../helpers.h"
+
+
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_token_modifier, G_TYPE_SCAN_TOKEN_MODIFIER, NULL);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_token_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_scan_token_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int ret;                                /* Bilan de lecture des args.  */
+
+#define SCAN_TOKEN_MODIFIER_DOC                                     \
+    "An *TokenModifier* object is the root class of all modifiers"  \
+    " for byte patterns."
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = tampon de données à consulter.                        *
+*                args = arguments fournis pour la conduite de l'opération.    *
+*                                                                             *
+*  Description : Transforme une séquence d'octets pour motif de recherche.    *
+*                                                                             *
+*  Retour      : Liste des nouvelle(s) séquence(s) d'octets obtenue(s).       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_token_modifier_transform(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à faire remonter      */
+    const char *data;                       /* Séquence d'octets à traiter */
+    Py_ssize_t len;                         /* Quantité de ces données     */
+    int ret;                                /* Bilan de lecture des args.  */
+    sized_binary_t src;                     /* Entrée au format adapté     */
+    GScanTokenModifier *modifier;           /* Version native de l'instance*/
+    sized_binary_t *dest;                   /* Liste des nouvelles chaînes */
+    size_t count;                           /* Taille de cette liste       */
+    bool status;                            /* Bilan de l'opération        */
+    size_t i;                               /* Boucle de parcours          */
+
+#define SCAN_TOKEN_MODIFIER_TRANSFORM_METHOD PYTHON_METHOD_DEF      \
+(                                                                   \
+    transform, "$self, data",                                       \
+    METH_VARARGS, py_scan_token_modifier,                           \
+    "Transform data from a byte pattern for an incoming scan.\n"    \
+    "\n"                                                            \
+    "The data has to be provided as bytes.\n"                       \
+    "\n"                                                            \
+    "The method returns a tuple of transformed data as bytes, or"   \
+    " *None* in case of error."                                     \
+)
+
+    ret = PyArg_ParseTuple(args, "s#", &data, &len);
+    if (!ret) return NULL;
+
+    src.data = (char *)data;
+    src.len = len;
+
+    modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(self));
+
+    status = g_scan_token_modifier_transform(modifier, &src, &dest, &count);
+
+    if (status)
+    {
+        result = PyTuple_New(count);
+
+        for (i = 0; i < count; i++)
+        {
+            PyTuple_SetItem(result, i, PyBytes_FromStringAndSize(dest[i].data, dest[i].len));
+            exit_szstr(&dest[i]);
+        }
+
+        free(dest);
+
+    }
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = classe représentant un composant nommé à manipuler.*
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit le désignation associée à un composant nommé.        *
+*                                                                             *
+*  Retour      : Description courante.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_token_modifier_get_name(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Décompte à retourner        */
+    GScanTokenModifier *modifier;           /* Version native              */
+    char *name;                             /* Désignation à convertir     */
+
+#define SCAN_TOKEN_MODIFIER_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+(                                                           \
+    name, py_scan_token_modifier,                           \
+    "Call name for the modifier.\n"                         \
+    "\n"                                                    \
+    "The result is a string."                               \
+)
+
+    modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(self));
+
+    name = g_scan_token_modifier_get_name(modifier);
+
+    if (name == NULL)
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+    else
+    {
+        result = PyUnicode_FromString(name);
+        free(name);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_token_modifier_type(void)
+{
+    static PyMethodDef py_scan_token_modifier_methods[] = {
+        SCAN_TOKEN_MODIFIER_TRANSFORM_METHOD,
+        { NULL }
+    };
+
+    static PyGetSetDef py_scan_token_modifier_getseters[] = {
+        SCAN_TOKEN_MODIFIER_NAME_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_scan_token_modifier_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.analysis.scan.patterns.TokenModifier",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = SCAN_TOKEN_MODIFIER_DOC,
+
+        .tp_methods     = py_scan_token_modifier_methods,
+        .tp_getset      = py_scan_token_modifier_getseters,
+
+        .tp_init        = py_scan_token_modifier_init,
+        .tp_new         = py_scan_token_modifier_new,
+
+    };
+
+    return &py_scan_token_modifier_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....TokenModifier'.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_scan_token_modifier_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'TokenModifier' */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_scan_token_modifier_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+        dict = PyModule_GetDict(module);
+
+        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_TOKEN_MODIFIER, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en transformation de séquence d'octets.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_scan_token_modifier(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_token_modifier_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to token modifier");
+            break;
+
+        case 1:
+            *((GScanTokenModifier **)dst) = G_SCAN_TOKEN_MODIFIER(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifier.h b/plugins/pychrysalide/analysis/scan/patterns/modifier.h
new file mode 100644
index 0000000..770b2c1
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifier.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier.h - prototypes pour l'équivalent Python du fichier "analysis/scan/modifier.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_token_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.TokenModifier'. */
+bool ensure_python_scan_token_modifier_is_registered(void);
+
+/* Tente de convertir en transformation de séquence d'octets. */
+int convert_to_scan_token_modifier(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am
new file mode 100644
index 0000000..baf7ed5
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am
@@ -0,0 +1,17 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanpatternsmodifiers.la
+
+libpychrysaanalysisscanpatternsmodifiers_la_SOURCES = \
+	hex.h hex.c								\
+	list.h list.c							\
+	module.h module.c						\
+	plain.h plain.c							\
+	rev.h rev.c
+
+libpychrysaanalysisscanpatternsmodifiers_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
+	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanpatternsmodifiers_la_SOURCES:%c=)
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c
new file mode 100644
index 0000000..d0d1e1f
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "hex.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/hex.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_hex_modifier, G_TYPE_SCAN_HEX_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_hex_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_scan_hex_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int ret;                                /* Bilan de lecture des args.  */
+
+#define SCAN_HEX_MODIFIER_DOC                                               \
+    "The *HexModifier* class transforms a byte pattern into its"            \
+    " corresponding byte sequence in lower case."                           \
+    "\n"                                                                    \
+    "Instances can be created using the following constructor:\n"           \
+    "\n"                                                                    \
+    "    HexModifier()"
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_hex_modifier_type(void)
+{
+    static PyMethodDef py_scan_hex_modifier_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_scan_hex_modifier_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_scan_hex_modifier_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.analysis.scan.patterns.modifiers.HexModifier",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = SCAN_HEX_MODIFIER_DOC,
+
+        .tp_methods     = py_scan_hex_modifier_methods,
+        .tp_getset      = py_scan_hex_modifier_getseters,
+
+        .tp_init        = py_scan_hex_modifier_init,
+        .tp_new         = py_scan_hex_modifier_new,
+
+    };
+
+    return &py_scan_hex_modifier_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....HexModifier'.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_scan_hex_modifier_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'HexModifier' */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_scan_hex_modifier_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_scan_token_modifier_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_HEX_MODIFIER, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en transmission d'octets à l'identique.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_scan_hex_modifier(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_hex_modifier_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to hex modifier");
+            break;
+
+        case 1:
+            *((GScanHexModifier **)dst) = G_SCAN_HEX_MODIFIER(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h
new file mode 100644
index 0000000..5d70a01
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_hex_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.HexModifier'. */
+bool ensure_python_scan_hex_modifier_is_registered(void);
+
+/* Tente de convertir en transmission d'octets à l'identique. */
+int convert_to_scan_hex_modifier(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c
new file mode 100644
index 0000000..7c77d63
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c
@@ -0,0 +1,320 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/list.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "list.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/list.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_modifier_list, G_TYPE_SCAN_MODIFIER_LIST);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_modifier_list_init(PyObject *, PyObject *, PyObject *);
+
+/* Intègre un nouveau transformateur dans une liste. */
+static PyObject *py_scan_modifier_list_add(PyObject *, PyObject *);
+
+/* Fournit les transformateurs associés à la liste. */
+static PyObject *py_scan_modifier_list_get_modifiers(PyObject *, void *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_scan_modifier_list_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int ret;                                /* Bilan de lecture des args.  */
+
+#define SCAN_MODIFIER_LIST_DOC                                              \
+    "The *ModifierList* class is a special modifier which groups a list of" \
+    " modifiers for byte patterns."                                         \
+    "\n"                                                                    \
+    "Instances can be created using the following constructor:\n"           \
+    "\n"                                                                    \
+    "    ModifierList()"                                                    \
+    "\n"                                                                    \
+    "The keyword for such a modifier is *(list)*."
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = projet d'étude à manipuler.                           *
+*                args = arguments accompagnant l'appel.                       *
+*                                                                             *
+*  Description : Intègre un nouveau transformateur dans une liste.            *
+*                                                                             *
+*  Retour      : Bilan de l'ajout : False si un élément similaire est déjà là.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_modifier_list_add(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Absence de retour Python    */
+    GScanTokenModifier *modifier;           /* Modificateur à intégrer     */
+    int ret;                                /* Bilan de lecture des args.  */
+    GScanModifierList *list;                /* Version GLib du type        */
+    bool status;                            /* Bilan de l'opération        */
+
+#define SCAN_MODIFIER_LIST_ADD_METHOD PYTHON_METHOD_DEF                     \
+(                                                                           \
+    add, "$self, modifier, /",                                              \
+    METH_VARARGS, py_scan_modifier_list,                                    \
+    "Add an extra modifier to the list.\n"                                  \
+    "\n"                                                                    \
+    "This *modifier* parameter has to be a"                                 \
+    " pychrysalide.analysis.scan.patterns.TokenModifier instance."          \
+    "\n"                                                                    \
+    "The function returns *True* if the provided modifier did not already"  \
+    " exist in the list, *False* otherwise."                                \
+)
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_scan_token_modifier, &modifier);
+    if (!ret) return NULL;
+
+    list = G_SCAN_MODIFIER_LIST(pygobject_get(self));
+
+    status = g_scan_modifier_list_add(list, modifier);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit les transformateurs associés à la liste.             *
+*                                                                             *
+*  Retour      : Liste de modificateurs de séquence d'octets.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_modifier_list_get_modifiers(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Résultat à retourner        */
+    GScanModifierList *list;                /* Version GLib du type        */
+    size_t count;                           /* Nombre de transformateurs   */
+    size_t i;                               /* Boucle de parcours          */
+    GScanTokenModifier *modifier;           /* Modificateur de la liste    */
+
+#define SCAN_MODIFIER_LIST_MODIFIERS_ATTRIB PYTHON_GET_DEF_FULL                             \
+(                                                                                           \
+    modifiers, py_scan_modifier_list,                                                       \
+    "List of all modifiers contained in a list.\n"                                          \
+    "\n"                                                                                    \
+    "The returned value is a tuple of pychrysalide.analysis.scan.patterns.TokenModifier"    \
+    " instances."                                                                           \
+)
+
+    list = G_SCAN_MODIFIER_LIST(pygobject_get(self));
+
+    count = g_scan_modifier_list_count(list);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+    {
+        modifier = g_scan_modifier_list_get(list, i);
+
+        PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(modifier)));
+
+        g_object_unref(modifier);
+
+    }
+
+    return result;
+
+}
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_modifier_list_type(void)
+{
+    static PyMethodDef py_scan_modifier_list_methods[] = {
+        SCAN_MODIFIER_LIST_ADD_METHOD,
+        { NULL }
+    };
+
+    static PyGetSetDef py_scan_modifier_list_getseters[] = {
+        SCAN_MODIFIER_LIST_MODIFIERS_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_scan_modifier_list_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.analysis.scan.patterns.modifiers.ModifierList",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = SCAN_MODIFIER_LIST_DOC,
+
+        .tp_methods     = py_scan_modifier_list_methods,
+        .tp_getset      = py_scan_modifier_list_getseters,
+
+        .tp_init        = py_scan_modifier_list_init,
+        .tp_new         = py_scan_modifier_list_new,
+
+    };
+
+    return &py_scan_modifier_list_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....ModifierList'.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_scan_modifier_list_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'ModifierList'  */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_scan_modifier_list_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_scan_token_modifier_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_MODIFIER_LIST, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en liste de transormations d'octets.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_scan_modifier_list(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_modifier_list_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to modifier list");
+            break;
+
+        case 1:
+            *((GScanModifierList **)dst) = G_SCAN_MODIFIER_LIST(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h
new file mode 100644
index 0000000..133de8d
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/list.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_modifier_list_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.ModifierList'. */
+bool ensure_python_scan_modifier_list_is_registered(void);
+
+/* Tente de convertir en liste de transormations d'octets. */
+int convert_to_scan_modifier_list(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c
new file mode 100644
index 0000000..1e9bda7
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c
@@ -0,0 +1,110 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire modifiers en tant que module
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+
+
+#include "hex.h"
+#include "list.h"
+#include "plain.h"
+#include "rev.h"
+#include "../../../../helpers.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : super = module dont la définition est à compléter.           *
+*                                                                             *
+*  Description : Ajoute le module 'analysis....modifiers' à un module Python. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool add_analysis_scan_patterns_modifiers_module(PyObject *super)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *module;                       /* Sous-module mis en place    */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_DOC    \
+    "This module provide all the features useful for scanning"      \
+    " binary contents."
+
+    static PyModuleDef py_chrysalide_analysis_scan_patterns_modifiers_module = {
+
+        .m_base = PyModuleDef_HEAD_INIT,
+
+        .m_name = "pychrysalide.analysis.scan.patterns.modifiers",
+        .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_DOC,
+
+        .m_size = -1,
+
+    };
+
+    module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_modifiers_module);
+
+    result = (module != NULL);
+
+    if (!result)
+        Py_XDECREF(module);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Intègre les objets du module 'analysis...patterns.modifiers'.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool populate_analysis_scan_patterns_modifiers_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    if (result) result = ensure_python_scan_hex_modifier_is_registered();
+    if (result) result = ensure_python_scan_modifier_list_is_registered();
+    if (result) result = ensure_python_scan_plain_modifier_is_registered();
+    if (result) result = ensure_python_scan_reverse_modifier_is_registered();
+
+    assert(result);
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h
new file mode 100644
index 0000000..8094efc
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire modifiers en tant que module
+ *
+ * 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.patterns.modifiers' à un module Python. */
+bool add_analysis_scan_patterns_modifiers_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.patterns.modifiers'. */
+bool populate_analysis_scan_patterns_modifiers_module(void);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c
new file mode 100644
index 0000000..7a260c1
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/plain.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "plain.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/plain.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_plain_modifier, G_TYPE_SCAN_PLAIN_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_plain_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_scan_plain_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int ret;                                /* Bilan de lecture des args.  */
+
+#define SCAN_PLAIN_MODIFIER_DOC                                             \
+    "The *PlainModifier* class provide an transmision of a byte pattern"    \
+    " without any modification."                                            \
+    "\n"                                                                    \
+    "Instances can be created using the following constructor:\n"           \
+    "\n"                                                                    \
+    "    PlainModifier()"
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_plain_modifier_type(void)
+{
+    static PyMethodDef py_scan_plain_modifier_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_scan_plain_modifier_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_scan_plain_modifier_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.analysis.scan.patterns.modifiers.PlainModifier",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = SCAN_PLAIN_MODIFIER_DOC,
+
+        .tp_methods     = py_scan_plain_modifier_methods,
+        .tp_getset      = py_scan_plain_modifier_getseters,
+
+        .tp_init        = py_scan_plain_modifier_init,
+        .tp_new         = py_scan_plain_modifier_new,
+
+    };
+
+    return &py_scan_plain_modifier_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....PlainModifier'.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_scan_plain_modifier_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'PlainModifier' */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_scan_plain_modifier_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_scan_token_modifier_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_PLAIN_MODIFIER, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en transmission d'octets à l'identique.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_scan_plain_modifier(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_plain_modifier_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to plain modifier");
+            break;
+
+        case 1:
+            *((GScanPlainModifier **)dst) = G_SCAN_PLAIN_MODIFIER(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h
new file mode 100644
index 0000000..03949d8
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/plain.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_plain_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.PlainModifier'. */
+bool ensure_python_scan_plain_modifier_is_registered(void);
+
+/* Tente de convertir en transmission d'octets à l'identique. */
+int convert_to_scan_plain_modifier(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c
new file mode 100644
index 0000000..6ee350c
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "rev.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/modifiers/rev.h>
+
+
+#include "../modifier.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_reverse_modifier, G_TYPE_SCAN_REVERSE_MODIFIER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_reverse_modifier_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_scan_reverse_modifier_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    int ret;                                /* Bilan de lecture des args.  */
+
+#define SCAN_HEX_MODIFIER_DOC                                               \
+    "The *ReverseModifier* class transforms a byte pattern by reversing"    \
+    " the order of each bytes."                                             \
+    "\n"                                                                    \
+    "Instances can be created using the following constructor:\n"           \
+    "\n"                                                                    \
+    "    ReverseModifier()"
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_reverse_modifier_type(void)
+{
+    static PyMethodDef py_scan_reverse_modifier_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_scan_reverse_modifier_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_scan_reverse_modifier_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.analysis.scan.patterns.modifiers.ReverseModifier",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = SCAN_HEX_MODIFIER_DOC,
+
+        .tp_methods     = py_scan_reverse_modifier_methods,
+        .tp_getset      = py_scan_reverse_modifier_getseters,
+
+        .tp_init        = py_scan_reverse_modifier_init,
+        .tp_new         = py_scan_reverse_modifier_new,
+
+    };
+
+    return &py_scan_reverse_modifier_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....ReverseModifier'.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_scan_reverse_modifier_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'HexModifier' */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_scan_reverse_modifier_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_scan_token_modifier_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_REVERSE_MODIFIER, type))
+            return false;
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en transformation d'octets par inverse.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_scan_reverse_modifier(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_reverse_modifier_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to reverse modifier");
+            break;
+
+        case 1:
+            *((GScanReverseModifier **)dst) = G_SCAN_REVERSE_MODIFIER(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h
new file mode 100644
index 0000000..fe10e1e
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rev.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/rev.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_reverse_modifier_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.ReverseModifier'. */
+bool ensure_python_scan_reverse_modifier_is_registered(void);
+
+/* Tente de convertir en transformation d'octets par inverse. */
+int convert_to_scan_reverse_modifier(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/module.c b/plugins/pychrysalide/analysis/scan/patterns/module.c
index f8db49e..123b23a 100644
--- a/plugins/pychrysalide/analysis/scan/patterns/module.c
+++ b/plugins/pychrysalide/analysis/scan/patterns/module.c
@@ -29,7 +29,9 @@
 
 
 #include "backend.h"
+#include "modifier.h"
 #include "backends/module.h"
+#include "modifiers/module.h"
 #include "../../../helpers.h"
 
 
@@ -71,6 +73,7 @@ bool add_analysis_scan_patterns_module(PyObject *super)
     result = (module != NULL);
 
     if (result) result = add_analysis_scan_patterns_backends_module(module);
+    if (result) result = add_analysis_scan_patterns_modifiers_module(module);
 
     if (!result)
         Py_XDECREF(module);
@@ -99,8 +102,10 @@ bool populate_analysis_scan_patterns_module(void)
     result = true;
 
     if (result) result = ensure_python_engine_backend_is_registered();
+    if (result) result = ensure_python_scan_token_modifier_is_registered();
 
     if (result) result = populate_analysis_scan_patterns_backends_module();
+    if (result) result = populate_analysis_scan_patterns_modifiers_module();
 
     assert(result);
 
diff --git a/src/analysis/scan/context-int.h b/src/analysis/scan/context-int.h
index 3a971b8..8a5fbaf 100644
--- a/src/analysis/scan/context-int.h
+++ b/src/analysis/scan/context-int.h
@@ -74,6 +74,7 @@ struct _GScanContext
     GScanOptions *options;                  /* Options d'analyses          */
 
     GBinContent *content;                   /* Contenu binaire traité      */
+    bool scan_done;                         /* Phase d'analyse terminée ?  */
 
     patid_t next_patid;                     /* Prochain indice utilisable  */
 
diff --git a/src/analysis/scan/context.c b/src/analysis/scan/context.c
index f108e93..a3be86b 100644
--- a/src/analysis/scan/context.c
+++ b/src/analysis/scan/context.c
@@ -55,7 +55,7 @@ static void add_match_to_full_match_tracker(full_match_tracker_t *, GScanMatch *
 
 
 
-
+/* --------------------- MEMORISATION DE PROGRESSIONS D'ANALYSE --------------------- */
 
 
 /* Initialise la classe des contextes de suivi d'analyses. */
@@ -72,10 +72,6 @@ static void g_scan_context_finalize(GScanContext *);
 
 
 
-
-
-
-
 /* ---------------------------------------------------------------------------------- */
 /*                     ADMINISTRATION DES CORRESPONDANCES TOTALES                     */
 /* ---------------------------------------------------------------------------------- */
@@ -191,10 +187,9 @@ static void add_match_to_full_match_tracker(full_match_tracker_t *tracker, GScan
 
 
 
-
-
-
-
+/* ---------------------------------------------------------------------------------- */
+/*                       MEMORISATION DE PROGRESSIONS D'ANALYSE                       */
+/* ---------------------------------------------------------------------------------- */
 
 
 /* Indique le type défini pour un contexte de suivi d'analyse. */
@@ -242,6 +237,7 @@ static void g_scan_context_init(GScanContext *context)
     context->options = NULL;
 
     context->content = NULL;
+    context->scan_done = false;
 
     context->next_patid = 0;
 
@@ -378,7 +374,7 @@ GScanContext *g_scan_context_new(GScanOptions *options)
 *                                                                             *
 ******************************************************************************/
 
-GScanOptions *g_scan_context_get_options(GScanContext *context)
+GScanOptions *g_scan_context_get_options(const GScanContext *context)
 {
     GScanOptions *result;                   /* Ensemble à retourner        */
 
@@ -467,6 +463,48 @@ GBinContent *g_scan_context_get_content(const GScanContext *context)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : context = instance à consulter.                              *
+*                                                                             *
+*  Description : Indique si la phase d'analyse de contenu est terminée.       *
+*                                                                             *
+*  Retour      : true si la phase de scan est terminée, false sinon.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_context_is_scan_done(const GScanContext *context)
+{
+    bool result;                            /* Statut à retourner          */
+
+    result = context->scan_done;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : context = instance à mettre à jour.                          *
+*                                                                             *
+*  Description : Note que la phase d'analyse de contenu est terminée.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_context_mark_scan_as_done(GScanContext *context)
+{
+    context->scan_done = true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : context = instance à mettre à jour.                          *
 *                id      = identifiant du motif trouvé.                       *
 *                offset  = localisation du motif au sein d'un contenu.        *
@@ -615,41 +653,6 @@ const GScanMatch **g_scan_context_get_full_matches(const GScanContext *context,
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : context = mémoire de résultats d'analyse à consulter.        *
-*                                                                             *
-*  Description : Affiche les correspondances identifiées.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-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);
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : context = mémoire de résultats d'analyse à compléter.        *
 *                name    = désignation de la règle ciblée.                    *
 *                expr    = expression de condition à réduire.                 *
diff --git a/src/analysis/scan/context.h b/src/analysis/scan/context.h
index 563a53e..ff6b373 100644
--- a/src/analysis/scan/context.h
+++ b/src/analysis/scan/context.h
@@ -66,7 +66,7 @@ GType g_scan_context_get_type(void);
 GScanContext *g_scan_context_new(GScanOptions *);
 
 /* Fournit l'ensemble des options à respecter pour les analyses. */
-GScanOptions *g_scan_context_get_options(GScanContext *);
+GScanOptions *g_scan_context_get_options(const GScanContext *);
 
 /* Fournit un identifiant unique pour un motif recherché. */
 patid_t g_scan_context_get_new_pattern_id(GScanContext *);
@@ -77,6 +77,12 @@ void g_scan_context_set_content(GScanContext *, GBinContent *);
 /* Fournit une référence au contenu principal analysé. */
 GBinContent *g_scan_context_get_content(const GScanContext *);
 
+/* Indique si la phase d'analyse de contenu est terminée. */
+bool g_scan_context_is_scan_done(const GScanContext *);
+
+/* Note que la phase d'analyse de contenu est terminée. */
+void g_scan_context_mark_scan_as_done(GScanContext *);
+
 /* Enregistre une correspondance partielle dans un contenu. */
 void g_scan_context_register_atom_match(GScanContext *, patid_t, phys_t);
 
@@ -89,9 +95,6 @@ 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(GScanContext *);
-
 /* Intègre une condition de correspondance pour règle. */
 bool g_scan_context_set_rule_condition(GScanContext *, const char *, const GScanExpression *);
 
diff --git a/src/analysis/scan/core.c b/src/analysis/scan/core.c
index d940ab5..d102d58 100644
--- a/src/analysis/scan/core.c
+++ b/src/analysis/scan/core.c
@@ -25,6 +25,8 @@
 
 
 #include <config.h>
+#include <malloc.h>
+#include <string.h>
 
 
 #include "items/count.h"
@@ -38,8 +40,168 @@
 #endif
 #include "items/time/make.h"
 #include "items/time/now.h"
+#include "patterns/modifiers/hex.h"
+#include "patterns/modifiers/plain.h"
+#include "patterns/modifiers/rev.h"
 
 
+/* Liste des modificateurs disponibles */
+
+typedef struct _available_modifier_t
+{
+    char *name;                             /* Désignation humaine         */
+    GScanTokenModifier *instance;           /* Mécanisme correspondant     */
+
+} available_modifier_t;
+
+static available_modifier_t *__modifiers = NULL;
+static size_t __modifiers_count = 0;
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à rendre disponible.                 *
+*                                                                             *
+*  Description : Inscrit un modificateur dans la liste des disponibles.       *
+*                                                                             *
+*  Retour      : Bilan des enregistrements effectués : true si nouveauté.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_scan_token_modifier(GScanTokenModifier *modifier)
+{
+    bool result;                            /* Bilan à retourner           */
+    char *name;                             /* Nom donné au modificateur   */
+    GScanTokenModifier *found;              /* Alternative présente        */
+    available_modifier_t *last;             /* Emplacement disponible      */
+
+    name = g_scan_token_modifier_get_name(modifier);
+
+    found = find_scan_token_modifiers_for_name(name);
+
+    result = (found == NULL);
+
+    if (!result)
+        free(name);
+
+    else
+    {
+        __modifiers_count++;
+        __modifiers = realloc(__modifiers, __modifiers_count * sizeof(available_modifier_t));
+
+        last = &__modifiers[__modifiers_count - 1];
+
+        last->name = name;
+        last->instance = modifier;
+
+        g_object_ref(G_OBJECT(modifier));
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Charge tous les modificateurs de base.                       *
+*                                                                             *
+*  Retour      : Bilan des opérations d'enregistrement.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool load_all_known_scan_token_modifiers(void)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+#define REGISTER_SCAN_MODIFIER(m)                   \
+    ({                                              \
+        bool __status;                              \
+        __status = register_scan_token_modifier(m); \
+        g_object_unref(G_OBJECT(m));                \
+        __status;                                   \
+    })
+
+    if (result) result = REGISTER_SCAN_MODIFIER(g_scan_hex_modifier_new());
+    if (result) result = REGISTER_SCAN_MODIFIER(g_scan_plain_modifier_new());
+    if (result) result = REGISTER_SCAN_MODIFIER(g_scan_reverse_modifier_new());
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Décharge tous les modificateurs inscrits.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void unload_all_scan_token_modifiers(void)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < __modifiers_count; i++)
+        g_object_unref(G_OBJECT(__modifiers[i].instance));
+
+    if (__modifiers != NULL)
+        free(__modifiers);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : name = désignation du modificateur recherché.                *
+*                                                                             *
+*  Description : Fournit le modificateur correspondant à un nom.              *
+*                                                                             *
+*  Retour      : Instance du modificateur identifié ou NULL.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanTokenModifier *find_scan_token_modifiers_for_name(const char *name)
+{
+    GScanTokenModifier *result;             /* Instance à renvoyer         */
+    size_t i;                               /* Boucle de parcours          */
+    available_modifier_t *registered;       /* Infos d'enregistrement      */
+
+    result = NULL;
+
+    for (i = 0; i < __modifiers_count; i++)
+    {
+        registered = __modifiers + i;
+
+        if (strcmp(registered->name, name) == 0)
+        {
+            result = registered->instance;
+            g_object_ref(G_OBJECT(result));
+            break;
+        }
+
+    }
+
+    return result;
+
+}
+
 
 /******************************************************************************
 *                                                                             *
diff --git a/src/analysis/scan/core.h b/src/analysis/scan/core.h
index 21d6e7c..86a47da 100644
--- a/src/analysis/scan/core.h
+++ b/src/analysis/scan/core.h
@@ -26,9 +26,22 @@
 
 
 #include "space.h"
+#include "patterns/modifier.h"
 
 
 
+/* Inscrit un modificateur dans la liste des disponibles. */
+bool register_scan_token_modifier(GScanTokenModifier *);
+
+/* Charge tous les modificateurs de base. */
+bool load_all_known_scan_token_modifiers(void);
+
+/* Décharge tous les modificateurs inscrits. */
+void unload_all_scan_token_modifiers(void);
+
+/* Fournit le modificateur correspondant à un nom. */
+GScanTokenModifier *find_scan_token_modifiers_for_name(const char *);
+
 /* Inscrit les principales fonctions dans l'espace racine. */
 bool populate_main_scan_namespace(GScanNamespace *);
 
diff --git a/src/analysis/scan/expr-int.h b/src/analysis/scan/expr-int.h
index 48668b5..30a32d0 100644
--- a/src/analysis/scan/expr-int.h
+++ b/src/analysis/scan/expr-int.h
@@ -54,10 +54,10 @@ typedef ScanReductionState (* reduce_expr_fc) (GScanExpression *, GScanContext *
 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 *);
+typedef bool (* count_scan_expr_fc) (const GScanExpression *, GScanContext *, size_t *);
 
 /* Fournit un élément donné issu d'un ensemble constitué. */
-typedef bool (* get_scan_expr_fc) (const GScanExpression *, size_t, GScanExpression **);
+typedef bool (* get_scan_expr_fc) (const GScanExpression *, size_t, GScanContext *, GScanExpression **);
 
 /* Réalise l'intersection entre deux ensembles. */
 typedef GScanExpression * (* intersect_scan_expr_fc) (GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *);
diff --git a/src/analysis/scan/expr.c b/src/analysis/scan/expr.c
index 808b14f..2b00544 100644
--- a/src/analysis/scan/expr.c
+++ b/src/analysis/scan/expr.c
@@ -466,6 +466,7 @@ bool g_scan_expression_handle_set_features(const GScanExpression *expr)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
 *                count = quantité d'éléments déterminée. [OUT]                *
 *                                                                             *
 *  Description : Dénombre les éléments portés par une expression.             *
@@ -476,7 +477,7 @@ bool g_scan_expression_handle_set_features(const GScanExpression *expr)
 *                                                                             *
 ******************************************************************************/
 
-bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count)
+bool g_scan_expression_count_items(const GScanExpression *expr, GScanContext *ctx, size_t *count)
 {
     bool result;                            /* Bilan à retourner           */
     GScanExpressionClass *class;            /* Classe à activer            */
@@ -486,7 +487,7 @@ bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count)
     class = G_SCAN_EXPRESSION_GET_CLASS(expr);
 
     if (class->count != NULL)
-        result = class->count(expr, count);
+        result = class->count(expr, ctx, count);
     else
         result = false;
 
@@ -504,6 +505,7 @@ bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count)
 *                                                                             *
 *  Paramètres  : expr  = expression à consulter.                              *
 *                index = indice de l'élément à transférer.                    *
+*                ctx   = contexte de suivi de l'analyse courante.             *
 *                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
 *                                                                             *
 *  Description : Fournit un élément donné issu d'un ensemble constitué.       *
@@ -514,7 +516,7 @@ bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count)
 *                                                                             *
 ******************************************************************************/
 
-bool g_scan_expression_get_item(const GScanExpression *expr, size_t index, GScanExpression **out)
+bool g_scan_expression_get_item(const GScanExpression *expr, size_t index, GScanContext *ctx, GScanExpression **out)
 {
     bool result;                            /* Bilan à retourner           */
     GScanExpressionClass *class;            /* Classe à activer            */
@@ -525,7 +527,7 @@ bool g_scan_expression_get_item(const GScanExpression *expr, size_t index, GScan
 
     if (class->get != NULL)
     {
-        result = class->get(expr, index, out);
+        result = class->get(expr, index, ctx, out);
 
         if (*out != NULL)
             g_object_ref(G_OBJECT(*out));
@@ -574,27 +576,27 @@ static GScanExpression *_g_scan_expression_intersect(GScanExpression *expr, cons
 
     result = NULL;
 
-    valid = g_scan_expression_count_items(other, &other_count);
+    valid = g_scan_expression_count_items(other, ctx, &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);
+        valid = g_scan_expression_count_items(expr, ctx, &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);
+            valid = g_scan_expression_get_item(expr, k, ctx, &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);
+                valid = g_scan_expression_get_item(other, i, ctx, &item);
                 if (!valid) break;
 
                 valid = g_comparable_item_compare_rich(comparable, G_COMPARABLE_ITEM(item), RCO_EQ, &status);
@@ -619,7 +621,7 @@ static GScanExpression *_g_scan_expression_intersect(GScanExpression *expr, cons
 
         for (i = 0; i < other_count && result == NULL; i++)
         {
-            valid = g_scan_expression_get_item(other, i, &item);
+            valid = g_scan_expression_get_item(other, i, ctx, &item);
             if (!valid) break;
 
             valid = g_comparable_item_compare_rich(comparable, G_COMPARABLE_ITEM(item), RCO_EQ, &status);
diff --git a/src/analysis/scan/expr.h b/src/analysis/scan/expr.h
index dd4bc3f..797abec 100644
--- a/src/analysis/scan/expr.h
+++ b/src/analysis/scan/expr.h
@@ -50,7 +50,7 @@ typedef struct _GScanExpressionClass GScanExpressionClass;
 
 
 /* Types naturel équivalant à l'expression */
-typedef enum _ExprValueType
+typedef enum _ExprValueType /* REMME */
 {
     EVT_BOOLEAN,                            /* Valeur booléenne            */
     EVT_INTEGER,                            /* Nombre entier 64 bits       */
@@ -97,10 +97,10 @@ bool g_scan_expression_reduce_to_boolean(GScanExpression *, GScanContext *, GSca
 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 *);
+bool g_scan_expression_count_items(const GScanExpression *, GScanContext *, size_t *);
 
 /* Fournit un élément donné issu d'un ensemble constitué. */
-bool g_scan_expression_get_item(const GScanExpression *, size_t, GScanExpression **);
+bool g_scan_expression_get_item(const GScanExpression *, size_t, GScanContext *, 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 1266a63..d1a122a 100644
--- a/src/analysis/scan/exprs/Makefile.am
+++ b/src/analysis/scan/exprs/Makefile.am
@@ -11,8 +11,12 @@ libanalysisscanexprs_la_SOURCES =			\
 	call.h call.c							\
 	counter-int.h							\
 	counter.h counter.c						\
+	handler-int.h							\
+	handler.h handler.c						\
 	intersect-int.h							\
 	intersect.h intersect.c					\
+	item-int.h								\
+	item.h item.c							\
 	literal-int.h							\
 	literal.h literal.c						\
 	logical-int.h							\
diff --git a/src/analysis/scan/exprs/counter.c b/src/analysis/scan/exprs/counter.c
index 290fd02..bb4e523 100644
--- a/src/analysis/scan/exprs/counter.c
+++ b/src/analysis/scan/exprs/counter.c
@@ -50,7 +50,7 @@ static void g_scan_match_counter_finalize(GScanMatchCounter *);
 
 
 /* Réduit une expression à une forme plus simple. */
-static bool g_scan_match_counter_reduce(GScanMatchCounter *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_match_counter_reduce(GScanMatchCounter *, GScanContext *, GScanScope *, GScanExpression **);
 
 
 
@@ -226,22 +226,22 @@ bool g_scan_match_counter_create(GScanMatchCounter *counter, GSearchPattern *pat
 *                                                                             *
 ******************************************************************************/
 
-static bool g_scan_match_counter_reduce(GScanMatchCounter *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_match_counter_reduce(GScanMatchCounter *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
 {
-    bool result;                            /* Bilan à retourner           */
+    ScanReductionState result;              /* Etat synthétisé à retourner */
     size_t count;                           /* Quantité de correspondances */
-    const GScanMatch **matches;             /* Correspondances établies    */
-
-
-    matches = g_scan_context_get_full_matches(ctx, expr->pattern, &count);
 
+    if (g_scan_context_is_scan_done(ctx))
+    {
+        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 = SRS_REDUCED;
 
-    *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ count });
-    result = true;
-
+    }
+    else
+        result = SRS_WAIT_FOR_SCAN;
 
     return result;
 
diff --git a/src/analysis/scan/exprs/handler-int.h b/src/analysis/scan/exprs/handler-int.h
new file mode 100644
index 0000000..f707fdb
--- /dev/null
+++ b/src/analysis/scan/exprs/handler-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * handler-int.h - prototypes internes pour la manipulation des correspondances établies lors d'un scan
+ *
+ * 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_HANDLER_INT_H
+#define _ANALYSIS_SCAN_EXPRS_HANDLER_INT_H
+
+
+#include "handler.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Manipulation des correspondances établies lors d'un scan de binaire (instance) */
+struct _GScanPatternHandler
+{
+    GScanExpression parent;                 /* A laisser en premier        */
+
+    GSearchPattern *pattern;                /* Motif associé               */
+    ScanHandlerType type;                   /* Manipulation attendue       */
+
+};
+
+/* Manipulation des correspondances établies lors d'un scan de binaire (classe) */
+struct _GScanPatternHandlerClass
+{
+    GScanExpressionClass parent;            /* A laisser en premier        */
+
+};
+
+
+/* Met en place une manipulation de correspondances établies. */
+bool g_scan_pattern_handler_create(GScanPatternHandler *, GSearchPattern *, ScanHandlerType);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_HANDLER_INT_H */
diff --git a/src/analysis/scan/exprs/handler.c b/src/analysis/scan/exprs/handler.c
new file mode 100644
index 0000000..a14140a
--- /dev/null
+++ b/src/analysis/scan/exprs/handler.c
@@ -0,0 +1,402 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * handler.c - manipulation des correspondances établies lors d'un scan
+ *
+ * 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 "handler.h"
+
+
+#include <assert.h>
+
+
+#include "literal.h"
+#include "handler-int.h"
+#include "../matches/bytes.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des manipulations de correspondances. */
+static void g_scan_pattern_handler_class_init(GScanPatternHandlerClass *);
+
+/* Initialise une instance de manipulation de correspondances. */
+static void g_scan_pattern_handler_init(GScanPatternHandler *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_pattern_handler_dispose(GScanPatternHandler *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_pattern_handler_finalize(GScanPatternHandler *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_pattern_handler_reduce(GScanPatternHandler *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_pattern_handler_reduce_to_boolean(GScanPatternHandler *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Dénombre les éléments portés par une expression. */
+static bool g_scan_pattern_handler_count_items(const GScanPatternHandler *, GScanContext *, size_t *);
+
+/* Fournit un élément donné issu d'un ensemble constitué. */
+static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *, size_t, GScanContext *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une manipulation de correspondances établies lors d'un scan. */
+G_DEFINE_TYPE(GScanPatternHandler, g_scan_pattern_handler, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des manipulations de correspondances.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_pattern_handler_class_init(GScanPatternHandlerClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanExpressionClass *expr;             /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pattern_handler_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_pattern_handler_finalize;
+
+    expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+    expr->reduce = (reduce_expr_fc)g_scan_pattern_handler_reduce;
+    expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_pattern_handler_reduce_to_boolean;
+    expr->count = (count_scan_expr_fc)g_scan_pattern_handler_count_items;
+    expr->get = (get_scan_expr_fc)g_scan_pattern_handler_get_item;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : handler = instance à initialiser.                            *
+*                                                                             *
+*  Description : Initialise une instance de manipulation de correspondances.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_pattern_handler_init(GScanPatternHandler *handler)
+{
+    handler->pattern = NULL;
+    handler->type = SHT_RAW;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : handler = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_pattern_handler_dispose(GScanPatternHandler *handler)
+{
+    g_clear_object(&handler->pattern);
+
+    G_OBJECT_CLASS(g_scan_pattern_handler_parent_class)->dispose(G_OBJECT(handler));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : handler = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_pattern_handler_finalize(GScanPatternHandler *handler)
+{
+    G_OBJECT_CLASS(g_scan_pattern_handler_parent_class)->finalize(G_OBJECT(handler));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = motif à impliquer.                                 *
+*                type    = type de manipulation attendue.                     *
+*                                                                             *
+*  Description : Met en place une manipulation de correspondances établies.   *
+*                                                                             *
+*  Retour      : Expression mise en place.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanExpression *g_scan_pattern_handler_new(GSearchPattern *pattern, ScanHandlerType type)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_PATTERN_HANDLER, NULL);
+
+    if (!g_scan_pattern_handler_create(G_SCAN_PATTERN_HANDLER(result), pattern, type))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : handler = instance à initialiser pleinement.                 *
+*                pattern = motif à impliquer.                                 *
+*                type    = type de manipulation attendue.                     *
+*                                                                             *
+*  Description : Met en place une manipulation de correspondances établies.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_pattern_handler_create(GScanPatternHandler *handler, GSearchPattern *pattern, ScanHandlerType type)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    handler->pattern = pattern;
+    g_object_ref(G_OBJECT(pattern));
+
+    handler->type = type;
+
+    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_pattern_handler_reduce(GScanPatternHandler *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    ScanReductionState result;              /* Etat synthétisé à retourner */
+
+    if (g_scan_context_is_scan_done(ctx))
+        result = SRS_REDUCED;
+
+    else
+        result = SRS_WAIT_FOR_SCAN;
+
+    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_pattern_handler_reduce_to_boolean(GScanPatternHandler *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t count;                           /* Quantité de correspondances */
+
+    result = true;
+
+    g_scan_context_get_full_matches(ctx, expr->pattern, &count);
+
+    *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ count > 0 });
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                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_pattern_handler_count_items(const GScanPatternHandler *expr, GScanContext *ctx, size_t *count)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    assert(g_scan_context_is_scan_done(ctx));
+
+    g_scan_context_get_full_matches(ctx, expr->pattern, count);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : expr  = expression à consulter.                              *
+*                index = indice de l'élément à transférer.                    *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                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_pattern_handler_get_item(const GScanPatternHandler *expr, size_t index, GScanContext *ctx, GScanExpression **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t count;                           /* Quantité de correspondances */
+    const GScanMatch **matches;             /* Correspondances en place    */
+    const GScanBytesMatch *match;           /* Correspondance ciblée       */
+    phys_t start;                           /* Point de départ du motif    */
+    phys_t end;                             /* Point d'arrivée du motif    */
+    phys_t len;                             /* Taille du motif             */
+    GBinContent *content;                   /* Contenu binaire à relire    */
+    vmpa2t pos;                             /* Tête de lecture             */
+    const bin_t *data;                      /* Accès aux données brutes    */
+    sized_string_t binary;                  /* Conversion de formats       */
+
+    assert(g_scan_context_is_scan_done(ctx));
+
+    matches = g_scan_context_get_full_matches(ctx, expr->pattern, &count);
+
+    result = (index < count);
+    if (!result) goto done;
+
+    result = G_IS_SCAN_BYTES_MATCH(matches[index]);
+    if (!result) goto done;
+
+    match = G_SCAN_BYTES_MATCH(matches[index]);
+
+    len = g_scan_bytes_match_get_location(match, &start, &end);
+
+    switch (expr->type)
+    {
+        case SHT_RAW:
+            content = g_scan_bytes_match_get_content(match);
+
+            init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
+
+            data = g_binary_content_get_raw_access(content, &pos, len);
+
+            binary.data = data;
+            binary.len = len;
+
+            *out = g_scan_literal_expression_new(LVT_STRING, &binary);
+
+            g_object_unref(G_OBJECT(content));
+            break;
+
+        case SHT_START:
+            *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ start });
+            break;
+
+        case SHT_LENGTH:
+            *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ len });
+            break;
+
+        case SHT_END:
+            *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ end });
+            break;
+
+    }
+
+ done:
+
+    return result;
+
+}
diff --git a/src/analysis/scan/exprs/handler.h b/src/analysis/scan/exprs/handler.h
new file mode 100644
index 0000000..8ad700a
--- /dev/null
+++ b/src/analysis/scan/exprs/handler.h
@@ -0,0 +1,66 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * handler.h - prototypes pour la manipulation des correspondances établies lors d'un scan
+ *
+ * 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_HANDLER_H
+#define _ANALYSIS_SCAN_EXPRS_HANDLER_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_PATTERN_HANDLER            g_scan_pattern_handler_get_type()
+#define G_SCAN_PATTERN_HANDLER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PATTERN_HANDLER, GScanPatternHandler))
+#define G_IS_SCAN_PATTERN_HANDLER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PATTERN_HANDLER))
+#define G_SCAN_PATTERN_HANDLER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PATTERN_HANDLER, GScanPatternHandlerClass))
+#define G_IS_SCAN_PATTERN_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PATTERN_HANDLER))
+#define G_SCAN_PATTERN_HANDLER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PATTERN_HANDLER, GScanPatternHandlerClass))
+
+
+/* Manipulation des correspondances établies lors d'un scan de binaire (instance) */
+typedef struct _GScanPatternHandler GScanPatternHandler;
+
+/* Manipulation des correspondances établies lors d'un scan de binaire (classe) */
+typedef struct _GScanPatternHandlerClass GScanPatternHandlerClass;
+
+
+/* Type de manipulation représentée */
+typedef enum _ScanHandlerType
+{
+    SHT_RAW,                                /* Correspondances brutes      */
+    SHT_START,                              /* Départs de correspondances  */
+    SHT_LENGTH,                             /* Taille de correspondances   */
+    SHT_END,                                /* Fins de correspondances     */
+
+} ScanHandlerType;
+
+
+/* Indique le type défini pour une manipulation de correspondances établies lors d'un scan. */
+GType g_scan_pattern_handler_get_type(void);
+
+/* Met en place une manipulation de correspondances établies. */
+GScanExpression *g_scan_pattern_handler_new(GSearchPattern *, ScanHandlerType);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_HANDLER_H */
diff --git a/src/analysis/scan/exprs/item-int.h b/src/analysis/scan/exprs/item-int.h
new file mode 100644
index 0000000..56b159a
--- /dev/null
+++ b/src/analysis/scan/exprs/item-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item-int.h - prototypes internes pour la récupération d'un élément à partir d'une série
+ *
+ * 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_ITEM_INT_H
+#define _ANALYSIS_SCAN_EXPRS_ITEM_INT_H
+
+
+#include "item.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Accès à un élément donné d'une série établie (instance) */
+struct _GScanSetItem
+{
+    GScanExpression parent;                 /* A laisser en premier        */
+
+    GScanExpression *set;                   /* Série d'éléments à consulter*/
+    GScanExpression *index;                 /* Indice de l'élément visé    */
+
+};
+
+/* Accès à un élément donné d'une série établie (classe) */
+struct _GScanSetItemClass
+{
+    GScanExpressionClass parent;            /* A laisser en premier        */
+
+};
+
+
+/* Met en place un accès à un élément donné d'une série. */
+bool g_scan_set_item_create(GScanSetItem *, GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_ITEM_INT_H */
diff --git a/src/analysis/scan/exprs/item.c b/src/analysis/scan/exprs/item.c
new file mode 100644
index 0000000..a6b22f0
--- /dev/null
+++ b/src/analysis/scan/exprs/item.c
@@ -0,0 +1,346 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.c - récupération d'un élément à partir d'une série
+ *
+ * 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 "literal.h"
+#include "item-int.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des accès à un élément de série. */
+static void g_scan_set_item_class_init(GScanSetItemClass *);
+
+/* Initialise une instance d'accès à un élément de série. */
+static void g_scan_set_item_init(GScanSetItem *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_set_item_dispose(GScanSetItem *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_set_item_finalize(GScanSetItem *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_set_item_reduce(GScanSetItem *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       INTRODUCTION D'UNE NOUVELLE EXPRESSION                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour la récupération d'un élément à partir d'une série. */
+G_DEFINE_TYPE(GScanSetItem, g_scan_set_item, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des accès à un élément de série.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_set_item_class_init(GScanSetItemClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanExpressionClass *expr;             /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_set_item_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_set_item_finalize;
+
+    expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+    expr->reduce = (reduce_expr_fc)g_scan_set_item_reduce;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance d'accès à un élément de série.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_set_item_init(GScanSetItem *item)
+{
+    item->set = NULL;
+    item->index = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_set_item_dispose(GScanSetItem *item)
+{
+    g_clear_object(&item->set);
+    g_clear_object(&item->index);
+
+    G_OBJECT_CLASS(g_scan_set_item_parent_class)->dispose(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_set_item_finalize(GScanSetItem *item)
+{
+    G_OBJECT_CLASS(g_scan_set_item_parent_class)->finalize(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : set   = ensemble d'éléments à considérer.                    *
+*                index = indice de l'élément à viser.                         *
+*                                                                             *
+*  Description : Met en place un accès à un élément donné d'une série.        *
+*                                                                             *
+*  Retour      : Expression mise en place.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanExpression *g_scan_set_item_new(GScanExpression *set, GScanExpression *index)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_SET_ITEM, NULL);
+
+    if (!g_scan_set_item_create(G_SCAN_SET_ITEM(result), set, index))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = instance à initialiser pleinement.                   *
+*                set   = ensemble d'éléments à considérer.                    *
+*                index = indice de l'élément à viser.                         *
+*                                                                             *
+*  Description : Met en place un accès à un élément donné d'une série.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_set_item_create(GScanSetItem *item, GScanExpression *set, GScanExpression *index)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    item->set = set;
+    g_object_ref(G_OBJECT(set));
+
+    item->index = index;
+    g_object_ref(G_OBJECT(index));
+
+    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_set_item_reduce(GScanSetItem *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    ScanReductionState result;              /* Etat synthétisé à retourner */
+    GScanExpression *new_set;               /* Expression réduite (série) */
+    GScanExpression *new_index;             /* Expression réduite (indice) */
+    ScanReductionState state_set;           /* Etat synthétisé #1          */
+    ScanReductionState state_index;         /* Etat synthétisé #2          */
+    GScanLiteralExpression *op_index;       /* Indice d'accès final        */
+    LiteralValueType vtype;                 /* Type de valeur portée       */
+    long long val_s;                        /* Valeur de l'indice (signée) */
+    unsigned long long val_u;               /* Valeur de l'indice (!signée)*/
+    bool status;                            /* Statut final de récupération*/
+
+    /* Réduction des éléments considérés */
+
+    new_set = NULL;
+    new_index = NULL;
+
+    state_set = g_scan_expression_reduce(expr->set, ctx, scope, &new_set);
+    if (state_set == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    state_index = g_scan_expression_reduce(expr->index, ctx, scope, &new_index);
+    if (state_index == SRS_UNRESOLVABLE)
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    /* Validation de la nature des éléments en jeu */
+
+    if (state_set == SRS_REDUCED && !g_scan_expression_handle_set_features(new_set))
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    if (state_index == SRS_REDUCED && !G_IS_SCAN_LITERAL_EXPRESSION(new_index))
+    {
+        result = SRS_UNRESOLVABLE;
+        goto exit;
+    }
+
+    /* Tentative d'accès à un élément de série */
+
+    if (state_set == SRS_REDUCED && state_index == SRS_REDUCED)
+    {
+        op_index = G_SCAN_LITERAL_EXPRESSION(new_index);
+        vtype = g_scan_literal_expression_get_value_type(op_index);
+
+        if (vtype == LVT_SIGNED_INTEGER)
+        {
+            if (!g_scan_literal_expression_get_signed_integer_value(op_index, &val_s))
+            {
+                result = SRS_UNRESOLVABLE;
+                goto exit;
+            }
+
+            if (val_s < 0)
+            {
+                result = SRS_UNRESOLVABLE;
+                goto exit;
+            }
+
+            status = g_scan_expression_get_item(expr->set, val_s, ctx, out);
+
+        }
+        else if (vtype == LVT_UNSIGNED_INTEGER)
+        {
+            if (!g_scan_literal_expression_get_unsigned_integer_value(op_index, &val_u))
+            {
+                result = SRS_UNRESOLVABLE;
+                goto exit;
+            }
+
+            status = g_scan_expression_get_item(expr->set, val_u, ctx, out);
+
+        }
+
+        result = (status ? SRS_REDUCED : SRS_UNRESOLVABLE);
+
+    }
+
+    /* Mise à jour de la progression ? */
+
+    else
+    {
+        assert(state_set == SRS_WAIT_FOR_SCAN || state_index == SRS_WAIT_FOR_SCAN);
+
+        if (new_set != expr->set || new_index != expr->index)
+            *out = g_scan_set_item_new(new_set, new_index);
+
+        result = SRS_WAIT_FOR_SCAN;
+
+    }
+
+    /* Sortie propre */
+
+ exit:
+
+    g_clear_object(&new_set);
+    g_clear_object(&new_index);
+
+    return result;
+
+}
diff --git a/src/analysis/scan/exprs/item.h b/src/analysis/scan/exprs/item.h
new file mode 100644
index 0000000..9d3cdfb
--- /dev/null
+++ b/src/analysis/scan/exprs/item.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - prototypes pour la récupération d'un élément à partir d'une série
+ *
+ * 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_ITEM_H
+#define _ANALYSIS_SCAN_EXPRS_ITEM_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_SET_ITEM            g_scan_set_item_get_type()
+#define G_SCAN_SET_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SET_ITEM, GScanSetItem))
+#define G_IS_SCAN_SET_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SET_ITEM))
+#define G_SCAN_SET_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SET_ITEM, GScanSetItemClass))
+#define G_IS_SCAN_SET_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SET_ITEM))
+#define G_SCAN_SET_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SET_ITEM, GScanSetItemClass))
+
+
+/* Accès à un élément donné d'une série établie (instance) */
+typedef struct _GScanSetItem GScanSetItem;
+
+/* Accès à un élément donné d'une série établie (classe) */
+typedef struct _GScanSetItemClass GScanSetItemClass;
+
+
+/* Indique le type défini pour la récupération d'un élément à partir d'une série. */
+GType g_scan_set_item_get_type(void);
+
+/* Met en place un accès à un élément donné d'une série. */
+GScanExpression *g_scan_set_item_new(GScanExpression *, GScanExpression *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_EXPRS_ITEM_H */
diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c
index e468382..070c177 100644
--- a/src/analysis/scan/exprs/literal.c
+++ b/src/analysis/scan/exprs/literal.c
@@ -60,7 +60,7 @@ static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression
 static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **);
 
 /* Dénombre les éléments portés par une expression. */
-static bool g_scan_literal_expression_count(const GScanLiteralExpression *, size_t *);
+static bool g_scan_literal_expression_count(const GScanLiteralExpression *, GScanContext *, size_t *);
 
 
 
@@ -623,6 +623,7 @@ static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
 *                count = quantité d'éléments déterminée. [OUT]                *
 *                                                                             *
 *  Description : Dénombre les éléments portés par une expression.             *
@@ -633,7 +634,7 @@ static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_scan_literal_expression_count(const GScanLiteralExpression *expr, size_t *count)
+static bool g_scan_literal_expression_count(const GScanLiteralExpression *expr, GScanContext *ctx, size_t *count)
 {
     bool result;                            /* Bilan à retourner           */
 
diff --git a/src/analysis/scan/exprs/set.c b/src/analysis/scan/exprs/set.c
index 0a93ced..d76af4d 100644
--- a/src/analysis/scan/exprs/set.c
+++ b/src/analysis/scan/exprs/set.c
@@ -60,10 +60,10 @@ static ScanReductionState g_scan_generic_set_reduce(GScanGenericSet *, GScanCont
 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 *);
+static bool g_scan_generic_set_count_items(const GScanGenericSet *, GScanContext *, 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 **);
+static bool g_scan_generic_set_get_item(const GScanGenericSet *, size_t, GScanContext *, GScanExpression **);
 
 
 
@@ -328,6 +328,7 @@ static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *expr, GScanCon
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : expr  = expression à consulter.                              *
+*                ctx   = contexte de suivi de l'analyse courante.             *
 *                count = quantité d'éléments déterminée. [OUT]                *
 *                                                                             *
 *  Description : Dénombre les éléments portés par une expression.             *
@@ -338,7 +339,7 @@ static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *expr, GScanCon
 *                                                                             *
 ******************************************************************************/
 
-static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, size_t *count)
+static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, GScanContext *ctx, size_t *count)
 {
     bool result;                            /* Bilan à retourner           */
 
@@ -355,6 +356,7 @@ static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, size_t *
 *                                                                             *
 *  Paramètres  : expr  = expression à consulter.                              *
 *                index = indice de l'élément à transférer.                    *
+*                ctx   = contexte de suivi de l'analyse courante.             *
 *                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
 *                                                                             *
 *  Description : Fournit un élément donné issu d'un ensemble constitué.       *
@@ -365,7 +367,7 @@ static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, size_t *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_scan_generic_set_get_item(const GScanGenericSet *expr, size_t index, GScanExpression **out)
+static bool g_scan_generic_set_get_item(const GScanGenericSet *expr, size_t index, GScanContext *ctx, GScanExpression **out)
 {
     bool result;                            /* Bilan à retourner           */
 
diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y
index 10e1d42..c0aa52d 100644
--- a/src/analysis/scan/grammar.y
+++ b/src/analysis/scan/grammar.y
@@ -6,7 +6,7 @@
 
 
 /* Affiche un message d'erreur suite à l'analyse en échec. */
-static int yyerror(GContentScanner *, yyscan_t, GScanRule **, void/*GBytesPattern*/ **, char **, size_t *, size_t *, char *);
+static int yyerror(GContentScanner *, yyscan_t, GScanRule **, sized_string_t *, sized_string_t *, void/*GBytesPattern*/ **, char **, size_t *, size_t *, char *);
 
 %}
 
@@ -16,34 +16,26 @@ static int yyerror(GContentScanner *, yyscan_t, GScanRule **, void/*GBytesPatter
 #define YY_TYPEDEF_YY_SCANNER_T
 typedef void *yyscan_t;
 
+#include "core.h"
 #include "scanner.h"
 #include "exprs/access.h"
 #include "exprs/arithmetic.h"
 #include "exprs/call.h"
 #include "exprs/counter.h"
+#include "exprs/handler.h"
 #include "exprs/intersect.h"
+#include "exprs/item.h"
 #include "exprs/literal.h"
 #include "exprs/logical.h"
 #include "exprs/set.h"
 #include "exprs/relational.h"
 #include "exprs/strop.h"
+#include "patterns/modifier.h"
+#include "patterns/modifiers/list.h"
+#include "patterns/tokens/hex.h"
 #include "patterns/tokens/plain.h"
-
-
-#if 0 /////////////////////////////////////////////////////////////////////////::
-#define handle_coder_conversions(c, r)                              \
-    ({                                                              \
-        encoding_spec *__spec;                                      \
-        encoding_syntax *__syntax;                                  \
-        conv_list *__list;                                          \
-        bool __status;                                              \
-        __spec = get_current_encoding_spec(c);                      \
-        __syntax = get_current_encoding_syntax(__spec);             \
-        __list = get_conversions_in_encoding_syntax(__syntax);      \
-        __status = load_convs_from_raw_block(__list, r);            \
-        if (!__status) YYABORT;                                     \
-    })
-#endif ///////////////////////////////////////////////////////////////////////////
+#include "patterns/tokens/nodes/plain.h"
+#include "../../core/logs.h"
 
 }
 
@@ -58,9 +50,25 @@ typedef void *yyscan_t;
 
 
 
+    sized_string_t *tmp_cstring;            /* Série d'octets reconstituée */
+
+    struct {
+        bin_t byte;                         /* Valeur partielle recherchée */
+        uint8_t mask;                       /* Masque associé              */
+    } semi_mask;
+
+
 
     GScanRule *rule;                        /* Nouvelle règle à intégrer   */
-    void/*GBytesPattern*/ *pattern;                 /* Nouveau motif à considérer  */
+
+
+
+    GScanTokenNode *node;                   /* Bribe de motif à intégrer   */
+    GSearchPattern *pattern;                /* Nouveau motif à considérer  */
+
+    GScanTokenModifier *modifier;
+
+
     GScanExpression *expr;                  /* Expression de condition     */
 
     struct {
@@ -78,13 +86,13 @@ typedef void *yyscan_t;
 
 %define api.pure full
 
-%parse-param { GContentScanner *scanner } { yyscan_t yyscanner } { GScanRule **built_rule } { void /*GBytesPattern*/ **built_pattern } { char **buf } { size_t *allocated } { size_t *used }
-%lex-param { yyscan_t yyscanner } { void/*GBytesPattern*/ **built_pattern } { char **buf } { size_t *allocated } { size_t *used }
+%parse-param { GContentScanner *scanner } { yyscan_t yyscanner } { GScanRule **built_rule } { sized_string_t *tmp_0} { sized_string_t *tmp_1} { void /*GBytesPattern*/ **built_pattern } { char **buf } { size_t *allocated } { size_t *used }
+%lex-param { yyscan_t yyscanner } { sized_string_t *tmp_0} { sized_string_t *tmp_1} { void/*GBytesPattern*/ **built_pattern } { char **buf } { size_t *allocated } { size_t *used }
 
 %code provides {
 
 #define YY_DECL \
-    int rost_lex(YYSTYPE *yylval_param, yyscan_t yyscanner, void/*GBytesPattern*/ **built_pattern, char **buf, size_t *allocated, size_t *used)
+    int rost_lex(YYSTYPE *yylval_param, yyscan_t yyscanner, sized_string_t *tmp_0, sized_string_t *tmp_1, void/*GBytesPattern*/ **built_pattern, char **buf, size_t *allocated, size_t *used)
 
 YY_DECL;
 
@@ -97,13 +105,26 @@ YY_DECL;
 %token RULE_NAME
 
 %token STRINGS CONDITION
-%token IDENTIFIER
+
 %token BYTES_ID
 %token BYTES_ID_COUNTER
-%token BYTES_ID_LOCATION
+%token BYTES_ID_START
 %token BYTES_ID_LENGTH
+%token BYTES_ID_END
 %token NAME
 
+
+%token HEX_BYTES
+%token FULL_MASK
+%token SEMI_MASK
+
+
+%token REGEX_BYTES
+%token REGEX_CLASSES
+%token REGEX_RANGE
+
+
+
 %token BRACE_IN BRACE_OUT ASSIGN COLON
 
 
@@ -143,11 +164,20 @@ YY_DECL;
 %token MUL              "*"
 %token DIV              "/"
 %token MOD              "%"
+%token TILDE            "~"
+
+%token HOOK_O           "["
+%token HOOK_C           "]"
+
+%token BRACKET_O        "{"
+%token BRACKET_C        "}"
+%token QUESTION         "?"
 
 %token PAREN_O          "("
 %token PAREN_C          ")"
 %token COMMA            ","
 %token DOT              "."
+%token PIPE             "|"
 
 %token NONE             "none"
 %token ANY              "any"
@@ -160,7 +190,11 @@ YY_DECL;
 %type <sized_cstring> RULE_NAME
 
 
-%type <sized_cstring> IDENTIFIER BYTES_ID_COUNTER
+%type <sized_cstring> BYTES_ID
+%type <sized_cstring> BYTES_ID_COUNTER
+%type <sized_cstring> BYTES_ID_START
+%type <sized_cstring> BYTES_ID_LENGTH
+%type <sized_cstring> BYTES_ID_END
 %type <sized_cstring> NAME
 
 
@@ -173,8 +207,27 @@ YY_DECL;
 %type <sized_cstring> PLAIN_STRING
 %type <pattern> MASKED_STRING
 
+%type <tmp_cstring> HEX_BYTES
+%type <unsigned_integer> FULL_MASK
+%type <semi_mask> SEMI_MASK
+
+%type <tmp_cstring> REGEX_BYTES
+
+
+%type <modifier> modifiers
+%type <modifier> _modifiers
+%type <modifier> chained_modifiers
+%type <modifier> mod_stage
+%type <modifier> modifier
+
+%type <pattern> hex_pattern
+%type <node> hex_tokens
+%type <node> hex_token
+
+
+
 %type <expr> cexpression _cexpression
-%type <expr> pattern_match
+
 %type <expr> literal
 %type <expr> item_chain
 %type <args_list> call_args
@@ -185,7 +238,16 @@ YY_DECL;
 %type <expr> set_counter
 %type <expr> set
 %type <expr> set_items
+%type <expr> set_access
 %type <expr> intersection
+%type <expr> pattern_handler
+
+
+
+
+
+%left PIPE
+
 
 
 %left OR
@@ -200,6 +262,11 @@ YY_DECL;
 
 
 
+%left HOOK_O HOOK_C
+
+
+
+
 %destructor { printf("-------- Discarding symbol %p.\n", $$); } <rule>
 
 
@@ -257,14 +324,28 @@ strings : /* empty */
         ;
 
 
-string_decls : string_decl
-             | string_decls string_decl
-             ;
+      string_decls : string_decl
+                   | hex_pattern
+                   {
+                       if ($1 == NULL) YYERROR;
+                       g_scan_rule_add_local_variable(*built_rule, $1);
+                       g_object_unref(G_OBJECT($1));
+                   }
+                   | regex_pattern
+                   | string_decls string_decl
+                   | string_decls hex_pattern
+                   {
+                       if ($2 == NULL) YYERROR;
+                       g_scan_rule_add_local_variable(*built_rule, $2);
+                       g_object_unref(G_OBJECT($2));
+                   }
+                   | string_decls regex_pattern
+                   ;
 
-string_decl : IDENTIFIER ASSIGN PLAIN_STRING
+string_decl : BYTES_ID ASSIGN PLAIN_STRING modifiers
             {
                 GSearchPattern *__pat;
-                __pat = g_plain_bytes_new((uint8_t *)$3.data, $3.len);
+                __pat = g_scan_plain_bytes_new(&$3, NULL, SPBF_NONE);
                 g_search_pattern_set_name(__pat, $1.data, $1.len);
                 g_scan_rule_add_local_variable(*built_rule, __pat);
                 g_object_unref(G_OBJECT(__pat));
@@ -281,7 +362,7 @@ string_decl : IDENTIFIER ASSIGN PLAIN_STRING
                 g_object_unref(G_OBJECT(__pat));
                 */
             }
-            | IDENTIFIER ASSIGN MASKED_STRING
+            | BYTES_ID ASSIGN MASKED_STRING
             {
                 printf("built %p\n", $3);
                 /*
@@ -301,6 +382,267 @@ string_decl : IDENTIFIER ASSIGN PLAIN_STRING
             }
             ;
 
+
+/**
+ * Prise en charge des modificateurs.
+ */
+
+         modifiers : /* empty */
+                   {
+                       $$ = NULL;
+                   }
+                   | _modifiers
+                   {
+
+                    // if (...) useless
+
+                   }
+                   ;
+
+        _modifiers : mod_stage
+                   {
+                       $$ = $1;
+                   }
+                   | chained_modifiers
+                   {
+                       $$ = $1;
+                   }
+                   ;
+
+ chained_modifiers : _modifiers "|" _modifiers
+                   ;
+
+         mod_stage : modifier
+                   {
+                       $$ = $1;
+                   }
+                   | mod_stage modifier
+                   {
+                       bool status;
+
+                       if (G_IS_SCAN_MODIFIER_LIST($1))
+                           $$ = $1;
+                       else
+                       {
+                           $$ = g_scan_modifier_list_new();
+                           g_scan_modifier_list_add(G_SCAN_MODIFIER_LIST($$), $1);
+                       }
+
+                       status = g_scan_modifier_list_add(G_SCAN_MODIFIER_LIST($$), $2);
+                       if (!status)
+                       {
+                           if (1)
+                               log_simple_message(LMT_WARNING, "modifier already taken into account!");
+                           g_object_unref(G_OBJECT($2));
+                       }
+
+                   }
+                   ;
+
+          modifier : NAME
+                   {
+                       $$ = find_scan_token_modifiers_for_name($1.data);
+                       if ($$ == NULL) YYERROR;
+                   }
+                   | "(" chained_modifiers ")"
+                   {
+                       $$ = $2;
+                   }
+                   ;
+
+/**
+ * Définition de motif en hexadécimal.
+ */
+
+       hex_pattern : BYTES_ID ASSIGN hex_tokens
+                   {
+                       $$ = g_scan_hex_bytes_new($3);
+                       g_search_pattern_set_name($$, $1.data, $1.len);
+                   }
+                   ;
+
+        hex_tokens : hex_token
+                   {
+                       $$ = $1;
+                   }
+                   | hex_tokens hex_token
+                   {
+
+                   }
+                   ;
+
+         hex_token : HEX_BYTES
+                   {
+                       $$ = g_scan_token_node_plain_new($1, NULL, SPNF_NONE);
+                   }
+                   | FULL_MASK
+                   {
+                       printf("mask len: %llu\n", $1);
+                   }
+                   | SEMI_MASK
+                   {
+                       printf("semi mask: %hhx / %hhx \n", $1.byte, $1.mask);
+                   }
+                   | hex_range
+                   {
+                       printf("...range...\n");
+                   }
+                   | "~" hex_token
+                   {
+
+                       printf("hex -- NOT --\n");
+
+                   }
+                   | "(" hex_token "|" hex_token ")"
+                   {
+
+                       printf("hex -- OR --\n");
+
+                   }
+                   ;
+
+         hex_range : "[" "-" "]"
+                   {
+
+                       printf("got inf range\n");
+
+                   }
+                   | "[" UNSIGNED_INTEGER "]"
+                   {
+
+                       printf("got range [%llu]\n", $2);
+
+                   }
+                   | "[" UNSIGNED_INTEGER "-" "]"
+                   {
+
+                       printf("got range [%llu -> ]\n", $2);
+
+                   }
+                   | "[" "-" UNSIGNED_INTEGER "]"
+                   {
+
+                       printf("got range [ -> %llu]\n", $3);
+
+                   }
+                   | "[" UNSIGNED_INTEGER "-" UNSIGNED_INTEGER "]"
+                   {
+
+                       printf("got range [%llu -> %llu]\n", $2, $4);
+
+                   }
+                   ;
+
+/**
+ * Définition de motif sous forme d'expression régulière
+ */
+
+     regex_pattern : BYTES_ID ASSIGN regex_tokens
+                   {
+
+                   }
+                   ;
+
+      regex_tokens : regex_token
+                   {
+
+                   }
+                   | regex_tokens regex_token
+                   {
+
+                   }
+                   | "(" regex_tokens_list ")"
+                   {
+
+                       printf("regex -- OR --\n");
+
+                   }
+                   | regex_tokens "(" regex_tokens_list ")"
+                   {
+
+                       printf("regex -- OR --\n");
+
+                   }
+                   ;
+
+
+ regex_tokens_list : regex_tokens
+                   | regex_tokens_list "|" regex_tokens
+                   ;
+
+
+       regex_token : _regex_token
+                   {
+
+                   }
+                   | _regex_token regex_repeat
+                   {
+
+                   }
+                   ;
+
+      _regex_token : DOT
+                   {
+                       printf("reg dot!\n");
+                   }
+                   | REGEX_BYTES
+                   {
+                       printf("reg bytes: '%s' (l=%zu)\n", $1->data, $1->len);
+                   }
+                   | REGEX_CLASSES
+                   {
+                       printf("reg class!\n");
+                   }
+                   | "[" REGEX_RANGE "]"
+                   {
+                       printf("reg range!\n");
+                   }
+                   ;
+
+      regex_repeat : "*"
+                   {
+                       printf("  .. repeat: *\n");
+                   }
+                   | "+"
+                   {
+                       printf("  .. repeat: +\n");
+                   }
+                   | "?"
+                   {
+                       printf("  .. repeat: ?\n");
+                   }
+                   | "{" UNSIGNED_INTEGER "}"
+                   {
+
+                       printf("  .. repeat {%llu}\n", $2);
+
+                   }
+                   | "{" UNSIGNED_INTEGER "," "}"
+                   {
+
+                       printf("  .. repeat {%llu,}\n", $2);
+
+                   }
+                   | "{" "," UNSIGNED_INTEGER "}"
+                   {
+
+                       printf("  .. repeat {,%llu}\n", $3);
+
+                   }
+                   | "{" UNSIGNED_INTEGER "," UNSIGNED_INTEGER "}"
+                   {
+
+                       printf("  .. repeat {%llu,%llu}\n", $2, $4);
+
+                   }
+                   ;
+
+
+
+/**
+ * Définition des conditions.
+ */
+
       condition : CONDITION COLON cexpression
                 {
                     g_scan_rule_set_match_condition(*built_rule, $3);
@@ -310,49 +652,19 @@ string_decl : IDENTIFIER ASSIGN PLAIN_STRING
 
     cexpression : _cexpression { $$ = $1; if ($$ == NULL) { printf("ERROR !!!\n"); YYERROR; } }
 
-   _cexpression : IDENTIFIER
-                {
-                printf("named var: %s\n", "$1");
-                $$ = NULL;
-                /*
-                   GSearchPattern *__pat;
-                   GMatchCounter *__counter;
-                   __pat = g_scan_rule_get_local_variable(*built_rule, $1);
-                   if (__pat != NULL)
-                   {
-                       __counter = g_match_counter_new(__pat);
-                       g_scan_rule_add_condition(*built_rule, G_MATCH_CONDITION(__counter));
-                       g_object_unref(G_OBJECT(__counter));
-                       g_object_unref(G_OBJECT(__pat));
-                   }
-                */
-                }
-                | 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);
-                    if (__pat == NULL)
-                        $$ = NULL;
-                    else
-                    {
-                        $$ = g_scan_match_counter_new(__pat);
-                        g_object_unref(G_OBJECT(__pat));
-                    }
-                }
-                ;
+      _cexpression : literal { $$ = $1; }
+                   | item_chain { $$ = $1; }
+                   | logical_expr { $$ = $1; }
+                   | relational_expr { $$ = $1; }
+                   | string_op { $$ = $1; }
+                   | arithm_expr { $$ = $1; }
+                   | set_counter { $$ = $1; }
+                   | set { $$ = $1; }
+                   | set_access { $$ = $1; }
+                   | intersection { $$ = $1; }
+                   | pattern_handler { $$ = $1; }
+                   | "(" cexpression ")" { $$ = $2; }
+                   ;
 
         literal : "true"
                 {
@@ -538,16 +850,83 @@ set_counter : "none" "of" "them" { $$ = g_scan_literal_expression_new(LVT_BOOLEA
                 }
                 ;
 
-   intersection : cexpression "in" cexpression
-                {
-                    $$ = g_scan_sets_intersection_new($1, $3);
-                    g_object_unref(G_OBJECT($1));
-                    g_object_unref(G_OBJECT($3));
-                }
-                ;
-
+        set_access : cexpression "[" cexpression "]"
+                   {
+                       $$ = g_scan_set_item_new($1, $3);
+                       g_object_unref(G_OBJECT($1));
+                       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));
+                   }
+                   ;
 
+   pattern_handler : BYTES_ID
+                   {
+                       GSearchPattern *__pat;
+                       __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+                       if (__pat == NULL)
+                           $$ = NULL;
+                       else
+                       {
+                           $$ = g_scan_pattern_handler_new(__pat, SHT_RAW);
+                           g_object_unref(G_OBJECT(__pat));
+                       }
+                   }
+                   | BYTES_ID_COUNTER
+                   {
+                       GSearchPattern *__pat;
+                       __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+                       if (__pat == NULL)
+                           $$ = NULL;
+                       else
+                       {
+                           $$ = g_scan_match_counter_new(__pat);
+                           g_object_unref(G_OBJECT(__pat));
+                       }
+                   }
+                   | BYTES_ID_START
+                   {
+                       GSearchPattern *__pat;
+                       __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+                       if (__pat == NULL)
+                           $$ = NULL;
+                       else
+                       {
+                           $$ = g_scan_pattern_handler_new(__pat, SHT_START);
+                           g_object_unref(G_OBJECT(__pat));
+                       }
+                   }
+                   | BYTES_ID_LENGTH
+                   {
+                       GSearchPattern *__pat;
+                       __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+                       if (__pat == NULL)
+                           $$ = NULL;
+                       else
+                       {
+                           $$ = g_scan_pattern_handler_new(__pat, SHT_LENGTH);
+                           g_object_unref(G_OBJECT(__pat));
+                       }
+                   }
+                   | BYTES_ID_END
+                   {
+                       GSearchPattern *__pat;
+                       __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+                       if (__pat == NULL)
+                           $$ = NULL;
+                       else
+                       {
+                           $$ = g_scan_pattern_handler_new(__pat, SHT_END);
+                           g_object_unref(G_OBJECT(__pat));
+                       }
+                   }
+                   ;
 
 %%
 
@@ -566,7 +945,7 @@ set_counter : "none" "of" "them" { $$ = g_scan_literal_expression_new(LVT_BOOLEA
 *                                                                             *
 ******************************************************************************/
 
-static int yyerror(GContentScanner *scanner, yyscan_t yyscanner, GScanRule **built_rule, void/*GBytesPattern*/ **built_pattern, char **buf, size_t *allocated, size_t *used, char *msg)
+static int yyerror(GContentScanner *scanner, yyscan_t yyscanner, GScanRule **built_rule, sized_string_t *tmp_0, sized_string_t *tmp_1, void/*GBytesPattern*/ **built_pattern, char **buf, size_t *allocated, size_t *used, char *msg)
 {
 	printf("YYERROR line %d: %s\n", yyget_lineno(yyscanner), msg);
 
@@ -593,6 +972,8 @@ bool process_rules_definitions(GContentScanner *scanner, const char *text, size_
 {
     bool result;                            /* Bilan à renvoyer            */
     GScanRule *built_rule;                  /* Règle en construction       */
+    sized_string_t tmp_0;                   /* Zone tampon #1              */
+    sized_string_t tmp_1;                   /* Zone tampon #2              */
     void /*GBytesPattern*/ *built_pattern;           /* Motif en construction       */
     char *buf;                              /* Zone de travail temporaire  */
     size_t allocated;                       /* Taille de mémoire allouée   */
@@ -604,6 +985,13 @@ bool process_rules_definitions(GContentScanner *scanner, const char *text, size_
     result = false;
 
     built_rule = NULL;
+
+    tmp_0.data = malloc((length + 1) * sizeof(bin_t));
+    tmp_0.len = 0;
+
+    tmp_1.data = malloc((length + 1) * sizeof(bin_t));
+    tmp_1.len = 0;
+
     built_pattern = NULL;
 
     allocated = 256;
@@ -616,7 +1004,7 @@ bool process_rules_definitions(GContentScanner *scanner, const char *text, size_
 
     state = rost__scan_bytes(text, length, lexstate);
 
-    status = yyparse(scanner, lexstate, &built_rule, &built_pattern, &buf, &allocated, &used);
+    status = yyparse(scanner, lexstate, &built_rule, &tmp_0, &tmp_1, &built_pattern, &buf, &allocated, &used);
 
     result = (status == EXIT_SUCCESS);
 
@@ -624,6 +1012,9 @@ bool process_rules_definitions(GContentScanner *scanner, const char *text, size_
 
     rost_lex_destroy(lexstate);
 
+    exit_szstr(&tmp_0);
+    exit_szstr(&tmp_1);
+
     free(buf);
 
     return result;
diff --git a/src/analysis/scan/items/count.c b/src/analysis/scan/items/count.c
index d87d33b..9040ec4 100644
--- a/src/analysis/scan/items/count.c
+++ b/src/analysis/scan/items/count.c
@@ -232,7 +232,7 @@ static bool g_scan_count_function_run_call(GScanCountFunction *item, GScanExpres
 
     else
     {
-        result = g_scan_expression_count_items(args[0], &value);
+        result = g_scan_expression_count_items(args[0], ctx, &value);
 
         if (result)
             *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ value }));
diff --git a/src/analysis/scan/match-int.h b/src/analysis/scan/match-int.h
index 9030d75..cf774c4 100644
--- a/src/analysis/scan/match-int.h
+++ b/src/analysis/scan/match-int.h
@@ -29,8 +29,11 @@
 
 
 
-/* Affiche une correspondance sur la sortie standard. */
-typedef void (* display_scan_match_fc) (const GScanMatch *);
+/* Affiche une correspondance au format texte. */
+typedef void (* output_scan_match_to_text_fc) (const GScanMatch *, int);
+
+/* Affiche une correspondance au format JSON. */
+typedef void (* output_scan_match_to_json_fc) (const GScanMatch *, const sized_string_t *, unsigned int, int);
 
 
 /* Correspondance trouvée avec un motif (instance) */
@@ -47,7 +50,8 @@ struct _GScanMatchClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
-    display_scan_match_fc display;          /* Impression des résultats    */
+    output_scan_match_to_text_fc to_text;   /* Impression au format texte  */
+    output_scan_match_to_json_fc to_json;    /* Impression au format JSON   */
 
 };
 
diff --git a/src/analysis/scan/match.c b/src/analysis/scan/match.c
index c7e2a78..b0b4320 100644
--- a/src/analysis/scan/match.c
+++ b/src/analysis/scan/match.c
@@ -157,8 +157,9 @@ GSearchPattern *g_scan_match_get_source(const GScanMatch *match)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : match = définition de correspondance à manipuler.            *
+*                fd    = canal d'écriture.                                    *
 *                                                                             *
-*  Description : Affiche une correspondance sur la sortie standard.           *
+*  Description : Affiche une correspondance au format texte.                  *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -166,12 +167,97 @@ GSearchPattern *g_scan_match_get_source(const GScanMatch *match)
 *                                                                             *
 ******************************************************************************/
 
-void g_scan_match_display(const GScanMatch *match)
+void g_scan_match_output_to_text(const GScanMatch *match, int fd)
 {
     GScanMatchClass *class;                 /* Classe à activer            */
 
     class = G_SCAN_MATCH_GET_CLASS(match);
 
-    class->display(match);
+    class->to_text(match, fd);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : match = définition de correspondance à manipuler.            *
+*                                                                             *
+*  Description : Convertit une correspondance en texte.                       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_match_convert_as_text(const GScanMatch *match)
+{
+    /* TODO */
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : match    = définition de correspondance à manipuler.         *
+*                padding  = éventuel bourrage initial à placer ou NULL.       *
+*                level    = profondeur actuelle.                              *
+*                fd       = canal d'écriture.                                 *
+*                trailing = impose une virgule finale ?                       *
+*                                                                             *
+*  Description : Affiche une correspondance au format JSON.                   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_match_output_to_json(const GScanMatch *match, const sized_string_t *padding, unsigned int level, int fd, bool trailing)
+{
+    unsigned int i;                         /* Boucle de parcours          */
+    GScanMatchClass *class;                 /* Classe à activer            */
+
+    /* Introduction */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "{\n", 2);
+
+    /* Affichage du contenu */
+
+    class = G_SCAN_MATCH_GET_CLASS(match);
+
+    class->to_json(match, padding, level + 1, fd);
+
+    /* Conclusion */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    if (trailing)
+        write(fd, "},\n", 3);
+    else
+        write(fd, "}\n", 2);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : match = définition de correspondance à manipuler.            *
+*                                                                             *
+*  Description : Convertit une correspondance en JSON.                        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_match_convert_as_json(const GScanMatch *match)
+{
+    /* TODO */
 
 }
diff --git a/src/analysis/scan/match.h b/src/analysis/scan/match.h
index 0990ae0..e713b5d 100644
--- a/src/analysis/scan/match.h
+++ b/src/analysis/scan/match.h
@@ -29,6 +29,7 @@
 
 
 #include "pattern.h"
+#include "../../common/szstr.h"
 
 
 
@@ -53,8 +54,17 @@ GType g_scan_match_get_type(void);
 /* Indique la source du motif d'origine recherché. */
 GSearchPattern *g_scan_match_get_source(const GScanMatch *);
 
-/* Affiche une correspondance sur la sortie standard. */
-void g_scan_match_display(const GScanMatch *);
+/* Affiche une correspondance au format texte. */
+void g_scan_match_output_to_text(const GScanMatch *, int);
+
+/* Convertit une correspondance en texte. */
+void g_scan_match_convert_as_text(const GScanMatch *);
+
+/* Affiche une correspondance au format JSON. */
+void g_scan_match_output_to_json(const GScanMatch *, const sized_string_t *, unsigned int, int, bool);
+
+/* Convertit une correspondance en JSON. */
+void g_scan_match_convert_as_json(const GScanMatch *);
 
 
 
diff --git a/src/analysis/scan/matches/bytes-int.h b/src/analysis/scan/matches/bytes-int.h
index c983aa3..6f7e60b 100644
--- a/src/analysis/scan/matches/bytes-int.h
+++ b/src/analysis/scan/matches/bytes-int.h
@@ -33,7 +33,7 @@
 
 
 /* Correspondance trouvée avec une chaîne (instance) */
-struct _GBytesMatch
+struct _GScanBytesMatch
 {
     GScanMatch parent;                      /* A laisser en premier        */
 
@@ -45,7 +45,7 @@ struct _GBytesMatch
 };
 
 /* Correspondance trouvée avec une chaîne (classe) */
-struct _GBytesMatchClass
+struct _GScanBytesMatchClass
 {
     GScanMatchClass parent;                 /* A laisser en premier        */
 
@@ -53,7 +53,7 @@ struct _GBytesMatchClass
 
 
 /* Met en place une correspondance trouvée avec un motif. */
-bool g_bytes_match_create(GBytesMatch *, GSearchPattern *, GBinContent *, phys_t, phys_t);
+bool g_scan_bytes_match_create(GScanBytesMatch *, GSearchPattern *, GBinContent *, phys_t, phys_t);
 
 
 
diff --git a/src/analysis/scan/matches/bytes.c b/src/analysis/scan/matches/bytes.c
index 90fa27d..043170e 100644
--- a/src/analysis/scan/matches/bytes.c
+++ b/src/analysis/scan/matches/bytes.c
@@ -24,10 +24,14 @@
 #include "bytes.h"
 
 
+#include <assert.h>
 #include <ctype.h>
+#include <stdio.h>
 
 
 #include "bytes-int.h"
+#include "../../../common/cpp.h"
+#include "../../../core/logs.h"
 
 
 
@@ -35,24 +39,27 @@
 
 
 /* Initialise la classe des correspondances de chaînes. */
-static void g_bytes_match_class_init(GBytesMatchClass *);
+static void g_scan_bytes_match_class_init(GScanBytesMatchClass *);
 
 /* Initialise une instance de correspondance de chaîne trouvée. */
-static void g_bytes_match_init(GBytesMatch *);
+static void g_scan_bytes_match_init(GScanBytesMatch *);
 
 /* Supprime toutes les références externes. */
-static void g_bytes_match_dispose(GBytesMatch *);
+static void g_scan_bytes_match_dispose(GScanBytesMatch *);
 
 /* Procède à la libération totale de la mémoire. */
-static void g_bytes_match_finalize(GBytesMatch *);
+static void g_scan_bytes_match_finalize(GScanBytesMatch *);
 
 
 
 /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
 
 
-/* Affiche une correspondance sur la sortie standard. */
-static void g_bytes_match_display(const GBytesMatch *);
+/* Affiche une correspondance au format texte. */
+static void g_scan_bytes_match_output_to_text(const GScanBytesMatch *, int);
+
+/* Affiche une correspondance au format JSON. */
+static void g_scan_bytes_match_output_to_json(const GScanBytesMatch *, const sized_string_t *, unsigned int, int);
 
 
 
@@ -62,7 +69,7 @@ static void g_bytes_match_display(const GBytesMatch *);
 
 
 /* Indique le type défini pour un correspondance de chaîne identifiée. */
-G_DEFINE_TYPE(GBytesMatch, g_bytes_match, G_TYPE_SCAN_MATCH);
+G_DEFINE_TYPE(GScanBytesMatch, g_scan_bytes_match, G_TYPE_SCAN_MATCH);
 
 
 /******************************************************************************
@@ -77,19 +84,20 @@ G_DEFINE_TYPE(GBytesMatch, g_bytes_match, G_TYPE_SCAN_MATCH);
 *                                                                             *
 ******************************************************************************/
 
-static void g_bytes_match_class_init(GBytesMatchClass *klass)
+static void g_scan_bytes_match_class_init(GScanBytesMatchClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GScanMatchClass *match;                 /* Version parente de la classe*/
 
     object = G_OBJECT_CLASS(klass);
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_bytes_match_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_bytes_match_finalize;
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_bytes_match_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_bytes_match_finalize;
 
     match = G_SCAN_MATCH_CLASS(klass);
 
-    match->display = (display_scan_match_fc)g_bytes_match_display;
+    match->to_text = (output_scan_match_to_text_fc)g_scan_bytes_match_output_to_text;
+    match->to_json = (output_scan_match_to_json_fc)g_scan_bytes_match_output_to_json;
 
 }
 
@@ -106,7 +114,7 @@ static void g_bytes_match_class_init(GBytesMatchClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_bytes_match_init(GBytesMatch *match)
+static void g_scan_bytes_match_init(GScanBytesMatch *match)
 {
     match->content = NULL;
 
@@ -128,11 +136,11 @@ static void g_bytes_match_init(GBytesMatch *match)
 *                                                                             *
 ******************************************************************************/
 
-static void g_bytes_match_dispose(GBytesMatch *match)
+static void g_scan_bytes_match_dispose(GScanBytesMatch *match)
 {
     g_clear_object(&match->content);
 
-    G_OBJECT_CLASS(g_bytes_match_parent_class)->dispose(G_OBJECT(match));
+    G_OBJECT_CLASS(g_scan_bytes_match_parent_class)->dispose(G_OBJECT(match));
 
 }
 
@@ -149,9 +157,9 @@ static void g_bytes_match_dispose(GBytesMatch *match)
 *                                                                             *
 ******************************************************************************/
 
-static void g_bytes_match_finalize(GBytesMatch *match)
+static void g_scan_bytes_match_finalize(GScanBytesMatch *match)
 {
-    G_OBJECT_CLASS(g_bytes_match_parent_class)->finalize(G_OBJECT(match));
+    G_OBJECT_CLASS(g_scan_bytes_match_parent_class)->finalize(G_OBJECT(match));
 
 }
 
@@ -171,13 +179,13 @@ static void g_bytes_match_finalize(GBytesMatch *match)
 *                                                                             *
 ******************************************************************************/
 
-GScanMatch *g_bytes_match_new(GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
+GScanMatch *g_scan_bytes_match_new(GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
 {
     GScanMatch *result;                     /* Structure à retourner       */
 
-    result = g_object_new(G_TYPE_BYTES_MATCH, NULL);
+    result = g_object_new(G_TYPE_SCAN_BYTES_MATCH, NULL);
 
-    if (!g_bytes_match_create(G_BYTES_MATCH(result), source, content, start, len))
+    if (!g_scan_bytes_match_create(G_SCAN_BYTES_MATCH(result), source, content, start, len))
         g_clear_object(&result);
 
     return result;
@@ -201,7 +209,7 @@ GScanMatch *g_bytes_match_new(GSearchPattern *source, GBinContent *content, phys
 *                                                                             *
 ******************************************************************************/
 
-bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
+bool g_scan_bytes_match_create(GScanBytesMatch *match, GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
 {
     bool result;                            /* Bilan à retourner           */
     GScanMatch *base;                       /* Lien vers les infos de base */
@@ -224,6 +232,58 @@ bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinConten
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : match = informations de correspondance à consulter.          *
+*                                                                             *
+*  Description : Fournit une référence au contenu lié à la correspondance.    *
+*                                                                             *
+*  Retour      : Content binaire associé au context.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_scan_bytes_match_get_content(const GScanBytesMatch *match)
+{
+    GBinContent *result;                    /* Instance à retourner        */
+
+    result = match->content;
+
+    g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : match = informations de correspondance à consulter.          *
+*                start = position de départ d'un motif détecté. [OUT]         *
+*                end   = position d'arrivée d'un motif détecté. [OUT]         *
+*                                                                             *
+*  Description : Indique la localisation d'une correspondance établie.        *
+*                                                                             *
+*  Retour      : Taille mesurée de la correspondance.                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *match, phys_t *start, phys_t *end)
+{
+    phys_t result;                          /* Taille à retourner          */
+
+    result = match->len;
+
+    *start = match->start;
+    *end = match->start + result;
+
+    return result;
+
+}
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
@@ -233,8 +293,9 @@ bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinConten
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : match = définition de correspondance à manipuler.            *
+*                fd    = canal d'écriture.                                    *
 *                                                                             *
-*  Description : Affiche une correspondance sur la sortie standard.           *
+*  Description : Affiche une correspondance au format texte.                  *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -242,15 +303,34 @@ bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinConten
 *                                                                             *
 ******************************************************************************/
 
-static void g_bytes_match_display(const GBytesMatch *match)
+static void g_scan_bytes_match_output_to_text(const GScanBytesMatch *match, int fd)
 {
+    char value[2 + ULLONG_MAXLEN];          /* Impression de la position   */
+    int ret;                                /* Bilan d'une conversion      */
     GScanMatch *base;                       /* Lien vers les infos de base */
     const char *name;                       /* Désignation du motif ciblé  */
     vmpa2t pos;                             /* Tête de lecture             */
     const bin_t *data;                      /* Accès aux données brutes    */
-    phys_t i;                               /* Boucle de parcours          */
+    phys_t k;                               /* Boucle de parcours #2       */
+
+    /* Position dans le binaire (hexadécimal) */
+
+    ret = snprintf(value, ULLONG_MAXLEN, "0x%llx", (unsigned long long)match->start);
+
+    if (ret > 0)
+        write(fd, value, ret);
 
-    /* Affichage d'un repère */
+    else
+    {
+        log_simple_message(LMT_EXT_ERROR, "Error while converting offset to hex!");
+        write(fd, "\"<error>\"", 9);
+    }
+
+    write(fd, ":", 1);
+
+    /* Affichage de la désignation */
+
+    write(fd, "$", 1);
 
     base = G_SCAN_MATCH(match);
 
@@ -262,25 +342,151 @@ static void g_bytes_match_display(const GBytesMatch *match)
      * Cette absence de nom est supportée ici.
      */
 
-    if (name == NULL)
-        name = "";
+    if (name != NULL)
+        write(fd, name, strlen(name));
+
+    write(fd, ": ", 2);
+
+    /* Affichage du contenu */
+
+    init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL);
+
+    data = g_binary_content_get_raw_access(match->content, &pos, match->len);
+
+    for (k = 0; k < match->len; k++)
+    {
+        if (isprint(data[k]))
+            write(fd, &data[k], 1);
+
+        else
+        {
+            write(fd, "\\x", 2);
+
+            ret = snprintf(value, ULLONG_MAXLEN, "%02hhx", data[k]);
+
+            if (ret > 0)
+            {
+                assert(ret == 2);
+                write(fd, value, ret);
+            }
+
+            else
+            {
+                log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
+                write(fd, "??", 2);
+            }
+
+        }
+
+    }
+
+    write(fd, "\n", 1);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : match   = définition de correspondance à manipuler.          *
+*                padding = éventuel bourrage initial à placer ou NULL.        *
+*                level   = profondeur actuelle.                               *
+*                fd      = canal d'écriture.                                  *
+*                                                                             *
+*  Description : Affiche une correspondance au format JSON.                   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_bytes_match_output_to_json(const GScanBytesMatch *match, const sized_string_t *padding, unsigned int level, int fd)
+{
+    unsigned int i;                         /* Boucle de parcours #1       */
+    vmpa2t pos;                             /* Tête de lecture             */
+    char value[4 + ULLONG_MAXLEN];          /* Impression de la position   */
+    int ret;                                /* Bilan d'une conversion      */
+    const bin_t *data;                      /* Accès aux données brutes    */
+    phys_t k;                               /* Boucle de parcours #2       */
+
+    /* Position dans le binaire (décimal) */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "\"offset\": ", 10);
+
+    ret = snprintf(value, ULLONG_MAXLEN, "%llu", (unsigned long long)match->start);
+
+    if (ret > 0)
+        write(fd, value, ret);
+
+    else
+    {
+        log_simple_message(LMT_EXT_ERROR, "Error while converting offset!");
+        write(fd, "null", 4);
+    }
+
+    write(fd, ",\n", 2);
+
+    /* Position dans le binaire (hexadécimal) */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "\"offset_hex\": ", 14);
 
-    printf("0x%llx:$%s: ", (unsigned long long)match->start, name);
+    ret = snprintf(value, ULLONG_MAXLEN, "\"0x%llx\"", (unsigned long long)match->start);
+
+    if (ret > 0)
+        write(fd, value, ret);
+
+    else
+    {
+        log_simple_message(LMT_EXT_ERROR, "Error while converting offset to hex!");
+        write(fd, "null", 4);
+    }
+
+    write(fd, ",\n", 2);
 
     /* Affichage du contenu */
 
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "\"content\": \"", 12);
+
     init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL);
 
     data = g_binary_content_get_raw_access(match->content, &pos, match->len);
 
-    for (i = 0; i < match->len; i++)
+    for (k = 0; k < match->len; k++)
     {
-        if (isprint(data[i]))
-            printf("%c", data[i]);
+        if (isprint(data[k]))
+            write(fd, &data[k], 1);
+
         else
-            printf("\\x%02hhx", data[i]);
+        {
+            write(fd, "\\x", 2);
+
+            ret = snprintf(value, ULLONG_MAXLEN, "%02hhx", data[k]);
+
+            if (ret > 0)
+            {
+                assert(ret == 2);
+                write(fd, value, ret);
+            }
+
+            else
+            {
+                log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
+                write(fd, "??", 2);
+            }
+
+        }
+
     }
 
-    printf("\n");
+    write(fd, "\"\n", 2);
 
 }
diff --git a/src/analysis/scan/matches/bytes.h b/src/analysis/scan/matches/bytes.h
index 22e76a6..e599ee4 100644
--- a/src/analysis/scan/matches/bytes.h
+++ b/src/analysis/scan/matches/bytes.h
@@ -33,26 +33,32 @@
 
 
 
-#define G_TYPE_BYTES_MATCH            g_bytes_match_get_type()
-#define G_BYTES_MATCH(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BYTES_MATCH, GBytesMatch))
-#define G_IS_BYTES_MATCH(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BYTES_MATCH))
-#define G_BYTES_MATCH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BYTES_MATCH, GBytesMatchClass))
-#define G_IS_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BYTES_MATCH))
-#define G_BYTES_MATCH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BYTES_MATCH, GBytesMatchClass))
+#define G_TYPE_SCAN_BYTES_MATCH            g_scan_bytes_match_get_type()
+#define G_SCAN_BYTES_MATCH(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatch))
+#define G_IS_SCAN_BYTES_MATCH(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_BYTES_MATCH))
+#define G_SCAN_BYTES_MATCH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatchClass))
+#define G_IS_SCAN_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_BYTES_MATCH))
+#define G_SCAN_BYTES_MATCH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatchClass))
 
 
 /* Correspondance trouvée avec une chaîne (instance) */
-typedef struct _GBytesMatch GBytesMatch;
+typedef struct _GScanBytesMatch GScanBytesMatch;
 
 /* Correspondance trouvée avec une chaîne (classe) */
-typedef struct _GBytesMatchClass GBytesMatchClass;
+typedef struct _GScanBytesMatchClass GScanBytesMatchClass;
 
 
 /* Indique le type défini pour un correspondance de chaîne identifiée. */
-GType g_bytes_match_get_type(void);
+GType g_scan_bytes_match_get_type(void);
 
 /* Prend note d'une correspondance trouvée avec un motif. */
-GScanMatch *g_bytes_match_new(GSearchPattern *, GBinContent *, phys_t, phys_t);
+GScanMatch *g_scan_bytes_match_new(GSearchPattern *, GBinContent *, phys_t, phys_t);
+
+/* Fournit une référence au contenu lié à la correspondance. */
+GBinContent *g_scan_bytes_match_get_content(const GScanBytesMatch *);
+
+/* Indique la localisation d'une correspondance établie. */
+phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *, phys_t *, phys_t *);
 
 
 
diff --git a/src/analysis/scan/matches/pending.c b/src/analysis/scan/matches/pending.c
index 73b7a06..9d1037d 100644
--- a/src/analysis/scan/matches/pending.c
+++ b/src/analysis/scan/matches/pending.c
@@ -79,46 +79,52 @@ void exit_pending_matches(pending_matches_t *matches)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : matches = suivi de correspondances à consulter.              *
-*                start   = point de départ d'une suite pour de correspondance.*
-*                mindex  = indice de départ et d'arrivée. [OUT]               *
 *                                                                             *
-*  Description : Détermine la zone de correspondance idéale pour complément.  *
+*  Description : Dénombre les correspondances établies jusque là.             *
 *                                                                             *
-*  Retour      : Bilan de l'opération : true en cas de succès des recherches. *
+*  Retour      : Quantité de correspondances complètes jusqu'à présent.       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool find_target_in_pending_matches(pending_matches_t *matches, phys_t start, size_t *target)
+size_t count_pending_matches(const pending_matches_t *matches)
 {
-    bool result;                            /* Bilan à retourner           */
-    size_t i;                               /* Boucle de parcours          */
-    match_area_t *area;                     /* Zone à initialiser          */
+    size_t result;                          /* Quantité à renvoyer         */
 
-    assert(*target <= matches->used);
+    result = matches->used;
 
-    result = false;
+    return result;
 
-    for (i = *target; i < matches->used; i++)
-    {
-        area = &matches->areas[i];
+}
 
-        if ((area->start + area->length) == start)
-        {
-            *target = i;
-            result = true;
-            break;
-        }
 
-    }
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : matches = suivi de correspondances à consulter.              *
+*                count   = nombre de correspondances en attente. [OUT]        *
+*                                                                             *
+*  Description : Fournit la liste des correspondances établies à présent.     *
+*                                                                             *
+*  Retour      : Liste de correspondances en lecture seule.                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const match_area_t *get_all_pending_matches(const pending_matches_t *matches, size_t *count)
+{
+    match_area_t *result;                   /* Série à renvoyer            */
+
+    result = matches->areas;
+
+    *count = matches->used;
 
     return result;
 
 }
 
 
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : matches = suivi de correspondances à compléter.              *
@@ -133,7 +139,7 @@ bool find_target_in_pending_matches(pending_matches_t *matches, phys_t start, si
 *                                                                             *
 ******************************************************************************/
 
-void add_pending_matches(pending_matches_t *matches, phys_t start, phys_t length)
+void add_pending_match(pending_matches_t *matches, phys_t start, phys_t length)
 {
     match_area_t *area;                     /* Zone à initialiser          */
 
@@ -148,7 +154,9 @@ void add_pending_matches(pending_matches_t *matches, phys_t start, phys_t length
     area = &matches->areas[matches->used++];
 
     area->start = start;
-    area->length = length;
+    area->end = start + length;
+
+    area->ttl = 1;
 
 }
 
@@ -167,21 +175,71 @@ void add_pending_matches(pending_matches_t *matches, phys_t start, phys_t length
 *                                                                             *
 ******************************************************************************/
 
-void extend_pending_matches(pending_matches_t *matches, size_t target, phys_t length)
+void extend_pending_match(pending_matches_t *matches, size_t target, phys_t end)
+{
+    match_area_t *area;                     /* Zone à actualiser           */
+
+    assert(target < matches->used);
+
+    area = &matches->areas[matches->used++];
+
+    if (area->ttl == 0)
+    {
+        area->end = end;
+
+        area->ttl = 1;
+
+    }
+    else
+    {
+        assert(area->ttl == 1);
+
+        add_pending_match(matches, area->start, end - area->start);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : matches = suivi de correspondances à consulter.              *
+*                target  = indice de la zone de correspondance concernée.     *
+*                pos     = position à tester.                                 *
+*                                                                             *
+*  Description : Détermine si une correspondance se termine à une position.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool has_pending_match_ending_at(const pending_matches_t *matches, size_t target, phys_t pos)
 {
+    bool result;                            /* Statut à retourner          */
+    match_area_t *area;                     /* Couverture visée            */
+
     assert(target < matches->used);
 
-    matches->areas[target].length += length;
+    area = &matches->areas[target];
+
+    result = (area->end == pos);
+
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : matches = suivi de correspondances à modifier.               *
+*  Paramètres  : matches = suivi de correspondances à consulter.              *
 *                target  = indice de la zone de correspondance concernée.     *
+*                pos     = position à tester.                                 *
+*                min     = borne inférieure de l'espace à considérer.         *
+*                max     = borne supérieure de l'espace à considérer.         *
 *                                                                             *
-*  Description : Retire une correspondance finalement non établie du suivi.   *
+*  Description : Détermine si une correspondance se situe dans une plage.     *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -189,14 +247,135 @@ void extend_pending_matches(pending_matches_t *matches, size_t target, phys_t le
 *                                                                             *
 ******************************************************************************/
 
-void remove_pending_matches(pending_matches_t *matches, size_t target)
+bool has_pending_match_ending_between(const pending_matches_t *matches, size_t target, phys_t pos, phys_t min, phys_t max)
 {
+    bool result;                            /* Statut à retourner          */
+    match_area_t *area;                     /* Couverture visée            */
+
     assert(target < matches->used);
 
-    if ((target + 1) < matches->used)
-        memmove(&matches->areas[target], &matches->areas[target + 1],
-                (matches->used - target - 1) * sizeof(match_area_t));
+    area = &matches->areas[target];
+
+    result = ((area->end + min) <= pos && pos <= (area->end + max));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : matches = suivi de correspondances à modifier.               *
+*                                                                             *
+*  Description : Réinitialisation à 0 tous les TTL de correspondances.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void reset_pending_matches_ttl(pending_matches_t *matches)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < matches->used; i++)
+        matches->areas[i].ttl = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : matches = suivi de correspondances à modifier.               *
+*                                                                             *
+*  Description : Retire toutes les correspondances sans issue pour l'analyse. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void purge_pending_matches(pending_matches_t *matches)
+{
+    match_area_t *del_start;                /* Départ d'une zone morte     */
+    match_area_t *del_end;                  /* Fin d'une zone morte        */
+    size_t del_remaining;                   /* Nombre de valides ensuite   */
+    size_t del_count;                       /* Nombre d'éléments à effacer */
+    size_t i;                               /* Boucle de parcours          */
+
+    /**
+     * Note : le code original était le suivant :
+     *
+
+     *    for (i = matches->used; i > 0; i--)
+     *        if (matches->areas[i - 1].ttl == 0)
+     *        {
+     *            memmove(&matches->areas[i - 1], &matches->areas[i], (matches->used - i) * sizeof(match_area_t));
+     *            matches->used--;
+     *        }
+     *
+     * Pour éviter les appels à memmove(), un déplacement par blocs est désormais visée.
+     */
+
+    del_start = NULL;
+    del_end = NULL;
+    del_count = 0;
+    del_remaining = 0;
 
-    matches->used--;
+    /* Suppression en bloc si possible */
+
+    for (i = matches->used; i > 0; i--)
+    {
+        if (matches->areas[i - 1].ttl == 0)
+        {
+            del_start = &matches->areas[i - 1];
+
+            if (del_end == NULL)
+            {
+                del_end = del_start;
+                del_remaining = matches->used - i;
+            }
+
+            del_count++;
+
+        }
+        else
+        {
+            if (del_start != NULL)
+            {
+                assert(&matches->areas[i] == del_start);
+
+                if (del_remaining > 0)
+                    memmove(del_start, del_end + 1, del_remaining * sizeof(match_area_t));
+
+                assert(matches->used > del_count);
+                matches->used -= del_count;
+
+                del_start = NULL;
+                del_end = NULL;
+                del_count = 0;
+                del_remaining = 0;
+
+            }
+
+        }
+
+    }
+
+    /* Dernier traitement au besoin */
+
+    if (del_start != NULL)
+    {
+        assert(&matches->areas[0] == del_start);
+
+        if (del_remaining > 0)
+            memmove(del_start, del_end + 1, del_remaining * sizeof(match_area_t));
+
+        assert(matches->used >= del_count);
+        matches->used -= del_count;
+
+    }
 
 }
diff --git a/src/analysis/scan/matches/pending.h b/src/analysis/scan/matches/pending.h
index de2fd5f..0a1fe5c 100644
--- a/src/analysis/scan/matches/pending.h
+++ b/src/analysis/scan/matches/pending.h
@@ -25,6 +25,9 @@
 #define _ANALYSIS_SCAN_MATCHES_PENDING_H
 
 
+#include <stdbool.h>
+
+
 #include "../../content.h"
 
 
@@ -33,7 +36,9 @@
 typedef struct _match_area_t
 {
     phys_t start;                           /* Point de départ             */
-    phys_t length;                          /* Taille de la zone couverte  */
+    phys_t end;                             /* Point d'arrivée (exclus)    */
+
+    unsigned long ttl;                      /* Durée de vie pour analyse   */
 
 } match_area_t;
 
@@ -55,21 +60,34 @@ void init_pending_matches(pending_matches_t *);
 /* Libère la mémoire utilisée par une consolidation. */
 void exit_pending_matches(pending_matches_t *);
 
+// TODO ajouter un assert(used == 0) si !initialized */
 #define are_pending_matches_initialized(pm) pm->initialized
 
 #define set_pending_matches_initialized(pm) pm->initialized = true
 
-/* Détermine la zone de correspondance idéale pour complément. */
-bool find_target_in_pending_matches(pending_matches_t *, phys_t, size_t *);
+/* Dénombre les correspondances établies jusque là. */
+size_t count_pending_matches(const pending_matches_t *);
+
+/* Fournit la liste des correspondances établies à présent. */
+const match_area_t *get_all_pending_matches(const pending_matches_t *, size_t *);
 
 /*  Ajoute au suivi la définition d'une nouvelle correspondance. */
-void add_pending_matches(pending_matches_t *, phys_t, phys_t);
+void add_pending_match(pending_matches_t *, phys_t, phys_t);
 
 /* Etend une zone couverte dans le suivi des correspondances. */
-void extend_pending_matches(pending_matches_t *, size_t, phys_t);
+void extend_pending_match(pending_matches_t *, size_t, phys_t);
+
+/* Détermine si une correspondance se situe dans une plage. */
+bool has_pending_match_ending_between(const pending_matches_t *, size_t, phys_t, phys_t, phys_t);
+
+/* Détermine si une correspondance se termine à une position. */
+bool has_pending_match_ending_at(const pending_matches_t *, size_t, phys_t);
+
+/* Réinitialisation à 0 tous les TTL de correspondances. */
+void reset_pending_matches_ttl(pending_matches_t *);
 
-/* Retire une correspondance finalement non établie du suivi. */
-void remove_pending_matches(pending_matches_t *, size_t);
+/* Retire toutes les correspondances sans issue pour l'analyse. */
+void purge_pending_matches(pending_matches_t *);
 
 
 
diff --git a/src/analysis/scan/options-int.h b/src/analysis/scan/options-int.h
index a7772ed..4e85974 100644
--- a/src/analysis/scan/options-int.h
+++ b/src/analysis/scan/options-int.h
@@ -36,6 +36,8 @@ struct _GScanOptions
 
     GType data_backend;                     /* Choix du moteur d'analyse   */
 
+    bool print_json;                        /* Sortie au format json ?     */
+    bool print_strings;                     /* Affichage de correspondances*/
     bool print_stats;                       /* Affichage de statistiques ? */
 
 };
diff --git a/src/analysis/scan/options.c b/src/analysis/scan/options.c
index 89e411e..cb56c2b 100644
--- a/src/analysis/scan/options.c
+++ b/src/analysis/scan/options.c
@@ -199,6 +199,92 @@ void g_scan_options_set_backend_for_data(GScanOptions *options, GType backend)
 *                                                                             *
 *  Paramètres  : options = ensemble d'options d'analyses à consulter.         *
 *                                                                             *
+*  Description : Impose le format JSON comme type de sortie.                  *
+*                                                                             *
+*  Retour      : Etat de l'option visée à conservé.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_options_get_print_json(const GScanOptions *options)
+{
+    bool result;                            /* Statut à retourner          */
+
+    result = options->print_json;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : options = ensemble d'options d'analyses à modifier.          *
+*                state   = état de l'option visée à conserver.                *
+*                                                                             *
+*  Description : Mémorise le format JSON comme type de sortie.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_options_set_print_json(GScanOptions *options, bool state)
+{
+    options->print_json = state;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : options = ensemble d'options d'analyses à consulter.         *
+*                                                                             *
+*  Description : Indique un besoin d'affichage des correspondances finales.   *
+*                                                                             *
+*  Retour      : Etat de l'option visée à conservé.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_options_get_print_strings(const GScanOptions *options)
+{
+    bool result;                            /* Statut à retourner          */
+
+    result = options->print_strings;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : options = ensemble d'options d'analyses à modifier.          *
+*                state   = état de l'option visée à conserver.                *
+*                                                                             *
+*  Description : Mémorise un besoin d'affichage des correspondances finales.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_options_set_print_strings(GScanOptions *options, bool state)
+{
+    options->print_strings = state;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : options = ensemble d'options d'analyses à consulter.         *
+*                                                                             *
 *  Description : Indique un besoin de statistiques en fin de compilation.     *
 *                                                                             *
 *  Retour      : Etat de l'option visée à conservé.                           *
diff --git a/src/analysis/scan/options.h b/src/analysis/scan/options.h
index a7931c5..6b027e3 100644
--- a/src/analysis/scan/options.h
+++ b/src/analysis/scan/options.h
@@ -57,6 +57,18 @@ GType g_scan_options_get_backend_for_data(const GScanOptions *);
 /* Sélectionne un type de moteur d'analyse pour données brutes. */
 void g_scan_options_set_backend_for_data(GScanOptions *, GType);
 
+/* Impose le format JSON comme type de sortie. */
+bool g_scan_options_get_print_json(const GScanOptions *);
+
+/* Mémorise le format JSON comme type de sortie. */
+void g_scan_options_set_print_json(GScanOptions *, bool);
+
+/* Indique un besoin d'affichage des correspondances finales. */
+bool g_scan_options_get_print_strings(const GScanOptions *);
+
+/* Mémorise un besoin d'affichage des correspondances finales. */
+void g_scan_options_set_print_strings(GScanOptions *, bool);
+
 /* Indique un besoin de statistiques en fin de compilation. */
 bool g_scan_options_get_print_stats(const GScanOptions *);
 
diff --git a/src/analysis/scan/pattern-int.h b/src/analysis/scan/pattern-int.h
index 03af30f..b510c75 100644
--- a/src/analysis/scan/pattern-int.h
+++ b/src/analysis/scan/pattern-int.h
@@ -28,9 +28,15 @@
 #include "pattern.h"
 
 
+#include "context.h"
 
-/* Décompte le nombre de correspondances identifiées. */
-typedef size_t (* count_pattern_matchs_fc) (const GSearchPattern *);
+
+
+/* Affiche un motif de recherche au format texte. */
+typedef void (* output_pattern_to_text_fc) (const GSearchPattern *, GScanContext *, int);
+
+/* Affiche un motif de recherche au format JSON. */
+typedef void (* output_pattern_to_json_fc) (const GSearchPattern *, GScanContext *, const sized_string_t *, unsigned int, int);
 
 
 /* Motif à rechercher au sein d'un contenu (instance) */
@@ -47,7 +53,8 @@ struct _GSearchPatternClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
-    count_pattern_matchs_fc count;          /* Décompte des résultats      */
+    output_pattern_to_text_fc to_text;      /* Impression au format texte  */
+    output_pattern_to_json_fc to_json;      /* Impression au format JSON   */
 
 };
 
diff --git a/src/analysis/scan/pattern.c b/src/analysis/scan/pattern.c
index 53a2662..5b966d2 100644
--- a/src/analysis/scan/pattern.c
+++ b/src/analysis/scan/pattern.c
@@ -186,25 +186,122 @@ void g_search_pattern_set_name(GSearchPattern *pattern, const char *name, size_t
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : pattern = définition de motif à consulter.                   *
+*  Paramètres  : pattern = définition de motif à considérer.                  *
+*                context = contexte de l'analyse à mener.                     *
+*                fd      = canal d'écriture.                                  *
 *                                                                             *
-*  Description : Décompte le nombre de correspondances identifiées.           *
+*  Description : Affiche un motif de recherche au format texte.               *
 *                                                                             *
-*  Retour      : Quantité d'identifications réalisées.                        *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-size_t g_search_pattern_count_matchs(const GSearchPattern *pattern)
+void g_search_pattern_output_to_text(const GSearchPattern *pattern, GScanContext *context, int fd)
 {
-    size_t result;                          /* Décompte à retourner        */
     GSearchPatternClass *class;             /* Classe à activer            */
 
     class = G_SEARCH_PATTERN_GET_CLASS(pattern);
 
-    result = 0;//class->count(pattern);
+    class->to_text(pattern, context, fd);
 
-    return result;
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = définition de motif à considérer.                  *
+*                context = contexte de l'analyse à mener.                     *
+*                                                                             *
+*  Description : Convertit un motif de recherche en texte.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_search_pattern_convert_as_text(const GSearchPattern *pattern, GScanContext *context)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = définition de motif à considérer.                  *
+*                context  = contexte de l'analyse à mener.                    *
+*                padding  = éventuel bourrage initial à placer ou NULL.       *
+*                level    = profondeur actuelle.                              *
+*                fd       = canal d'écriture.                                 *
+*                trailing = impose une virgule finale ?                       *
+*                                                                             *
+*  Description : Affiche un motif de recherche au format JSON.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_search_pattern_output_to_json(const GSearchPattern *pattern, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd, bool trailing)
+{
+    unsigned int i;                         /* Boucle de parcours          */
+    GSearchPatternClass *class;             /* Classe à activer            */
+
+    /* Introduction */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "{\n", 2);
+
+    /* Désignation du motif */
+
+    for (i = 0; i < (level + 1); i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "\"name\": \"$", 10);
+
+    write(fd, pattern->name, strlen(pattern->name));
+
+    write(fd, "\",\n", 3);
+
+    /* Affichage du contenu */
+
+    class = G_SEARCH_PATTERN_GET_CLASS(pattern);
+
+    class->to_json(pattern, context, padding, level + 1, fd);
+
+    /* Conclusion */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    if (trailing)
+        write(fd, "},\n", 3);
+    else
+        write(fd, "}\n", 2);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = définition de motif à considérer.                  *
+*                context = contexte de l'analyse à mener.                     *
+*                                                                             *
+*  Description : Convertit un motif de recherche en JSON.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_search_pattern_convert_as_json(const GSearchPattern *pattern, GScanContext *context)
+{
+    /* TODO */
 
 }
diff --git a/src/analysis/scan/pattern.h b/src/analysis/scan/pattern.h
index 9ea66d3..0e4327d 100644
--- a/src/analysis/scan/pattern.h
+++ b/src/analysis/scan/pattern.h
@@ -30,9 +30,14 @@
 
 #include "../../arch/archbase.h"
 #include "../../arch/vmpa.h"
+#include "../../common/szstr.h"
 
 
 
+/* Depuis context.h: contexte de suivi d'une analyse en cours (instance) */
+typedef struct _GScanContext GScanContext;
+;
+
 #define G_TYPE_SEARCH_PATTERN            g_search_pattern_get_type()
 #define G_SEARCH_PATTERN(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SEARCH_PATTERN, GSearchPattern))
 #define G_IS_SEARCH_PATTERN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SEARCH_PATTERN))
@@ -57,8 +62,17 @@ const char *g_search_pattern_get_name(const GSearchPattern *);
 /* Inscrit la désignation attribuée à un motif de recherche. */
 void g_search_pattern_set_name(GSearchPattern *, const char *, size_t);
 
-/* Décompte le nombre de correspondances identifiées. */
-size_t g_search_pattern_count_matchs(const GSearchPattern *);
+/* Affiche un motif de recherche au format texte. */
+void g_search_pattern_output_to_text(const GSearchPattern *, GScanContext *, int);
+
+/* Convertit un motif de recherche en texte. */
+void g_search_pattern_convert_as_text(const GSearchPattern *, GScanContext *);
+
+/* Affiche un motif de recherche au format JSON. */
+void g_search_pattern_output_to_json(const GSearchPattern *, GScanContext *, const sized_string_t *, unsigned int, int, bool);
+
+/* Convertit un motif de recherche en JSON. */
+void g_search_pattern_convert_as_json(const GSearchPattern *, GScanContext *);
 
 
 
diff --git a/src/analysis/scan/patterns/Makefile.am b/src/analysis/scan/patterns/Makefile.am
index 4082275..c3d0994 100644
--- a/src/analysis/scan/patterns/Makefile.am
+++ b/src/analysis/scan/patterns/Makefile.am
@@ -5,14 +5,17 @@ noinst_LTLIBRARIES  = libanalysisscanpatterns.la
 libanalysisscanpatterns_la_SOURCES =		\
 	backend-int.h							\
 	backend.h backend.c						\
+	modifier-int.h							\
+	modifier.h modifier.c					\
 	token-int.h								\
 	token.h token.c
 
 libanalysisscanpatterns_la_LIBADD = 		\
 	backends/libanalysisscanpatternsbackends.la \
+	modifiers/libanalysisscanpatternsmodifiers.la \
 	tokens/libanalysisscanpatternstokens.la
 
-libanalysisscanpatterns_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+libanalysisscanpatterns_la_CFLAGS = $(LIBGOBJ_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS)
 
 
 devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
@@ -20,4 +23,4 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
 dev_HEADERS = $(libanalysisscanpatterns_la_SOURCES:%c=)
 
 
-SUBDIRS = backends tokens
+SUBDIRS = backends modifiers tokens
diff --git a/src/analysis/scan/patterns/modifier-int.h b/src/analysis/scan/patterns/modifier-int.h
new file mode 100644
index 0000000..246c139
--- /dev/null
+++ b/src/analysis/scan/patterns/modifier-int.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier-int.h - prototypes internes pour la modification d'une séquence d'octets pour un motif recherché
+ *
+ * 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_MODIFIER_INT_H
+#define _ANALYSIS_SCAN_MODIFIER_INT_H
+
+
+#include "modifier.h"
+
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+typedef char * (* get_scan_modifier_name_fc) (const GScanTokenModifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+typedef bool (* transform_scan_token_fc) (const GScanTokenModifier *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+/* Transformation d'une séquence d'octets en une ou plusieurs autres formes (instance) */
+struct _GScanTokenModifier
+{
+    GObject parent;                         /* A laisser en premier        */
+
+};
+
+/* Transformation d'une séquence d'octets en une ou plusieurs autres formes (classe) */
+struct _GScanTokenModifierClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+    get_scan_modifier_name_fc get_name;     /* Fourniture du nom d'appel   */
+
+    transform_scan_token_fc transform;      /* Opération de transformation */
+
+};
+
+
+
+#endif  /* _ANALYSIS_SCAN_MODIFIER_INT_H */
diff --git a/src/analysis/scan/patterns/modifier.c b/src/analysis/scan/patterns/modifier.c
new file mode 100644
index 0000000..77d8bfd
--- /dev/null
+++ b/src/analysis/scan/patterns/modifier.c
@@ -0,0 +1,181 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier.c - modification d'une séquence d'octets pour un motif recherché
+ *
+ * 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 "modifier.h"
+
+
+#include "modifier-int.h"
+
+
+
+/* Initialise la classe des transformations d'octets. */
+static void g_scan_token_modifier_class_init(GScanTokenModifierClass *);
+
+/* Initialise une instance de transformation d'octets. */
+static void g_scan_token_modifier_init(GScanTokenModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_token_modifier_dispose(GScanTokenModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_token_modifier_finalize(GScanTokenModifier *);
+
+
+
+/* Indique le type défini pour une transformation d'une séquence d'octets. */
+G_DEFINE_TYPE(GScanTokenModifier, g_scan_token_modifier, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des transformations d'octets.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_modifier_class_init(GScanTokenModifierClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_modifier_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_token_modifier_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance à initialiser.                           *
+*                                                                             *
+*  Description : Initialise une instance de transformation d'octets.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_modifier_init(GScanTokenModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_modifier_dispose(GScanTokenModifier *modifier)
+{
+    G_OBJECT_CLASS(g_scan_token_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_modifier_finalize(GScanTokenModifier *modifier)
+{
+    G_OBJECT_CLASS(g_scan_token_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à consulter.                         *
+*                                                                             *
+*  Description : Fournit le nom d'appel d'un modificateur pour motif.         *
+*                                                                             *
+*  Retour      : Désignation humaine.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *g_scan_token_modifier_get_name(const GScanTokenModifier *modifier)
+{
+    char *result;                           /* Désignation à retourner     */
+    GScanTokenModifierClass *class;         /* Classe à activer            */
+
+    class = G_SCAN_TOKEN_MODIFIER_GET_CLASS(modifier);
+
+    result = class->get_name(modifier);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à solliciter.                        *
+*                src      = séquence d'octets à traiter.                      *
+*                dest     = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+*                count    = quantité de ces séquences.                        *
+*                                                                             *
+*  Description : Transforme une séquence d'octets pour motif de recherche.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération : succès ou échec.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_token_modifier_transform(const GScanTokenModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count)
+{
+    bool result;                            /* Bilan d'opération à renvoyer*/
+    GScanTokenModifierClass *class;         /* Classe à activer            */
+
+    class = G_SCAN_TOKEN_MODIFIER_GET_CLASS(modifier);
+
+    result = class->transform(modifier, src, dest, count);
+
+    return result;
+
+}
diff --git a/src/analysis/scan/patterns/modifier.h b/src/analysis/scan/patterns/modifier.h
new file mode 100644
index 0000000..a195ca8
--- /dev/null
+++ b/src/analysis/scan/patterns/modifier.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier.h - prototypes pour la modification d'une séquence d'octets pour un motif recherché
+ *
+ * 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_MODIFIER_H
+#define _ANALYSIS_SCAN_MODIFIER_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../../../common/szstr.h"
+
+
+
+#define G_TYPE_SCAN_TOKEN_MODIFIER            g_scan_token_modifier_get_type()
+#define G_SCAN_TOKEN_MODIFIER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_MODIFIER, GScanTokenModifier))
+#define G_IS_SCAN_TOKEN_MODIFIER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_MODIFIER))
+#define G_SCAN_TOKEN_MODIFIER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_MODIFIER, GScanTokenModifierClass))
+#define G_IS_SCAN_TOKEN_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_MODIFIER))
+#define G_SCAN_TOKEN_MODIFIER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_MODIFIER, GScanTokenModifierClass))
+
+
+/* Transformation d'une séquence d'octets en une ou plusieurs autres formes (instance) */
+typedef struct _GScanTokenModifier GScanTokenModifier;
+
+/* Transformation d'une séquence d'octets en une ou plusieurs autres formes (classe) */
+typedef struct _GScanTokenModifierClass GScanTokenModifierClass;
+
+
+/* Indique le type défini pour une transformation d'une séquence d'octets. */
+GType g_scan_token_modifier_get_type(void);
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+char *g_scan_token_modifier_get_name(const GScanTokenModifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+bool g_scan_token_modifier_transform(const GScanTokenModifier *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_MODIFIER_H */
diff --git a/src/analysis/scan/patterns/modifiers/Makefile.am b/src/analysis/scan/patterns/modifiers/Makefile.am
new file mode 100644
index 0000000..fe5263c
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/Makefile.am
@@ -0,0 +1,17 @@
+
+noinst_LTLIBRARIES  = libanalysisscanpatternsmodifiers.la
+
+
+libanalysisscanpatternsmodifiers_la_SOURCES = \
+	hex.h hex.c								\
+	list-int.h								\
+	list.h list.c							\
+	plain.h plain.c							\
+	rev.h rev.c
+
+libanalysisscanpatternsmodifiers_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanpatternsmodifiers_la_SOURCES:%c=)
diff --git a/src/analysis/scan/patterns/modifiers/hex.c b/src/analysis/scan/patterns/modifiers/hex.c
new file mode 100644
index 0000000..cf1583c
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/hex.c
@@ -0,0 +1,252 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.c - transformation en version hexadécimale d'une séquence d'octets
+ *
+ * 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 "hex.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "../modifier-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transformations en hexadécimal. */
+static void g_scan_hex_modifier_class_init(GScanHexModifierClass *klass);
+
+/* Initialise une instance de transformation en hexadécimal. */
+static void g_scan_hex_modifier_init(GScanHexModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_hex_modifier_dispose(GScanHexModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_hex_modifier_finalize(GScanHexModifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_hex_modifier_get_name(const GScanHexModifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_hex_modifier_transform(const GScanHexModifier *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         RECHERCHE D'UN MOTIF DE TEXTE BRUT                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transformation d'une séquence d'octets dans sa version hexadécimale. */
+G_DEFINE_TYPE(GScanHexModifier, g_scan_hex_modifier, G_TYPE_SCAN_TOKEN_MODIFIER);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des transformations en hexadécimal.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_modifier_class_init(GScanHexModifierClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanTokenModifierClass *modifier;      /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_hex_modifier_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_hex_modifier_finalize;
+
+    modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+    modifier->get_name = (get_scan_modifier_name_fc)g_scan_hex_modifier_get_name;
+
+    modifier->transform = (transform_scan_token_fc)g_scan_hex_modifier_transform;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance à initialiser.                           *
+*                                                                             *
+*  Description : Initialise une instance de transformation en hexadécimal.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_modifier_init(GScanHexModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_modifier_dispose(GScanHexModifier *modifier)
+{
+    G_OBJECT_CLASS(g_scan_hex_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_modifier_finalize(GScanHexModifier *modifier)
+{
+    G_OBJECT_CLASS(g_scan_hex_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Construit un modificateur fournistant une vue hexadécimale.  *
+*                                                                             *
+*  Retour      : Mécanisme mis en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_hex_modifier_new(void)
+{
+    GScanTokenModifier *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_HEX_MODIFIER, NULL);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à consulter.                         *
+*                                                                             *
+*  Description : Fournit le nom d'appel d'un modificateur pour motif.         *
+*                                                                             *
+*  Retour      : Désignation humaine.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_hex_modifier_get_name(const GScanHexModifier *modifier)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("hex");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à solliciter.                        *
+*                src      = séquence d'octets à traiter.                      *
+*                dest     = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+*                count    = quantité de ces séquences.                        *
+*                                                                             *
+*  Description : Transforme une séquence d'octets pour motif de recherche.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération : succès ou échec.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_hex_modifier_transform(const GScanHexModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count)
+{
+    bool result;                            /* Bilan d'opération à renvoyer*/
+    sized_binary_t *binary;                 /* Raccourci vers le stockage  */
+    size_t i;                               /* Boucle de parcours          */
+
+    static char *alphabet = "0123456789abcdef";
+
+    result = true;
+
+    *dest = malloc(1 * sizeof(sized_binary_t));
+    *count = 1;
+
+    binary = &(*dest)[0];
+
+    binary->len = src->len * 2;
+    binary->data = malloc(binary->len);
+
+    for (i = 0; i < src->len; i++)
+    {
+        binary->data[i * 2 + 0] = alphabet[src->data[i] >> 4];
+        binary->data[i * 2 + 1] = alphabet[src->data[i] & 0xf];
+    }
+
+    return result;
+
+}
diff --git a/src/analysis/scan/patterns/modifiers/hex.h b/src/analysis/scan/patterns/modifiers/hex.h
new file mode 100644
index 0000000..1a9b410
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/hex.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.h - prototypes pour la transformation en version hexadécimale d'une séquence d'octets
+ *
+ * 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_PATTERNS_MODIFIERS_HEX_H
+#define _ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H
+
+
+#include <glib-object.h>
+
+
+#include "../modifier.h"
+
+
+
+#define G_TYPE_SCAN_HEX_MODIFIER            g_scan_hex_modifier_get_type()
+#define G_SCAN_HEX_MODIFIER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_HEX_MODIFIER, GScanHexModifier))
+#define G_IS_SCAN_HEX_MODIFIER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_HEX_MODIFIER))
+#define G_SCAN_HEX_MODIFIER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_HEX_MODIFIER, GScanHexModifierClass))
+#define G_IS_SCAN_HEX_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_HEX_MODIFIER))
+#define G_SCAN_HEX_MODIFIER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_HEX_MODIFIER, GScanHexModifierClass))
+
+
+/* Transformation d'une séquence d'octets dans sa version hexadécimale (instance) */
+typedef GScanTokenModifier GScanHexModifier;
+
+/* Transformation d'une séquence d'octets dans sa version hexadécimale (classe) */
+typedef GScanTokenModifierClass GScanHexModifierClass;
+
+
+/* Indique le type défini pour une transformation d'une séquence d'octets dans sa version hexadécimale. */
+GType g_scan_hex_modifier_get_type(void);
+
+/* Construit un modificateur fournistant une vue hexadécimale. */
+GScanTokenModifier *g_scan_hex_modifier_new(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H */
diff --git a/src/analysis/scan/patterns/modifiers/list-int.h b/src/analysis/scan/patterns/modifiers/list-int.h
new file mode 100644
index 0000000..c8ed64b
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/list-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list-int.h - prototypes internes pour la gestion d'une liste de transformateurs
+ *
+ * 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_MODIFIERS_LIST_INT_H
+#define _ANALYSIS_SCAN_MODIFIERS_LIST_INT_H
+
+
+#include "list.h"
+
+
+#include "../modifier-int.h"
+
+
+
+/* Liste de transformations d'une séquence d'octets (instance) */
+struct _GScanModifierList
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    GScanTokenModifier **modifiers;         /* Liste de transformateurs    */
+    size_t count;                           /* Taille de cette liste       */
+
+};
+
+/* Liste de transformations d'une séquence d'octets (classe) */
+struct _GScanModifierListClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+};
+
+
+
+#endif  /* _ANALYSIS_SCAN_MODIFIERS_LIST_INT_H */
diff --git a/src/analysis/scan/patterns/modifiers/list.c b/src/analysis/scan/patterns/modifiers/list.c
new file mode 100644
index 0000000..e08d509
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/list.c
@@ -0,0 +1,405 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.c - gestion d'une liste de transformateurs
+ *
+ * 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 "list.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "list-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des liste de transformations d'octets. */
+static void g_scan_modifier_list_class_init(GScanModifierListClass *);
+
+/* Initialise une instance de liste de transformations d'octets. */
+static void g_scan_modifier_list_init(GScanModifierList *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_modifier_list_dispose(GScanModifierList *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_modifier_list_finalize(GScanModifierList *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_modifier_list_get_name(const GScanModifierList *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_modifier_list_transform(const GScanModifierList *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         RECHERCHE D'UN MOTIF DE TEXTE BRUT                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une série de transformations d'octets. */
+G_DEFINE_TYPE(GScanModifierList, g_scan_modifier_list, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des liste de transformations d'octets.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_modifier_list_class_init(GScanModifierListClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanTokenModifierClass *modifier;      /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_modifier_list_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_modifier_list_finalize;
+
+    modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+    modifier->get_name = (get_scan_modifier_name_fc)g_scan_modifier_list_get_name;
+
+    modifier->transform = (transform_scan_token_fc)g_scan_modifier_list_transform;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance de liste de transformations d'octets.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_modifier_list_init(GScanModifierList *list)
+{
+    list->modifiers = NULL;
+    list->count = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_modifier_list_dispose(GScanModifierList *list)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < list->count; i++)
+        g_clear_object(&list->modifiers[i]);
+
+    G_OBJECT_CLASS(g_scan_modifier_list_parent_class)->dispose(G_OBJECT(list));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_modifier_list_finalize(GScanModifierList *list)
+{
+    if (list->modifiers != NULL)
+        free(list->modifiers);
+
+    G_OBJECT_CLASS(g_scan_modifier_list_parent_class)->finalize(G_OBJECT(list));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Construit une liste de modificateurs d'octets.               *
+*                                                                             *
+*  Retour      : Mécanisme mis en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_modifier_list_new(void)
+{
+    GScanTokenModifier *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_MODIFIER_LIST, NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list     = liste de modificateurs à étendre.                 *
+*                modifier = modificateur à intégrer.                          *
+*                                                                             *
+*  Description : Intègre un nouveau transformateur dans une liste.            *
+*                                                                             *
+*  Retour      : Bilan de l'ajout : false si un élément similaire est déjà là.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_modifier_list_add(GScanModifierList *list, GScanTokenModifier *modifier)
+{
+    bool result;                            /* Bilan à retourner           */
+    char *name;                             /* Désignation du modificateur */
+    size_t i;                               /* Boucle de parcours          */
+    char *other;                            /* Désignation de ses collègues*/
+
+    /* Recherche d'une redondance */
+
+    /**
+     * Note : deux listes identiques passent sans soucis.
+     * TODO : comparer les transformateurs ?
+     */
+
+    result = true;
+
+    if (!G_IS_SCAN_MODIFIER_LIST(modifier))
+    {
+        name = g_scan_token_modifier_get_name(modifier);
+
+        for (i = 0; i < list->count && result; i++)
+        {
+            if (G_IS_SCAN_MODIFIER_LIST(list->modifiers[i]))
+                continue;
+
+            other = g_scan_token_modifier_get_name(list->modifiers[i]);
+
+            result = (strcmp(name, other) != 0);
+
+            free(other);
+
+        }
+
+    }
+
+    free(name);
+
+    if (!result)
+        goto done;
+
+    /* Inclusion dans la liste */
+
+    list->modifiers = realloc(list->modifiers, ++list->count * sizeof(GScanTokenModifier *));
+
+    list->modifiers[list->count - 1] = modifier;
+    g_object_ref(G_OBJECT(modifier));
+
+ done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list = série à consulter.                                    *
+*                                                                             *
+*  Description : Indique le nombre de transformateurs intégrés dans la liste. *
+*                                                                             *
+*  Retour      : Nombre de modificateurs représentés.                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t g_scan_modifier_list_count(const GScanModifierList *list)
+{
+    size_t result;                          /* Quantité à retourner        */
+
+    result = list->count;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list  = série à consulter.                                   *
+*                index = indice du paramètre à retourner.                     *
+*                                                                             *
+*  Description : Fournit un transformateur donné de la liste.                 *
+*                                                                             *
+*  Retour      : Modificateur inclus dans la liste ou NULL si mauvais indice. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_modifier_list_get(const GScanModifierList *list, size_t index)
+{
+    GScanTokenModifier *result;             /* Instance à retourner        */
+
+    assert(index < list->count);
+
+    if (index < list->count)
+    {
+        result = list->modifiers[index];
+        g_object_ref(G_OBJECT(result));
+    }
+
+    else
+        result = NULL;
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à consulter.                         *
+*                                                                             *
+*  Description : Fournit le nom d'appel d'un modificateur pour motif.         *
+*                                                                             *
+*  Retour      : Désignation humaine.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_modifier_list_get_name(const GScanModifierList *modifier)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("(list)");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à solliciter.                        *
+*                src      = séquence d'octets à traiter.                      *
+*                dest     = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+*                count    = quantité de ces séquences.                        *
+*                                                                             *
+*  Description : Transforme une séquence d'octets pour motif de recherche.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération : succès ou échec.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_modifier_list_transform(const GScanModifierList *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count)
+{
+    bool result;                            /* Bilan d'opération à renvoyer*/
+    size_t i;                               /* Boucle de parcours #1       */
+    sized_binary_t *extra;                  /* Motifs supplémentaires      */
+    size_t extra_count;                     /* Quantité de ces motifs      */
+    sized_binary_t *new;                    /* Nouvel emplacement libre    */
+    size_t k;                               /* Boucle de parcours #2       */
+
+    *dest = NULL;
+    *count = 0;
+
+    for (i = 0; i < modifier->count; i++)
+    {
+        result = g_scan_token_modifier_transform(modifier->modifiers[i], src, &extra, &extra_count);
+        if (!result) goto exit;
+
+        new = (*dest) + *count;
+
+        *count += extra_count;
+        *dest = realloc(*dest, *count * sizeof(sized_binary_t)); 
+
+        for (k = 0; k < extra_count; k++, new++)
+            copy_szstr(*new, extra[k]);
+
+        free(extra);
+
+    }
+
+ exit:
+
+    if (!result)
+    {
+        for (i = 0; i < *count; i++)
+            exit_szstr(dest[i]);
+
+        if (*dest != NULL)
+            free(*dest);
+
+        *dest = NULL;
+        *count = 0;
+
+    }
+
+    return result;
+
+}
diff --git a/src/analysis/scan/patterns/modifiers/list.h b/src/analysis/scan/patterns/modifiers/list.h
new file mode 100644
index 0000000..abd1eae
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/list.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.h - prototypes pour la gestion d'une liste de transformateurs
+ *
+ * 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_MODIFIERS_LIST_H
+#define _ANALYSIS_SCAN_MODIFIERS_LIST_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../modifier.h"
+
+
+
+#define G_TYPE_SCAN_MODIFIER_LIST            g_scan_modifier_list_get_type()
+#define G_SCAN_MODIFIER_LIST(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MODIFIER_LIST, GScanModifierList))
+#define G_IS_SCAN_MODIFIER_LIST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MODIFIER_LIST))
+#define G_SCAN_MODIFIER_LIST_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MODIFIER_LIST, GScanModifierListClass))
+#define G_IS_SCAN_MODIFIER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MODIFIER_LIST))
+#define G_SCAN_MODIFIER_LIST_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MODIFIER_LIST, GScanModifierListClass))
+
+
+/* Liste de transformations d'une séquence d'octets (instance) */
+typedef struct _GScanModifierList GScanModifierList;
+
+/* Liste de transformations d'une séquence d'octets (classe) */
+typedef struct _GScanModifierListClass GScanModifierListClass;
+
+
+/* Indique le type défini pour une série de transformations d'octets. */
+GType g_scan_modifier_list_get_type(void);
+
+/* Construit une liste de modificateurs d'octets. */
+GScanTokenModifier *g_scan_modifier_list_new(void);
+
+/* Intègre un nouveau transformateur dans une liste. */
+bool g_scan_modifier_list_add(GScanModifierList *, GScanTokenModifier *);
+
+/* Indique le nombre de transformateurs intégrés dans la liste. */
+size_t g_scan_modifier_list_count(const GScanModifierList *);
+
+/* Fournit un transformateur donné de la liste. */
+GScanTokenModifier *g_scan_modifier_list_get(const GScanModifierList *, size_t);
+
+
+
+#endif  /* _ANALYSIS_SCAN_MODIFIERS_LIST_H */
diff --git a/src/analysis/scan/patterns/modifiers/plain.c b/src/analysis/scan/patterns/modifiers/plain.c
new file mode 100644
index 0000000..5837d46
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/plain.c
@@ -0,0 +1,245 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.c - transmission à l'identique d'une séquence d'octets
+ *
+ * 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 "plain.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "../modifier-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions à l'identique. */
+static void g_scan_plain_modifier_class_init(GScanPlainModifierClass *klass);
+
+/* Initialise une instance de transmission à l'identique. */
+static void g_scan_plain_modifier_init(GScanPlainModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_plain_modifier_dispose(GScanPlainModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_plain_modifier_finalize(GScanPlainModifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_plain_modifier_get_name(const GScanPlainModifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_plain_modifier_transform(const GScanPlainModifier *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         RECHERCHE D'UN MOTIF DE TEXTE BRUT                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transmission à l'identique d'une séquence d'octets. */
+G_DEFINE_TYPE(GScanPlainModifier, g_scan_plain_modifier, G_TYPE_SCAN_TOKEN_MODIFIER);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des transmissions à l'identique.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_plain_modifier_class_init(GScanPlainModifierClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanTokenModifierClass *modifier;      /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_plain_modifier_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_plain_modifier_finalize;
+
+    modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+    modifier->get_name = (get_scan_modifier_name_fc)g_scan_plain_modifier_get_name;
+
+    modifier->transform = (transform_scan_token_fc)g_scan_plain_modifier_transform;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance à initialiser.                           *
+*                                                                             *
+*  Description : Initialise une instance de transmission à l'identique.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_plain_modifier_init(GScanPlainModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_plain_modifier_dispose(GScanPlainModifier *modifier)
+{
+    G_OBJECT_CLASS(g_scan_plain_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_plain_modifier_finalize(GScanPlainModifier *modifier)
+{
+    G_OBJECT_CLASS(g_scan_plain_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Construit un modificateur livrant des octets à l'identique.  *
+*                                                                             *
+*  Retour      : Mécanisme mis en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_plain_modifier_new(void)
+{
+    GScanTokenModifier *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_PLAIN_MODIFIER, NULL);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à consulter.                         *
+*                                                                             *
+*  Description : Fournit le nom d'appel d'un modificateur pour motif.         *
+*                                                                             *
+*  Retour      : Désignation humaine.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_plain_modifier_get_name(const GScanPlainModifier *modifier)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("plain");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à solliciter.                        *
+*                src      = séquence d'octets à traiter.                      *
+*                dest     = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+*                count    = quantité de ces séquences.                        *
+*                                                                             *
+*  Description : Transforme une séquence d'octets pour motif de recherche.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération : succès ou échec.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_plain_modifier_transform(const GScanPlainModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count)
+{
+    bool result;                            /* Bilan d'opération à renvoyer*/
+    sized_binary_t *binary;                 /* Raccourci vers le stockage  */
+
+    result = true;
+
+    *dest = malloc(1 * sizeof(sized_binary_t));
+    *count = 1;
+
+    binary = &(*dest)[0];
+
+    binary->len = src->len;
+    binary->data = malloc(binary->len);
+
+    memcpy(binary->data, src->data, src->len);
+
+    return result;
+
+}
diff --git a/src/analysis/scan/patterns/modifiers/plain.h b/src/analysis/scan/patterns/modifiers/plain.h
new file mode 100644
index 0000000..ecabefd
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/plain.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.h - prototypes pour la transmission à l'identique d'une séquence d'octets
+ *
+ * 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_PATTERNS_MODIFIERS_PLAIN_H
+#define _ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H
+
+
+#include <glib-object.h>
+
+
+#include "../modifier.h"
+
+
+
+#define G_TYPE_SCAN_PLAIN_MODIFIER            g_scan_plain_modifier_get_type()
+#define G_SCAN_PLAIN_MODIFIER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PLAIN_MODIFIER, GScanPlainModifier))
+#define G_IS_SCAN_PLAIN_MODIFIER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PLAIN_MODIFIER))
+#define G_SCAN_PLAIN_MODIFIER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PLAIN_MODIFIER, GScanPlainModifierClass))
+#define G_IS_SCAN_PLAIN_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PLAIN_MODIFIER))
+#define G_SCAN_PLAIN_MODIFIER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PLAIN_MODIFIER, GScanPlainModifierClass))
+
+
+/* Transmission à l'identique d'une séquence d'octets (instance) */
+typedef GScanTokenModifier GScanPlainModifier;
+
+/* Transmission à l'identique d'une séquence d'octets (classe) */
+typedef GScanTokenModifierClass GScanPlainModifierClass;
+
+
+/* Indique le type défini pour une transmission à l'identique d'une séquence d'octets. */
+GType g_scan_plain_modifier_get_type(void);
+
+/* Construit un modificateur livrant des octets à l'identique. */
+GScanTokenModifier *g_scan_plain_modifier_new(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H */
diff --git a/src/analysis/scan/patterns/modifiers/rev.c b/src/analysis/scan/patterns/modifiers/rev.c
new file mode 100644
index 0000000..d22b549
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/rev.c
@@ -0,0 +1,247 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rev.c - transormation via inversement d'une séquence d'octets
+ *
+ * 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 "rev.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "../modifier-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions via inversement. */
+static void g_scan_reverse_modifier_class_init(GScanReverseModifierClass *klass);
+
+/* Initialise une instance de transmission via inversement. */
+static void g_scan_reverse_modifier_init(GScanReverseModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_reverse_modifier_dispose(GScanReverseModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_reverse_modifier_finalize(GScanReverseModifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_reverse_modifier_get_name(const GScanReverseModifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_reverse_modifier_transform(const GScanReverseModifier *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         RECHERCHE D'UN MOTIF DE TEXTE BRUT                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation via inversement d'une séquence d'octets. */
+G_DEFINE_TYPE(GScanReverseModifier, g_scan_reverse_modifier, G_TYPE_SCAN_TOKEN_MODIFIER);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des transmissions via inversement.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_reverse_modifier_class_init(GScanReverseModifierClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanTokenModifierClass *modifier;      /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_reverse_modifier_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_reverse_modifier_finalize;
+
+    modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+    modifier->get_name = (get_scan_modifier_name_fc)g_scan_reverse_modifier_get_name;
+
+    modifier->transform = (transform_scan_token_fc)g_scan_reverse_modifier_transform;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance à initialiser.                           *
+*                                                                             *
+*  Description : Initialise une instance de transmission via inversement.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_reverse_modifier_init(GScanReverseModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_reverse_modifier_dispose(GScanReverseModifier *modifier)
+{
+    G_OBJECT_CLASS(g_scan_reverse_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_reverse_modifier_finalize(GScanReverseModifier *modifier)
+{
+    G_OBJECT_CLASS(g_scan_reverse_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Construit un modificateur livrant des octets inversés.       *
+*                                                                             *
+*  Retour      : Mécanisme mis en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_reverse_modifier_new(void)
+{
+    GScanTokenModifier *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_REVERSE_MODIFIER, NULL);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à consulter.                         *
+*                                                                             *
+*  Description : Fournit le nom d'appel d'un modificateur pour motif.         *
+*                                                                             *
+*  Retour      : Désignation humaine.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_scan_reverse_modifier_get_name(const GScanReverseModifier *modifier)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("rev");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : modifier = modificateur à solliciter.                        *
+*                src      = séquence d'octets à traiter.                      *
+*                dest     = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+*                count    = quantité de ces séquences.                        *
+*                                                                             *
+*  Description : Transforme une séquence d'octets pour motif de recherche.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération : succès ou échec.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_reverse_modifier_transform(const GScanReverseModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count)
+{
+    bool result;                            /* Bilan d'opération à renvoyer*/
+    sized_binary_t *binary;                 /* Raccourci vers le stockage  */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    *dest = malloc(1 * sizeof(sized_binary_t));
+    *count = 1;
+
+    binary = &(*dest)[0];
+
+    binary->len = src->len;
+    binary->data = malloc(binary->len);
+
+    for (i = 0; i < src->len; i++)
+        binary->data[src->len - i - 1] = src->data[i];
+
+    return result;
+
+}
diff --git a/src/analysis/scan/patterns/modifiers/rev.h b/src/analysis/scan/patterns/modifiers/rev.h
new file mode 100644
index 0000000..5b4e398
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/rev.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rev.h - prototypes pour la transormation via inversement d'une séquence d'octets
+ *
+ * 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_PATTERNS_MODIFIERS_REV_H
+#define _ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H
+
+
+#include <glib-object.h>
+
+
+#include "../modifier.h"
+
+
+
+#define G_TYPE_SCAN_REVERSE_MODIFIER            g_scan_reverse_modifier_get_type()
+#define G_SCAN_REVERSE_MODIFIER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_REVERSE_MODIFIER, GScanReverseModifier))
+#define G_IS_SCAN_REVERSE_MODIFIER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_REVERSE_MODIFIER))
+#define G_SCAN_REVERSE_MODIFIER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_REVERSE_MODIFIER, GScanReverseModifierClass))
+#define G_IS_SCAN_REVERSE_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_REVERSE_MODIFIER))
+#define G_SCAN_REVERSE_MODIFIER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_REVERSE_MODIFIER, GScanReverseModifierClass))
+
+
+/* Transormation via inversement d'une séquence d'octets (instance) */
+typedef GScanTokenModifier GScanReverseModifier;
+
+/* Transormation via inversement d'une séquence d'octets (classe) */
+typedef GScanTokenModifierClass GScanReverseModifierClass;
+
+
+/* Indique le type défini pour une transormation via inversement d'une séquence d'octets. */
+GType g_scan_reverse_modifier_get_type(void);
+
+/* Construit un modificateur livrant des octets inversés. */
+GScanTokenModifier *g_scan_reverse_modifier_new(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H */
diff --git a/src/analysis/scan/patterns/token-int.h b/src/analysis/scan/patterns/token-int.h
index a9667c9..294a3b1 100644
--- a/src/analysis/scan/patterns/token-int.h
+++ b/src/analysis/scan/patterns/token-int.h
@@ -44,6 +44,8 @@ struct _GStringToken
 {
     GSearchPattern parent;                  /* A laisser en premier        */
 
+    GScanTokenNode *root;                   /* Motif à rechercher          */
+
 };
 
 /* Encadrement d'une bribe de recherche textuelle (classe) */
@@ -57,5 +59,9 @@ struct _GStringTokenClass
 };
 
 
+/* Met en place un gestionnaire de recherche de binaire. */
+bool g_string_token_create(GStringToken *, GScanTokenNode *);
+
+
 
 #endif  /* _ANALYSIS_SCAN_PATTERNS_TOKEN_INT_H */
diff --git a/src/analysis/scan/patterns/token.c b/src/analysis/scan/patterns/token.c
index d8a5cbc..cc2d87a 100644
--- a/src/analysis/scan/patterns/token.c
+++ b/src/analysis/scan/patterns/token.c
@@ -25,12 +25,18 @@
 
 
 #include <assert.h>
+#include <stdio.h>
 
 
 #include "token-int.h"
+#include "../../../common/cpp.h"
+#include "../../../core/logs.h"
 
 
 
+/* ------------------------- CIBLAGE DES SEQUENCES D'OCTETS ------------------------- */
+
+
 /* Initialise la classe des bribes de recherche textuelle. */
 static void g_string_token_class_init(GStringTokenClass *);
 
@@ -45,6 +51,22 @@ static void g_string_token_finalize(GStringToken *);
 
 
 
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Affiche un motif de recherche au format texte. */
+static void g_string_token_output_to_text(const GStringToken *, GScanContext *, int);
+
+/* Affiche un motif de recherche au format JSON. */
+static void g_string_token_output_to_json(const GStringToken *, GScanContext *, const sized_string_t *, unsigned int, int);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           CIBLAGE DES SEQUENCES D'OCTETS                           */
+/* ---------------------------------------------------------------------------------- */
+
+
 /* Indique le type défini pour une bribe de recherche textuelle. */
 G_DEFINE_TYPE(GStringToken, g_string_token, G_TYPE_SEARCH_PATTERN);
 
@@ -73,9 +95,8 @@ static void g_string_token_class_init(GStringTokenClass *klass)
 
     pattern = G_SEARCH_PATTERN_CLASS(klass);
 
-    //pattern->prepare = (prepare_pattern_fc)g_string_token_prepare;
-    //pattern->analyze = (analyze_pattern_fc)g_string_token_analyze;
-    //pattern->count = (count_pattern_matchs_fc);
+    pattern->to_text = (output_pattern_to_text_fc)g_string_token_output_to_text;
+    pattern->to_json = (output_pattern_to_json_fc)g_string_token_output_to_json;
 
 }
 
@@ -94,6 +115,7 @@ static void g_string_token_class_init(GStringTokenClass *klass)
 
 static void g_string_token_init(GStringToken *token)
 {
+    token->root = NULL;
 
 }
 
@@ -138,6 +160,33 @@ static void g_string_token_finalize(GStringToken *token)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : token = encadrement de motif à initialiser pleinement.       *
+*                root  = représentation du motif à recherche.                 *
+*                                                                             *
+*  Description : Met en place un gestionnaire de recherche de binaire.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_string_token_create(GStringToken *token, GScanTokenNode *root)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    token->root = root;
+    g_object_ref(G_OBJECT(root));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : token   = définition de la bribe à enregistrer.              *
 *                context = contexte de l'analyse à mener.                     *
 *                backend = moteur de recherche à préchauffer.                 *
@@ -151,7 +200,7 @@ static void g_string_token_finalize(GStringToken *token)
 *                                                                             *
 ******************************************************************************/
 
-bool g_string_token_enroll(GStringToken *token, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+bool g_string_token_enroll__old(GStringToken *token, GScanContext *context, GEngineBackend *backend, size_t maxsize)
 {
     bool result;                            /* Statut à retourner          */
     GStringTokenClass *class;               /* Classe de l'instance        */
@@ -166,6 +215,16 @@ bool g_string_token_enroll(GStringToken *token, GScanContext *context, GEngineBa
 
 }
 
+bool g_string_token_enroll(GStringToken *token, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+{
+    bool result;                            /* Statut à retourner          */
+
+    result = g_scan_token_node_enroll(token->root, context, backend, maxsize);
+
+    return result;
+
+}
+
 
 /******************************************************************************
 *                                                                             *
@@ -182,7 +241,7 @@ bool g_string_token_enroll(GStringToken *token, GScanContext *context, GEngineBa
 *                                                                             *
 ******************************************************************************/
 
-void g_string_token_check(const GStringToken *token, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+void g_string_token_check__old(const GStringToken *token, GScanContext *context, GBinContent *content, pending_matches_t *matches)
 {
     GStringTokenClass *class;               /* Classe de l'instance        */
 
@@ -191,3 +250,114 @@ void g_string_token_check(const GStringToken *token, GScanContext *context, GBin
     class->check(token, context, content, matches);
 
 }
+
+void g_string_token_check(const GStringToken *token, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+{
+    g_scan_token_node_check(token->root, context, content, matches, NULL);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = définition de motif à considérer.                  *
+*                context = contexte de l'analyse à mener.                     *
+*                fd      = canal d'écriture.                                  *
+*                                                                             *
+*  Description : Affiche un motif de recherche au format texte.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_string_token_output_to_text(const GStringToken *pattern, GScanContext *context, int fd)
+{
+    const GScanMatch **matches;             /* Correspondances établies    */
+    size_t count;                           /* Quantité de cette liste     */
+    size_t i;                               /* Boucle de parcours          */
+
+    matches = g_scan_context_get_full_matches(context, G_SEARCH_PATTERN(pattern), &count);
+
+    for (i = 0; i < count; i++)
+        g_scan_match_output_to_text(matches[i], fd);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = définition de motif à considérer.                  *
+*                context  = contexte de l'analyse à mener.                    *
+*                padding  = éventuel bourrage initial à placer ou NULL.       *
+*                level    = profondeur actuelle.                              *
+*                fd       = canal d'écriture.                                 *
+*                                                                             *
+*  Description : Affiche un motif de recherche au format JSON.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_string_token_output_to_json(const GStringToken *pattern, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd)
+{
+    unsigned int i;                         /* Boucle de parcours #1       */
+    const GScanMatch **matches;             /* Correspondances établies    */
+    size_t count;                           /* Quantité de cette liste     */
+    char value[ULLONG_MAXLEN];              /* Impression de la position   */
+    int ret;                                /* Bilan d'une conversion      */
+    size_t k;                               /* Boucle de parcours #2       */
+    bool trailing;                          /* Virgule finale              */
+
+    matches = g_scan_context_get_full_matches(context, G_SEARCH_PATTERN(pattern), &count);
+
+    /* Nombre de correspondances */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "\"match_count\": ", 15);
+
+    ret = snprintf(value, ULLONG_MAXLEN, "%zu", count);
+
+    if (ret > 0)
+        write(fd, value, ret);
+
+    else
+    {
+        log_simple_message(LMT_EXT_ERROR, "Error while converting value!");
+        write(fd, "null", 4);
+    }
+
+    write(fd, ",\n", 2);
+
+    /* Détail des correspondances */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "\"matches\": [\n", 13);
+
+    for (k = 0; k < count; k++)
+    {
+        trailing = ((k + 1) < count);
+
+        g_scan_match_output_to_json(matches[k], padding, level + 1, fd, trailing);
+
+    }
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "]\n", 2);
+
+}
diff --git a/src/analysis/scan/patterns/token.h b/src/analysis/scan/patterns/token.h
index c1cb173..879d912 100644
--- a/src/analysis/scan/patterns/token.h
+++ b/src/analysis/scan/patterns/token.h
@@ -29,6 +29,7 @@
 
 
 #include "backend.h"
+#include "tokens/node.h"
 #include "../matches/pending.h"
 
 
diff --git a/src/analysis/scan/patterns/tokens/Makefile.am b/src/analysis/scan/patterns/tokens/Makefile.am
index 00cff2a..7fb515f 100644
--- a/src/analysis/scan/patterns/tokens/Makefile.am
+++ b/src/analysis/scan/patterns/tokens/Makefile.am
@@ -3,11 +3,23 @@ noinst_LTLIBRARIES  = libanalysisscanpatternstokens.la
 
 
 libanalysisscanpatternstokens_la_SOURCES =	\
+	atom.h atom.c							\
+	hex-int.h								\
+	hex.h hex.c								\
+	node-int.h								\
+	node.h node.c							\
+	plain-int.h								\
 	plain.h plain.c
 
+libanalysisscanpatternstokens_la_LIBADD = 		\
+	nodes/libanalysisscanpatternstokensnodes.la
+
 libanalysisscanpatternstokens_la_CFLAGS = $(LIBGOBJ_CFLAGS)
 
 
 devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
 
 dev_HEADERS = $(libanalysisscanpatternstokens_la_SOURCES:%c=)
+
+
+SUBDIRS = nodes
diff --git a/src/analysis/scan/patterns/tokens/atom.c b/src/analysis/scan/patterns/tokens/atom.c
new file mode 100644
index 0000000..fcb585d
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/atom.c
@@ -0,0 +1,364 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * atom.c - détermination d'atomes à partir de motifs
+ *
+ * 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 "atom.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+
+/**
+ * Remplacement des fonctions de <ctypes.h> dans support des locales.
+ */
+
+#define IS_CH_LETTER(ch) (('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z'))
+
+#define MAKE_CH_UPPER(ch) (ch & 0xdf)
+#define MAKE_CH_LOWER(ch) (ch | 0x20)
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ch      = octet dont la valeur est à analyser.               *
+*                seen    = suivi des octets déjà rencontrés. [OUT]            * 
+*                letters = nombre de lettres rencontrées. [OUT]               *
+*                                                                             *
+*  Description : Note l'intêret de rechercher un octet particulier.           *
+*                                                                             *
+*  Retour      : Note positive ou négative.                                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int rate_byte_quality(bin_t ch, bitfield_t *seen, size_t *letters)
+{
+    int result;                             /* Note à retourner            */
+
+    switch (ch)
+    {
+        case 0x00:
+        case 0x20:
+        case 0x90:
+        case 0xcc:
+        case 0xff:
+            result = 12;
+            break;
+
+        case 'A' ... 'Z':
+        case 'z' ... 'z':
+            if (letters == NULL)
+                result = 20;
+            else
+            {
+                result = 18;
+                (*letters)++;
+            }
+            break;
+
+        default:
+            result = 20;
+            break;
+
+    }
+
+    set_in_bit_field(seen, ch, 1);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : seen = suivi des octets déjà rencontrés.                     * 
+*                max  = nombre d'octets considérés à la base.                 *
+*                                                                             *
+*  Description : Termine la notation d'un ensemble d'octets.                  *
+*                                                                             *
+*  Retour      : Note positive ou négative.                                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int finish_quality_rating(const bitfield_t *seen, size_t max)
+{
+    int result;                             /* Note à retourner            */
+    size_t uniq;                            /* Quantié d'octets uniques    */
+    bool bad;                               /* Indice de mauvaise qualité  */
+
+    uniq = popcount_for_bit_field(seen);
+
+    if (uniq == 1)
+    {
+        bad = test_in_bit_field(seen, 0x00)
+            || test_in_bit_field(seen, 0x20)
+            || test_in_bit_field(seen, 0x90)
+            || test_in_bit_field(seen, 0xcc)
+            || test_in_bit_field(seen, 0xff);
+
+        result = (bad ? -10 * max : 2);
+
+    }
+
+    else
+        result = uniq * 2;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : raw     = définition de la bribe à enregistrer.              *
+*                maxsize = taille max. des atomes (mise en commun optimisée). *
+*                atom    = informations de suivi constituées. [OUT]           *
+*                letters = nombre de lettres rencontrées. [OUT]               *
+*                                                                             *
+*  Description : Détermine la portion idéale de recherche.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void find_best_atom(const sized_binary_t *raw, size_t maxsize, tracked_scan_atom_t *atom, size_t *letters)
+{
+    size_t i;                               /* Boucle de parcours #1       */
+    bin_t ch;                               /* Octets à étudier            */
+    size_t best_letters;                    /* Mémorisation de décompte    */
+    size_t *ptr_letters;                    /* Pointeur vers le décompte   */
+    int best_rating;                        /* Meilleur notation obtenue   */
+    bitfield_t *seen;                       /* Mémorise les octets déjà vus*/
+    size_t max_loop;                        /* Limitation des itérations   */
+    size_t k;                               /* Boucle de parcours #2       */
+    size_t local_letters;                   /* Décompte courant des lettres*/
+    int local_rating;                       /* Notation courante           */
+
+    /* Si la chaîne fournie est plus petite que la taille d'un atome... */
+    if (raw->len <= maxsize)
+    {
+        atom->pos = 0;
+        atom->len = raw->len;
+        atom->rem = 0;
+
+        if (letters != NULL)
+        {
+            *letters = 0;
+
+            for (i = 0; i < raw->len; i++)
+            {
+                ch = raw->data[i];
+
+                if (IS_CH_LETTER(ch))
+                    (*letters)++;
+
+            }
+
+        }
+
+    }
+
+    /* ... ou si une sélection doit s'opérer */
+    else
+    {
+        /* Etablissement d'une mesure de référence à la position 0 */
+
+        atom->pos = 0;
+        atom->len = maxsize;
+
+        ptr_letters = (letters != NULL ? &best_letters : NULL);
+
+        best_letters = 0;
+        best_rating = 0;
+
+        seen = create_bit_field(256, false);
+
+        for (k = 0; k < maxsize; k++)
+            best_rating += rate_byte_quality(raw->data[k], seen, ptr_letters);
+
+        best_rating += finish_quality_rating(seen, maxsize);
+
+        /* Parcours du reste du contenu */
+
+        max_loop = (raw->len - maxsize);
+
+        ptr_letters = (letters != NULL ? &local_letters : NULL);
+
+        for (i = 1; i < max_loop; i++)
+        {
+            local_letters = 0;
+            local_rating = 0;
+
+            reset_all_in_bit_field(seen);
+
+            for (k = 0; k < maxsize; k++)
+                local_rating += rate_byte_quality(raw->data[i + k], seen, ptr_letters);
+
+            local_rating += finish_quality_rating(seen, maxsize);
+
+            if (local_rating > best_rating)
+            {
+                atom->pos = i;
+
+                best_letters = local_letters;
+                best_rating = local_rating;
+
+            }
+
+        }
+
+        /* Conclusion */
+
+        delete_bit_field(seen);
+
+        atom->rem = raw->len - atom->pos - maxsize;
+
+        if (letters != NULL)
+            *letters = best_letters;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : src   = chaîne ed référence à dupliquer.                     *
+*                count = nombre de lettres présentes.                         *
+*                                                                             *
+*  Description : Etablit la liste des cas de figures ignorant la casse.       *
+*                                                                             *
+*  Retour      : Liste de toutes les combinaisons possibles.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *src, size_t count)
+{
+    sized_binary_t *result;                 /* Liste à retourner           */
+    size_t i;                               /* Boucle de parcours #1       */
+    size_t replaced;                        /* 2^(alternatives créées)     */
+#ifndef NDEBUG
+    size_t check;                           /* Validation du compte max.   */
+#endif
+    bin_t ch;                               /* Octet à recopier            */
+    size_t k;                               /* Boucle de parcours #2       */
+    size_t divisor;                         /* Taille de la découpe        */
+    size_t quotient;                        /* Reste de la position        */
+
+    count *= 2;
+
+    /* Création du réceptacle */
+
+    result = malloc(count * sizeof(tracked_scan_atom_t));
+
+    for (i = 0; i < count; i++)
+    {
+        result[i].data = malloc(src->len);
+        result[i].len = src->len;
+    }
+
+    /* Remplissage */
+
+    replaced = 2;
+
+#ifndef NDEBUG
+    check = 1;
+#endif
+
+    for (i = 0; i < src->len; i++)
+    {
+        ch = src->data[i];
+
+        if (IS_CH_LETTER(ch))
+        {
+            for (k = 0; k < count; k++)
+            {
+                divisor = count / replaced;
+                quotient = k / divisor;
+
+                if ((quotient % 2) == 0)
+                    result[k].data[i] = MAKE_CH_UPPER(ch);
+                else
+                    result[k].data[i] = MAKE_CH_LOWER(ch);
+
+            }
+
+            replaced *= 2;
+
+#ifndef NDEBUG
+            check++;
+            assert((check - 1) <= count);
+#endif
+
+        }
+        else
+            for (k = 0; k < count; k++)
+                result[k].data[i] = ch;
+
+    }
+
+    assert((check - 1) == count);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : raw     = définition de la bribe à enregistrer.              *
+*                context = contexte de l'analyse à mener.                     *
+*                backend = moteur de recherche à préchauffer.                 *
+*                atom    = informations de suivi constituées. [OUT]           *
+*                                                                             *
+*  Description : Enregistre l'atome déterminé d'une série d'octets.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération à renvoyer.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool enroll_prepared_atom(const sized_binary_t *raw, GScanContext *context, GEngineBackend *backend, tracked_scan_atom_t *atom)
+{
+    bool result;                            /* Statut à retourner          */
+    const bin_t *data;                      /* Données à rechercher        */
+
+    data = raw->data + atom->pos;
+
+    atom->pid = g_engine_backend_enroll_plain_pattern(backend, context, data, atom->len);
+
+    result = (atom->pid != INVALID_PATTERN_ID);
+
+    return result;
+
+}
diff --git a/src/analysis/scan/patterns/tokens/atom.h b/src/analysis/scan/patterns/tokens/atom.h
new file mode 100644
index 0000000..daa1f16
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/atom.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * atom.h - prototypes pour la détermination d'atomes à partir de motifs
+ *
+ * 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_PATTERNS_TOKENS_ATOM_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_ATOM_H
+
+
+#include <stdbool.h>
+
+
+#include "../backend.h"
+#include "../../context.h"
+#include "../../../../arch/vmpa.h"
+#include "../../../../common/bits.h"
+#include "../../../../common/szstr.h"
+
+
+
+/* Suivi des motifs réellement recherchés */
+typedef struct _tracked_scan_atom_t
+{
+    phys_t pos;                             /* Début de sélection atomique */
+    phys_t len;                             /* Taille de ladite sélection  */
+    phys_t rem;                             /* Reste après l'atome         */
+
+    patid_t pid;                            /* Identifiant de la bribe     */
+
+} tracked_scan_atom_t;
+
+
+/* Note l'intêret de rechercher un octet particulier. */
+int rate_byte_quality(bin_t, bitfield_t *, size_t *);
+
+/* Termine la notation d'un ensemble d'octets. */
+int finish_quality_rating(const bitfield_t *, size_t);
+
+/* Détermine la portion idéale de recherche. */
+void find_best_atom(const sized_binary_t *, size_t , tracked_scan_atom_t *, size_t *);
+
+/* Etablit la liste des cas de figures ignorant la casse. */
+sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *, size_t);
+
+/* Enregistre l'atome déterminé d'une série d'octets. */
+bool enroll_prepared_atom(const sized_binary_t *, GScanContext *, GEngineBackend *, tracked_scan_atom_t *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_ATOM_H */
diff --git a/src/analysis/scan/patterns/tokens/hex-int.h b/src/analysis/scan/patterns/tokens/hex-int.h
new file mode 100644
index 0000000..f0460c8
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/hex-int.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex-int.h - prototypes internes pour la recherche de morceaux de 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_PATTERNS_TOKENS_HEX_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_HEX_INT_H
+
+
+#include "hex.h"
+
+
+#include "atom.h"
+#include "../token-int.h"
+
+
+
+/* Encadrement d'une recherche de morceaux de binaire (instance) */
+struct _GScanHexBytes
+{
+    GStringToken parent;                    /* A laisser en premier        */
+
+};
+
+/* Encadrement d'une recherche de morceaux de binaire (classe) */
+struct _GScanHexBytesClass
+{
+    GStringTokenClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Met en place un gestionnaire de recherche de binaire. */
+bool g_scan_hex_bytes_create(GScanHexBytes *, GScanTokenNode *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_HEX_INT_H */
diff --git a/src/analysis/scan/patterns/tokens/hex.c b/src/analysis/scan/patterns/tokens/hex.c
new file mode 100644
index 0000000..c1cdbdf
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/hex.c
@@ -0,0 +1,457 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.c - recherche de morceaux de 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 "hex.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "hex-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des recherches de texte brut. */
+static void g_scan_hex_bytes_class_init(GScanHexBytesClass *klass);
+
+/* Initialise une instance de recherche de texte brut. */
+static void g_scan_hex_bytes_init(GScanHexBytes *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_hex_bytes_dispose(GScanHexBytes *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_hex_bytes_finalize(GScanHexBytes *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Affiche un motif de recherche au format texte. */
+static void g_scan_hex_bytes_output_to_text(const GScanHexBytes *, GScanContext *, int);
+
+/* Affiche un motif de recherche au format JSON. */
+static void g_scan_hex_bytes_output_to_json(const GScanHexBytes *, GScanContext *, const sized_string_t *, unsigned int, int);
+
+/* Inscrit la définition d'un motif dans un moteur de recherche. */
+//static bool g_scan_hex_bytes_enroll(GScanHexBytes *, GScanContext *, GEngineBackend *, size_t);
+
+/* Transforme les correspondances locales en trouvailles. */
+//static void g_scan_hex_bytes_check(const GScanHexBytes *, GScanContext *, GBinContent *, pending_matches_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         RECHERCHE D'UN MOTIF DE TEXTE BRUT                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */
+G_DEFINE_TYPE(GScanHexBytes, g_scan_hex_bytes, G_TYPE_STRING_TOKEN);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des recherches de texte brut.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_bytes_class_init(GScanHexBytesClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GSearchPatternClass *pattern;           /* Version de classe ancêtre   */
+    GStringTokenClass *token;               /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_hex_bytes_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_hex_bytes_finalize;
+
+    pattern = G_SEARCH_PATTERN_CLASS(klass);
+
+    pattern->to_text = (output_pattern_to_text_fc)g_scan_hex_bytes_output_to_text;
+    pattern->to_json = (output_pattern_to_json_fc)g_scan_hex_bytes_output_to_json;
+
+    token = G_STRING_TOKEN_CLASS(klass);
+
+    //token->enroll = (enroll_token_fc)g_scan_hex_bytes_enroll;
+    //token->check = (check_token_fc)g_scan_hex_bytes_check;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bytes = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une instance de recherche de texte brut.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_bytes_init(GScanHexBytes *bytes)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bytes = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_bytes_dispose(GScanHexBytes *bytes)
+{
+    G_OBJECT_CLASS(g_scan_hex_bytes_parent_class)->dispose(G_OBJECT(bytes));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bytes = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_bytes_finalize(GScanHexBytes *bytes)
+{
+    G_OBJECT_CLASS(g_scan_hex_bytes_parent_class)->finalize(G_OBJECT(bytes));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : root  = représentation du motif à recherche.                 *
+*                                                                             *
+*  Description : Construit un gestionnaire de recherche de texte brut.        *
+*                                                                             *
+*  Retour      : Mécanismes mis en place.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GSearchPattern *g_scan_hex_bytes_new(GScanTokenNode *root)
+{
+    GSearchPattern *result;                 /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_HEX_BYTES, NULL);
+
+    if (!g_scan_hex_bytes_create(G_SCAN_HEX_BYTES(result), root))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bytes = encadrement de motif à initialiser pleinement.       *
+*                root  = représentation du motif à recherche.                 *
+*                                                                             *
+*  Description : Met en place un gestionnaire de recherche de binaire.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_hex_bytes_create(GScanHexBytes *bytes, GScanTokenNode *root)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_string_token_create(G_STRING_TOKEN(bytes), root);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = définition de motif à considérer.                  *
+*                context = contexte de l'analyse à mener.                     *
+*                fd      = canal d'écriture.                                  *
+*                                                                             *
+*  Description : Affiche un motif de recherche au format texte.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_bytes_output_to_text(const GScanHexBytes *pattern, GScanContext *context, int fd)
+{
+    G_SEARCH_PATTERN_CLASS(g_scan_hex_bytes_parent_class)->to_text(G_SEARCH_PATTERN(pattern), context, fd);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = définition de motif à considérer.                  *
+*                context  = contexte de l'analyse à mener.                    *
+*                padding  = éventuel bourrage initial à placer ou NULL.       *
+*                level    = profondeur actuelle.                              *
+*                fd       = canal d'écriture.                                 *
+*                                                                             *
+*  Description : Affiche un motif de recherche au format JSON.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_bytes_output_to_json(const GScanHexBytes *pattern, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd)
+{
+    G_SEARCH_PATTERN_CLASS(g_scan_hex_bytes_parent_class)->to_json(G_SEARCH_PATTERN(pattern), context, padding, level, fd);
+
+    /* TODO */
+
+}
+
+#if 0
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bytes   = définition de la bribe à enregistrer.              *
+*                context = contexte de l'analyse à mener.                     *
+*                backend = moteur de recherche à préchauffer.                 *
+*                maxsize = taille max. des atomes (mise en commun optimisée). *
+*                                                                             *
+*  Description : Inscrit la définition d'un motif dans un moteur de recherche.*
+*                                                                             *
+*  Retour      : Bilan de l'opération à renvoyer.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_hex_bytes_enroll(GScanHexBytes *bytes, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+{
+    bool result;                            /* Statut à retourner          */
+    size_t i;                               /* Boucle de parcours #1       */
+    tracked_scan_atom_t atom;               /* Atome identifié             */
+    size_t letters;                         /* Nombre de lettres présentes */
+    size_t k;                               /* Boucle de parcours #2       */
+    size_t extra_count;                     /* Quantité pour l'exhaustivité*/
+    sized_binary_t *extra;                  /* Couverture supplémntaire    */
+    size_t remaining;                       /* Quantité restant à traiter  */
+
+    /* Génération d'une base de chaînes à couvrir */
+
+    if (bytes->modifier == NULL)
+    {
+        bytes->raw = malloc(sizeof(sized_binary_t));
+        bytes->count = 1;
+
+        szstrdup(&bytes[0].raw[0], &bytes->orig);
+
+        result = true;
+
+    }
+    else
+        result = g_scan_token_modifier_transform(bytes->modifier, &bytes->orig, &bytes->raw, &bytes->count);
+
+    if (!result)
+        goto exit;
+
+    /* Préparation pour la mémorisation des atomes */
+
+    bytes->atoms = malloc(bytes->count * sizeof(tracked_scan_atom_t));
+
+    /* Recherche des atomes */
+
+    for (i = 0; i < bytes->count; i++)
+    {
+        if (bytes->flags & SPBF_CASE_INSENSITIVE)
+        {
+            find_best_atom(&bytes->raw[i], maxsize, &atom, &letters);
+
+            if (letters == 0)
+                bytes->atoms[i] = atom;
+
+            /* Insertion des combinaisons pour couvrir toutes les casses */
+            else
+            {
+                for (k = 0, extra_count = 1; k < letters; k++, extra_count *= 2)
+                    ;
+
+                extra = make_atoms_case_insensitive(&bytes->raw[i], extra_count);
+
+                remaining = bytes->count - i - 1;
+
+                bytes->count += (extra_count - 1);
+
+                bytes->raw = realloc(bytes->raw, bytes->count * sizeof(sized_binary_t));
+
+                memmove(&bytes->raw[i + extra_count], &bytes->raw[i + 1], remaining * sizeof(sized_binary_t));
+
+                for (k = 0; k < extra_count; k++)
+                    bytes->raw[i + k] = extra[k];
+
+                free(extra);
+
+                bytes->atoms = realloc(bytes->raw, bytes->count * sizeof(tracked_scan_atom_t));
+
+                for (k = 0; k < extra_count; k++)
+                    bytes->atoms[i + k] = atom;
+
+                i += extra_count - 1;
+
+            }
+
+        }
+
+        else
+            find_best_atom(&bytes->raw[i], maxsize, &bytes->atoms[i], &letters);
+
+    }
+
+    /* Enregistrements en masse */
+
+
+    for (i = 0; i < bytes->count && result; i++)
+        result = enroll_prepared_atom(&bytes->raw[i], context, backend, &bytes->atoms[i]);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bytes   = définition de la bribe à manipuler.                *
+*                context = contexte de l'analyse à mener.                     *
+*                content = accès au contenu brut pour vérifications (optim.)  *
+*                matches = suivi des correspondances à consolider.            *
+*                                                                             *
+*  Description : Transforme les correspondances locales en trouvailles.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_hex_bytes_check(const GScanHexBytes *bytes, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+{
+    size_t i;                               /* Boucle de parcours #1       */
+    const sized_binary_t *raw;              /* Données brutes d'origine    */
+    const tracked_scan_atom_t *atom;        /* Atome correspondant         */
+    size_t count;                           /* Quantité de bribes trouvées */
+    const phys_t *found;                    /* Localisations des bribes    */
+    size_t k;                               /* Boucle de parcours #2       */
+    phys_t start;                           /* Point de départ             */
+    vmpa2t pos;                             /* Position dans les données   */
+    const bin_t *ptr;                       /* Accès aux données brutes    */
+    int ret;                                /* Bilan d'une comparaison     */
+
+    for (i = 0; i < bytes->count; i++)
+    {
+        raw = &bytes->raw[i];
+        atom = &bytes->atoms[i];
+
+        found = g_scan_context_get_atom_matches(context, atom->pid, &count);
+
+        for (k = 0; k < count; k++)
+        {
+            start = found[k] - atom->pos;
+
+            init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
+
+            /* Validation du contenu avant l'atome */
+
+            if (atom->pos > 0)
+            {
+                ptr = g_binary_content_get_raw_access(content, &pos, atom->pos);
+
+                ret = memcmp(raw->data, ptr, atom->pos);
+                if (ret != 0) continue;
+
+            }
+
+            /* Validation du contenu après l'atome */
+
+            if (atom->rem > 0)
+            {
+                advance_vmpa(&pos, atom->len);
+
+                ptr = g_binary_content_get_raw_access(content, &pos, atom->rem);
+
+                ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem);
+                if (ret != 0) continue;
+
+            }
+
+            /* Mémorisation de la correspondance */
+
+            add_pending_matches(matches, start, raw->len);
+
+        }
+
+    }
+
+}
+
+#endif
diff --git a/src/analysis/scan/patterns/tokens/hex.h b/src/analysis/scan/patterns/tokens/hex.h
new file mode 100644
index 0000000..1db8eb6
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/hex.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.h - prototypes pour la recherche de morceaux de 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_PATTERNS_TOKENS_HEX_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_HEX_H
+
+
+#include <glib-object.h>
+
+
+#include "node.h"
+#include "../../pattern.h"
+
+
+
+#define G_TYPE_SCAN_HEX_BYTES            g_scan_hex_bytes_get_type()
+#define G_SCAN_HEX_BYTES(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_HEX_BYTES, GScanHexBytes))
+#define G_IS_SCAN_HEX_BYTES(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_HEX_BYTES))
+#define G_SCAN_HEX_BYTES_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_HEX_BYTES, GScanHexBytesClass))
+#define G_IS_SCAN_HEX_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_HEX_BYTES))
+#define G_SCAN_HEX_BYTES_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_HEX_BYTES, GScanHexBytesClass))
+
+
+/* Encadrement d'une recherche de morceaux de binaire (instance) */
+typedef struct _GScanHexBytes GScanHexBytes;
+
+/* Encadrement d'une recherche de morceaux de binaire (classe) */
+typedef struct _GScanHexBytesClass GScanHexBytesClass;
+
+
+/* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */
+GType g_scan_hex_bytes_get_type(void);
+
+/* Construit un gestionnaire de recherche de texte brut. */
+GSearchPattern *g_scan_hex_bytes_new(GScanTokenNode *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_HEX_H */
diff --git a/src/analysis/scan/patterns/tokens/node-int.h b/src/analysis/scan/patterns/tokens/node-int.h
new file mode 100644
index 0000000..c543cbf
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/node-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * node-int.h - prototypes internes pour la décomposition d'un motif de recherche en atomes assemblés
+ *
+ * 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_PATTERNS_TOKENS_NODE_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODE_INT_H
+
+
+#include "node.h"
+
+
+
+/* Inscrit la définition d'un motif dans un moteur de recherche. */
+typedef bool (* enroll_scan_token_node_fc) (GScanTokenNode *, GScanContext *, GEngineBackend *, size_t);
+
+/* Transforme les correspondances locales en trouvailles. */
+typedef void (* check_scan_token_node_fc) (const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, const node_search_offset_t *);
+
+
+/* Décomposition d'un motif de recherche en atomes (instance) */
+struct _GScanTokenNode
+{
+    GObject parent;                         /* A laisser en premier        */
+
+};
+
+/* Décomposition d'un motif de recherche en atomes (classe) */
+struct _GScanTokenNodeClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+    enroll_scan_token_node_fc enroll;       /* Inscription d'un motif      */
+    check_scan_token_node_fc check;         /* Conversion en trouvailles   */
+
+};
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODE_INT_H */
diff --git a/src/analysis/scan/patterns/tokens/node.c b/src/analysis/scan/patterns/tokens/node.c
new file mode 100644
index 0000000..224328a
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/node.c
@@ -0,0 +1,195 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * node.c - décomposition d'un motif de recherche en atomes assemblés
+ *
+ * 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 "node.h"
+
+
+#include <assert.h>
+
+
+#include "node-int.h"
+
+
+
+/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */
+
+
+/* Initialise la classe des éléments de décomposition. */
+static void g_scan_token_node_class_init(GScanTokenNodeClass *klass);
+
+/* Initialise une instance d'élément décomposant un motif. */
+static void g_scan_token_node_init(GScanTokenNode *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_token_node_dispose(GScanTokenNode *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_token_node_finalize(GScanTokenNode *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          DECOMPOSITION DE MOTIF RECHERCHE                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un élément décomposant un motif d'octets à rechercher. */
+G_DEFINE_TYPE(GScanTokenNode, g_scan_token_node, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des éléments de décomposition.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_class_init(GScanTokenNodeClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_node_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_token_node_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : node = instance à initialiser.                               *
+*                                                                             *
+*  Description : Initialise une instance d'élément décomposant un motif.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_init(GScanTokenNode *node)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : node = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_dispose(GScanTokenNode *node)
+{
+    G_OBJECT_CLASS(g_scan_token_node_parent_class)->dispose(G_OBJECT(node));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : node = instance d'objet GLib à traiter.                      *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_finalize(GScanTokenNode *node)
+{
+    G_OBJECT_CLASS(g_scan_token_node_parent_class)->finalize(G_OBJECT(node));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : node    = définition de la bribe à enregistrer.              *
+*                context = contexte de l'analyse à mener.                     *
+*                backend = moteur de recherche à préchauffer.                 *
+*                maxsize = taille max. des atomes (mise en commun optimisée). *
+*                                                                             *
+*  Description : Inscrit la définition d'un motif dans un moteur de recherche.*
+*                                                                             *
+*  Retour      : Bilan de l'opération à renvoyer.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+{
+    bool result;                            /* Statut à retourner          */
+    GScanTokenNodeClass *class;             /* Classe de l'instance        */
+
+    assert(g_engine_backend_get_atom_max_size(backend) == maxsize);
+
+    class = G_SCAN_TOKEN_NODE_GET_CLASS(node);
+
+    result = class->enroll(node, context, backend, maxsize);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : node    = définition de la bribe à manipuler.                *
+*                context = contexte de l'analyse à mener.                     *
+*                content = accès au contenu brut pour vérifications (optim.)  *
+*                matches = suivi des correspondances à consolider.            *
+*                offset  = tolérance dans les positions à appliquer.          *
+*                                                                             *
+*  Description : Transforme les correspondances locales en trouvailles.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_token_node_check(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, const node_search_offset_t *offset)
+{
+    GScanTokenNodeClass *class;             /* Classe de l'instance        */
+
+    class = G_SCAN_TOKEN_NODE_GET_CLASS(node);
+
+    class->check(node, context, content, matches, offset);
+
+}
diff --git a/src/analysis/scan/patterns/tokens/node.h b/src/analysis/scan/patterns/tokens/node.h
new file mode 100644
index 0000000..4c9eb48
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/node.h
@@ -0,0 +1,77 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * node.h - prototypes pour la décomposition d'un motif de recherche en atomes assemblés
+ *
+ * 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_PATTERNS_TOKENS_NODE_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../backend.h"
+#include "../../context.h"
+#include "../../matches/pending.h"
+
+
+#define G_TYPE_SCAN_TOKEN_NODE            g_scan_token_node_get_type()
+#define G_SCAN_TOKEN_NODE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE, GScanTokenNode))
+#define G_IS_SCAN_TOKEN_NODE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE))
+#define G_SCAN_TOKEN_NODE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE, GScanTokenNodeClass))
+#define G_IS_SCAN_TOKEN_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE))
+#define G_SCAN_TOKEN_NODE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE, GScanTokenNodeClass))
+
+
+/* Décomposition d'un motif de recherche en atomes (instance) */
+typedef struct _GScanTokenNode GScanTokenNode;
+
+/* Décomposition d'un motif de recherche en atomes (classe) */
+typedef struct _GScanTokenNodeClass GScanTokenNodeClass;
+
+
+/* Indique le type défini pour un élément décomposant un motif d'octets à rechercher. */
+GType g_scan_token_node_get_type(void);
+
+
+// TODO
+// validate
+// force_plain_registration // set begin/end
+
+
+/* Inscrit la définition d'un motif dans un moteur de recherche. */
+bool g_scan_token_node_enroll(GScanTokenNode *, GScanContext *, GEngineBackend *, size_t);
+
+/* Mémorisation d'une souplesse dans les positions visées */
+typedef struct _node_search_offset_t
+{
+    phys_t min;                             /* Position minimale           */
+    phys_t max;                             /* Position maxnimale           */
+
+} node_search_offset_t;
+
+/* Transforme les correspondances locales en trouvailles. */
+void g_scan_token_node_check(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, const node_search_offset_t *);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODE_H */
diff --git a/src/analysis/scan/patterns/tokens/nodes/Makefile.am b/src/analysis/scan/patterns/tokens/nodes/Makefile.am
new file mode 100644
index 0000000..c20beaf
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/Makefile.am
@@ -0,0 +1,16 @@
+
+noinst_LTLIBRARIES  = libanalysisscanpatternstokensnodes.la
+
+
+libanalysisscanpatternstokensnodes_la_SOURCES =	\
+	hub-int.h								\
+	hub.h hub.c								\
+	plain-int.h								\
+	plain.h plain.c
+
+libanalysisscanpatternstokensnodes_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanpatternstokensnodes_la_SOURCES:%c=)
diff --git a/src/analysis/scan/patterns/tokens/nodes/hub-int.h b/src/analysis/scan/patterns/tokens/nodes/hub-int.h
new file mode 100644
index 0000000..df05112
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/hub-int.h
@@ -0,0 +1,51 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hub-int.h - prototypes internes pour un groupe de décompositions de motif de recherche en atomes assemblés
+ *
+ * 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_PATTERNS_TOKENS_NODES_HUB_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_INT_H
+
+
+#include "hub.h"
+
+
+#include "../node-int.h"
+
+
+
+/* Groupe de décompositions de motif de recherche en atomes (instance) */
+struct _GScanTokenNodeHub
+{
+    GScanTokenNode parent;                  /* A laisser en premier        */
+
+};
+
+/* Groupe de décompositions de motif de recherche en atomes (classe) */
+struct _GScanTokenNodeHubClass
+{
+    GScanTokenNodeClass parent;             /* A laisser en premier        */
+
+};
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_INT_H */
diff --git a/src/analysis/scan/patterns/tokens/nodes/hub.c b/src/analysis/scan/patterns/tokens/nodes/hub.c
new file mode 100644
index 0000000..a11531d
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/hub.c
@@ -0,0 +1,150 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hub.c - groupe de décompositions de motif de recherche en atomes assemblés
+ *
+ * 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 "hub.h"
+
+
+#include "hub-int.h"
+
+
+
+/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */
+
+
+/* Initialise la classe des groupes de décompositions. */
+static void g_scan_token_node_hub_class_init(GScanTokenNodeHubClass *klass);
+
+/* Initialise une instance de groupe de décompositions. */
+static void g_scan_token_node_hub_init(GScanTokenNodeHub *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_token_node_hub_dispose(GScanTokenNodeHub *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_token_node_hub_finalize(GScanTokenNodeHub *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          DECOMPOSITION DE MOTIF RECHERCHE                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un groupe de décompositions de motif d'octets à rechercher. */
+G_DEFINE_TYPE(GScanTokenNodeHub, g_scan_token_node_hub, G_TYPE_SCAN_TOKEN_NODE);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des groupes de décompositions.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_hub_class_init(GScanTokenNodeHubClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_node_hub_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_token_node_hub_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : hub = instance à initialiser.                                *
+*                                                                             *
+*  Description : Initialise une instance de groupe de décompositions.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_hub_init(GScanTokenNodeHub *hub)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : hub = instance d'objet GLib à traiter.                       *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_hub_dispose(GScanTokenNodeHub *hub)
+{
+    G_OBJECT_CLASS(g_scan_token_node_hub_parent_class)->dispose(G_OBJECT(hub));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : hub = instance d'objet GLib à traiter.                       *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_hub_finalize(GScanTokenNodeHub *hub)
+{
+    G_OBJECT_CLASS(g_scan_token_node_hub_parent_class)->finalize(G_OBJECT(hub));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+
+
diff --git a/src/analysis/scan/patterns/tokens/nodes/hub.h b/src/analysis/scan/patterns/tokens/nodes/hub.h
new file mode 100644
index 0000000..b2cb0fc
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/hub.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hub.h - prototypes pour un groupe de décompositions de motif de recherche en atomes assemblés
+ *
+ * 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_PATTERNS_TOKENS_NODES_HUB_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_H
+
+
+#include <glib-object.h>
+
+
+#include "../node.h"
+
+
+
+#define G_TYPE_SCAN_TOKEN_NODE_HUB            g_scan_token_node_hub_get_type()
+#define G_SCAN_TOKEN_NODE_HUB(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE_HUB, GScanTokenNodeHub))
+#define G_IS_SCAN_TOKEN_NODE_HUB(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE_HUB))
+#define G_SCAN_TOKEN_NODE_HUB_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE_HUB, GScanTokenNodeHubClass))
+#define G_IS_SCAN_TOKEN_NODE_HUB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE_HUB))
+#define G_SCAN_TOKEN_NODE_HUB_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE_HUB, GScanTokenNodeHubClass))
+
+
+/* Groupe de décompositions de motif de recherche en atomes (instance) */
+typedef struct _GScanTokenNodeHub GScanTokenNodeHub;
+
+/* Groupe de décompositions de motif de recherche en atomes (classe) */
+typedef struct _GScanTokenNodeHubClass GScanTokenNodeHubClass;
+
+
+/* Indique le type défini pour un groupe de décompositions de motif d'octets à rechercher. */
+GType g_scan_token_node_hub_get_type(void);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_H */
diff --git a/src/analysis/scan/patterns/tokens/nodes/plain-int.h b/src/analysis/scan/patterns/tokens/nodes/plain-int.h
new file mode 100644
index 0000000..a38359d
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/plain-int.h
@@ -0,0 +1,64 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain-int.h - prototypes internes pour la gestion d'une recherche de motif textuel
+ *
+ * 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_PATTERNS_TOKENS_NODES_PLAIN_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_PLAIN_INT_H
+
+
+#include "plain.h"
+
+
+#include "../node-int.h"
+#include "../atom.h"
+
+
+
+/* Bribe de motif textuelle pour recherches (instance) */
+struct _GScanTokenNodePlain
+{
+    GScanTokenNode parent;                  /* A laisser en premier        */
+
+    sized_binary_t orig;                    /* Motif d'origine avant modifs*/
+    GScanTokenModifier *modifier;           /* Transformateur pour le motif*/
+    ScanPlainNodeFlags flags;               /* Fanions associés au motif   */
+
+    sized_binary_t *raw;                    /* Liste de motifs à couvrir   */
+    tracked_scan_atom_t *atoms;             /* Atomes correspondants       */
+    size_t count;                           /* Taille de cette liste       */
+
+};
+
+/* Bribe de motif textuelle pour recherches (instance) */
+struct _GScanTokenNodePlainClass
+{
+    GScanTokenNodeClass parent;             /* A laisser en premier        */
+
+};
+
+
+/* Met en place un un noeud représentant un motif textuel. */
+bool g_scan_token_node_plain_create(GScanTokenNodePlain *, const sized_binary_t *, GScanTokenModifier *, ScanPlainNodeFlags);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_PLAIN_INT_H */
diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.c b/src/analysis/scan/patterns/tokens/nodes/plain.c
new file mode 100644
index 0000000..ee87c73
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/plain.c
@@ -0,0 +1,582 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.c - gestion d'une recherche de motif textuel
+ *
+ * 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 "plain.h"
+
+
+#include "plain-int.h"
+
+
+
+/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */
+
+
+/* Initialise la classe des noeuds pour motif textuel. */
+static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *klass);
+
+/* Initialise une instance de noeud pour motif textuel. */
+static void g_scan_token_node_plain_init(GScanTokenNodePlain *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_token_node_plain_dispose(GScanTokenNodePlain *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_token_node_plain_finalize(GScanTokenNodePlain *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Inscrit la définition d'un motif dans un moteur de recherche. */
+static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *, GScanContext *, GEngineBackend *, size_t );
+
+/* Détermine si un contenu d'intérêt est présent à une position. */
+static bool check_scan_token_node_plain_content(const sized_binary_t *, const tracked_scan_atom_t *, phys_t, GBinContent *);
+
+/* Transforme les correspondances locales en trouvailles. */
+static void g_scan_plain_bytes_check(const GScanTokenNodePlain *, GScanContext *, GBinContent *, pending_matches_t *, const node_search_offset_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          DECOMPOSITION DE MOTIF RECHERCHE                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un noeud représentant une bribe de texte à retrouver. */
+G_DEFINE_TYPE(GScanTokenNodePlain, g_scan_token_node_plain, G_TYPE_SCAN_TOKEN_NODE);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des noeuds pour motif textuel.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GScanTokenNodeClass *node;              /* Version de classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_node_plain_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_token_node_plain_finalize;
+
+    node = G_SCAN_TOKEN_NODE_CLASS(klass);
+
+    node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_plain_enroll;
+    node->check = (check_scan_token_node_fc)g_scan_plain_bytes_check;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plain = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une instance de noeud pour motif textuel.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_plain_init(GScanTokenNodePlain *plain)
+{
+    init_szstr(&plain->orig);
+    plain->modifier = NULL;
+    plain->flags = SPNF_NONE;
+
+    plain->raw = NULL;
+    plain->atoms = NULL;
+    plain->count = 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plain = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_plain_dispose(GScanTokenNodePlain *plain)
+{
+    g_clear_object(&plain->modifier);
+
+    G_OBJECT_CLASS(g_scan_token_node_plain_parent_class)->dispose(G_OBJECT(plain));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plain = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_token_node_plain_finalize(GScanTokenNodePlain *plain)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    exit_szstr(&plain->orig);
+
+    for (i = 0; i < plain->count; i++)
+        exit_szstr(&plain->raw[i]);
+
+    if (plain->raw != NULL)
+        free(plain->raw);
+
+    if (plain->atoms != NULL)
+        free(plain->atoms);
+
+    G_OBJECT_CLASS(g_scan_token_node_plain_parent_class)->finalize(G_OBJECT(plain));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : text     = texte brut à rechercher.                          *
+*                modifier = transformateur éventuel à solliciter.             *
+*                flags    = particularités à prendre en considération.        *
+*                                                                             *
+*  Description : Construit un noeud représentant un motif textuel.            *
+*                                                                             *
+*  Retour      : Mécanismes mis en place.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanTokenNode *g_scan_token_node_plain_new(const sized_binary_t *text, GScanTokenModifier *modifier, ScanPlainNodeFlags flags)
+{
+    GScanTokenNode *result;                 /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_TOKEN_NODE_PLAIN, NULL);
+
+    if (!g_scan_token_node_plain_create(G_SCAN_TOKEN_NODE_PLAIN(result), text, modifier, flags))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plain    = encadrement de motif à initialiser pleinement.    *
+*                text     = texte brut à rechercher.                          *
+*                modifier = transformateur éventuel à solliciter.             *
+*                flags    = particularités à prendre en considération.        *
+*                                                                             *
+*  Description : Met en place un un noeud représentant un motif textuel.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_token_node_plain_create(GScanTokenNodePlain *plain, const sized_binary_t *text, GScanTokenModifier *modifier, ScanPlainNodeFlags flags)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    szstrdup(&plain->orig, text);
+
+    if (modifier != NULL)
+    {
+        plain->modifier = modifier;
+        g_object_ref(G_OBJECT(modifier));
+    }
+
+    plain->flags = flags;
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : node    = définition de la bribe à enregistrer.              *
+*                context = contexte de l'analyse à mener.                     *
+*                backend = moteur de recherche à préchauffer.                 *
+*                maxsize = taille max. des atomes (mise en commun optimisée). *
+*                                                                             *
+*  Description : Inscrit la définition d'un motif dans un moteur de recherche.*
+*                                                                             *
+*  Retour      : Bilan de l'opération à renvoyer.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+{
+    bool result;                            /* Statut à retourner          */
+    size_t i;                               /* Boucle de parcours #1       */
+    tracked_scan_atom_t atom;               /* Atome identifié             */
+    size_t letters;                         /* Nombre de lettres présentes */
+    size_t k;                               /* Boucle de parcours #2       */
+    size_t extra_count;                     /* Quantité pour l'exhaustivité*/
+    sized_binary_t *extra;                  /* Couverture supplémntaire    */
+    size_t remaining;                       /* Quantité restant à traiter  */
+
+    /* Génération d'une base de chaînes à couvrir */
+
+    if (node->modifier == NULL)
+    {
+        node->raw = malloc(sizeof(sized_binary_t));
+        node->count = 1;
+
+        szstrdup(&node->raw[0], &node->orig);
+
+        result = true;
+
+    }
+    else
+        result = g_scan_token_modifier_transform(node->modifier, &node->orig, &node->raw, &node->count);
+
+    if (!result)
+        goto exit;
+
+    /* Préparation pour la mémorisation des atomes */
+
+    node->atoms = malloc(node->count * sizeof(tracked_scan_atom_t));
+
+    /* Validation du besoin effectif dans les cas extrèmes */
+
+
+
+    // TODO : if (orig.len < ...)
+
+
+
+    /* Recherche des atomes */
+
+    for (i = 0; i < node->count; i++)
+    {
+        if (node->flags & SPNF_CASE_INSENSITIVE)
+        {
+            find_best_atom(&node->raw[i], maxsize, &atom, &letters);
+
+            if (letters == 0)
+                node->atoms[i] = atom;
+
+            /* Insertion des combinaisons pour couvrir toutes les casses */
+            else
+            {
+                for (k = 0, extra_count = 1; k < letters; k++, extra_count *= 2)
+                    ;
+
+                extra = make_atoms_case_insensitive(&node->raw[i], extra_count);
+
+                remaining = node->count - i - 1;
+
+                node->count += (extra_count - 1);
+
+                node->raw = realloc(node->raw, node->count * sizeof(sized_binary_t));
+
+                memmove(&node->raw[i + extra_count], &node->raw[i + 1], remaining * sizeof(sized_binary_t));
+
+                for (k = 0; k < extra_count; k++)
+                    node->raw[i + k] = extra[k];
+
+                free(extra);
+
+                node->atoms = realloc(node->raw, node->count * sizeof(tracked_scan_atom_t));
+
+                for (k = 0; k < extra_count; k++)
+                    node->atoms[i + k] = atom;
+
+                i += extra_count - 1;
+
+            }
+
+        }
+
+        else
+            find_best_atom(&node->raw[i], maxsize, &node->atoms[i], &letters);
+
+    }
+
+    /* Enregistrements en masse */
+
+    for (i = 0; i < node->count && result; i++)
+        result = enroll_prepared_atom(&node->raw[i], context, backend, &node->atoms[i]);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : raw     = contneu brut à retrouver idéalement.               *
+*                atom    = contenu brut représentatif ciblé.                  *
+*                start   = point d'analyse à respecter.                       *
+*                content = accès au contenu brut pour vérifications (optim.)  *
+*                                                                             *
+*  Description : Détermine si un contenu d'intérêt est présent à une position.*
+*                                                                             *
+*  Retour      : Bilan de l'analyse : true pour une correspondance.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const tracked_scan_atom_t *atom, phys_t start, GBinContent *content)
+{
+    bool result;                            /* Bilan à retourner           */
+    vmpa2t pos;                             /* Position dans les données   */
+    const bin_t *ptr;                       /* Accès aux données brutes    */
+    int ret;                                /* Bilan d'une comparaison     */
+
+    result = false;
+
+    init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
+
+    /* Validation du contenu avant l'atome */
+
+    if (atom->pos > 0)
+    {
+        ptr = g_binary_content_get_raw_access(content, &pos, atom->pos);
+
+        ret = memcmp(raw->data, ptr, atom->pos);
+        if (ret != 0) goto done;
+
+    }
+
+    /* Validation du contenu après l'atome */
+
+    if (atom->rem > 0)
+    {
+        advance_vmpa(&pos, atom->len);
+
+        ptr = g_binary_content_get_raw_access(content, &pos, atom->rem);
+
+        ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem);
+        if (ret != 0) goto done;
+
+    }
+
+    result = true;
+
+ done:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : node    = définition de la bribe à manipuler.                *
+*                context = contexte de l'analyse à mener.                     *
+*                content = accès au contenu brut pour vérifications (optim.)  *
+*                matches = suivi des correspondances à consolider.            *
+*                offset  = tolérance dans les positions à appliquer.          *
+*                                                                             *
+*  Description : Transforme les correspondances locales en trouvailles.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, const node_search_offset_t *offset)
+{
+    bool initialized;                       /* Initialisation du suivi ?   */
+    size_t i;                               /* Boucle de parcours #1       */
+    const sized_binary_t *raw;              /* Données brutes d'origine    */
+    const tracked_scan_atom_t *atom;        /* Atome correspondant         */
+    size_t count;                           /* Quantité de bribes trouvées */
+    const phys_t *found;                    /* Localisations des bribes    */
+    size_t k;                               /* Boucle de parcours #2       */
+    phys_t start;                           /* Point de départ             */
+    bool status;                            /* Bilan d'une correspondance  */
+    size_t pcount;                          /* Nombre de correspondances   */
+    size_t p;                               /* Boucle de parcours #3       */
+
+    initialized = are_pending_matches_initialized(matches);
+
+    for (i = 0; i < node->count; i++)
+    {
+        raw = &node->raw[i];
+        atom = &node->atoms[i];
+
+        found = g_scan_context_get_atom_matches(context, atom->pid, &count);
+
+        if (!initialized)
+        {
+            for (k = 0; k < count; k++)
+            {
+                start = found[k] - atom->pos;
+
+                /**
+                 * Si personne n'a manipulé les pré-résultats, mais qu'un décallage
+                 * est spécifié par un noeud précédent, une validation sur la base
+                 * d'une position 0 est menée.
+                 */
+                if (offset != NULL)
+                {
+                    if (start < offset->min || start > offset->max)
+                        continue;
+                }
+
+                status = check_scan_token_node_plain_content(raw, atom, start, content);
+
+                if (status)
+                    /**
+                     * Il ne peut y avoir qu'une seule séquence d'octets à un même
+                     * emplacement, donc le couple (start, len) enregistré est
+                     * unique.
+                     */
+                    add_pending_match(matches, start, raw->len);
+
+            }
+
+        }
+
+        else
+        {
+            reset_pending_matches_ttl(matches);
+
+            pcount = count_pending_matches(matches);
+
+            for (p = 0; p < pcount; p++)
+                for (k = 0; k < count; k++)
+                {
+                    start = found[k] - atom->pos;
+
+                    /**
+                     * Si bornes de tolérance il y a, on valide la position.
+                     *
+                     * Sinon les correspondances passées et actuelle doivent
+                     * être jointes.
+                     */
+                    if (offset != NULL)
+                    {
+                        if (!has_pending_match_ending_between(matches, p, start, offset->min, offset->max))
+                            continue;
+                    }
+                    else
+                    {
+                        if (!has_pending_match_ending_at(matches, p, start))
+                            continue;
+                    }
+
+                    status = check_scan_token_node_plain_content(raw, atom, start, content);
+
+                    if (status)
+                    {
+                        /**
+                         * Même si une base de couples uniques est assurée,
+                         * la constitution d'un ensemble de noeuds peut amener une
+                         * redondance dans les emplacements de correspondances.
+                         *
+                         * Par exemple, pour la séquence d'octets analysés suivante :
+                         *
+                         *    aaa....bbb
+                         *
+                         * La définition { (61 61 | 61 61 61) [4-5] 62 62 62 } peut établir
+                         * les correspondances suivantes :
+                         *
+                         *    aa.....bbb -> couple pending[x] (0;2) puis (0;10)
+                         *           ^
+                         *     aa....bbb -> couple pending[y] (1;3) puis (1;10)
+                         *           ^
+                         *    aaa....bbb -> couple pending[z] (0;3) puis (0;10)
+                         *           ^
+                         *
+                         * Par ailleurs, une même base de départ peut conduire
+                         * à plusieurs zone de correspondances.
+                         *
+                         * Par exemple, pour la séquence d'octets analysés suivante :
+                         *
+                         *    aa..bb..bb
+                         *
+                         * La définition { 61 61 [2-6] 62 62 } peut établir
+                         * les correspondances suivantes :
+                         *
+                         *    aa..bb..bb -> couple pending[x] (0;2) puis (0;6)
+                         *        ^
+                         *    aa..bb..bb -> couple pending[x] (0;2) puis (0;10)
+                         *            ^
+                         */
+
+                        /**
+                         * La seconde situation est prise en compte par la fonction
+                         * extend_pending_match() qui s'appuie sur le TTL pour dupliquer
+                         * la correspondance pending[x] initiale. Le nouvel élément est
+                         * placé en fin de liste, ce qui ne boulverse pas le parcours
+                         * de liste courant, la valeur de pcount n'étant pas actualisée.
+                         */
+
+                        extend_pending_match(matches, p, start + raw->len);
+
+                    }
+
+                }
+
+            purge_pending_matches(matches);
+
+        }
+
+    }
+
+    set_pending_matches_initialized(matches);
+
+}
diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.h b/src/analysis/scan/patterns/tokens/nodes/plain.h
new file mode 100644
index 0000000..33e7feb
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/plain.h
@@ -0,0 +1,70 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.h - prototypes pour la gestion d'une recherche de motif textuel
+ *
+ * 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_PATTERNS_TOKENS_NODES_PLAIN_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_PLAIN_H
+
+
+#include <glib-object.h>
+
+
+#include "../node.h"
+#include "../../modifier.h"
+#include "../../../../../common/szstr.h"
+
+
+
+#define G_TYPE_SCAN_TOKEN_NODE_PLAIN            g_scan_token_node_plain_get_type()
+#define G_SCAN_TOKEN_NODE_PLAIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE_PLAIN, GScanTokenNodePlain))
+#define G_IS_SCAN_TOKEN_NODE_PLAIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE_PLAIN))
+#define G_SCAN_TOKEN_NODE_PLAIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE_PLAIN, GScanTokenNodePlainClass))
+#define G_IS_SCAN_TOKEN_NODE_PLAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE_PLAIN))
+#define G_SCAN_TOKEN_NODE_PLAIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE_PLAIN, GScanTokenNodePlainClass))
+
+
+/* Bribe de motif textuelle pour recherches (instance) */
+typedef struct _GScanTokenNodePlain GScanTokenNodePlain;
+
+/* Bribe de motif textuelle pour recherches (classe) */
+typedef struct _GScanTokenNodePlainClass GScanTokenNodePlainClass;
+
+
+/* Propriétés d'un élément textuel à rechercher */
+typedef enum _ScanPlainNodeFlags
+{
+    SPNF_NONE             = 0x0,            /* Aucune particularité        */
+    SPNF_CASE_INSENSITIVE = 0x1,            /* Ignorance de la casse       */
+    SPNF_FULL_WORD        = 0x2,            /* Recherche de mot entier     */
+
+} ScanPlainNodeFlags;
+
+
+/* Indique le type défini pour un noeud représentant une bribe de texte à retrouver. */
+GType g_scan_token_node_plain_get_type(void);
+
+/* Construit un noeud représentant un motif textuel. */
+GScanTokenNode *g_scan_token_node_plain_new(const sized_binary_t *, GScanTokenModifier *, ScanPlainNodeFlags);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_PLAIN_H */
diff --git a/src/analysis/scan/patterns/tokens/plain-int.h b/src/analysis/scan/patterns/tokens/plain-int.h
new file mode 100644
index 0000000..40a71b5
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/plain-int.h
@@ -0,0 +1,64 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain-int.h - prototypes internes pour la recherche d'une chaîne de caractères brute
+ *
+ * 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_PATTERNS_TOKENS_PLAIN_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_PLAIN_INT_H
+
+
+#include "plain.h"
+
+
+#include "atom.h"
+#include "../token-int.h"
+
+
+
+/* Encadrement d'une recherche de texte brut (instance) */
+struct _GScanPlainBytes
+{
+    GStringToken parent;                    /* A laisser en premier        */
+
+    sized_binary_t orig;                    /* Motif d'origine avant modifs*/
+    GScanTokenModifier *modifier;           /* Transformateur pour le motif*/
+    ScanPlainBytesFlags flags;              /* Fanions associés au motif   */
+
+    sized_binary_t *raw;                    /* Liste de motifs à couvrir   */
+    tracked_scan_atom_t *atoms;             /* Atomes correspondants       */
+    size_t count;                           /* Taille de cette liste       */
+
+};
+
+/* Encadrement d'une recherche de texte brut (classe) */
+struct _GScanPlainBytesClass
+{
+    GStringTokenClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Met en place un gestionnaire de recherche de texte brut. */
+bool g_scan_plain_bytes_create(GScanPlainBytes *, const sized_binary_t *, GScanTokenModifier *, ScanPlainBytesFlags);
+
+
+
+#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_PLAIN_INT_H */
diff --git a/src/analysis/scan/patterns/tokens/plain.c b/src/analysis/scan/patterns/tokens/plain.c
index 9eb731e..26e7dfa 100644
--- a/src/analysis/scan/patterns/tokens/plain.c
+++ b/src/analysis/scan/patterns/tokens/plain.c
@@ -28,59 +28,41 @@
 #include <string.h>
 
 
-#include "../token-int.h"
+#include "plain-int.h"
 
 
 
 /* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
 
 
-/* Encadrement d'une recherche de texte brut (instance) */
-struct _GPlainBytes
-{
-    GStringToken parent;                    /* A laisser en premier        */
-
-    uint8_t *raw;                           /* Octets recherchés           */
-    size_t allocated;                       /* Taille allouée              */
-    size_t used;                            /* Quantité d'octets utilisée  */
-
-    phys_t atom_pos;                        /* Début de sélection atomique */
-    phys_t atom_len;                        /* Taille de ladite sélection  */
-    phys_t atom_rem;                        /* Reste après l'atome         */
-    patid_t pid;                            /* Identifiant de la bribe     */
-
-};
-
-/* Encadrement d'une recherche de texte brut (classe) */
-struct _GPlainBytesClass
-{
-    GStringTokenClass parent;               /* A laisser en premier        */
-
-};
-
-
 /* Initialise la classe des recherches de texte brut. */
-static void g_plain_bytes_class_init(GPlainBytesClass *klass);
+static void g_scan_plain_bytes_class_init(GScanPlainBytesClass *klass);
 
 /* Initialise une instance de recherche de texte brut. */
-static void g_plain_bytes_init(GPlainBytes *);
+static void g_scan_plain_bytes_init(GScanPlainBytes *);
 
 /* Supprime toutes les références externes. */
-static void g_plain_bytes_dispose(GPlainBytes *);
+static void g_scan_plain_bytes_dispose(GScanPlainBytes *);
 
 /* Procède à la libération totale de la mémoire. */
-static void g_plain_bytes_finalize(GPlainBytes *);
+static void g_scan_plain_bytes_finalize(GScanPlainBytes *);
 
 
 
 /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
 
 
+/* Affiche un motif de recherche au format texte. */
+static void g_scan_plain_bytes_output_to_text(const GScanPlainBytes *, GScanContext *, int);
+
+/* Affiche un motif de recherche au format JSON. */
+static void g_scan_plain_bytes_output_to_json(const GScanPlainBytes *, GScanContext *, const sized_string_t *, unsigned int, int);
+
 /* Inscrit la définition d'un motif dans un moteur de recherche. */
-static bool g_plain_bytes_enroll(GPlainBytes *, GScanContext *, GEngineBackend *, size_t);
+static bool g_scan_plain_bytes_enroll(GScanPlainBytes *, GScanContext *, GEngineBackend *, size_t);
 
 /* Transforme les correspondances locales en trouvailles. */
-static void g_plain_bytes_check(const GPlainBytes *, GScanContext *, GBinContent *, pending_matches_t *);
+static void g_scan_plain_bytes_check(const GScanPlainBytes *, GScanContext *, GBinContent *, pending_matches_t *);
 
 
 
@@ -90,7 +72,7 @@ static void g_plain_bytes_check(const GPlainBytes *, GScanContext *, GBinContent
 
 
 /* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */
-G_DEFINE_TYPE(GPlainBytes, g_plain_bytes, G_TYPE_STRING_TOKEN);
+G_DEFINE_TYPE(GScanPlainBytes, g_scan_plain_bytes, G_TYPE_STRING_TOKEN);
 
 
 /******************************************************************************
@@ -105,7 +87,7 @@ G_DEFINE_TYPE(GPlainBytes, g_plain_bytes, G_TYPE_STRING_TOKEN);
 *                                                                             *
 ******************************************************************************/
 
-static void g_plain_bytes_class_init(GPlainBytesClass *klass)
+static void g_scan_plain_bytes_class_init(GScanPlainBytesClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
     GSearchPatternClass *pattern;           /* Version de classe ancêtre   */
@@ -113,26 +95,25 @@ static void g_plain_bytes_class_init(GPlainBytesClass *klass)
 
     object = G_OBJECT_CLASS(klass);
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_plain_bytes_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_plain_bytes_finalize;
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_plain_bytes_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_scan_plain_bytes_finalize;
 
     pattern = G_SEARCH_PATTERN_CLASS(klass);
 
-    //pattern->prepare = (prepare_pattern_fc)g_plain_bytes_prepare;
-    //pattern->analyze = (analyze_pattern_fc)g_plain_bytes_analyze;
-    //pattern->count = (count_pattern_matchs_fc);
+    pattern->to_text = (output_pattern_to_text_fc)g_scan_plain_bytes_output_to_text;
+    pattern->to_json = (output_pattern_to_json_fc)g_scan_plain_bytes_output_to_json;
 
     token = G_STRING_TOKEN_CLASS(klass);
 
-    token->enroll = (enroll_token_fc)g_plain_bytes_enroll;
-    token->check = (check_token_fc)g_plain_bytes_check;
+    token->enroll = (enroll_token_fc)g_scan_plain_bytes_enroll;
+    token->check = (check_token_fc)g_scan_plain_bytes_check;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : pattern = instance à initialiser.                            *
+*  Paramètres  : bytes = instance à initialiser.                              *
 *                                                                             *
 *  Description : Initialise une instance de recherche de texte brut.          *
 *                                                                             *
@@ -142,16 +123,15 @@ static void g_plain_bytes_class_init(GPlainBytesClass *klass)
 *                                                                             *
 ******************************************************************************/
 
-static void g_plain_bytes_init(GPlainBytes *bytes)
+static void g_scan_plain_bytes_init(GScanPlainBytes *bytes)
 {
-    bytes->raw = NULL;
-    bytes->allocated = 0;
-    bytes->used = 0;
+    init_szstr(&bytes->orig);
+    bytes->modifier = NULL;
+    bytes->flags = SPBF_NONE;
 
-    bytes->atom_pos = 0;
-    bytes->atom_len = 0;
-    bytes->atom_rem = 0;
-    bytes->pid = INVALID_PATTERN_ID;
+    bytes->raw = NULL;
+    bytes->atoms = NULL;
+    bytes->count = 0;
 
 }
 
@@ -168,9 +148,11 @@ static void g_plain_bytes_init(GPlainBytes *bytes)
 *                                                                             *
 ******************************************************************************/
 
-static void g_plain_bytes_dispose(GPlainBytes *bytes)
+static void g_scan_plain_bytes_dispose(GScanPlainBytes *bytes)
 {
-    G_OBJECT_CLASS(g_plain_bytes_parent_class)->dispose(G_OBJECT(bytes));
+    g_clear_object(&bytes->modifier);
+
+    G_OBJECT_CLASS(g_scan_plain_bytes_parent_class)->dispose(G_OBJECT(bytes));
 
 }
 
@@ -187,20 +169,31 @@ static void g_plain_bytes_dispose(GPlainBytes *bytes)
 *                                                                             *
 ******************************************************************************/
 
-static void g_plain_bytes_finalize(GPlainBytes *bytes)
+static void g_scan_plain_bytes_finalize(GScanPlainBytes *bytes)
 {
+    size_t i;                               /* Boucle de parcours          */
+
+    exit_szstr(&bytes->orig);
+
+    for (i = 0; i < bytes->count; i++)
+        exit_szstr(&bytes->raw[i]);
+
     if (bytes->raw != NULL)
         free(bytes->raw);
 
-    G_OBJECT_CLASS(g_plain_bytes_parent_class)->finalize(G_OBJECT(bytes));
+    if (bytes->atoms != NULL)
+        free(bytes->atoms);
+
+    G_OBJECT_CLASS(g_scan_plain_bytes_parent_class)->finalize(G_OBJECT(bytes));
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : text = texte brut à rechercher.                              *
-*                len  = longueur de ce texte.                                 *
+*  Paramètres  : text     = texte brut à rechercher.                          *
+*                modifier = transformateur éventuel à solliciter.             *
+*                flags    = particularités à prendre en considération.        *
 *                                                                             *
 *  Description : Construit un gestionnaire de recherche de texte brut.        *
 *                                                                             *
@@ -210,19 +203,51 @@ static void g_plain_bytes_finalize(GPlainBytes *bytes)
 *                                                                             *
 ******************************************************************************/
 
-GSearchPattern *g_plain_bytes_new(const uint8_t *raw, size_t len)
+GSearchPattern *g_scan_plain_bytes_new(const sized_binary_t *text, GScanTokenModifier *modifier, ScanPlainBytesFlags flags)
 {
-    GPlainBytes *result;                    /* Structure à retourner       */
+    GSearchPattern *result;                 /* Structure à retourner       */
 
-    result = g_object_new(G_TYPE_PLAIN_BYTES, NULL);
+    result = g_object_new(G_TYPE_SCAN_PLAIN_BYTES, NULL);
 
-    result->raw = malloc(len);
-    result->allocated = len;
-    result->used = len;
+    if (!g_scan_plain_bytes_create(G_SCAN_PLAIN_BYTES(result), text, modifier, flags))
+        g_clear_object(&result);
 
-    memcpy(result->raw, raw, len);
+    return result;
+
+}
 
-    return G_SEARCH_PATTERN(result);
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : bytes    = encadrement de motif à initialiser pleinement.    *
+*                text     = texte brut à rechercher.                          *
+*                modifier = transformateur éventuel à solliciter.             *
+*                flags    = particularités à prendre en considération.        *
+*                                                                             *
+*  Description : Met en place un gestionnaire de recherche de texte brut.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_plain_bytes_create(GScanPlainBytes *bytes, const sized_binary_t *text, GScanTokenModifier *modifier, ScanPlainBytesFlags flags)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    szstrdup(&bytes->orig, text);
+
+    if (modifier != NULL)
+    {
+        bytes->modifier = modifier;
+        g_object_ref(G_OBJECT(modifier));
+    }
+
+    bytes->flags = flags;
+
+    return result;
 
 }
 
@@ -235,6 +260,52 @@ GSearchPattern *g_plain_bytes_new(const uint8_t *raw, size_t len)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : pattern = définition de motif à considérer.                  *
+*                context = contexte de l'analyse à mener.                     *
+*                fd      = canal d'écriture.                                  *
+*                                                                             *
+*  Description : Affiche un motif de recherche au format texte.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_plain_bytes_output_to_text(const GScanPlainBytes *pattern, GScanContext *context, int fd)
+{
+    G_SEARCH_PATTERN_CLASS(g_scan_plain_bytes_parent_class)->to_text(G_SEARCH_PATTERN(pattern), context, fd);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : pattern = définition de motif à considérer.                  *
+*                context  = contexte de l'analyse à mener.                    *
+*                padding  = éventuel bourrage initial à placer ou NULL.       *
+*                level    = profondeur actuelle.                              *
+*                fd       = canal d'écriture.                                 *
+*                                                                             *
+*  Description : Affiche un motif de recherche au format JSON.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_scan_plain_bytes_output_to_json(const GScanPlainBytes *pattern, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd)
+{
+    G_SEARCH_PATTERN_CLASS(g_scan_plain_bytes_parent_class)->to_json(G_SEARCH_PATTERN(pattern), context, padding, level, fd);
+
+    /* TODO */
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : bytes   = définition de la bribe à enregistrer.              *
 *                context = contexte de l'analyse à mener.                     *
 *                backend = moteur de recherche à préchauffer.                 *
@@ -248,39 +319,99 @@ GSearchPattern *g_plain_bytes_new(const uint8_t *raw, size_t len)
 *                                                                             *
 ******************************************************************************/
 
-static bool g_plain_bytes_enroll(GPlainBytes *bytes, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+static bool g_scan_plain_bytes_enroll(GScanPlainBytes *bytes, GScanContext *context, GEngineBackend *backend, size_t maxsize)
 {
+    return false;
+#if 0
     bool result;                            /* Statut à retourner          */
+    size_t i;                               /* Boucle de parcours #1       */
+    tracked_scan_atom_t atom;               /* Atome identifié             */
+    size_t letters;                         /* Nombre de lettres présentes */
+    size_t k;                               /* Boucle de parcours #2       */
+    size_t extra_count;                     /* Quantité pour l'exhaustivité*/
+    sized_binary_t *extra;                  /* Couverture supplémntaire    */
+    size_t remaining;                       /* Quantité restant à traiter  */
 
+    /* Génération d'une base de chaînes à couvrir */
 
-    result = true;
-
+    if (bytes->modifier == NULL)
+    {
+        bytes->raw = malloc(sizeof(sized_binary_t));
+        bytes->count = 1;
 
+        szstrdup(&bytes[0].raw[0], &bytes->orig);
 
-    bytes->atom_pos = 0;
+        result = true;
 
-    if (bytes->used > maxsize)  // Attention à la position de départ (à retrancher) !
-    {
-        bytes->atom_len = maxsize;
-        bytes->atom_rem = bytes->used - maxsize;
     }
     else
+        result = g_scan_token_modifier_transform(bytes->modifier, &bytes->orig, &bytes->raw, &bytes->count);
+
+    if (!result)
+        goto exit;
+
+    /* Préparation pour la mémorisation des atomes */
+
+    bytes->atoms = malloc(bytes->count * sizeof(tracked_scan_atom_t));
+
+    /* Recherche des atomes */
+
+    for (i = 0; i < bytes->count; i++)
     {
-        bytes->atom_len = bytes->used;
-        bytes->atom_rem = 0;
-    }
+        if (bytes->flags & SPBF_CASE_INSENSITIVE)
+        {
+            find_best_atom(&bytes->raw[i], maxsize, &atom, &letters);
 
+            if (letters == 0)
+                bytes->atoms[i] = atom;
 
-    bytes->pid = g_engine_backend_enroll_plain_pattern(backend, context, bytes->raw, bytes->atom_len);
+            /* Insertion des combinaisons pour couvrir toutes les casses */
+            else
+            {
+                for (k = 0, extra_count = 1; k < letters; k++, extra_count *= 2)
+                    ;
 
+                extra = make_atoms_case_insensitive(&bytes->raw[i], extra_count);
 
+                remaining = bytes->count - i - 1;
 
-    result = (bytes->pid != INVALID_PATTERN_ID);
+                bytes->count += (extra_count - 1);
 
+                bytes->raw = realloc(bytes->raw, bytes->count * sizeof(sized_binary_t));
 
+                memmove(&bytes->raw[i + extra_count], &bytes->raw[i + 1], remaining * sizeof(sized_binary_t));
 
-    return result;
+                for (k = 0; k < extra_count; k++)
+                    bytes->raw[i + k] = extra[k];
+
+                free(extra);
+
+                bytes->atoms = realloc(bytes->raw, bytes->count * sizeof(tracked_scan_atom_t));
+
+                for (k = 0; k < extra_count; k++)
+                    bytes->atoms[i + k] = atom;
 
+                i += extra_count - 1;
+
+            }
+
+        }
+
+        else
+            find_best_atom(&bytes->raw[i], maxsize, &bytes->atoms[i], &letters);
+
+    }
+
+    /* Enregistrements en masse */
+
+
+    for (i = 0; i < bytes->count && result; i++)
+        result = enroll_prepared_atom(&bytes->raw[i], context, backend, &bytes->atoms[i]);
+
+ exit:
+
+    return result;
+#endif
 }
 
 
@@ -299,76 +430,64 @@ static bool g_plain_bytes_enroll(GPlainBytes *bytes, GScanContext *context, GEng
 *                                                                             *
 ******************************************************************************/
 
-static void g_plain_bytes_check(const GPlainBytes *bytes, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+static void g_scan_plain_bytes_check(const GScanPlainBytes *bytes, GScanContext *context, GBinContent *content, pending_matches_t *matches)
 {
-    bool initialized;                       /* Initialisation du suivi ?   */
+#if 0
+
+    size_t i;                               /* Boucle de parcours #1       */
+    const sized_binary_t *raw;              /* Données brutes d'origine    */
+    const tracked_scan_atom_t *atom;        /* Atome correspondant         */
     size_t count;                           /* Quantité de bribes trouvées */
     const phys_t *found;                    /* Localisations des bribes    */
-    size_t mindex;                          /* Indice d'élément à compléter*/
-    size_t i;                               /* Boucle de parcours          */
+    size_t k;                               /* Boucle de parcours #2       */
     phys_t start;                           /* Point de départ             */
     vmpa2t pos;                             /* Position dans les données   */
     const bin_t *ptr;                       /* Accès aux données brutes    */
     int ret;                                /* Bilan d'une comparaison     */
 
-    initialized = are_pending_matches_initialized(matches);
-
-    found = g_scan_context_get_atom_matches(context, bytes->pid, &count);
-
-    mindex = 0;
-
-    for (i = 0; i < count; i++)
+    for (i = 0; i < bytes->count; i++)
     {
-        start = found[i] - bytes->atom_pos;
-
-        /* Recherche d'un point de départ attendu et conforme ? */
+        raw = &bytes->raw[i];
+        atom = &bytes->atoms[i];
 
-        if (initialized)
-            if (!find_target_in_pending_matches(matches, start, &mindex))
-                continue;
+        found = g_scan_context_get_atom_matches(context, atom->pid, &count);
 
-        init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
-
-        /* Validation du contenu avant l'atome */
-
-        if (bytes->atom_pos > 0)
+        for (k = 0; k < count; k++)
         {
-            ptr = g_binary_content_get_raw_access(content, &pos, bytes->atom_len);
-
-            ret = memcmp(bytes->raw + bytes->atom_pos, ptr, bytes->atom_len);
-            if (ret != 0) goto exclude_false_positive;
+            start = found[k] - atom->pos;
 
-        }
+            init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
 
-        /* Validation du contenu après l'atome */
+            /* Validation du contenu avant l'atome */
 
-        if (bytes->atom_rem > 0)
-        {
-            advance_vmpa(&pos, bytes->atom_len);
+            if (atom->pos > 0)
+            {
+                ptr = g_binary_content_get_raw_access(content, &pos, atom->pos);
 
-            ptr = g_binary_content_get_raw_access(content, &pos, bytes->atom_rem);
+                ret = memcmp(raw->data, ptr, atom->pos);
+                if (ret != 0) continue;
 
-            ret = memcmp(bytes->raw + bytes->atom_pos + bytes->atom_len, ptr, bytes->atom_rem);
-            if (ret != 0) goto exclude_false_positive;
+            }
 
-        }
+            /* Validation du contenu après l'atome */
 
-        /* Mémorisation de la correspondance */
+            if (atom->rem > 0)
+            {
+                advance_vmpa(&pos, atom->len);
 
-        if (initialized)
-            extend_pending_matches(matches, mindex, bytes->used);
-        else
-            add_pending_matches(matches, start, bytes->used);
+                ptr = g_binary_content_get_raw_access(content, &pos, atom->rem);
 
-        continue;
+                ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem);
+                if (ret != 0) continue;
 
- exclude_false_positive:
+            }
 
-        if (initialized)
-            remove_pending_matches(matches, mindex);
+            /* Mémorisation de la correspondance */
 
-    }
+            add_pending_matches(matches, start, raw->len);
 
-    set_pending_matches_initialized(matches);
+        }
 
+    }
+#endif
 }
diff --git a/src/analysis/scan/patterns/tokens/plain.h b/src/analysis/scan/patterns/tokens/plain.h
index de1d4ec..80a0b4d 100644
--- a/src/analysis/scan/patterns/tokens/plain.h
+++ b/src/analysis/scan/patterns/tokens/plain.h
@@ -26,41 +26,44 @@
 
 
 #include <glib-object.h>
-#include <stdint.h>
 
 
+#include "../modifier.h"
 #include "../../pattern.h"
+#include "../../../../common/szstr.h"
 
 
 
-#define G_TYPE_PLAIN_BYTES            g_plain_bytes_get_type()
-#define G_PLAIN_BYTES(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLAIN_BYTES, GPlainBytes))
-#define G_IS_PLAIN_BYTES(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLAIN_BYTES))
-#define G_PLAIN_BYTES_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PLAIN_BYTES, GPlainBytesClass))
-#define G_IS_PLAIN_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PLAIN_BYTES))
-#define G_PLAIN_BYTES_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PLAIN_BYTES, GPlainBytesClass))
+#define G_TYPE_SCAN_PLAIN_BYTES            g_scan_plain_bytes_get_type()
+#define G_SCAN_PLAIN_BYTES(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PLAIN_BYTES, GScanPlainBytes))
+#define G_IS_SCAN_PLAIN_BYTES(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PLAIN_BYTES))
+#define G_SCAN_PLAIN_BYTES_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PLAIN_BYTES, GScanPlainBytesClass))
+#define G_IS_SCAN_PLAIN_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PLAIN_BYTES))
+#define G_SCAN_PLAIN_BYTES_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PLAIN_BYTES, GScanPlainBytesClass))
 
 
 /* Représentation d'une suite d'octets à retrouver (instance) */
-typedef struct _GPlainBytes GPlainBytes;
+typedef struct _GScanPlainBytes GScanPlainBytes;
 
 /* Représentation d'une suite d'octets à retrouver (classe) */
-typedef struct _GPlainBytesClass GPlainBytesClass;
+typedef struct _GScanPlainBytesClass GScanPlainBytesClass;
 
 
 /* Propriétés d'un élément textuel à rechercher */
-typedef enum _StringTokenAttrib
+typedef enum _ScanPlainBytesFlags
 {
-    STP_CASE_INSENSITIVE,
+    SPBF_NONE             = 0x0,            /* Aucune particularité        */
+    SPBF_CASE_INSENSITIVE = 0x1,            /* Ignorance de la casse       */
+    SPBF_FULL_WORD        = 0x2,            /* Recherche de mot entier     */
 
-} StringTokenAttrib;
+} ScanPlainBytesFlags;
 
 
 /* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */
-GType g_plain_bytes_get_type(void);
+GType g_scan_plain_bytes_get_type(void);
 
 /* Construit un gestionnaire de recherche de texte brut. */
-GSearchPattern *g_plain_bytes_new(const uint8_t *, size_t);
+GSearchPattern *g_scan_plain_bytes_new(const sized_binary_t *, GScanTokenModifier *, ScanPlainBytesFlags);
 
 
 
diff --git a/src/analysis/scan/rule-int.h b/src/analysis/scan/rule-int.h
index cc10b08..b43cba9 100644
--- a/src/analysis/scan/rule-int.h
+++ b/src/analysis/scan/rule-int.h
@@ -40,9 +40,9 @@ struct _GScanRule
     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   */
-    size_t data_used;                       /* Nombre d'éléments présents  */
+    GSearchPattern **bytes_locals;          /* Variables de données        */
+    size_t bytes_allocated;                 /* Taille allouée du tableau   */
+    size_t bytes_used;                      /* Nombre d'éléments présents  */
 
     GScanExpression *condition;             /* Condition de correspondance */
 
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c
index 6ca97ab..4727c9d 100644
--- a/src/analysis/scan/rule.c
+++ b/src/analysis/scan/rule.c
@@ -93,9 +93,9 @@ static void g_scan_rule_init(GScanRule *rule)
     rule->name = NULL;
     rule->name_hash = 0;
 
-    rule->data_locals = NULL;
-    rule->data_allocated = 0;
-    rule->data_used = 0;
+    rule->bytes_locals = NULL;
+    rule->bytes_allocated = 0;
+    rule->bytes_used = 0;
 
     rule->condition = NULL;
 
@@ -118,8 +118,8 @@ static void g_scan_rule_dispose(GScanRule *rule)
 {
     size_t i;                               /* Boucle de parcours          */
 
-    for (i = 0; i < rule->data_used; i++)
-        g_clear_object(&rule->data_locals[i]);
+    for (i = 0; i < rule->bytes_used; i++)
+        g_clear_object(&rule->bytes_locals[i]);
 
     g_clear_object(&rule->condition);
 
@@ -219,13 +219,13 @@ void g_scan_rule_add_local_variable(GScanRule *rule, GSearchPattern *pattern)
 {
     if (G_IS_STRING_TOKEN(pattern))
     {
-        if (rule->data_used == rule->data_allocated)
+        if (rule->bytes_used == rule->bytes_allocated)
         {
-            rule->data_allocated += PATTERN_ALLOC_SIZE;
-            rule->data_locals = realloc(rule->data_locals, rule->data_allocated * sizeof(GSearchPattern *));
+            rule->bytes_allocated += PATTERN_ALLOC_SIZE;
+            rule->bytes_locals = realloc(rule->bytes_locals, rule->bytes_allocated * sizeof(GSearchPattern *));
         }
 
-        rule->data_locals[rule->data_used++] = pattern;
+        rule->bytes_locals[rule->bytes_used++] = pattern;
         g_object_ref(G_OBJECT(pattern));
 
     }
@@ -254,13 +254,13 @@ GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *targ
 
     result = NULL;
 
-    for (i = 0; i < rule->data_used; i++)
+    for (i = 0; i < rule->bytes_used; i++)
     {
-        name = g_search_pattern_get_name(rule->data_locals[i]);
+        name = g_search_pattern_get_name(rule->bytes_locals[i]);
 
         if (strcmp(name, target) == 0)
         {
-            result = rule->data_locals[i];
+            result = rule->bytes_locals[i];
             break;
         }
 
@@ -327,9 +327,9 @@ bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanCo
 
     maxsize = g_engine_backend_get_atom_max_size(backend);
 
-    for (i = 0; i < rule->data_used && result; i++)
+    for (i = 0; i < rule->bytes_used && result; i++)
     {
-        pattern = rule->data_locals[i];
+        pattern = rule->bytes_locals[i];
         result = g_string_token_enroll(G_STRING_TOKEN(pattern), context, backend, maxsize);
     }
 
@@ -380,11 +380,11 @@ void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *c
 
     /* Consolidation des résultats */
 
-    for (i = 0; i < rule->data_used; i++)
+    for (i = 0; i < rule->bytes_used; i++)
     {
         init_pending_matches(&matches);
 
-        pattern = rule->data_locals[i];
+        pattern = rule->bytes_locals[i];
 
         g_string_token_check(G_STRING_TOKEN(pattern), context, content, &matches);
 
@@ -392,7 +392,9 @@ void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *c
         {
             area = &matches.areas[k];
 
-            match = g_bytes_match_new(G_SEARCH_PATTERN(pattern), content, area->start, area->length);
+            match = g_scan_bytes_match_new(G_SEARCH_PATTERN(pattern), content,
+                                           area->start, area->end - area->start);
+
             g_scan_context_register_full_match(context, match);
             g_object_unref(G_OBJECT(match));
 
@@ -407,3 +409,161 @@ void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *c
     g_object_unref(G_OBJECT(content));
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : rule    = règle de détection à considérer.                   *
+*                context = contexte de l'analyse à mener.                     *
+*                fd      = canal d'écriture.                                  *
+*                                                                             *
+*  Description : Affiche une règle au format texte.                           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_rule_output_to_text(const GScanRule *rule, GScanContext *context, int fd)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < rule->bytes_used; i++)
+        g_search_pattern_output_to_text(rule->bytes_locals[i], context, fd);
+
+    if (g_scan_context_has_match_for_rule(context, rule->name))
+    {
+        write(fd, "Rule '", 6);
+        write(fd, rule->name, strlen(rule->name));
+        write(fd, "' has matched!\n", 15);
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : rule    = règle de détection à considérer.                   *
+*                context = contexte de l'analyse à mener.                     *
+*                                                                             *
+*  Description : Convertit une règle en texte.                                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_rule_convert_as_text(const GScanRule *rule, GScanContext *context)
+{
+    /* TODO */
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : rule     = règle de détection à considérer.                  *
+*                context  = contexte de l'analyse à mener.                    *
+*                padding  = éventuel bourrage initial à placer ou NULL.       *
+*                level    = profondeur actuelle.                              *
+*                fd       = canal d'écriture.                                 *
+*                trailing = impose une virgule finale ?                       *
+*                                                                             *
+*  Description : Affiche une règle au format JSON.                            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_rule_output_to_json(const GScanRule *rule, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd, bool trailing)
+{
+    size_t i;                               /* Boucle de parcours          */
+    bool sub_trailing;                      /* Virgule finale              */
+
+    /* Introduction */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "{\n", 2);
+
+    /* Désignation de la règle */
+
+    for (i = 0; i < (level + 1); i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "\"name\": \"", 9);
+
+    write(fd, rule->name, strlen(rule->name));
+
+    write(fd, "\",\n", 3);
+
+    /* Affichage des correspondances d'octets */
+
+    for (i = 0; i < (level + 1); i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "\"bytes_patterns\": [\n", 20);
+
+    for (i = 0; i < rule->bytes_used; i++)
+    {
+        sub_trailing = ((i + 1) < rule->bytes_used);
+
+        g_search_pattern_output_to_json(rule->bytes_locals[i], context, padding, level + 2, fd, sub_trailing);
+
+    }
+
+    for (i = 0; i < (level + 1); i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "],\n", 3);
+
+    /* Bilan du filtrage */
+
+    for (i = 0; i < (level + 1); i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "\"matched\": ", 11);
+
+    if (g_scan_context_has_match_for_rule(context, rule->name))
+        write(fd, "true", 4);
+    else
+        write(fd, "false", 5);
+
+    write(fd, "\n", 1);
+
+    /* Conclusion */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    if (trailing)
+        write(fd, "},\n", 3);
+    else
+        write(fd, "}\n", 2);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : rule    = règle de détection à considérer.                   *
+*                context = contexte de l'analyse à mener.                     *
+*                                                                             *
+*  Description : Convertit une règle en JSON.                                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_rule_convert_as_json(const GScanRule *rule, GScanContext *context)
+{
+    /* TODO */
+
+}
diff --git a/src/analysis/scan/rule.h b/src/analysis/scan/rule.h
index 12a435c..cb2c287 100644
--- a/src/analysis/scan/rule.h
+++ b/src/analysis/scan/rule.h
@@ -34,6 +34,7 @@
 #include "expr.h"
 #include "patterns/backend.h"
 #include "../../common/fnv1a.h"
+#include "../../common/szstr.h"
 
 
 
@@ -76,6 +77,18 @@ bool g_scan_rule_setup_backend(GScanRule *, GEngineBackend *, GScanContext *);
 /* Lance une analyse d'un contenu binaire selon une règle. */
 void g_scan_rule_check(GScanRule *, GEngineBackend *, GScanContext *);
 
+/* Affiche une règle au format texte. */
+void g_scan_rule_output_to_text(const GScanRule *, GScanContext *, int);
+
+/* Convertit une règle en texte. */
+void g_scan_rule_convert_as_text(const GScanRule *, GScanContext *);
+
+/* Affiche une règle au format JSON. */
+void g_scan_rule_output_to_json(const GScanRule *, GScanContext *, const sized_string_t *, unsigned int, int, bool);
+
+/* Convertit une règle en JSON. */
+void g_scan_rule_convert_as_json(const GScanRule *, GScanContext *);
+
 
 
 #endif  /* _ANALYSIS_SCAN_RULE_H */
diff --git a/src/analysis/scan/scanner.c b/src/analysis/scan/scanner.c
index ce8d677..b550b1f 100644
--- a/src/analysis/scan/scanner.c
+++ b/src/analysis/scan/scanner.c
@@ -510,6 +510,8 @@ GScanContext *g_content_scanner_analyze(GContentScanner *scanner, GScanOptions *
 
     g_engine_backend_run_scan(scanner->data_backend, result);
 
+    g_scan_context_mark_scan_as_done(result);
+
     for (i = 0; i < scanner->rule_count; i++)
         g_scan_rule_check(scanner->rules[i], scanner->data_backend, result);
 
@@ -518,3 +520,117 @@ GScanContext *g_content_scanner_analyze(GContentScanner *scanner, GScanOptions *
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : scanner = gestionnaire de recherche à consulter.             *
+*                context = contexte de l'analyse à mener.                     *
+*                fd      = canal d'écriture.                                  *
+*                                                                             *
+*  Description : Affiche un gestionnaire de recherches au format texte.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_content_scanner_output_to_text(const GContentScanner *scanner, GScanContext *context, int fd)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    /* Sous-traitance aux règles */
+
+    for (i = 0; i < scanner->rule_count; i++)
+        g_scan_rule_output_to_text(scanner->rules[i], context, fd);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : scanner = gestionnaire de recherche à consulter.             *
+*                context = contexte de l'analyse à mener.                     *
+*                                                                             *
+*  Description : Convertit un gestionnaire de recherches en texte.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_content_scanner_convert_as_text(const GContentScanner *scanner, GScanContext *context)
+{
+    /* TODO */
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : scanner = gestionnaire de recherche à consulter.             *
+*                context = contexte de l'analyse à mener.                     *
+*                padding = éventuel bourrage initial à placer ou NULL.        *
+*                level   = profondeur actuelle.                               *
+*                fd      = canal d'écriture.                                  *
+*                                                                             *
+*  Description : Affiche un gestionnaire de recherches au format JSON.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_content_scanner_output_to_json(const GContentScanner *scanner, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd)
+{
+    size_t i;                               /* Boucle de parcours          */
+    bool trailing;                          /* Virgule finale              */
+
+    /* Introduction */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "[\n", 2);
+
+    /* Sous-traitance aux règles */
+
+    for (i = 0; i < scanner->rule_count; i++)
+    {
+        trailing = ((i + 1) < scanner->rule_count);
+
+        g_scan_rule_output_to_json(scanner->rules[i], context, padding, level + 1, fd, trailing);
+
+    }
+
+    /* Conclusion */
+
+    for (i = 0; i < level; i++)
+        write(fd, padding->data, padding->len);
+
+    write(fd, "]\n", 2);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : scanner = gestionnaire de recherche à consulter.             *
+*                context = contexte de l'analyse à mener.                     *
+*                                                                             *
+*  Description : Convertit un gestionnaire de recherches en JSON.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_content_scanner_convert_as_json(const GContentScanner *scanner, GScanContext *context)
+{
+    /* TODO */
+
+}
diff --git a/src/analysis/scan/scanner.h b/src/analysis/scan/scanner.h
index f838344..58dbe19 100644
--- a/src/analysis/scan/scanner.h
+++ b/src/analysis/scan/scanner.h
@@ -32,6 +32,7 @@
 #include "expr.h"
 #include "options.h"
 #include "rule.h"
+#include "../../common/szstr.h"
 
 
 
@@ -71,6 +72,18 @@ 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 *);
 
+/* Affiche un gestionnaire de recherches au format texte. */
+void g_content_scanner_output_to_text(const GContentScanner *, GScanContext *, int);
+
+/* Convertit un gestionnaire de recherches en texte. */
+void g_content_scanner_convert_as_text(const GContentScanner *, GScanContext *);
+
+/* Affiche un gestionnaire de recherches au format JSON. */
+void g_content_scanner_output_to_json(const GContentScanner *, GScanContext *, const sized_string_t *, unsigned int, int);
+
+/* Convertit un gestionnaire de recherches en JSON. */
+void g_content_scanner_convert_as_json(const GContentScanner *, GScanContext *);
+
 
 
 #endif  /* _ANALYSIS_SCAN_SCANNER_H */
diff --git a/src/analysis/scan/tokens.l b/src/analysis/scan/tokens.l
index f3dbc79..18594c4 100644
--- a/src/analysis/scan/tokens.l
+++ b/src/analysis/scan/tokens.l
@@ -15,47 +15,140 @@
 #include <stdlib.h>
 
 
-#define read_block(tmp)                                                     \
-    ({                                                                      \
-        unsigned int __depth;                                               \
-        bool __is_string;                                                   \
-        char *__iter;                                                       \
-                                                                            \
-        __depth = 1;                                                        \
-        __is_string = false;                                                \
-                                                                            \
-        for (__iter = temp; __depth > 0; __iter += (__depth > 0 ? 1 : 0))   \
-        {                                                                   \
-            *__iter = input();                                              \
-                                                                            \
-            switch (*__iter)                                                \
-            {                                                               \
-                case '"':                                                   \
-                    __is_string = !__is_string;                             \
-                    break;                                                  \
-                                                                            \
-                case '{':                                                   \
-                    if (!__is_string) __depth++;                            \
-                    break;                                                  \
-                                                                            \
-                case '}':                                                   \
-                    if (!__is_string)                                       \
-                    {                                                       \
-                        __depth--;                                          \
-                        if (__depth == 0) unput('}');                       \
-                    }                                                       \
-                    break;                                                  \
-                                                                            \
-            }                                                               \
-                                                                            \
-        }                                                                   \
-                                                                            \
-        *__iter = '\0';                                                     \
-                                                                            \
-    })
 
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : src = liste d'octets à traiter.                              *
+*                len = taille de cette liste.                                 *
+*                out = série d'octets bruts obtenue. [OUT]                    *
+*                                                                             *
+*  Description : Transcrit une série d'octets en en remplaçant certains.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void rost_unescape_bytes(const char *src, size_t len, sized_string_t *out)
+{
+    size_t i;                               /* Boucle de parcours          */
+    bin_t byte;                             /* Octet à analyser            */
+    bin_t next;                             /* Octet suivant               */
+
+    out->len = 0;
+
+    for (i = 0; i < len; i++)
+    {
+        byte = src[i];
+
+        switch (byte)
+        {
+            case '\\':
+
+                next = src[i + 1];
+
+                switch (next)
+                {
+                    case '\a':
+                        out->data[out->len++] = '\\';
+                        break;
+
+                    case '\t':
+                        out->data[out->len++] = '\t';
+                        break;
+
+                    case '\n':
+                        out->data[out->len++] = '\n';
+                        break;
+
+                    case '\v':
+                        out->data[out->len++] = '\v';
+                        break;
+
+                    case '\f':
+                        out->data[out->len++] = '\f';
+                        break;
+
+                    case '\r':
+                        out->data[out->len++] = '\r';
+                        break;
+
+                    case '\\':
+                        out->data[out->len++] = '\\';
+                        break;
+
+                    case 'x':
+
+                        next = src[i + 2];
+
+                        switch (next)
+                        {
+                            case '0' ... '9':
+                                out->data[out->len] = (next - '0');
+                                break;
+
+                            case 'A' ... 'F':
+                                out->data[out->len] = 0x10 + (next - 'A');
+                                break;
+
+                            case 'a' ... 'f':
+                                out->data[out->len] = 0x10 + (next - 'a');
+                                break;
+
+                        }
+
+                        out->data[out->len] <<= 4;
+
+                        next = src[i + 3];
+
+                        switch (next)
+                        {
+                            case '0' ... '9':
+                                out->data[out->len] |= (next - '0');
+                                break;
+
+                            case 'A' ... 'F':
+                                out->data[out->len] |= 0x10 + (next - 'A');
+                                break;
+
+                            case 'a' ... 'f':
+                                out->data[out->len] |= 0x10 + (next - 'a');
+                                break;
+
+                        }
+
+                        out->len++;
+
+                        i += 2;
+                        break;
+
+                    case '{':
+                        out->data[out->len++] = '{';
+                        break;
+
+                    case '}':
+                        out->data[out->len++] = '}';
+                        break;
+
+                }
+
+                i++;
+                break;
+
+            default:
+                out->data[out->len++] = byte;
+                break;
+
+        }
+
+    }
+
+}
+
+
 
 #define PUSH_STATE(s) yy_push_state(s, yyscanner)
 #define POP_STATE     yy_pop_state(yyscanner)
@@ -88,9 +181,15 @@
 %x raw_block
 
 %x strings
-%x strval
-%x strval_raw
-%x strval_hex
+%x bytes_value
+%x bytes_value_raw
+
+%x bytes_hex
+%x bytes_hex_range
+
+%x bytes_regex
+%x bytes_regex_quantifier
+%x bytes_regex_range
 
 %x condition
 %x strlit
@@ -101,6 +200,22 @@
 %x comment
 
 
+
+hbyte [0-9a-fA-F]{2}
+
+reg_allowed [^^$.|/{}()\[\]*+?\\]
+reg_allowed_escaped \\^|\\$|\\\.|\\\||\\\/|\\\{|\\\}|\\\(|\\\)|\\\[|\\\]|\\\*|\\\+|\\\?|\\\\
+reg_escaped \\a|\\t|\\n|\\v|\\f|\\r
+reg_byte \\x[0-9a-fA-F]{2}
+
+regular_chars {reg_allowed}|{reg_allowed_escaped}|{reg_escaped}|{reg_byte}
+
+reg_classes \\w|\\W|\\s|\\S|\\d|\\D|\\b|\\B
+
+
+bytes_id [A-Za-z_][A-Za-z0-9_]*
+
+
 %%
 
 
@@ -139,8 +254,8 @@
 <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; }
+<bytes_hex_range,bytes_regex_quantifier,condition>(0|[1-9][0-9]*)      { yylval->unsigned_integer = strtoull(yytext, NULL, 10); return UNSIGNED_INTEGER; }
+<bytes_hex_range,bytes_regex_quantifier,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; }
@@ -181,6 +296,195 @@
 
 
 
+%{ /* Définition de motif en hexadécimal */ %}
+
+                   <bytes_value>"{" {
+                                        POP_STATE;
+                                        PUSH_STATE(bytes_hex);
+                                    }
+
+                     <bytes_hex>"}" { POP_STATE; }
+
+                     <bytes_hex>"[" {
+                                        PUSH_STATE(bytes_hex_range);
+                                        return HOOK_O;
+                                    }
+
+               <bytes_hex_range>"-" { return MINUS; }
+
+               <bytes_hex_range>"]" {
+                                        POP_STATE;
+                                        return HOOK_C;
+                                    }
+
+                     <bytes_hex>"(" { return PAREN_O; }
+
+                     <bytes_hex>")" { return PAREN_C; }
+
+                     <bytes_hex>"|" { return PIPE; }
+
+                     <bytes_hex>"~" { return TILDE; }
+
+   <bytes_hex>{hbyte}([ ]*{hbyte})* {
+                                        bool even;
+                                        size_t i;
+                                        bin_t byte;
+                                        bin_t value;
+
+                                        tmp_0->len = 0;
+
+                                        even = true;
+
+                                        for (i = 0; i < yyleng; i++)
+                                        {
+                                            byte = yytext[i];
+
+                                            switch (byte)
+                                            {
+                                                case ' ':
+                                                    continue;
+                                                    break;
+
+                                                case '0' ... '9':
+                                                    value = (byte - '0');
+                                                    break;
+
+                                                case 'A' ... 'F':
+                                                    value = 0x10 + (byte - 'A');
+                                                    break;
+
+                                                case 'a' ... 'f':
+                                                    value = 0x10 + (byte - 'a');
+                                                    break;
+
+                                            }
+
+                                            if (even)
+                                            {
+                                                tmp_0->data[tmp_0->len] = (value << 4);
+                                                even = false;
+                                            }
+
+                                            else
+                                            {
+                                                tmp_0->data[tmp_0->len++] |= value;
+                                                even = true;
+                                            }
+
+                                        }
+
+                                        assert(even);
+
+#ifndef NDEBUG
+                                        /* Pour rendre plus lisibles les impressions de débogage */
+                                        tmp_0->data[tmp_0->len] = '\0';
+#endif
+
+                                        yylval->tmp_cstring = tmp_0;
+                                        return HEX_BYTES;
+
+                                    }
+
+   <bytes_hex>[\?]{2}([ ]*[\?]{2})* {
+                                        unsigned long long counter;
+                                        size_t i;
+
+                                        counter = 0;
+
+                                        for (i = 0; i < yyleng; i++)
+                                            if (yytext[i] == '?')
+                                                counter++;
+
+                                        assert(counter % 2 == 0);
+
+                                        yylval->unsigned_integer = counter / 2;
+                                        return FULL_MASK;
+
+                                    }
+
+
+%{ /* Définition d'expressions régulières */ %}
+
+                   <bytes_value>"/" {
+                                        POP_STATE;
+                                        printf(" -- regex\n");
+                                        PUSH_STATE(bytes_regex);
+                                    }
+
+                   <bytes_regex>"/" { printf("exit regex\n"); POP_STATE; }
+
+                   <bytes_regex>"." { return DOT; }
+
+    <bytes_regex>({regular_chars})+ {
+                                        rost_unescape_bytes(yytext, yyleng, tmp_0);
+
+                                        printf(" regular: '%s'\n", yytext);
+
+#ifndef NDEBUG
+                                        /* Pour rendre plus lisibles les impressions de débogage */
+                                        tmp_0->data[tmp_0->len] = '\0';
+#endif
+
+                                        yylval->tmp_cstring = tmp_0;
+                                        return REGEX_BYTES;
+
+                                    }
+
+      <bytes_regex>({reg_classes})+ {
+
+                                        return REGEX_CLASSES;
+
+                                    }
+
+%{ /* <bytes_regex>\[({regular_chars}|({regular_chars})-z|{reg_classes})+\] { */ %}
+
+
+                     <bytes_regex>"[" {
+                                        PUSH_STATE(bytes_regex_range);
+                                        printf(" !! entering range\n");
+                                        return HOOK_O;
+                                    }
+
+               <bytes_regex_range>"]" {
+                                        POP_STATE;
+                                        printf(" !! exiting range\n");
+                                        return HOOK_C;
+                                    }
+
+
+
+
+<bytes_regex_range>({regular_chars}|({regular_chars}-{regular_chars})|{reg_classes})+ {
+
+       printf("range: '%s'\n", yytext);
+                                        return REGEX_RANGE;
+
+                                    }
+
+                   <bytes_regex>"(" { return PAREN_O; }
+
+                   <bytes_regex>")" { return PAREN_C; }
+
+                   <bytes_regex>"|" { return PIPE; }
+
+                   <bytes_regex>"*" { return MUL; }
+                   <bytes_regex>"+" { return PLUS; }
+                   <bytes_regex>"?" { return QUESTION; }
+
+                   <bytes_regex>"{" {
+                                        PUSH_STATE(bytes_regex_quantifier);
+                                        return BRACKET_O;
+                                    }
+
+        <bytes_regex_quantifier>"," { return COMMA; }
+
+        <bytes_regex_quantifier>"}" {
+                                        POP_STATE;
+                                        return BRACKET_C;
+                                    }
+
+
+%{ /* Condition de correspondance */ %}
 
 <condition>"and"                { return AND; }
 <condition>"or"                 { return OR; }
@@ -208,10 +512,17 @@
 <condition>"/"                  { return DIV; }
 <condition>"%"                  { return MOD; }
 
-<condition>"("                  { return PAREN_O; }
-<condition>")"                  { return PAREN_C; }
-<condition>","                  { return COMMA; }
+<strings,condition>"("          { return PAREN_O; }
+<strings,condition>")"          { return PAREN_C; }
+<strings,condition>","          { return COMMA; }
+
+
+<condition>"["                  { return HOOK_O; }
+<condition>"]"                  { return HOOK_C; }
+
+
 <condition>"."                  { return DOT; }
+<strings>"|"                    { return PIPE; }
 
 <condition>"none"               { return NONE; }
 <condition>"any"                { return ANY; }
@@ -221,36 +532,51 @@
 <condition>"in"                 { return IN; }
 
 
-<strings,condition>$[A-Za-z0-9_]* {
-                                    yylval->sized_cstring.data = yytext + 1;
-                                    yylval->sized_cstring.len = yyleng - 1;
-                                    return IDENTIFIER;
-                                }
+    <strings,condition>${bytes_id}  {
+                                        yylval->sized_cstring.data = yytext + 1;
+                                        yylval->sized_cstring.len = yyleng - 1;
+                                        return BYTES_ID;
+                                    }
+
+             <condition>#{bytes_id} {
+                                        yylval->sized_cstring.data = yytext + 1;
+                                        yylval->sized_cstring.len = yyleng - 1;
+                                        return BYTES_ID_COUNTER;
+                                    }
+
+             <condition>@{bytes_id} {
+                                        yylval->sized_cstring.data = yytext + 1;
+                                        yylval->sized_cstring.len = yyleng - 1;
+                                        return BYTES_ID_START;
+                                    }
+
+             <condition>!{bytes_id} {
+                                        yylval->sized_cstring.data = yytext + 1;
+                                        yylval->sized_cstring.len = yyleng - 1;
+                                        return BYTES_ID_LENGTH;
+                                    }
+
+             <condition>~{bytes_id} {
+                                        yylval->sized_cstring.data = yytext + 1;
+                                        yylval->sized_cstring.len = yyleng - 1;
+                                        return BYTES_ID_END;
+                                    }
 
-<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_]* {
+
+<strings,condition>[A-Za-z_][A-Za-z0-9_]* {
                                     yylval->sized_cstring.data = yytext;
                                     yylval->sized_cstring.len = yyleng;
                                     return NAME;
                                 }
 
-<strings>"="                    { PUSH_STATE(strval); return ASSIGN; }
+<strings>"="                    { PUSH_STATE(bytes_value); return ASSIGN; }
 
 
-<strval>\"[^\"\\]+\"            {
+<bytes_value>\"[^\"\\]+\"            {
                                     POP_STATE;
                                     yylval->sized_cstring.data = yytext + 1;
                                     yylval->sized_cstring.len = yyleng - 2;
@@ -260,43 +586,28 @@
 
 
 
-<strval>"\""                    {
+<bytes_value>"\""                    {
                                     POP_STATE;
                                     // *built_pattern = g_bytes_pattern_new();
-                                    PUSH_STATE(strval_raw);
-                                }
-<strval>"{"                     {
-                                    POP_STATE;
-                                    // *built_pattern = g_bytes_pattern_new();
-                                    PUSH_STATE(strval_hex);
+                                    PUSH_STATE(bytes_value_raw);
                                 }
 
-<strval_raw>"\""                { POP_STATE; /*yylval->pattern = *built_pattern*/; return MASKED_STRING; }
+<bytes_value_raw>"\""                { POP_STATE; /*yylval->pattern = *built_pattern*/; return MASKED_STRING; }
 
-<strval_raw>"\\\""              { }//g_bytes_pattern_append_data(*built_pattern, '"', 0xff); }
-<strval_raw>"\\t"               { }//g_bytes_pattern_append_data(*built_pattern, '\t', 0xff); }
-<strval_raw>"\\r"               { }//g_bytes_pattern_append_data(*built_pattern, '\r', 0xff); }
-<strval_raw>"\\n"               { }//g_bytes_pattern_append_data(*built_pattern, '\n', 0xff); }
-<strval_raw>"\\\\"              { }//g_bytes_pattern_append_data(*built_pattern, '\\', 0xff); }
+<bytes_value_raw>"\\\""              { }//g_bytes_pattern_append_data(*built_pattern, '"', 0xff); }
+<bytes_value_raw>"\\t"               { }//g_bytes_pattern_append_data(*built_pattern, '\t', 0xff); }
+<bytes_value_raw>"\\r"               { }//g_bytes_pattern_append_data(*built_pattern, '\r', 0xff); }
+<bytes_value_raw>"\\n"               { }//g_bytes_pattern_append_data(*built_pattern, '\n', 0xff); }
+<bytes_value_raw>"\\\\"              { }//g_bytes_pattern_append_data(*built_pattern, '\\', 0xff); }
 
-<strval_raw>\\x[0-9a-fA-F]{2}   {
+<bytes_value_raw>\\x[0-9a-fA-F]{2} {
                                     uint8_t __ch;
                                     __ch = strtol(yytext + 2, NULL, 16);
+                                    printf("__ch: %hhx\n", __ch);
                                     //g_bytes_pattern_append_data(*built_pattern, __ch, 0xff);
                                 }
 
-<strval_raw>.                   { }//g_bytes_pattern_append_data(*built_pattern, *yytext, 0xff); }
-
-<strval_hex>"}"                 { POP_STATE; /*yylval->pattern = *built_pattern;*/ return MASKED_STRING; }
-
-<strval_hex>[0-9a-fA-F]{2}      {
-                                    uint8_t __ch;
-                                    __ch = strtol(yytext, NULL, 16);
-                                    //g_bytes_pattern_append_data(*built_pattern, __ch, 0xff);
-                                }
-
-<strval_hex>"??"                { /*g_bytes_pattern_insert_space(*built_pattern, 1, 1);*/ }
- 
+<bytes_value_raw>.                   { }//g_bytes_pattern_append_data(*built_pattern, *yytext, 0xff); }
 
 
 
@@ -318,7 +629,9 @@
 
 %{ /* Actions par défaut */ %}
 
-<*>[ \t\n]+                     { }
+<*>[ \t]+                     { }
+
+<*>[\n]                     { static int ln = 1; if (0) printf("----------- %%< -------------- %%< ---- %d\n", ln++); }
 
 <*>.                            {
                                     char *msg;
diff --git a/src/common/cpp.h b/src/common/cpp.h
index b1606ed..39e7676 100644
--- a/src/common/cpp.h
+++ b/src/common/cpp.h
@@ -46,6 +46,8 @@
 
 #define SIZE_T_MAXLEN strlen(XSTR(LONG_MAX))
 
+#define ULLONG_MAXLEN (sizeof(XSTR(ULLONG_MAX)) + 1)
+
 
 /**
  * Emprunt au noyau Linux (cf. include/linux/bug.h) pour les vérifications à la compilation.
diff --git a/src/common/szstr.h b/src/common/szstr.h
index d73e489..0091482 100644
--- a/src/common/szstr.h
+++ b/src/common/szstr.h
@@ -30,6 +30,7 @@
 
 
 #include "sort.h"
+#include "../arch/archbase.h"
 
 
 
@@ -42,6 +43,9 @@ typedef struct _sized_string_t
 } sized_string_t;
 
 
+typedef sized_string_t sized_binary_t;
+
+
 #define init_szstr(s)       \
     do                      \
     {                       \
@@ -59,6 +63,8 @@ typedef struct _sized_string_t
     }                                                   \
     while (0)
 
+#define copy_szstr(d, s) (d) = (s);
+
 #define exit_szstr(s)           \
     do                          \
     {                           \
diff --git a/src/core/core.c b/src/core/core.c
index 26469ff..626d58b 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -105,17 +105,18 @@ bool load_all_core_components(bool cs)
             explorer = g_content_explorer_new();
             set_current_content_explorer(explorer);
 
+            resolver = g_content_resolver_new();
+            set_current_content_resolver(resolver);
+
 #ifdef HAVE_MAGIC_SUPPORT
             if (result) result = init_magic_cookie();
 #endif
 
-            resolver = g_content_resolver_new();
-            set_current_content_resolver(resolver);
-
             root_ns = g_scan_namespace_new(NULL);
             set_rost_root_namespace(root_ns);
 
             if (result) result = populate_main_scan_namespace(root_ns);
+            if (result) result = load_all_known_scan_token_modifiers();
 
             if (result) result = init_segment_content_hash_table();
 
@@ -157,6 +158,7 @@ void unload_all_core_components(bool cs)
 
         unload_processors_definitions();
 
+        unload_all_scan_token_modifiers();
         set_rost_root_namespace(NULL);
 
 #ifdef HAVE_MAGIC_SUPPORT
diff --git a/src/rost.c b/src/rost.c
index 40fe587..66f2ba6 100644
--- a/src/rost.c
+++ b/src/rost.c
@@ -87,6 +87,8 @@ static void show_rost_help(const char *name)
     printf("\n");
 
     printf("\t-A --algorithm=name\tSelect one of the available algorithms for data: bitmap, acism (default: acsim).\n");
+    printf("\t-j --print-json\t\tPrint matching strings in JSON format.\n");
+    printf("\t-s --print-strings\tPrint matching strings.\n");
     printf("\t-S --print-stats\tPrint rules' statistics.\n");
     printf("\t-V --verbosity=level\tSet the log level (0 for all messages, %u for none).\n", LMT_COUNT);
 
@@ -165,11 +167,14 @@ int main(int argc, char **argv)
     GContentScanner *scanner;               /* Encadrement d'une recherche */
     GBinContent *content;                   /* Contenu à analyser          */
     GScanContext *context;                  /* Contexte des trouvailles    */
+    sized_string_t padding;                 /* Bourrage pour le JSON       */
 
     static struct option long_options[] = {
         { "help",           no_argument,        NULL,   'h' },
         { "version",        no_argument,        NULL,   'v' },
         { "algorithm",      required_argument,  NULL,   'A' },
+        { "print-json",     no_argument,        NULL,   'j' },
+        { "print-strings",  no_argument,        NULL,   's' },
         { "print-stats",    no_argument,        NULL,   'S' },
         { "verbosity",      required_argument,  NULL,   'V' },
         { NULL,             0,                  NULL,   0 }
@@ -190,7 +195,7 @@ int main(int argc, char **argv)
 
     while (true)
     {
-        ret = getopt_long(argc, argv, "hvA:SV:", long_options, &index);
+        ret = getopt_long(argc, argv, "hvA:jsSV:", long_options, &index);
         if (ret == -1) break;
 
         switch (ret)
@@ -212,6 +217,14 @@ int main(int argc, char **argv)
                     g_scan_options_set_backend_for_data(options, G_TYPE_INVALID);
                 break;
 
+            case 'j':
+                g_scan_options_set_print_json(options, true);
+                break;
+
+            case 's':
+                g_scan_options_set_print_strings(options, true);
+                break;
+
             case 'S':
                 g_scan_options_set_print_stats(options, true);
                 break;
@@ -288,7 +301,16 @@ int main(int argc, char **argv)
 
         context = g_content_scanner_analyze(scanner, options, content);
 
-        g_scan_context_display(context);
+        if (g_scan_options_get_print_json(options))
+        {
+            padding.data = "   ";
+            padding.len = 3;
+
+            g_content_scanner_output_to_json(scanner, context, &padding, 0, STDOUT_FILENO);
+
+        }
+        else
+            g_content_scanner_output_to_text(scanner, context, STDOUT_FILENO);
 
         g_object_unref(G_OBJECT(context));
         g_object_unref(G_OBJECT(content));
diff --git a/tests/analysis/scan/pyapi.py b/tests/analysis/scan/pyapi.py
index 1bba44e..b5b2453 100644
--- a/tests/analysis/scan/pyapi.py
+++ b/tests/analysis/scan/pyapi.py
@@ -1,8 +1,12 @@
 
+import binascii
+
 from chrysacase import ChrysalideTestCase
 from gi._constants import TYPE_INVALID
 from pychrysalide.analysis.scan import ScanExpression
 from pychrysalide.analysis.scan import ScanOptions
+from pychrysalide.analysis.scan import find_token_modifiers_for_name
+from pychrysalide.analysis.scan.patterns.modifiers import PlainModifier
 from pychrysalide.glibext import ComparableItem
 
 
@@ -24,6 +28,7 @@ class TestRostPythonAPI(ChrysalideTestCase):
 
             e = ScanExpression()
 
+
     def testBooleanComparison(self):
         """Compare custom scan expressions."""
 
@@ -56,3 +61,31 @@ class TestRostPythonAPI(ChrysalideTestCase):
         # TypeError: '<' not supported between instances of 'StrLenExpr' and 'StrLenExpr'
         with self.assertRaisesRegex(TypeError, '\'<\' not supported between instances'):
             self.assertTrue(e0 < e1)
+
+
+    def testBytePatternModifiers(self):
+        """Validate the bytes produced by modifiers."""
+
+        mod = find_token_modifiers_for_name('plain')
+        self.assertIsNotNone(mod)
+
+        source = b'ABC'
+        transformed = mod.transform(source)
+
+        self.assertEqual(source, transformed[0])
+
+        mod = find_token_modifiers_for_name('hex')
+        self.assertIsNotNone(mod)
+
+        source = b'ABC'
+        transformed = mod.transform(source)
+
+        self.assertEqual(binascii.hexlify(source), transformed[0])
+
+        mod = find_token_modifiers_for_name('rev')
+        self.assertIsNotNone(mod)
+
+        source = b'ABC'
+        transformed = mod.transform(source)
+
+        self.assertEqual(source[::-1], transformed[0])
diff --git a/tests/analysis/scan/scanning_hex.py b/tests/analysis/scan/scanning_hex.py
new file mode 100644
index 0000000..e009b79
--- /dev/null
+++ b/tests/analysis/scan/scanning_hex.py
@@ -0,0 +1,26 @@
+
+from common import RostTestClass
+from pychrysalide.analysis.contents import MemoryContent
+
+
+class TestRostScanning(RostTestClass):
+    """TestCases for the bytes section syntax."""
+
+    def testSimpleHexPattern(self):
+        """Test a simple hex pattern."""
+
+        cnt = MemoryContent(b'123-Abc-456')
+
+        rule = '''
+rule test {
+
+   strings:
+      $a = { 41 62 63 }
+
+   condition:
+      #a == 1 and @a[0] == 4
+
+}
+'''
+
+        self.check_rule_success(rule, content=cnt)
-- 
cgit v0.11.2-87-g4458