From 2553a987f2d8ba35d839152a35392ca29b409841 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 6 Oct 2023 10:55:34 +0200
Subject: Extend the Python API for ROST (items and literals).

---
 configure.ac                                       |   1 +
 plugins/pychrysalide/analysis/scan/Makefile.am     |   3 +-
 plugins/pychrysalide/analysis/scan/context.c       |  89 ++++-
 plugins/pychrysalide/analysis/scan/expr.c          |   2 +-
 .../pychrysalide/analysis/scan/exprs/Makefile.am   |  15 +
 .../pychrysalide/analysis/scan/exprs/constants.c   | 128 +++++++
 .../pychrysalide/analysis/scan/exprs/constants.h   |  42 +++
 plugins/pychrysalide/analysis/scan/exprs/literal.c | 281 ++++++++++++++
 plugins/pychrysalide/analysis/scan/exprs/literal.h |  45 +++
 plugins/pychrysalide/analysis/scan/exprs/module.c  | 103 +++++
 plugins/pychrysalide/analysis/scan/exprs/module.h  |  42 +++
 plugins/pychrysalide/analysis/scan/item.c          | 413 ++++++++++++++++++++-
 plugins/pychrysalide/analysis/scan/module.c        |   3 +
 src/rost.c                                         |   3 +
 14 files changed, 1157 insertions(+), 13 deletions(-)
 create mode 100644 plugins/pychrysalide/analysis/scan/exprs/Makefile.am
 create mode 100644 plugins/pychrysalide/analysis/scan/exprs/constants.c
 create mode 100644 plugins/pychrysalide/analysis/scan/exprs/constants.h
 create mode 100644 plugins/pychrysalide/analysis/scan/exprs/literal.c
 create mode 100644 plugins/pychrysalide/analysis/scan/exprs/literal.h
 create mode 100644 plugins/pychrysalide/analysis/scan/exprs/module.c
 create mode 100644 plugins/pychrysalide/analysis/scan/exprs/module.h

diff --git a/configure.ac b/configure.ac
index 2b105ba..7673a96 100644
--- a/configure.ac
+++ b/configure.ac
@@ -695,6 +695,7 @@ AC_CONFIG_FILES([Makefile
                  plugins/pychrysalide/analysis/db/items/Makefile
                  plugins/pychrysalide/analysis/disass/Makefile
                  plugins/pychrysalide/analysis/scan/Makefile
+                 plugins/pychrysalide/analysis/scan/exprs/Makefile
                  plugins/pychrysalide/analysis/scan/patterns/Makefile
                  plugins/pychrysalide/analysis/scan/patterns/backends/Makefile
                  plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile
diff --git a/plugins/pychrysalide/analysis/scan/Makefile.am b/plugins/pychrysalide/analysis/scan/Makefile.am
index 0b20ca5..8c9fb77 100644
--- a/plugins/pychrysalide/analysis/scan/Makefile.am
+++ b/plugins/pychrysalide/analysis/scan/Makefile.am
@@ -13,6 +13,7 @@ libpychrysaanalysisscan_la_SOURCES =		\
 	space.h space.c
 
 libpychrysaanalysisscan_la_LIBADD =			\
+	exprs/libpychrysaanalysisscanexprs.la	\
 	patterns/libpychrysaanalysisscanpatterns.la
 
 libpychrysaanalysisscan_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
@@ -24,4 +25,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
 dev_HEADERS = $(libpychrysaanalysisscan_la_SOURCES:%c=)
 
 
-SUBDIRS = patterns
+SUBDIRS = exprs patterns
diff --git a/plugins/pychrysalide/analysis/scan/context.c b/plugins/pychrysalide/analysis/scan/context.c
index 8f29457..7071935 100644
--- a/plugins/pychrysalide/analysis/scan/context.c
+++ b/plugins/pychrysalide/analysis/scan/context.c
@@ -32,10 +32,11 @@
 #include <analysis/content.h>
 #include <analysis/scan/context-int.h>
 #include <analysis/scan/expr.h>
-#include <plugins/pychrysalide/access.h>
-#include <plugins/pychrysalide/helpers.h>
-#include <plugins/pychrysalide/analysis/content.h>
-#include <plugins/pychrysalide/analysis/scan/expr.h>
+
+#include "expr.h"
+#include "../content.h" 
+#include "../../access.h"
+#include "../../helpers.h"
 
 
 
@@ -50,6 +51,12 @@ 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 *);
 
+/* Fournit une référence au contenu principal analysé. */
+static PyObject *py_scan_context_get_content(PyObject *, void *);
+
+/* Définit le contenu principal à analyser. */
+static int py_scan_context_set_content(PyObject *, PyObject *, void *);
+
 /* Indique si la phase d'analyse de contenu est terminée. */
 static PyObject *py_scan_context_is_scan_done(PyObject *, void *);
 
@@ -183,6 +190,79 @@ static PyObject *py_scan_context_has_match_for_rule(PyObject *self, PyObject *ar
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self    = classe représentant une routine binaire.           *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Fournit une référence au contenu principal analysé.          *
+*                                                                             *
+*  Retour      : Content binaire associé au context.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_scan_context_get_content(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Eléments à retourner        */
+    GScanContext *context;                  /* Version native              */
+    GBinContent *content;                   /* Contenu binaire à référencer*/
+
+#define SCAN_CONTEXT_CONTENT_ATTRIB PYTHON_GETSET_DEF_FULL  \
+(                                                           \
+    content, py_scan_context,                               \
+    "Link to the scanned binary content.\n"                 \
+    "\n"                                                    \
+    "The result is a pychrysalide.analysis.BinContent for"  \
+    " fully initialized context."                           \
+)
+
+    context = G_SCAN_CONTEXT(pygobject_get(self));
+    content = g_scan_context_get_content(context);
+
+    result = pygobject_new(G_OBJECT(content));
+
+    g_object_unref(G_OBJECT(content));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Définit le contenu principal à analyser.                     *
+*                                                                             *
+*  Retour      : Content binaire associé au context.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_scan_context_set_content(PyObject *self, PyObject *value, void *closure)
+{
+    GScanContext *context;                  /* Elément à consulter         */
+    int ret;                                /* Bilan de lecture des args.  */
+    GBinContent *content;                   /* Contenu binaire à référencer*/
+
+    ret = PyObject_IsInstance(value, (PyObject *)get_python_binary_content_type());
+    if (!ret) return -1;
+
+    context = G_SCAN_CONTEXT(pygobject_get(self));
+    content = G_BIN_CONTENT(pygobject_get(value));
+
+    g_scan_context_set_content(context, content);
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : self    = objet Python concerné par l'appel.                 *
 *                closure = non utilisé ici.                                   *
 *                                                                             *
@@ -242,6 +322,7 @@ PyTypeObject *get_python_scan_context_type(void)
     };
 
     static PyGetSetDef py_scan_context_getseters[] = {
+        SCAN_CONTEXT_CONTENT_ATTRIB,
         SCAN_CONTEXT_IS_SCAN_DONE_ATTRIB,
         { NULL }
     };
diff --git a/plugins/pychrysalide/analysis/scan/expr.c b/plugins/pychrysalide/analysis/scan/expr.c
index 3622e9b..2d8245a 100644
--- a/plugins/pychrysalide/analysis/scan/expr.c
+++ b/plugins/pychrysalide/analysis/scan/expr.c
@@ -107,7 +107,7 @@ static int py_scan_expression_init(PyObject *self, PyObject *args, PyObject *kwd
     " the following arguments as keyword parameters:\n"                 \
     "* *state*: initial state of reduction for the expression, as a"    \
     " pychrysalide.analysis.scan.ScanExpression.ScanReductionState"     \
-    " value."   \
+    " value."                                                           \
     "\n"                                                                \
     "The following methods have to be defined for new classes:\n"       \
     "* pychrysalide.analysis.scan.ScanExpression._cmp_rich().\n"
diff --git a/plugins/pychrysalide/analysis/scan/exprs/Makefile.am b/plugins/pychrysalide/analysis/scan/exprs/Makefile.am
new file mode 100644
index 0000000..e40d4de
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanexprs.la
+
+libpychrysaanalysisscanexprs_la_SOURCES = 	\
+	constants.h constants.c					\
+	literal.h literal.c						\
+	module.h module.c
+
+libpychrysaanalysisscanexprs_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+    $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanexprs_la_SOURCES:%c=)
diff --git a/plugins/pychrysalide/analysis/scan/exprs/constants.c b/plugins/pychrysalide/analysis/scan/exprs/constants.c
new file mode 100644
index 0000000..b11ac4c
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/constants.c
@@ -0,0 +1,128 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.c - ajout des constantes de base pour les expressions
+ *
+ * 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 "constants.h"
+
+
+#include <analysis/scan/exprs/literal.h>
+
+
+#include "../../../helpers.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type dont le dictionnaire est à compléter.            *
+*                                                                             *
+*  Description : Définit les constantes relatives aux expressions de scan.    *
+*                                                                             *
+*  Retour      : true en cas de succès de l'opération, false sinon.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool define_literal_expression_value_type_constants(PyTypeObject *type)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *values;                       /* Groupe de valeurs à établir */
+
+    values = PyDict_New();
+
+    result = add_const_to_group(values, "LVT_BOOLEAN", LVT_BOOLEAN);
+    if (result) result = add_const_to_group(values, "SIGNED_INTEGER", LVT_SIGNED_INTEGER);
+    if (result) result = add_const_to_group(values, "UNSIGNED_INTEGER", LVT_UNSIGNED_INTEGER);
+    if (result) result = add_const_to_group(values, "STRING", LVT_STRING);
+
+    if (!result)
+    {
+        Py_DECREF(values);
+        goto exit;
+    }
+
+    result = attach_constants_group_to_type(type, false, "LiteralValueType", values,
+                                            "Type of value carried by a literal scan expression.");
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en constante LiteralValueType.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_literal_expression_value_type(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+    unsigned long value;                    /* Valeur transcrite           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)&PyLong_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 LiteralValueType");
+            break;
+
+        case 1:
+            value = PyLong_AsUnsignedLong(arg);
+
+            if (value > LVT_REG_EXPR)
+            {
+                PyErr_SetString(PyExc_TypeError, "invalid value for LiteralValueType");
+                result = 0;
+            }
+
+            else
+                *((LiteralValueType *)dst) = value;
+
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/exprs/constants.h b/plugins/pychrysalide/analysis/scan/exprs/constants.h
new file mode 100644
index 0000000..e5b8e8c
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/constants.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.h - prototypes pour l'ajout des constantes de base pour les expressions
+ *
+ * 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_EXPRS_CONSTANTS_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit les constantes relatives aux expressions litérales. */
+bool define_literal_expression_value_type_constants(PyTypeObject *);
+
+/* Tente de convertir en constante LiteralValueType. */
+int convert_to_literal_expression_value_type(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H */
diff --git a/plugins/pychrysalide/analysis/scan/exprs/literal.c b/plugins/pychrysalide/analysis/scan/exprs/literal.c
new file mode 100644
index 0000000..d7ae002
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/literal.c
@@ -0,0 +1,281 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal.c - équivalent Python du fichier "analysis/scan/exprs/literal.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 "literal.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/exprs/literal-int.h>
+
+
+#include "constants.h"
+#include "../expr.h"
+#include "../../../access.h"
+#include "../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_literal_expression, G_TYPE_SCAN_LITERAL_EXPRESSION);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_literal_expression_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_literal_expression_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    PyObject *py_value;                     /* Valeur en version Python    */
+    int ret;                                /* Bilan de lecture des args.  */
+    LiteralValueType vtype;                 /* Valeur à porter             */
+    bool arg_boolean;                       /* Argument natif booléen      */
+    unsigned long long arg_uinteger;        /* Argument natif entier       */
+    sized_string_t arg_string;              /* Argument natif textuel      */
+    Py_ssize_t arg_str_length;              /* Taille de ce texte          */
+    void *arg_ptr;                          /* Pointeur vers un argument   */
+    GScanLiteralExpression *expr;           /* Création GLib à transmettre */
+
+#define SCAN_LITERAL_EXPRESSION_DOC                                 \
+    "A ScanLiteralExpression object defines expression carrying"    \
+    " literal values available for scan match conditions.\n"        \
+    "\n"                                                            \
+    "Instances can be created using one of the following"           \
+    " constructors:\n"                                              \
+    "\n"                                                            \
+    "    ScanLiteralExpression(value)"                              \
+    "\n"                                                            \
+    "\n"                                                            \
+    "Where *value* is either a boolean, an integer or bytes."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O", &py_value);
+    if (!ret) return -1;
+
+    if (PyBool_Check(py_value))
+    {
+        vtype = LVT_BOOLEAN;
+
+        arg_boolean = (py_value == Py_True);
+        arg_ptr = &arg_boolean;
+
+    }
+
+    else if (PyLong_Check(py_value))
+    {
+        if (1 /* sign - TODO */)
+            ;
+
+        vtype = LVT_UNSIGNED_INTEGER;
+
+        arg_uinteger = PyLong_AsUnsignedLongLong(py_value);
+        arg_ptr = &arg_uinteger;
+
+    }
+
+    else if (PyBytes_Check(py_value))
+    {
+        vtype = LVT_STRING;
+
+        ret = PyBytes_AsStringAndSize(py_value, &arg_string.data, &arg_str_length);
+        if (ret == -1) return -1;
+
+        arg_string.len = arg_str_length;
+        arg_ptr = &arg_string;
+
+    }
+
+    else
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unsupported Python value for a literal scan expression."));
+        return -1;
+    }
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    expr = G_SCAN_LITERAL_EXPRESSION(pygobject_get(self));
+
+    if (!g_scan_literal_expression_create(expr, vtype, arg_ptr))
+    {
+        PyErr_SetString(PyExc_ValueError, _("Unable to create literal expression."));
+        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_literal_expression_type(void)
+{
+    static PyMethodDef py_scan_literal_expression_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_scan_literal_expression_getseters[] = {
+        { NULL }
+    };
+
+    static PyTypeObject py_scan_literal_expression_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.analysis.scan.exprs.ScanLiteralExpression",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+        .tp_doc         = SCAN_LITERAL_EXPRESSION_DOC,
+
+        .tp_methods     = py_scan_literal_expression_methods,
+        .tp_getset      = py_scan_literal_expression_getseters,
+
+        .tp_init        = py_scan_literal_expression_init,
+        .tp_new         = py_scan_literal_expression_new,
+
+    };
+
+    return &py_scan_literal_expression_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide....PlainModifier'.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool ensure_python_scan_literal_expression_is_registered(void)
+{
+    PyTypeObject *type;                     /* Type Python 'PlainModifier' */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_scan_literal_expression_type();
+
+    if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+    {
+        module = get_access_to_python_module("pychrysalide.analysis.scan.exprs");
+
+        dict = PyModule_GetDict(module);
+
+        if (!ensure_python_scan_expression_is_registered())
+            return false;
+
+        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_LITERAL_EXPRESSION, type))
+            return false;
+
+        if (!define_literal_expression_value_type_constants(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_literal_expression(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_literal_expression_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 scan literal expression");
+            break;
+
+        case 1:
+            *((GScanLiteralExpression **)dst) = G_SCAN_LITERAL_EXPRESSION(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/exprs/literal.h b/plugins/pychrysalide/analysis/scan/exprs/literal.h
new file mode 100644
index 0000000..8e7ea70
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/literal.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal.h - équivalent Python du fichier "analysis/scan/exprs/literal.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_EXPRS_LITERAL_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_literal_expression_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.exprs.ScanLiteralExpression'. */
+bool ensure_python_scan_literal_expression_is_registered(void);
+
+/* Tente de convertir en transmission d'octets à l'identique. */
+int convert_to_scan_literal_expression(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H */
diff --git a/plugins/pychrysalide/analysis/scan/exprs/module.c b/plugins/pychrysalide/analysis/scan/exprs/module.c
new file mode 100644
index 0000000..4f38430
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/module.c
@@ -0,0 +1,103 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire exprs en tant que module
+ *
+ * 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 "module.h"
+
+
+#include <assert.h>
+
+
+#include "literal.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_exprs_module(PyObject *super)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *module;                       /* Sous-module mis en place    */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_DOC \
+    "This module provide expressions used to build a match condition."
+
+    static PyModuleDef py_chrysalide_analysis_scan_exprs_module = {
+
+        .m_base = PyModuleDef_HEAD_INIT,
+
+        .m_name = "pychrysalide.analysis.scan.exprs",
+        .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_DOC,
+
+        .m_size = -1,
+
+    };
+
+    module = build_python_module(super, &py_chrysalide_analysis_scan_exprs_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_exprs_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    if (result) result = ensure_python_scan_literal_expression_is_registered();
+
+    assert(result);
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/exprs/module.h b/plugins/pychrysalide/analysis/scan/exprs/module.h
new file mode 100644
index 0000000..ee4b8ab
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/exprs/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire exprs en tant que module
+ *
+ * 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_EXPRS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.exprs' à un module Python. */
+bool add_analysis_scan_exprs_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.exprs'. */
+bool populate_analysis_scan_exprs_module(void);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/item.c b/plugins/pychrysalide/analysis/scan/item.c
index 959694e..3f46067 100644
--- a/plugins/pychrysalide/analysis/scan/item.c
+++ b/plugins/pychrysalide/analysis/scan/item.c
@@ -38,14 +38,68 @@
 
 
 
-CREATE_DYN_CONSTRUCTOR(registered_item, G_TYPE_REGISTERED_ITEM);
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Initialise la classe des éléments appelables enregistrés. */
+static void py_registered_item_init_gclass(GRegisteredItemClass *, gpointer);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(registered_item, G_TYPE_REGISTERED_ITEM, py_registered_item_init_gclass);
 
 /* Initialise une instance sur la base du dérivé de GObject. */
 static int py_registered_item_init(PyObject *, PyObject *, PyObject *);
 
+/* Indique le nom associé à une expression d'évaluation. */
+static char *py_registered_item_get_name_wrapper(const GRegisteredItem *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool py_registered_item_resolve_wrapper(GRegisteredItem *, const char *, GScanContext *, GScanScope *, GRegisteredItem **);
+
+/* Réduit une expression à une forme plus simple. */
+static bool py_registered_item_reduce_wrapper(GRegisteredItem *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Effectue un appel à une fonction enregistrée. */
+static bool py_registered_item_run_call_wrapper(GRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */
+
+
 /* Lance une résolution d'élément à appeler. */
 static PyObject *py_registered_item_resolve(PyObject *, PyObject *);
 
+/* Fournit le désignation associée à un composant nommé. */
+static PyObject *py_registered_item_get_name(PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          GLUE POUR CREATION DEPUIS PYTHON                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class  = classe à initialiser.                               *
+*                unused = données non utilisées ici.                          *
+*                                                                             *
+*  Description : Initialise la classe des éléments appelables enregistrés.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void py_registered_item_init_gclass(GRegisteredItemClass *class, gpointer unused)
+{
+    class->get_name = py_registered_item_get_name_wrapper;
+    class->resolve = py_registered_item_resolve_wrapper;
+    class->reduce = py_registered_item_reduce_wrapper;
+    class->run_call = py_registered_item_run_call_wrapper;
+
+}
 
 
 /******************************************************************************
@@ -66,13 +120,22 @@ static int py_registered_item_init(PyObject *self, PyObject *args, PyObject *kwd
 {
     int ret;                                /* Bilan de lecture des args.  */
 
-#define REGISTERED_ITEM_DOC                                            \
-    "The *RegisteredItem* class defines the basics for evaluation"  \
-    " items involved into content scanning.\n"                      \
+#define REGISTERED_ITEM_DOC                                         \
+    "The *RegisteredItem* class is an abstract definition which is" \
+    " the base for all keywords involved in a match condition"      \
+    " expression.\n"                                                \
+    "\n"                                                            \
+    "Calls to the *__init__* constructor of this abstract object"   \
+    " expect no particular argument.\n"                             \
     "\n"                                                            \
-    "Instances can be created using the following constructor:\n"   \
+    "The following methods have to be defined for new classes:\n"   \
+    "* pychrysalide.analysis.scan.RegisteredItem._resolve();\n"     \
+    "* pychrysalide.analysis.scan.RegisteredItem._reduce();\n"      \
+    "* pychrysalide.analysis.scan.RegisteredItem._call().\n"        \
     "\n"                                                            \
-    "    RegisteredItem()"
+    "One item has to be defined as class attributes in the final"   \
+    " class:\n"                                                     \
+    "* pychrysalide.analysis.scan.RegisteredItem._name.\n"
 
     /* Initialisation d'un objet GLib */
 
@@ -86,6 +149,338 @@ static int py_registered_item_init(PyObject *self, PyObject *args, PyObject *kwd
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : item = élément d'appel à consulter.                          *
+*                                                                             *
+*  Description : Indique le nom associé à une expression d'évaluation.        *
+*                                                                             *
+*  Retour      : Désignation humaine de l'expression d'évaluation.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *py_registered_item_get_name_wrapper(const GRegisteredItem *item)
+{
+    char *result;                           /* Désignation à retourner     */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *pyname;                       /* Nom en objet Python         */
+    int ret;                                /* Bilan d'une conversion      */
+
+#define REGISTERED_ITEM_NAME_ATTRIB_WRAPPER PYTHON_GETTER_WRAPPER_DEF      \
+(                                                                       \
+    _name,                                                              \
+    "Provide the keyword of the expression item to be evaluated.\n"     \
+    "\n"                                                                \
+    "The result has to be a string."                                    \
+)
+
+    result = NULL;
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(item));
+
+    if (PyObject_HasAttrString(pyobj, "_name"))
+    {
+        pyname = PyObject_GetAttrString(pyobj, "_name");
+
+        if (pyname != NULL)
+        {
+            ret = PyUnicode_Check(pyname);
+
+            if (ret)
+                result = strdup(PyUnicode_AsUTF8(pyname));
+
+            Py_DECREF(pyname);
+
+        }
+
+    }
+
+    Py_DECREF(pyobj);
+
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item   = élément d'appel à consulter.                        *
+*                target = désignation de l'objet d'appel à identifier.        *
+*                ctx    = contexte de suivi de l'analyse courante.            *
+*                scope  = portée courante des variables locales.              *
+*                out    = zone d'enregistrement de la résolution opérée. [OUT]*
+*                                                                             *
+*  Description : Lance une résolution d'élément à solliciter.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool py_registered_item_resolve_wrapper(GRegisteredItem *item, const char *target, GScanContext *ctx, GScanScope *scope, GRegisteredItem **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *pyret;                        /* Bilan de consultation       */
+    GObject *gobj_ret;                      /* Bilan natif de consultation */
+
+#define REGISTERED_ITEM_RESOLVE_WRAPPER PYTHON_WRAPPER_DEF              \
+(                                                                       \
+    _cmp_rich, "$self, target, ctx, scope, /",                          \
+    METH_VARARGS,                                                       \
+    "Abstract method used to resolve an item by name.\n"                \
+    "\n"                                                                \
+    "The *target* argument provide the name of the searched item;"      \
+    " *ctx* is a pychrysalide.analysis.scan.ScanContext instance"       \
+    " providing information about the current state; *scope* is a"      \
+    " pychrysalide.analysis.scan.ScanScope offering a view on the"      \
+    " current namespace for variables.\n"                               \
+    "\n"                                                                \
+    "The result has to be a pychrysalide.analysis.scan.RegisteredItem"  \
+    " instance on success, or *None* in case of failure."               \
+)
+
+    result = false;
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(item));
+
+    if (has_python_method(pyobj, "_resolve"))
+    {
+        args = PyTuple_New(3);
+        PyTuple_SetItem(args, 0, PyUnicode_FromString(target));
+        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(ctx)));
+        PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(scope)));
+
+        pyret = run_python_method(pyobj, "_resolve", args);
+
+        if (pyret != NULL)
+        {
+            gobj_ret = pygobject_get(pyret);
+
+            if (G_IS_REGISTERED_ITEM(gobj_ret))
+            {
+                *out = G_REGISTERED_ITEM(gobj_ret);
+
+                g_object_ref(G_OBJECT(*out));
+                result = true;
+
+            }
+
+            Py_DECREF(pyret);
+
+        }
+
+        Py_DECREF(args);
+
+    }
+
+    Py_DECREF(pyobj);
+
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = élément d'appel à consulter.                         *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la réduction opérée. [OUT]  *
+*                                                                             *
+*  Description : Réduit une expression à une forme plus simple.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool py_registered_item_reduce_wrapper(GRegisteredItem *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *pyret;                        /* Bilan de consultation       */
+    GObject *gobj_ret;                      /* Bilan natif de consultation */
+
+#define REGISTERED_ITEM_REDUCE_WRAPPER PYTHON_WRAPPER_DEF               \
+(                                                                       \
+    _cmp_rich, "$self, ctx, scope, /",                                  \
+    METH_VARARGS,                                                       \
+    "Abstract method used to replace the item by an equivalent reduced" \
+    " value.\n"                                                         \
+    "\n"                                                                \
+    "The *ctx* argument is a pychrysalide.analysis.scan.ScanContext"    \
+    " instance providing information about the current state; *scope*"  \
+    " is a pychrysalide.analysis.scan.ScanScope offering a view on the" \
+    " current namespace for variables.\n"                               \
+    "\n"                                                                \
+    "The result has to be a pychrysalide.analysis.scan.ScanExpression"  \
+    " instance on success, or *None* in case of failure."               \
+)
+
+    result = false;
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(item));
+
+    if (has_python_method(pyobj, "_reduce"))
+    {
+        args = PyTuple_New(2);
+        PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(ctx)));
+        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(scope)));
+
+        pyret = run_python_method(pyobj, "_reduce", args);
+
+        if (pyret != NULL)
+        {
+            gobj_ret = pygobject_get(pyret);
+
+            if (G_IS_SCAN_EXPRESSION(gobj_ret))
+            {
+                *out = G_SCAN_EXPRESSION(gobj_ret);
+
+                g_object_ref(G_OBJECT(*out));
+                result = true;
+
+            }
+
+            Py_DECREF(pyret);
+
+        }
+
+        Py_DECREF(args);
+
+    }
+
+    Py_DECREF(pyobj);
+
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item  = élément d'appel à consulter.                         *
+*                args  = liste d'éventuels arguments fournis.                 *
+*                count = taille de cette liste.                               *
+*                ctx   = contexte de suivi de l'analyse courante.             *
+*                scope = portée courante des variables locales.               *
+*                out   = zone d'enregistrement de la résolution opérée. [OUT] *
+*                                                                             *
+*  Description : Effectue un appel à une fonction enregistrée.                *
+*                                                                             *
+*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool py_registered_item_run_call_wrapper(GRegisteredItem *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *sub_args;                     /* Sous-arguments pour l'appel */
+    size_t i;                               /* Boucle de parcours          */
+    PyObject *py_args;                      /* Arguments pour l'appel      */
+    PyObject *pyret;                        /* Bilan de consultation       */
+    GObject *gobj_ret;                      /* Bilan natif de consultation */
+
+#define REGISTERED_ITEM_CALL_WRAPPER PYTHON_WRAPPER_DEF                 \
+(                                                                       \
+    _cmp_rich, "$self, args, ctx, scope, /",                                  \
+    METH_VARARGS,                                                       \
+    "Abstract method used to replace the item and its arguments by an"  \
+    " equivalent reduced value.\n"                                      \
+    "\n"                                                                \
+    "The *args* argument is a tuple of already reduced"                 \
+    " pychrysalide.analysis.scan.ScanExpression objects; ctx* argument" \
+    " is a pychrysalide.analysis.scan.ScanContext instance providing"   \
+    " information about the current state; *scope* is a"                \
+    " pychrysalide.analysis.scan.ScanScope offering a view on the"      \
+    " current namespace for variables.\n"                               \
+    "\n"                                                                \
+    "The result has to be a pychrysalide.analysis.scan.ScanExpression"  \
+    " instance on success, or *None* in case of failure."               \
+)
+
+    result = false;
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(item));
+
+    if (has_python_method(pyobj, "_call"))
+    {
+        sub_args = PyTuple_New(count);
+
+        for (i = 0; i < count; i++)
+            PyTuple_SetItem(sub_args, 1, pygobject_new(G_OBJECT(args[i])));
+
+        py_args = PyTuple_New(3);
+        PyTuple_SetItem(py_args, 0, sub_args);
+        PyTuple_SetItem(py_args, 1, pygobject_new(G_OBJECT(ctx)));
+        PyTuple_SetItem(py_args, 2, pygobject_new(G_OBJECT(scope)));
+
+        pyret = run_python_method(pyobj, "_call", py_args);
+
+        if (pyret != NULL)
+        {
+            gobj_ret = pygobject_get(pyret);
+
+            if (G_IS_OBJECT(gobj_ret))
+            {
+                *out = gobj_ret;
+
+                g_object_ref(G_OBJECT(*out));
+                result = true;
+
+            }
+
+            Py_DECREF(pyret);
+
+        }
+
+        Py_DECREF(py_args);
+
+    }
+
+    Py_DECREF(pyobj);
+
+    PyGILState_Release(gstate);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           CONNEXION AVEC L'API DE PYTHON                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : self = élément d'appel à consulter.                          *
 *                args = arguments fournis pour l'opération.                   *
 *                                                                             *
@@ -227,11 +622,15 @@ static PyObject *py_registered_item_get_name(PyObject *self, void *closure)
 PyTypeObject *get_python_registered_item_type(void)
 {
     static PyMethodDef py_registered_item_methods[] = {
+        REGISTERED_ITEM_RESOLVE_WRAPPER,
+        REGISTERED_ITEM_REDUCE_WRAPPER,
+        REGISTERED_ITEM_CALL_WRAPPER,
         REGISTERED_ITEM_RESOLVE_METHOD,
         { NULL }
     };
 
     static PyGetSetDef py_registered_item_getseters[] = {
+        REGISTERED_ITEM_NAME_ATTRIB_WRAPPER,
         REGISTERED_ITEM_NAME_ATTRIB,
         { NULL }
     };
@@ -243,7 +642,7 @@ PyTypeObject *get_python_registered_item_type(void)
         .tp_name        = "pychrysalide.analysis.scan.RegisteredItem",
         .tp_basicsize   = sizeof(PyGObject),
 
-        .tp_flags       = Py_TPFLAGS_DEFAULT,
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
 
         .tp_doc         = REGISTERED_ITEM_DOC,
 
diff --git a/plugins/pychrysalide/analysis/scan/module.c b/plugins/pychrysalide/analysis/scan/module.c
index ff19d92..2c5b1ef 100644
--- a/plugins/pychrysalide/analysis/scan/module.c
+++ b/plugins/pychrysalide/analysis/scan/module.c
@@ -35,6 +35,7 @@
 #include "options.h"
 #include "scanner.h"
 #include "space.h"
+#include "exprs/module.h"
 #include "patterns/module.h"
 #include "../../helpers.h"
 
@@ -76,6 +77,7 @@ bool add_analysis_scan_module(PyObject *super)
 
     result = (module != NULL);
 
+    if (result) result = add_analysis_scan_exprs_module(module);
     if (result) result = add_analysis_scan_patterns_module(module);
 
     if (!result)
@@ -113,6 +115,7 @@ bool populate_analysis_scan_module(void)
 
     if (result) result = populate_scan_module_with_core_methods();
 
+    if (result) result = populate_analysis_scan_exprs_module();
     if (result) result = populate_analysis_scan_patterns_module();
 
     assert(result);
diff --git a/src/rost.c b/src/rost.c
index 1d4929f..d47237d 100644
--- a/src/rost.c
+++ b/src/rost.c
@@ -45,6 +45,7 @@
 #include "core/global.h"
 #include "core/logs.h"
 #include "core/paths.h"
+#include "plugins/pglist.h"
 
 
 
@@ -369,6 +370,8 @@ int main(int argc, char **argv)
     if (!load_all_core_components(true))
         goto done;
 
+    init_all_plugins(true);
+
     /* Traitement des recherches */
 
     if ((optind + 0) == argc)
-- 
cgit v0.11.2-87-g4458