summaryrefslogtreecommitdiff
path: root/src/analysis/scan/exprs
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/scan/exprs')
-rw-r--r--src/analysis/scan/exprs/Makefile.am40
-rw-r--r--src/analysis/scan/exprs/access-int.h74
-rw-r--r--src/analysis/scan/exprs/access.c508
-rw-r--r--src/analysis/scan/exprs/access.h66
-rw-r--r--src/analysis/scan/exprs/arithmetic-int.h60
-rw-r--r--src/analysis/scan/exprs/arithmetic.c641
-rw-r--r--src/analysis/scan/exprs/arithmetic.h67
-rw-r--r--src/analysis/scan/exprs/call-int.h58
-rw-r--r--src/analysis/scan/exprs/call.c467
-rw-r--r--src/analysis/scan/exprs/call.h56
-rw-r--r--src/analysis/scan/exprs/extract-int.h57
-rw-r--r--src/analysis/scan/exprs/extract.c396
-rw-r--r--src/analysis/scan/exprs/extract.h56
-rw-r--r--src/analysis/scan/exprs/handler-int.h68
-rw-r--r--src/analysis/scan/exprs/handler.c622
-rw-r--r--src/analysis/scan/exprs/handler.h80
-rw-r--r--src/analysis/scan/exprs/intersect-int.h58
-rw-r--r--src/analysis/scan/exprs/intersect.c290
-rw-r--r--src/analysis/scan/exprs/intersect.h55
-rw-r--r--src/analysis/scan/exprs/item-int.h58
-rw-r--r--src/analysis/scan/exprs/item.c353
-rw-r--r--src/analysis/scan/exprs/item.h55
-rw-r--r--src/analysis/scan/exprs/literal-int.h71
-rw-r--r--src/analysis/scan/exprs/literal.c734
-rw-r--r--src/analysis/scan/exprs/literal.h90
-rw-r--r--src/analysis/scan/exprs/logical-int.h60
-rw-r--r--src/analysis/scan/exprs/logical.c518
-rw-r--r--src/analysis/scan/exprs/logical.h65
-rw-r--r--src/analysis/scan/exprs/range-int.h58
-rw-r--r--src/analysis/scan/exprs/range.c355
-rw-r--r--src/analysis/scan/exprs/range.h55
-rw-r--r--src/analysis/scan/exprs/relational-int.h60
-rw-r--r--src/analysis/scan/exprs/relational.c411
-rw-r--r--src/analysis/scan/exprs/relational.h56
-rw-r--r--src/analysis/scan/exprs/set-int.h58
-rw-r--r--src/analysis/scan/exprs/set.c407
-rw-r--r--src/analysis/scan/exprs/set.h58
-rw-r--r--src/analysis/scan/exprs/setcounter-int.h69
-rw-r--r--src/analysis/scan/exprs/setcounter.c477
-rw-r--r--src/analysis/scan/exprs/setcounter.h81
-rw-r--r--src/analysis/scan/exprs/strop-int.h62
-rw-r--r--src/analysis/scan/exprs/strop.c455
-rw-r--r--src/analysis/scan/exprs/strop.h67
43 files changed, 8452 insertions, 0 deletions
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am
new file mode 100644
index 0000000..c97fa25
--- /dev/null
+++ b/src/analysis/scan/exprs/Makefile.am
@@ -0,0 +1,40 @@
+
+noinst_LTLIBRARIES = libanalysisscanexprs.la
+
+
+libanalysisscanexprs_la_SOURCES = \
+ access-int.h \
+ access.h access.c \
+ arithmetic-int.h \
+ arithmetic.h arithmetic.c \
+ call-int.h \
+ call.h call.c \
+ extract-int.h \
+ extract.h extract.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 \
+ logical.h logical.c \
+ range-int.h \
+ range.h range.c \
+ relational-int.h \
+ relational.h relational.c \
+ set-int.h \
+ set.h set.c \
+ setcounter-int.h \
+ setcounter.h setcounter.c \
+ strop-int.h \
+ strop.h strop.c
+
+libanalysisscanexprs_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanexprs_la_SOURCES:%c=)
diff --git a/src/analysis/scan/exprs/access-int.h b/src/analysis/scan/exprs/access-int.h
new file mode 100644
index 0000000..be37241
--- /dev/null
+++ b/src/analysis/scan/exprs/access-int.h
@@ -0,0 +1,74 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * access-int.h - prototypes internes pour l'accès à un élément d'expression sous-jacent
+ *
+ * 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_ACCESS_INT_H
+#define _ANALYSIS_SCAN_EXPRS_ACCESS_INT_H
+
+
+#include "access.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+typedef void (* copy_scan_access_fc) (GScanNamedAccess *, const GScanNamedAccess *);
+
+/* Accès à un élément d'expression sous-jacent (instance) */
+struct _GScanNamedAccess
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ union
+ {
+ GScanRegisteredItem *base; /* Base de recherche */
+ GScanRegisteredItem *resolved; /* Elément ciblé au final */
+ GObject *any; /* Accès indistinct */
+ };
+
+ char *target; /* Cible dans l'espace */
+
+ struct _GScanNamedAccess *next; /* Evnetuel prochain élément */
+
+};
+
+/* Accès à un élément d'expression sous-jacent (classe) */
+struct _GScanNamedAccessClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+ copy_scan_access_fc copy; /* Reproduction d'accès */
+
+};
+
+
+/* Met en place une expression d'accès. */
+bool g_scan_named_access_create(GScanNamedAccess *, const sized_string_t *);
+
+/* Prépare une réduction en menant une résolution locale. */
+GScanRegisteredItem *_g_scan_named_access_prepare_reduction(const GScanNamedAccess *, GScanContext *, GScanScope *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_ACCESS_INT_H */
diff --git a/src/analysis/scan/exprs/access.c b/src/analysis/scan/exprs/access.c
new file mode 100644
index 0000000..342c2d7
--- /dev/null
+++ b/src/analysis/scan/exprs/access.c
@@ -0,0 +1,508 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * access.c - accès à un élément d'expression sous-jacent
+ *
+ * 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 "access.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "access-int.h"
+#include "literal.h"
+#include "../../../core/global.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des appels de fonction avec arguments. */
+static void g_scan_named_access_class_init(GScanNamedAccessClass *);
+
+/* Initialise une instance d'appel de fonction avec arguments. */
+static void g_scan_named_access_init(GScanNamedAccess *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_named_access_dispose(GScanNamedAccess *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_named_access_finalize(GScanNamedAccess *);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+static void g_scan_named_access_copy(GScanNamedAccess *, const GScanNamedAccess *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_named_access_reduce(const GScanNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+G_DEFINE_TYPE(GScanNamedAccess, g_scan_named_access, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des appels de fonction avec arguments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_named_access_class_init(GScanNamedAccessClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_named_access_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_named_access_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->reduce = (reduce_expr_fc)g_scan_named_access_reduce;
+
+ klass->copy = g_scan_named_access_copy;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = instance à initialiser. *
+* *
+* Description : Initialise une instance d'appel de fonction avec arguments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_named_access_init(GScanNamedAccess *access)
+{
+ access->any = NULL;
+ access->target = NULL;
+
+ access->next = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_named_access_dispose(GScanNamedAccess *access)
+{
+ g_clear_object(&access->any);
+
+ g_clear_object(&access->next);
+
+ G_OBJECT_CLASS(g_scan_named_access_parent_class)->dispose(G_OBJECT(access));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_named_access_finalize(GScanNamedAccess *access)
+{
+ if (access->target != NULL)
+ free(access->target);
+
+ G_OBJECT_CLASS(g_scan_named_access_parent_class)->finalize(G_OBJECT(access));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de l'objet d'appel à identifier. *
+* *
+* Description : Organise un accès à un élément d'expression sous-jacent. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_named_access_new(const sized_string_t *target)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_NAMED_ACCESS, NULL);
+
+ if (!g_scan_named_access_create(G_SCAN_NAMED_ACCESS(result), target))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = instance à initialiser pleinement. *
+* target = désignation de l'objet d'appel à identifier. *
+* *
+* Description : Met en place une expression d'accès. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_named_access_create(GScanNamedAccess *access, const sized_string_t *target)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(access), SRS_PENDING);
+ if (!result) goto exit;
+
+ if (target != NULL)
+ access->target = strndup(target->data, target->len);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
+* *
+* Description : Reproduit un accès en place dans une nouvelle instance. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_named_access_copy(GScanNamedAccess *dest, const GScanNamedAccess *src)
+{
+ /**
+ * Les champs suivants sont voués à être remplacés ou supprimés.
+ *
+ * On évite donc une instanciation inutile.
+ */
+
+ /*
+ if (src->any != NULL)
+ {
+ dest->any = src->any;
+ g_object_ref(src->any);
+ }
+ */
+
+ if (src->target != NULL)
+ dest->target = strdup(src->target);
+
+ if (src->next != NULL)
+ {
+ dest->next = src->next;
+ g_object_ref(src->next);
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : accès = expression d'accès à copier. *
+* resolved = nouvelle base à imposer. *
+* *
+* Description : Reproduit un accès en place dans une nouvelle instance. *
+* *
+* Retour : Nouvelle instance d'expression d'accès. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *access, GScanRegisteredItem *resolved)
+{
+ GScanExpression *result; /* Instance copiée à retourner */
+ GType type; /* Type d'objet à copier */
+ GScanNamedAccessClass *class; /* Classe à activer */
+
+ type = G_TYPE_FROM_INSTANCE(access);
+
+ result = g_object_new(type, NULL);
+
+ class = G_SCAN_NAMED_ACCESS_GET_CLASS(access);
+
+ class->copy(G_SCAN_NAMED_ACCESS(result), access);
+
+ g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(result), resolved);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = expression d'appel à actualiser. *
+* base = zone de recherche pour la résolution à venir. *
+* *
+* Description : Définit une base de recherche pour la cible d'accès. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_named_access_set_base(GScanNamedAccess *access, GScanRegisteredItem *base)
+{
+ g_clear_object(&access->base);
+
+ access->base = base;
+ g_object_ref(G_OBJECT(base));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = expression d'appel à compléter. *
+* next = expression d'appel suivante dans la chaîne. *
+* *
+* Description : Complète la chaine d'accès à des expressions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_named_access_attach_next(GScanNamedAccess *access, GScanNamedAccess *next)
+{
+ if (access->next != NULL)
+ g_scan_named_access_attach_next(access->next, next);
+
+ else
+ {
+ access->next = next;
+ g_object_ref(G_OBJECT(next));
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* 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. *
+* *
+* Description : Prépare une réduction en menant une résolution locale. *
+* *
+* Retour : Elément résolu avec les moyens du bord ou NULL si échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanRegisteredItem *_g_scan_named_access_prepare_reduction(const GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope)
+{
+ GScanRegisteredItem *result; /* Etat synthétisé à retourner */
+ GScanRegisteredItem *base; /* Base de recherche courante */
+
+ result = NULL;
+
+ if (expr->target != NULL)
+ {
+ if (expr->base != NULL)
+ {
+ base = expr->base;
+ g_object_ref(G_OBJECT(base));
+ }
+ else
+ base = G_SCAN_REGISTERED_ITEM(get_rost_root_namespace());
+
+ g_scan_registered_item_resolve(base, expr->target, ctx, scope, &result);
+
+ g_object_unref(G_OBJECT(base));
+
+ }
+
+ /**
+ * Si plus aucune indication n'est diponible pour avancer dans les réductions,
+ * c'est que l'opération est déjà conclue.
+ */
+ else
+ {
+ assert(expr->resolved != NULL);
+
+ result = expr->resolved;
+ g_object_ref(G_OBJECT(result));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_named_access_reduce(const GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanRegisteredItem *resolved; /* Cible concrète obtenue */
+ GScanExpression *new_next; /* Nouvelle version du suivant */
+ const char *current_rule; /* Nom de la règle courante */
+ bool status; /* Bilan d'une autre règle */
+
+ resolved = _g_scan_named_access_prepare_reduction(expr, ctx, scope);
+
+ if (resolved != NULL)
+ {
+ result = SRS_PENDING;
+
+ /**
+ * Si l'élément résolu se trouve en fin de chaîne, alors cet élément
+ * est sollicité pour obtenir une expression d'évaluation classique.
+ * Le produit de cette réduction finale bénéficie d'une promotion et
+ * représente à lui seul la réduction produite pour la chaîne.
+ */
+ if (expr->next == NULL)
+ {
+ status = g_scan_registered_item_reduce(resolved, ctx, scope, out);
+
+ result = (status ? SRS_REDUCED : SRS_UNRESOLVABLE);
+
+ }
+
+ /**
+ * Sinon, l'élément résolu constitue une base pour l'étage suivant de
+ * la chaîne de résolution.
+ */
+ else
+ {
+ new_next = g_scan_named_access_duplicate(expr->next, resolved);
+
+ result = g_scan_expression_reduce(new_next, ctx, scope, out);
+
+ g_object_unref(G_OBJECT(new_next));
+
+ }
+
+ g_object_unref(G_OBJECT(resolved));
+
+ }
+
+ /**
+ * Si le nom fournit le correspond à aucun élément de la grammaire,
+ * des recherches sont menées ailleurs.
+ */
+ else
+ {
+ result = SRS_UNRESOLVABLE;
+
+ if (g_scan_context_has_rule_for_name(ctx, expr->target))
+ {
+ current_rule = g_scan_scope_get_rule_name(scope);
+
+ /* Si référence circulaire il y a... */
+ if (strcmp(current_rule, expr->target) == 0)
+ result = SRS_UNRESOLVABLE;
+
+ else
+ {
+ status = g_scan_context_has_match_for_rule(ctx, expr->target);
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+ result = SRS_REDUCED;
+
+ }
+
+ }
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/access.h b/src/analysis/scan/exprs/access.h
new file mode 100644
index 0000000..bf83dd0
--- /dev/null
+++ b/src/analysis/scan/exprs/access.h
@@ -0,0 +1,66 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * access.h - prototypes pour l'accès à un élément d'expression sous-jacent
+ *
+ * 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_ACCESS_H
+#define _ANALYSIS_SCAN_EXPRS_ACCESS_H
+
+
+#include "../expr.h"
+#include "../item.h"
+#include "../../../common/szstr.h"
+
+
+
+#define G_TYPE_SCAN_NAMED_ACCESS g_scan_named_access_get_type()
+#define G_SCAN_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccess))
+#define G_IS_SCAN_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_NAMED_ACCESS))
+#define G_SCAN_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccessClass))
+#define G_IS_SCAN_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_NAMED_ACCESS))
+#define G_SCAN_NAMED_ACCESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccessClass))
+
+
+/* Accès à un élément d'expression sous-jacent (instance) */
+typedef struct _GScanNamedAccess GScanNamedAccess;
+
+/* Accès à un élément d'expression sous-jacent (classe) */
+typedef struct _GScanNamedAccessClass GScanNamedAccessClass;
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+GType g_scan_named_access_get_type(void);
+
+/* Organise un accès à un élément d'expression sous-jacent. */
+GScanExpression *g_scan_named_access_new(const sized_string_t *);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *, GScanRegisteredItem *);
+
+/* Définit une base de recherche pour la cible d'accès. */
+void g_scan_named_access_set_base(GScanNamedAccess *, GScanRegisteredItem *);
+
+/* Complète la chaine d'accès à des expressions. */
+void g_scan_named_access_attach_next(GScanNamedAccess *, GScanNamedAccess *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_ACCESS_H */
diff --git a/src/analysis/scan/exprs/arithmetic-int.h b/src/analysis/scan/exprs/arithmetic-int.h
new file mode 100644
index 0000000..c5010b0
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmetic-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmetic-int.h - prototypes internes pour la gestion des opérations arithmétiques
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H
+#define _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H
+
+
+#include "arithmetic.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération arithmétique impliquant deux opérandes (instance) */
+struct _GScanArithmeticOperation
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ ArithmeticExpressionOperator operator; /* Type d'opération menée */
+
+ GScanExpression *left; /* Expression impactée #1 */
+ GScanExpression *right; /* Expression impactée #2 */
+
+};
+
+/* Opération arithmétique impliquant deux opérandes (classe) */
+struct _GScanArithmeticOperationClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une opération arithmétique entre expressions. */
+bool g_scan_arithmetic_operation_create(GScanArithmeticOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H */
diff --git a/src/analysis/scan/exprs/arithmetic.c b/src/analysis/scan/exprs/arithmetic.c
new file mode 100644
index 0000000..06cfc48
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmetic.c
@@ -0,0 +1,641 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmetic.c - gestion des opérations arithmétiques
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "arithmetic.h"
+
+
+#include <assert.h>
+
+
+#include "arithmetic-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations arithmétiques. */
+static void g_scan_arithmetic_operation_class_init(GScanArithmeticOperationClass *);
+
+/* Initialise une instance d'opération arithmétique. */
+static void g_scan_arithmetic_operation_init(GScanArithmeticOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_arithmetic_operation_dispose(GScanArithmeticOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_arithmetic_operation_finalize(GScanArithmeticOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_scan_arithmetic_operation_compare_rich(const GScanArithmeticOperation *, const GScanArithmeticOperation *, RichCmpOperation, bool *);
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_arithmetic_operation_reduce(const GScanArithmeticOperation *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+G_DEFINE_TYPE(GScanArithmeticOperation, g_scan_arithmetic_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations arithmétiques. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_class_init(GScanArithmeticOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_arithmetic_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_arithmetic_operation_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_arithmetic_operation_compare_rich;
+ expr->reduce = (reduce_expr_fc)g_scan_arithmetic_operation_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération arithmétique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_init(GScanArithmeticOperation *op)
+{
+ op->left = NULL;
+ op->right = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_dispose(GScanArithmeticOperation *op)
+{
+ g_clear_object(&op->left);
+ g_clear_object(&op->right);
+
+ G_OBJECT_CLASS(g_scan_arithmetic_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_finalize(GScanArithmeticOperation *op)
+{
+ G_OBJECT_CLASS(g_scan_arithmetic_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operator = type d'opération arithmétique à représenter. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Organise une opération arithmétique entre expressions. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_ARITHMETIC_OPERATION, NULL);
+
+ if (!g_scan_arithmetic_operation_create(G_SCAN_ARITHMETIC_OPERATION(result), operator, left, right))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser pleinement. *
+* operator = type d'opération booléenne à représenter. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Met en place une opération arithmétique entre expressions. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_arithmetic_operation_create(GScanArithmeticOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(op), SRS_PENDING);
+ if (!result) goto exit;
+
+ op->operator = operator;
+
+ op->left = left;
+ g_object_ref(G_OBJECT(op->left));
+
+ op->right = right;
+ g_object_ref(G_OBJECT(op->right));
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_arithmetic_operation_compare_rich(const GScanArithmeticOperation *item, const GScanArithmeticOperation *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_ARITHMETIC_OPERATION);
+ if (!result) goto done;
+
+ if (item->operator != other->operator)
+ {
+ result = compare_rich_integer_values_unsigned(item->operator, other->operator, op);
+ goto done;
+ }
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left),
+ G_COMPARABLE_ITEM(other->left),
+ op, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
+ G_COMPARABLE_ITEM(other->right),
+ op, status);
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_arithmetic_operation_reduce(const GScanArithmeticOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_left; /* Expression réduite (gauche) */
+ GScanExpression *new_right; /* Expression réduite (droite) */
+ ScanReductionState state_left; /* Etat synthétisé #1 */
+ ScanReductionState state_right; /* Etat synthétisé #2 */
+ GScanLiteralExpression *op_left; /* Opérande gauche final */
+ GScanLiteralExpression *op_right; /* Opérande droite final */
+ LiteralValueType vtype_left; /* Type de valeur portée #1 */
+ LiteralValueType vtype_right; /* Type de valeur portée #2 */
+ long long val_1_s; /* Première valeur à traiter */
+ unsigned long long val_1_u; /* Première valeur à traiter */
+ long long val_2_s; /* Seconde valeur à traiter */
+ unsigned long long val_2_u; /* Seconde valeur à traiter */
+ LiteralValueType state_final; /* Nature de la valeur finale */
+ long long reduced_s; /* Valeur réduite finale */
+ unsigned long long reduced_u; /* Valeur réduite finale */
+
+ /* Réduction des éléments considérés */
+
+ new_left = NULL;
+ new_right = NULL;
+
+ state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (state_left == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (state_right == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Construction d'une réduction locale ? */
+
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
+ {
+ /* Récupération de l'opérande de gauche */
+
+ op_left = G_SCAN_LITERAL_EXPRESSION(new_left);
+ vtype_left = g_scan_literal_expression_get_value_type(op_left);
+
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_signed_integer_value(op_left, &val_1_s))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else if (vtype_left == LVT_UNSIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_unsigned_integer_value(op_left, &val_1_u))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Récupération de l'opérande de droite */
+
+ op_right = G_SCAN_LITERAL_EXPRESSION(new_right);
+ vtype_right = g_scan_literal_expression_get_value_type(op_right);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_signed_integer_value(op_right, &val_2_s))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else if (vtype_right == LVT_UNSIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_unsigned_integer_value(op_right, &val_2_u))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Partie des calculs */
+
+ result = SRS_REDUCED;
+
+ switch (expr->operator)
+ {
+ case AEO_PLUS:
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s + val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ if ((long long)val_2_u > val_1_s)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s + (long long)val_2_u;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s + (long long)val_2_u;
+ }
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ if ((long long)val_1_u > val_2_s)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = (long long)val_1_u + val_2_s;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = (long long)val_1_u + val_2_s;
+ }
+
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u + val_2_u;
+
+ }
+ }
+ break;
+
+ case AEO_MINUS:
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ if (val_2_s < val_1_s)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s - val_2_s;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s - val_2_s;
+ }
+
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s - (long long)val_2_u;
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = (long long)val_1_u - val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ if (val_1_u > val_2_u)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u - val_2_u;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_u - val_2_u;
+ }
+
+ }
+ }
+ break;
+
+ case AEO_MUL:
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s * val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s * (long long)val_2_u;
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = (long long)val_1_u * val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u * val_2_u;
+
+ }
+ }
+ break;
+
+ case AEO_DIV:
+ if ((vtype_right == LVT_SIGNED_INTEGER && val_2_s == 0)
+ || (vtype_right == LVT_UNSIGNED_INTEGER && val_2_u == 0))
+ {
+ result = SRS_UNRESOLVABLE;
+ break;
+ }
+
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s / val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s / (long long)val_2_u;
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = (long long)val_1_u / val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u / val_2_u;
+
+ }
+ }
+ break;
+
+ case AEO_MOD:
+ result = SRS_UNRESOLVABLE;
+ /* FIXME
+ result = (val_2 != 0);
+ if (result)
+ reduced = val_1 % val_2;
+ */
+ break;
+
+ }
+
+ if (result == SRS_REDUCED)
+ {
+ if (state_final == LVT_SIGNED_INTEGER)
+ *out = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &reduced_s);
+ else
+ {
+ assert(state_final == LVT_UNSIGNED_INTEGER);
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &reduced_u);
+ }
+
+ }
+
+ }
+
+ /* Mise à jour de la progression ? */
+
+ else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
+ {
+ if (new_left != expr->left || new_right != expr->right)
+ *out = g_scan_arithmetic_operation_new(expr->operator, new_left, new_right);
+
+ result = SRS_WAIT_FOR_SCAN;
+
+ }
+
+ /* Cas des situations où les expressions ne sont pas exploitables (!) */
+ else
+ {
+ assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+ result = SRS_UNRESOLVABLE;
+
+ }
+
+ /* Sortie propre */
+
+ exit:
+
+ g_clear_object(&new_left);
+ g_clear_object(&new_right);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/arithmetic.h b/src/analysis/scan/exprs/arithmetic.h
new file mode 100644
index 0000000..8a1e844
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmetic.h
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmetic.h - prototypes pour la gestion des opérations arithmétiques
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H
+#define _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_ARITHMETIC_OPERATION g_scan_arithmetic_operation_get_type()
+#define G_SCAN_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperation))
+#define G_IS_SCAN_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION))
+#define G_SCAN_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperationClass))
+#define G_IS_SCAN_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_ARITHMETIC_OPERATION))
+#define G_SCAN_ARITHMETIC_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperationClass))
+
+
+/* Opération arithmétique impliquant deux opérandes (instance) */
+typedef struct _GScanArithmeticOperation GScanArithmeticOperation;
+
+/* Opération arithmétique impliquant deux opérandes (classe) */
+typedef struct _GScanArithmeticOperationClass GScanArithmeticOperationClass;
+
+
+/* Type d'opération arithmétique */
+typedef enum _ArithmeticExpressionOperator
+{
+ AEO_PLUS, /* Opération binaire "+" */
+ AEO_MINUS, /* Opération binaire "-" */
+ AEO_MUL, /* Opération binaire "*" */
+ AEO_DIV, /* Opération binaire "\" */
+ AEO_MOD, /* Opération binaire "%" */
+
+} ArithmeticExpressionOperator;
+
+
+/* Indique le type défini pour une opération arithmétique entre expressions. */
+GType g_scan_arithmetic_operation_get_type(void);
+
+/* Organise une opération arithmétique entre expressions. */
+GScanExpression *g_scan_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H */
diff --git a/src/analysis/scan/exprs/call-int.h b/src/analysis/scan/exprs/call-int.h
new file mode 100644
index 0000000..9646b95
--- /dev/null
+++ b/src/analysis/scan/exprs/call-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * call-int.h - prototypes internes pour l'organisation d'un appel à un élément de scan enregistré
+ *
+ * Copyright (C) 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_CALL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_CALL_INT_H
+
+
+#include "call.h"
+
+
+#include "access-int.h"
+
+
+
+/* Exécution d'une fonction auxiliaire d'analyse (instance) */
+struct _GScanPendingCall
+{
+ GScanNamedAccess parent; /* A laisser en premier */
+
+ GScanExpression **args; /* Arguments d'appel fournis */
+ size_t count; /* Quantité de ces arguments */
+
+};
+
+/* Exécution d'une fonction auxiliaire d'analyse (classe) */
+struct _GScanPendingCallClass
+{
+ GScanNamedAccessClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'appel. */
+bool g_scan_pending_call_create(GScanPendingCall *, const sized_string_t *, GScanExpression **, size_t);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_CALL_INT_H */
diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c
new file mode 100644
index 0000000..3997ff6
--- /dev/null
+++ b/src/analysis/scan/exprs/call.c
@@ -0,0 +1,467 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * call.c - organisation d'un appel à un élément de scan enregistré
+ *
+ * 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 "call.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "call-int.h"
+#include "../../../core/global.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des appels de fonction avec arguments. */
+static void g_scan_pending_call_class_init(GScanPendingCallClass *);
+
+/* Initialise une instance d'appel de fonction avec arguments. */
+static void g_scan_pending_call_init(GScanPendingCall *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_pending_call_dispose(GScanPendingCall *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_pending_call_finalize(GScanPendingCall *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_pending_call_reduce(const GScanPendingCall *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+static void g_scan_pending_call_copy(GScanPendingCall *, const GScanPendingCall *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+G_DEFINE_TYPE(GScanPendingCall, g_scan_pending_call, G_TYPE_SCAN_NAMED_ACCESS);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des appels de fonction avec arguments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_call_class_init(GScanPendingCallClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+ GScanNamedAccessClass *access; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pending_call_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_pending_call_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->reduce = (reduce_expr_fc)g_scan_pending_call_reduce;
+
+ access = G_SCAN_NAMED_ACCESS_CLASS(klass);
+
+ access->copy = (copy_scan_access_fc)g_scan_pending_call_copy;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : call = instance à initialiser. *
+* *
+* Description : Initialise une instance d'appel de fonction avec arguments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_call_init(GScanPendingCall *call)
+{
+ call->args = NULL;
+ call->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : call = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_call_dispose(GScanPendingCall *call)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < call->count; i++)
+ g_clear_object(&call->args[i]);
+
+ G_OBJECT_CLASS(g_scan_pending_call_parent_class)->dispose(G_OBJECT(call));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : call = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_call_finalize(GScanPendingCall *call)
+{
+ if (call->args != NULL)
+ free(call->args);
+
+ G_OBJECT_CLASS(g_scan_pending_call_parent_class)->finalize(G_OBJECT(call));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de l'objet d'appel à identifier. *
+* args = éventuelle liste d'arguments à actionner. *
+* count = quantité de ces arguments. *
+* *
+* Description : Organise un appel de fonction avec ses arguments. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_pending_call_new(const sized_string_t *target, GScanExpression **args, size_t count)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_PENDING_CALL, NULL);
+
+ if (!g_scan_pending_call_create(G_SCAN_PENDING_CALL(result), target, args, count))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : call = instance à initialiser pleinement. *
+* target = désignation de l'objet d'appel à identifier. *
+* args = éventuelle liste d'arguments à actionner. *
+* count = quantité de ces arguments. *
+* *
+* Description : Met en place une expression d'appel. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_pending_call_create(GScanPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = g_scan_named_access_create(G_SCAN_NAMED_ACCESS(call), target);
+ if (!result) goto exit;
+
+ call->args = malloc(count * sizeof(GScanExpression *));
+ call->count = count;
+
+ for (i = 0; i < count; i++)
+ {
+ call->args[i] = args[i];
+ g_object_ref(G_OBJECT(args[i]));
+ }
+
+ exit:
+
+ 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_pending_call_reduce(const GScanPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanNamedAccess *access; /* Autre vision de l'expression*/
+ GScanRegisteredItem *resolved; /* Cible concrète obtenue */
+ size_t i; /* Boucle de parcours #1 */
+ GScanExpression *arg; /* Argument réduit à échanger */
+ GScanExpression *new; /* Nouvelle réduction obtenue */
+ ScanReductionState state; /* Etat synthétisé d'un élément*/
+ size_t k; /* Boucle de parcours #2 */
+ GScanExpression **new_args; /* Nouvelle séquence d'args. */
+ GObject *final; /* Expression ou élément ? */
+ bool valid; /* Validité de l'élément */
+ GScanExpression *new_next; /* Nouvelle version du suivant */
+
+ access = G_SCAN_NAMED_ACCESS(expr);
+
+ resolved = _g_scan_named_access_prepare_reduction(access, ctx, scope);
+
+ if (resolved == NULL)
+ result = SRS_UNRESOLVABLE;
+
+ else
+ {
+ result = SRS_PENDING;
+
+ /* Actualisation nécessaire des arguments ? */
+
+ new_args = NULL;
+
+ for (i = 0; i < expr->count; i++)
+ {
+ arg = expr->args[i];
+
+ state = g_scan_expression_reduce(arg, ctx, scope, &new);
+ if (state == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ break;
+ }
+
+ if (state == SRS_WAIT_FOR_SCAN)
+ result = SRS_WAIT_FOR_SCAN;
+
+ if (new != arg)
+ {
+ if (new_args == NULL)
+ {
+ new_args = calloc(expr->count, sizeof(GScanExpression *));
+
+ for (k = 0; k < i; k++)
+ {
+ new_args[k] = expr->args[k];
+ g_object_ref(G_OBJECT(new_args[k]));
+ }
+
+ }
+
+ new_args[i] = new;
+
+ }
+
+ else
+ {
+ if (new_args != NULL)
+ new_args[i] = new;
+
+ else
+ g_object_unref(G_OBJECT(new));
+
+ }
+
+ }
+
+ /* Suite des traitements */
+
+ if (result == SRS_WAIT_FOR_SCAN)
+ {
+ /**
+ * Si changement il y a eu...
+ */
+ if (new_args != NULL)
+ {
+ *out = g_scan_pending_call_new(NULL, new_args, expr->count);
+
+ /**
+ * Fonctionnement équivalent de :
+ * g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(*out), resolved);
+ */
+ G_SCAN_NAMED_ACCESS(*out)->resolved = resolved;
+ g_object_ref(G_OBJECT(resolved));
+
+ if (G_SCAN_NAMED_ACCESS(expr)->next != NULL)
+ g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS(*out), G_SCAN_NAMED_ACCESS(expr)->next);
+
+ }
+
+ }
+
+ else if (result == SRS_PENDING)
+ {
+ if (new_args == NULL)
+ valid = g_scan_registered_item_run_call(resolved,
+ expr->args,
+ expr->count,
+ ctx, scope, &final);
+ else
+ valid = g_scan_registered_item_run_call(resolved,
+ new_args,
+ expr->count,
+ ctx, scope, &final);
+
+ if (valid && final != NULL)
+ {
+ /**
+ * Si le produit de l'appel à la fonction est une expression d'évaluation
+ * classique, alors ce produit constitue la réduction finale de la chaîne.
+ *
+ * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne.
+ */
+ if (!G_IS_SCAN_REGISTERED_ITEM(final))
+ {
+ if (access->next != NULL)
+ result = SRS_UNRESOLVABLE;
+
+ else
+ {
+ *out = G_SCAN_EXPRESSION(final);
+ g_object_ref(G_OBJECT(final));
+
+ result = SRS_REDUCED;
+
+ }
+
+ }
+ else
+ {
+ assert(access->next != NULL);
+
+ new_next = g_scan_named_access_duplicate(access->next, G_SCAN_REGISTERED_ITEM(final));
+
+ result = g_scan_expression_reduce(new_next, ctx, scope, out);
+
+ g_object_unref(G_OBJECT(new_next));
+
+ }
+
+ }
+
+ else
+ result = SRS_UNRESOLVABLE;
+
+ g_clear_object(&final);
+
+ }
+
+ /* Libération locale des arguments reconstruits */
+
+ if (new_args != NULL)
+ {
+ for (i = 0; i < expr->count; i++)
+ g_clear_object(&new_args[i]);
+ }
+
+ g_object_unref(G_OBJECT(resolved));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
+* *
+* Description : Reproduit un accès en place dans une nouvelle instance. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_call_copy(GScanPendingCall *dest, const GScanPendingCall *src)
+{
+ GScanNamedAccessClass *class; /* Classe parente à solliciter */
+ size_t i; /* Boucle de parcours */
+
+ class = G_SCAN_NAMED_ACCESS_CLASS(g_scan_pending_call_parent_class);
+
+ class->copy(G_SCAN_NAMED_ACCESS(dest), G_SCAN_NAMED_ACCESS(src));
+
+ dest->args = malloc(src->count * sizeof(GScanExpression *));
+ dest->count = src->count;
+
+ for (i = 0; i < src->count; i++)
+ {
+ dest->args[i] = src->args[i];
+ g_object_ref(G_OBJECT(src->args[i]));
+ }
+
+}
diff --git a/src/analysis/scan/exprs/call.h b/src/analysis/scan/exprs/call.h
new file mode 100644
index 0000000..c4d8964
--- /dev/null
+++ b/src/analysis/scan/exprs/call.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * call.h - prototypes pour l'organisation d'un appel à un élément de scan enregistré
+ *
+ * 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_CALL_H
+#define _ANALYSIS_SCAN_EXPRS_CALL_H
+
+
+#include "../expr.h"
+#include "../../../common/szstr.h"
+
+
+
+#define G_TYPE_SCAN_PENDING_CALL g_scan_pending_call_get_type()
+#define G_SCAN_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PENDING_CALL, GScanPendingCall))
+#define G_IS_SCAN_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PENDING_CALL))
+#define G_SCAN_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PENDING_CALL, GScanPendingCallClass))
+#define G_IS_SCAN_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PENDING_CALL))
+#define G_SCAN_PENDING_CALL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PENDING_CALL, GScanPendingCallClass))
+
+
+/* Exécution d'une fonction auxiliaire d'analyse (instance) */
+typedef struct _GScanPendingCall GScanPendingCall;
+
+/* Exécution d'une fonction auxiliaire d'analyse (classe) */
+typedef struct _GScanPendingCallClass GScanPendingCallClass;
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+GType g_scan_pending_call_get_type(void);
+
+/* Organise un appel de fonction avec ses arguments. */
+GScanExpression *g_scan_pending_call_new(const sized_string_t *, GScanExpression **, size_t);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_CALL_H */
diff --git a/src/analysis/scan/exprs/extract-int.h b/src/analysis/scan/exprs/extract-int.h
new file mode 100644
index 0000000..562e537
--- /dev/null
+++ b/src/analysis/scan/exprs/extract-int.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * extract-int.h - prototypes internes pour l'organisation d'une extraction d'un élément d'une série interne
+ *
+ * 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_EXTRACT_INT_H
+#define _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H
+
+
+#include "extract.h"
+
+
+#include "access-int.h"
+
+
+
+/* Extraction d'un élément donné au sein d'une série interne (instance) */
+struct _GScanPendingExtraction
+{
+ GScanNamedAccess parent; /* A laisser en premier */
+
+ GScanExpression *index; /* Arguments d'appel fournis */
+
+};
+
+/* Extraction d'un élément donné au sein d'une série interne (classe) */
+struct _GScanPendingExtractionClass
+{
+ GScanNamedAccessClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'extraction d'élément interne. */
+bool g_scan_pending_extraction_create(GScanPendingExtraction *, const sized_string_t *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H */
diff --git a/src/analysis/scan/exprs/extract.c b/src/analysis/scan/exprs/extract.c
new file mode 100644
index 0000000..b140ed9
--- /dev/null
+++ b/src/analysis/scan/exprs/extract.c
@@ -0,0 +1,396 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * extract.c - organisation d'une extraction d'un élément d'une série interne
+ *
+ * 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 "extract.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include "extract-int.h"
+#include "../../../core/global.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des extractions d'éléments internes. */
+static void g_scan_pending_extraction_class_init(GScanPendingExtractionClass *);
+
+/* Initialise une instance d'extraction d'élément interne. */
+static void g_scan_pending_extraction_init(GScanPendingExtraction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_pending_extraction_dispose(GScanPendingExtraction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_pending_extraction_finalize(GScanPendingExtraction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_pending_extraction_reduce(const GScanPendingExtraction *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+static void g_scan_pending_extraction_copy(GScanPendingExtraction *, const GScanPendingExtraction *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une extraction d'élément de série interne. */
+G_DEFINE_TYPE(GScanPendingExtraction, g_scan_pending_extraction, G_TYPE_SCAN_NAMED_ACCESS);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des extractions d'éléments internes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_extraction_class_init(GScanPendingExtractionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+ GScanNamedAccessClass *access; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pending_extraction_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_pending_extraction_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->reduce = (reduce_expr_fc)g_scan_pending_extraction_reduce;
+
+ access = G_SCAN_NAMED_ACCESS_CLASS(klass);
+
+ access->copy = (copy_scan_access_fc)g_scan_pending_extraction_copy;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : extract = instance à initialiser. *
+* *
+* Description : Initialise une instance d'extraction d'élément interne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_extraction_init(GScanPendingExtraction *extract)
+{
+ extract->index = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : extract = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_extraction_dispose(GScanPendingExtraction *extract)
+{
+ g_clear_object(&extract->index);
+
+ G_OBJECT_CLASS(g_scan_pending_extraction_parent_class)->dispose(G_OBJECT(extract));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : extract = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_extraction_finalize(GScanPendingExtraction *extract)
+{
+ G_OBJECT_CLASS(g_scan_pending_extraction_parent_class)->finalize(G_OBJECT(extract));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de l'objet d'appel à identifier. *
+* index = indice de l'élément à extraire. *
+* *
+* Description : Organise l'extraction d'un élément d'une série interne. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_pending_extraction_new(const sized_string_t *target, GScanExpression *index)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_PENDING_EXTRACTION, NULL);
+
+ if (!g_scan_pending_extraction_create(G_SCAN_PENDING_EXTRACTION(result), target, index))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : extract = instance à initialiser pleinement. *
+* target = désignation de l'objet d'appel à identifier. *
+* index = indice de l'élément à extraire. *
+* *
+* Description : Met en place une expression d'extraction d'élément interne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_pending_extraction_create(GScanPendingExtraction *extract, const sized_string_t *target, GScanExpression *index)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_named_access_create(G_SCAN_NAMED_ACCESS(extract), target);
+ if (!result) goto exit;
+
+ extract->index = index;
+ g_object_ref(G_OBJECT(index));
+
+ exit:
+
+ 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_pending_extraction_reduce(const GScanPendingExtraction *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanNamedAccess *access; /* Autre vision de l'expression*/
+ GScanRegisteredItem *resolved; /* Cible concrète obtenue */
+ GScanExpression *new; /* Nouvelle réduction obtenue */
+ GObject *final; /* Expression ou élément ? */
+ GScanExpression *new_next; /* Nouvelle version du suivant */
+
+ access = G_SCAN_NAMED_ACCESS(expr);
+
+ resolved = _g_scan_named_access_prepare_reduction(access, ctx, scope);
+
+ if (resolved == NULL)
+ result = SRS_UNRESOLVABLE;
+
+ else
+ {
+ /* Actualisation nécessaire des arguments ? */
+
+ result = g_scan_expression_reduce(expr->index, ctx, scope, &new);
+
+ /* Suite des traitements */
+
+ if (result == SRS_WAIT_FOR_SCAN)
+ {
+ /**
+ * Si changement il y a eu...
+ */
+ if (new != expr->index)
+ {
+ *out = g_scan_pending_extraction_new(NULL, new);
+
+ /**
+ * Fonctionnement équivalent de :
+ * g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(*out), resolved);
+ */
+ G_SCAN_NAMED_ACCESS(*out)->resolved = resolved;
+ g_object_ref(G_OBJECT(resolved));
+
+ if (G_SCAN_NAMED_ACCESS(expr)->next != NULL)
+ g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS(*out), G_SCAN_NAMED_ACCESS(expr)->next);
+
+ }
+
+ }
+
+ else if (result == SRS_REDUCED)
+ {
+ final = g_scan_registered_item_extract_at(resolved, new, ctx, scope);
+
+ if (final != NULL)
+ {
+ /**
+ * Si le produit de l'appel à la fonction est une expression d'évaluation
+ * classique, alors ce produit constitue la réduction finale de la chaîne.
+ *
+ * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne.
+ */
+ if (!G_IS_SCAN_REGISTERED_ITEM(final))
+ {
+ if (access->next != NULL)
+ result = SRS_UNRESOLVABLE;
+
+ else
+ {
+ *out = G_SCAN_EXPRESSION(final);
+ g_object_ref(G_OBJECT(final));
+
+ result = SRS_REDUCED;
+
+ }
+
+ }
+ else
+ {
+ if (access->next != NULL)
+ {
+ new_next = g_scan_named_access_duplicate(access->next, G_SCAN_REGISTERED_ITEM(final));
+
+ result = g_scan_expression_reduce(new_next, ctx, scope, out);
+
+ g_object_unref(G_OBJECT(new_next));
+
+ }
+
+ /**
+ * Le cas ci-après est typique de l'extension Kaitai : field[n]
+ * renvoie vers une instance GScanRegisteredItem (GKaitaiBrowser).
+ *
+ * Il n'y a donc pas d'expression en jeu, et l'élément est le dernier
+ * de la liste.
+ */
+ else
+ {
+ if (g_scan_registered_item_reduce(G_SCAN_REGISTERED_ITEM(final), ctx, scope, out))
+ result = SRS_REDUCED;
+ else
+ result = SRS_UNRESOLVABLE;
+
+ }
+
+ }
+
+ }
+
+ else
+ result = SRS_UNRESOLVABLE;
+
+ g_clear_object(&final);
+
+ }
+
+ /* Libération locale des arguments reconstruits */
+
+ g_clear_object(&new);
+
+ g_object_unref(G_OBJECT(resolved));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
+* *
+* Description : Reproduit un accès en place dans une nouvelle instance. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_extraction_copy(GScanPendingExtraction *dest, const GScanPendingExtraction *src)
+{
+ GScanNamedAccessClass *class; /* Classe parente à solliciter */
+
+ class = G_SCAN_NAMED_ACCESS_CLASS(g_scan_pending_extraction_parent_class);
+
+ class->copy(G_SCAN_NAMED_ACCESS(dest), G_SCAN_NAMED_ACCESS(src));
+
+ dest->index = src->index;
+ g_object_ref(G_OBJECT(src->index));
+
+}
diff --git a/src/analysis/scan/exprs/extract.h b/src/analysis/scan/exprs/extract.h
new file mode 100644
index 0000000..8ed1cfa
--- /dev/null
+++ b/src/analysis/scan/exprs/extract.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * extract.h - prototypes pour l'organisation d'une extraction d'un élément d'une série interne
+ *
+ * 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_EXTRACT_H
+#define _ANALYSIS_SCAN_EXPRS_EXTRACT_H
+
+
+#include "../expr.h"
+#include "../../../common/szstr.h"
+
+
+
+#define G_TYPE_SCAN_PENDING_EXTRACTION g_scan_pending_extraction_get_type()
+#define G_SCAN_PENDING_EXTRACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtraction))
+#define G_IS_SCAN_PENDING_EXTRACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PENDING_EXTRACTION))
+#define G_SCAN_PENDING_EXTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtractionClass))
+#define G_IS_SCAN_PENDING_EXTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PENDING_EXTRACTION))
+#define G_SCAN_PENDING_EXTRACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtractionClass))
+
+
+/* Extraction d'un élément donné au sein d'une série interne (instance) */
+typedef struct _GScanPendingExtraction GScanPendingExtraction;
+
+/* Extraction d'un élément donné au sein d'une série interne (classe) */
+typedef struct _GScanPendingExtractionClass GScanPendingExtractionClass;
+
+
+/* Indique le type défini pour une extraction d'élément de série interne. */
+GType g_scan_pending_extraction_get_type(void);
+
+/* Organise l'extraction d'un élément d'une série interne. */
+GScanExpression *g_scan_pending_extraction_new(const sized_string_t *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_EXTRACT_H */
diff --git a/src/analysis/scan/exprs/handler-int.h b/src/analysis/scan/exprs/handler-int.h
new file mode 100644
index 0000000..e051b30
--- /dev/null
+++ b/src/analysis/scan/exprs/handler-int.h
@@ -0,0 +1,68 @@
+
+/* 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 */
+
+ union
+ {
+ const GSearchPattern **patterns; /* Motifs associés */
+ GSearchPattern **ref_patterns; /* Motifs associés */
+ };
+ size_t count; /* Nombre de ces motifs */
+ bool shared; /* Définition de propriété */
+
+ 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_shared(GScanPatternHandler *, const GSearchPattern ** const, size_t, ScanHandlerType);
+
+/* Met en place une manipulation de correspondances établies. */
+bool g_scan_pattern_handler_create_and_ref(GScanPatternHandler *, GSearchPattern ** const, size_t, 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..2706dae
--- /dev/null
+++ b/src/analysis/scan/exprs/handler.c
@@ -0,0 +1,622 @@
+
+/* 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(const GScanPatternHandler *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_pattern_handler_reduce_to_boolean(const 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->patterns = NULL;
+ handler->count = 0;
+ handler->shared = true;
+
+ 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)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (!handler->shared)
+ for (i = 0; i < handler->count; i++)
+ g_clear_object(&handler->ref_patterns[i]);
+
+ 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)
+{
+ if (handler->patterns != NULL)
+ free(handler->patterns);
+
+ G_OBJECT_CLASS(g_scan_pattern_handler_parent_class)->finalize(G_OBJECT(handler));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : patterns = motifs à impliquer. *
+* count = quantité de ces motifs. *
+* 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_shared(const GSearchPattern ** const patterns, size_t count, ScanHandlerType type)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_PATTERN_HANDLER, NULL);
+
+ if (!g_scan_pattern_handler_create_shared(G_SCAN_PATTERN_HANDLER(result), patterns, count, type))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : handler = instance à initialiser pleinement. *
+* patterns = motifs à impliquer. *
+* count = quantité de ces motifs. *
+* 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_shared(GScanPatternHandler *handler, const GSearchPattern ** const patterns, size_t count, ScanHandlerType type)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(handler), SRS_WAIT_FOR_SCAN);
+ if (!result) goto exit;
+
+ handler->patterns = malloc(count * sizeof(GSearchPattern *));
+ handler->count = count;
+
+ memcpy(handler->patterns, patterns, count * sizeof(GSearchPattern *));
+
+ handler->shared = true;
+
+ handler->type = type;
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : patterns = motifs à impliquer. *
+* count = quantité de ces motifs. *
+* 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 ** const patterns, size_t count, ScanHandlerType type)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_PATTERN_HANDLER, NULL);
+
+ if (!g_scan_pattern_handler_create_and_ref(G_SCAN_PATTERN_HANDLER(result), patterns, count, type))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : handler = instance à initialiser pleinement. *
+* patterns = motifs à impliquer. *
+* count = quantité de ces motifs. *
+* 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_and_ref(GScanPatternHandler *handler, GSearchPattern ** const patterns, size_t count, ScanHandlerType type)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(handler), SRS_WAIT_FOR_SCAN);
+ if (!result) goto exit;
+
+ handler->patterns = malloc(count * sizeof(GSearchPattern *));
+ handler->count = count;
+
+ memcpy(handler->patterns, patterns, count * sizeof(GSearchPattern *));
+
+ for (i = 0; i < count; i++)
+ g_object_ref(G_OBJECT(patterns[i]));
+
+ handler->shared = false;
+
+ handler->type = type;
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : handler = instance à initialiser pleinement. *
+* *
+* Description : Indique le type de manipulation de correspondances spécifié. *
+* *
+* Retour : Type de manipulation de correspondances représentée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+ScanHandlerType g_scan_pattern_handler_get_handler_type(const GScanPatternHandler *handler)
+{
+ ScanHandlerType result; /* Nature à retourner */
+
+ result = handler->type;
+
+ return result;
+
+}
+
+
+#if 0 /* FIXME */
+
+/******************************************************************************
+* *
+* Paramètres : handler = instance à initialiser pleinement. *
+* ctx = contexte de suivi de l'analyse courante. *
+* count = quantité de correspondances enregistrées. [OUT] *
+* *
+* Description : Fournit la liste de toutes les correspondances représentées. *
+* *
+* Retour : Liste courante de correspondances établies. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanMatch **g_scan_pattern_handler_get_all_matches(const GScanPatternHandler *handler, GScanContext *ctx, size_t *count)
+{
+ GScanMatch **result; /* Liste à retourner */
+ size_t used; /* Indice pour le stockage */
+ size_t i; /* Boucle de parcours #1 */
+ size_t partial; /* Décompte partiel */
+ const GScanMatch **matches; /* Correspondances en place */
+ size_t k; /* Boucle de parcours #2 */
+
+ result = NULL;
+
+ if (!g_scan_pattern_handler_count_items(handler, ctx, count))
+ {
+ *count = 0;
+ goto exit;
+ }
+
+ if (*count == 0)
+ goto exit;
+
+ result = malloc(*count * sizeof(GScanMatch *));
+
+ used = 0;
+
+ for (i = 0; i < handler->count; i++)
+ {
+ matches = g_scan_context_get_full_matches(ctx, handler->patterns[i], &partial);
+
+ for (k = 0; k < partial; k++)
+ {
+ result[used++] = matches[k];
+ g_object_ref(G_OBJECT(matches[k]));
+ }
+
+ }
+
+ exit:
+
+ return result;
+
+}
+#endif
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* 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(const GScanPatternHandler *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ size_t count; /* Quantité de correspondances */
+
+ if (g_scan_context_is_scan_done(ctx))
+ {
+ if (expr->type == SHT_COUNTER)
+ {
+ if (!g_scan_pattern_handler_count_items(expr, ctx, &count))
+ result = SRS_UNRESOLVABLE;
+
+ else
+ {
+ result = SRS_REDUCED;
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ count });
+ }
+
+ }
+
+ else
+ 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(const GScanPatternHandler *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ size_t count; /* Quantité de correspondances */
+
+ result = g_scan_pattern_handler_count_items(expr, ctx, &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 */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ assert(g_scan_context_is_scan_done(ctx));
+
+ *count = 0;
+
+ for (i = 0; i < expr->count; i++)
+ *count += g_scan_context_count_full_matches(ctx, expr->patterns[i]);
+
+ 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 i; /* Boucle de parcours */
+ size_t count; /* Quantité de correspondances */
+ GScanMatches *matches; /* Correspondances d'un motif */
+ const match_area_t *area; /* Zone de correspondance */
+ 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 */
+
+ result = false;
+
+ assert(g_scan_context_is_scan_done(ctx));
+
+ /* Identification du motif concerné */
+
+ for (i = 0; i < expr->count; i++)
+ {
+ count = g_scan_context_count_full_matches(ctx, expr->patterns[i]);
+
+ if (index < count)
+ break;
+ else
+ index -= count;
+
+ }
+
+ if (i == expr->count) goto done;
+
+ /* Identification de la correspondance concernée */
+
+ matches = g_scan_context_get_full_matches(ctx, expr->patterns[i]);
+ if (matches == NULL) goto done;
+
+ area = g_scan_bytes_matches_get(G_SCAN_BYTES_MATCHES(matches), index);
+ if (area == NULL) goto done_with_matches;
+
+ /* Traitement adapté de la requête */
+
+ switch (expr->type)
+ {
+ case SHT_RAW:
+ content = g_scan_context_get_content(ctx);
+
+ init_vmpa(&pos, area->start, VMPA_NO_VIRTUAL);
+
+ data = g_binary_content_get_raw_access(content, &pos, area->end - area->start);
+
+ binary.static_bin_data = data;
+ binary.len = area->end - area->start;
+
+ *out = g_scan_literal_expression_new(LVT_STRING, &binary);
+
+ g_object_unref(G_OBJECT(content));
+ result = true;
+ break;
+
+ case SHT_COUNTER:
+ assert(false);
+ break;
+
+ case SHT_START:
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+ (unsigned long long []){ area->start });
+ result = true;
+ break;
+
+ case SHT_LENGTH:
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+ (unsigned long long []){ area->end - area->start });
+ result = true;
+ break;
+
+ case SHT_END:
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+ (unsigned long long []){ area->end });
+ result = true;
+ break;
+
+ }
+
+ done_with_matches:
+
+ g_object_unref(G_OBJECT(matches));
+
+ 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..a1ddf98
--- /dev/null
+++ b/src/analysis/scan/exprs/handler.h
@@ -0,0 +1,80 @@
+
+/* 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_COUNTER, /* Dénombrement de résultats */
+ 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_shared(const GSearchPattern ** const, size_t, ScanHandlerType);
+
+/* Met en place une manipulation de correspondances établies. */
+GScanExpression *g_scan_pattern_handler_new(GSearchPattern ** const, size_t, ScanHandlerType);
+
+/* Indique le type de manipulation de correspondances spécifié. */
+ScanHandlerType g_scan_pattern_handler_get_handler_type(const GScanPatternHandler *);
+
+#if 0 /* FIXME */
+
+/* Fournit la liste de toutes les correspondances représentées. */
+GScanMatch **g_scan_pattern_handler_get_all_matches(const GScanPatternHandler *, GScanContext *, size_t *);
+
+#endif
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_HANDLER_H */
diff --git a/src/analysis/scan/exprs/intersect-int.h b/src/analysis/scan/exprs/intersect-int.h
new file mode 100644
index 0000000..83e4251
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect-int.h - prototypes internes pour l'intersection d'ensembles aux types indentiques
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H
+#define _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H
+
+
+#include "intersect.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération d'intersection entre deux ensembles (instance) */
+struct _GScanSetsIntersection
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GScanExpression *first; /* Expression impactée #1 */
+ GScanExpression *second; /* Expression impactée #2 */
+
+};
+
+/* Opération d'intersection entre deux ensembles (classe) */
+struct _GScanSetsIntersectionClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'opération booléenne. */
+bool g_scan_sets_intersection_create(GScanSetsIntersection *, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H */
diff --git a/src/analysis/scan/exprs/intersect.c b/src/analysis/scan/exprs/intersect.c
new file mode 100644
index 0000000..c56d28c
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect.c
@@ -0,0 +1,290 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect.c - intersection d'ensembles aux types indentiques
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "intersect.h"
+
+
+#include <assert.h>
+
+
+#include "intersect-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des intersections entre deux ensembles. */
+static void g_scan_sets_intersection_class_init(GScanSetsIntersectionClass *);
+
+/* Initialise une instance d'intersection entre deux ensembles. */
+static void g_scan_sets_intersection_init(GScanSetsIntersection *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_sets_intersection_dispose(GScanSetsIntersection *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_sets_intersection_finalize(GScanSetsIntersection *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_sets_intersection_reduce(const GScanSetsIntersection *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une intersection entre deux ensembles. */
+G_DEFINE_TYPE(GScanSetsIntersection, g_scan_sets_intersection, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des intersections entre deux ensembles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_class_init(GScanSetsIntersectionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sets_intersection_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_sets_intersection_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->reduce = (reduce_expr_fc)g_scan_sets_intersection_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'intersection entre deux ensembles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_init(GScanSetsIntersection *inter)
+{
+ inter->first = NULL;
+ inter->second = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inter = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_dispose(GScanSetsIntersection *inter)
+{
+ g_clear_object(&inter->first);
+ g_clear_object(&inter->second);
+
+ G_OBJECT_CLASS(g_scan_sets_intersection_parent_class)->dispose(G_OBJECT(inter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inter = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_finalize(GScanSetsIntersection *inter)
+{
+ G_OBJECT_CLASS(g_scan_sets_intersection_parent_class)->finalize(G_OBJECT(inter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type d'opération booléenne à représenter. *
+* first = premier élément concerné. *
+* second = second élément concerné. *
+* *
+* Description : Organise une intersection entre deux ensembles. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_sets_intersection_new(GScanExpression *first, GScanExpression *second)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_SETS_INTERSECTION, NULL);
+
+ if (!g_scan_sets_intersection_create(G_SCAN_SETS_INTERSECTION(result), first, second))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inter = instance à initialiser pleinement. *
+* first = premier élément concerné. *
+* second = second élément concerné. *
+* *
+* Description : Met en place une expression d'opération booléenne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_sets_intersection_create(GScanSetsIntersection *inter, GScanExpression *first, GScanExpression *second)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ inter->first = first;
+ g_object_ref(G_OBJECT(first));
+
+ inter->second = second;
+ g_object_ref(G_OBJECT(second));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_sets_intersection_reduce(const GScanSetsIntersection *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_first; /* Nouvelle réduction #1 */
+ GScanExpression *new_second; /* Nouvelle réduction #2 */
+ ScanReductionState state_first; /* Etat synthétisé #1 */
+ ScanReductionState state_second; /* Etat synthétisé #2 */
+
+ new_first = NULL;
+ new_second = NULL;
+
+ state_first = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
+ if (state_first == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_second = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
+ if (state_second == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (state_first == SRS_WAIT_FOR_SCAN || state_second == SRS_WAIT_FOR_SCAN)
+ {
+ if (new_first != expr->first || new_second != expr->second)
+ *out = g_scan_sets_intersection_new(new_first, new_second);
+
+ result = SRS_WAIT_FOR_SCAN;
+
+ }
+
+ else
+ {
+ assert(state_first == SRS_REDUCED && state_second == SRS_REDUCED);
+
+ *out = g_scan_expression_intersect(new_first, new_second, ctx, scope);
+
+ result = (*out != NULL ? SRS_REDUCED : SRS_UNRESOLVABLE);
+
+ }
+
+ exit:
+
+ g_clear_object(&new_first);
+ g_clear_object(&new_second);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/intersect.h b/src/analysis/scan/exprs/intersect.h
new file mode 100644
index 0000000..56efdff
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect.h - prototypes pour l'intersection d'ensembles aux types indentiques
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_INTERSECT_H
+#define _ANALYSIS_SCAN_EXPRS_INTERSECT_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_SETS_INTERSECTION g_scan_sets_intersection_get_type()
+#define G_SCAN_SETS_INTERSECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersection))
+#define G_IS_SCAN_SETS_INTERSECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SETS_INTERSECTION))
+#define G_SCAN_SETS_INTERSECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersectionClass))
+#define G_IS_SCAN_SETS_INTERSECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SETS_INTERSECTION))
+#define G_SCAN_SETS_INTERSECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersectionClass))
+
+
+/* Opération d'intersection entre deux ensembles (instance) */
+typedef struct _GScanSetsIntersection GScanSetsIntersection;
+
+/* Opération d'intersection entre deux ensembles (classe) */
+typedef struct _GScanSetsIntersectionClass GScanSetsIntersectionClass;
+
+
+/* Indique le type défini pour une intersection entre deux ensembles. */
+GType g_scan_sets_intersection_get_type(void);
+
+/* Organise une intersection entre deux ensembles. */
+GScanExpression *g_scan_sets_intersection_new(GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_INTERSECT_H */
diff --git a/src/analysis/scan/exprs/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..a5a6fdf
--- /dev/null
+++ b/src/analysis/scan/exprs/item.c
@@ -0,0 +1,353 @@
+
+/* 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(const 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 = g_scan_expression_create(G_SCAN_EXPRESSION(item), SRS_PENDING);
+ if (!result) goto exit;
+
+ item->set = set;
+ g_object_ref(G_OBJECT(set));
+
+ item->index = index;
+ g_object_ref(G_OBJECT(index));
+
+ exit:
+
+ 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(const 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);
+
+ }
+
+ else
+ status = false;
+
+ 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-int.h b/src/analysis/scan/exprs/literal-int.h
new file mode 100644
index 0000000..b0a0ec5
--- /dev/null
+++ b/src/analysis/scan/exprs/literal-int.h
@@ -0,0 +1,71 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal-int.h - prototypes internes pour la représentation d'une valeur concrète
+ *
+ * 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_LITERAL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_LITERAL_INT_H
+
+
+#include "literal.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Expression portant une valeur concrète (instance) */
+struct _GScanLiteralExpression
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ LiteralValueType value_type; /* Type de valeur portée */
+
+ union
+ {
+ bool boolean; /* Valeur booléenne */
+ long long s_integer; /* Valeur entière 64 bits */
+ unsigned long long u_integer; /* Valeur entière 64 bits */
+ sized_string_t string; /* Chaîne de caractères */
+ struct
+ {
+ char *regex; /* Formulation d'origine */
+ regex_t preg; /* Expression rationnelle */
+ };
+
+ } value;
+
+};
+
+/* Expression portant une valeur concrète (classe) */
+struct _GScanLiteralExpressionClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression de valeur concrête. */
+bool g_scan_literal_expression_create(GScanLiteralExpression *, LiteralValueType, ...);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_LITERAL_INT_H */
diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c
new file mode 100644
index 0000000..b7aed5b
--- /dev/null
+++ b/src/analysis/scan/exprs/literal.c
@@ -0,0 +1,734 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal.c - représentation d'une valeur concrète
+ *
+ * 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 "literal.h"
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+#include "literal-int.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des expressions de valeur concrète. */
+static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *);
+
+/* Initialise une instance d'expression de valeur concrète. */
+static void g_scan_literal_expression_init(GScanLiteralExpression *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_literal_expression_dispose(GScanLiteralExpression *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_literal_expression_finalize(GScanLiteralExpression *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression *, const GScanLiteralExpression *, RichCmpOperation, bool *);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_literal_expression_reduce_to_boolean(const GScanLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Dénombre les éléments portés par une expression. */
+static bool g_scan_literal_expression_count(const GScanLiteralExpression *, GScanContext *, size_t *);
+
+/* Fournit un élément donné issu d'un ensemble constitué. */
+static bool g_scan_literal_expression_get_item(const GScanLiteralExpression *, size_t, GScanContext *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+G_DEFINE_TYPE(GScanLiteralExpression, g_scan_literal_expression, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des expressions de valeur concrète. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_literal_expression_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_literal_expression_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_literal_expression_compare_rich;
+ expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_literal_expression_reduce_to_boolean;
+ expr->count = (count_scan_expr_fc)g_scan_literal_expression_count;
+ expr->get = (get_scan_expr_fc)g_scan_literal_expression_get_item;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance à initialiser. *
+* *
+* Description : Initialise une instance d'expression de valeur concrète. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_literal_expression_init(GScanLiteralExpression *expr)
+{
+ G_SCAN_EXPRESSION(expr)->state = SRS_REDUCED;
+
+ memset(&expr->value, 0, sizeof(expr->value));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_literal_expression_dispose(GScanLiteralExpression *expr)
+{
+ G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->dispose(G_OBJECT(expr));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_literal_expression_finalize(GScanLiteralExpression *expr)
+{
+ switch (expr->value_type)
+ {
+ case LVT_STRING:
+ exit_szstr(&expr->value.string);
+ break;
+
+ case LVT_REG_EXPR:
+ if (expr->value.regex != NULL)
+ {
+ free(expr->value.regex);
+ regfree(&expr->value.preg);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->finalize(G_OBJECT(expr));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : vtype = type de valeur associée par l'expression. *
+* ... = valeur concrête à intégrer. *
+* *
+* Description : Organise un appel de fonction avec ses arguments. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_literal_expression_new(LiteralValueType vtype, ...)
+{
+ GScanExpression *result; /* Structure à retourner */
+ va_list ap; /* Liste d'arguements */
+ void *ptr; /* Vision générique de valeur */
+
+ result = g_object_new(G_TYPE_SCAN_LITERAL_EXPRESSION, NULL);
+
+ va_start(ap, vtype);
+
+ ptr = va_arg(ap, void *);
+
+ if (!g_scan_literal_expression_create(G_SCAN_LITERAL_EXPRESSION(result), vtype, ptr))
+ g_clear_object(&result);
+
+ va_end(ap);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance à initialiser pleinement. *
+* vtype = type de valeur associée par l'expression. *
+* ... = valeur concrête à intégrer. *
+* *
+* Description : Met en place une expression de valeur concrête. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_literal_expression_create(GScanLiteralExpression *expr, LiteralValueType vtype, ...)
+{
+ bool result; /* Bilan à retourner */
+ va_list ap; /* Liste d'arguements */
+ const bool *boolean; /* Valeur booléenne */
+ const long long *s_integer; /* Valeur entière 64 bits #1 */
+ const unsigned long long *u_integer; /* Valeur entière 64 bits #2 */
+ const sized_string_t *string; /* Chaîne de caractères */
+ const char *raw; /* Chaîne de caractères brute */
+ size_t len; /* Taille de la chaîne */
+ int cflags; /* Détails de compilation */
+ unsigned int i; /* Boucle de parcours */
+ char *tmp; /* Zone de travail temporaire */
+ int ret; /* Bilan d'une opération */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(expr), SRS_REDUCED);
+ if (!result) goto exit;
+
+ va_start(ap, vtype);
+
+ switch (vtype)
+ {
+ case LVT_BOOLEAN:
+ boolean = va_arg(ap, const bool *);
+ expr->value.boolean = *boolean;
+ result = true;
+ break;
+
+ case LVT_SIGNED_INTEGER:
+ s_integer = va_arg(ap, const long long *);
+ expr->value.s_integer = *s_integer;
+ result = true;
+ break;
+
+ case LVT_UNSIGNED_INTEGER:
+ u_integer = va_arg(ap, const unsigned long long *);
+ expr->value.u_integer = *u_integer;
+ result = true;
+ break;
+
+ case LVT_STRING:
+ string = va_arg(ap, const sized_string_t *);
+ szstrdup(&expr->value.string, string);
+ result = true;
+ break;
+
+ case LVT_REG_EXPR:
+ raw = va_arg(ap, const char *);
+ len = strlen(raw);
+
+ result = (len > 2 && raw[0] == '/');
+
+ cflags = REG_EXTENDED | REG_NOSUB;
+
+ for (i = 0; i < 2 && result; i++)
+ {
+ result = (len > 2);
+
+ if (raw[len - 1] == 'i')
+ {
+ cflags |= REG_ICASE;
+ len -= 1;
+ }
+
+ else if (raw[len - 1] == 's')
+ {
+ cflags |= REG_NEWLINE;
+ len -= 1;
+ }
+
+ else if (raw[len - 1] == '/')
+ break;
+
+ }
+
+ if (result)
+ result = (raw[len - 1] == '/');
+
+ if (result)
+ {
+ assert(len > 2);
+
+ tmp = strndup(&raw[1], len - 2);
+ ret = regcomp(&expr->value.preg, tmp, cflags);
+ free(tmp);
+
+ result = (ret == 0);
+
+ if (result)
+ expr->value.regex = strdup(raw);
+
+ }
+
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ va_end(ap);
+
+ expr->value_type = vtype;
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* *
+* Description : Indique le type de valeur portée par une expression. *
+* *
+* Retour : Type de valeur associée à l'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+LiteralValueType g_scan_literal_expression_get_value_type(const GScanLiteralExpression *expr)
+{
+ LiteralValueType result; /* Type à retourner */
+
+ result = expr->value_type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
+* value = valeur portée portée par l'expression. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression booléenne. *
+* *
+* Retour : true si l'expression est de type booléen, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_literal_expression_get_boolean_value(const GScanLiteralExpression *expr, bool *value)
+{
+ bool result; /* Etat à retourner */
+
+ result = (expr->value_type == LVT_BOOLEAN);
+
+ if (result)
+ *value = expr->value.boolean;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
+* value = valeur portée portée par l'expression. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression d'entier. *
+* *
+* Retour : true si l'expression est de type entier, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_literal_expression_get_signed_integer_value(const GScanLiteralExpression *expr, long long *value)
+{
+ bool result; /* Etat à retourner */
+
+ result = (expr->value_type == LVT_SIGNED_INTEGER);
+
+ if (result)
+ *value = expr->value.u_integer;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
+* value = valeur portée portée par l'expression. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression d'entier. *
+* *
+* Retour : true si l'expression est de type entier, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_literal_expression_get_unsigned_integer_value(const GScanLiteralExpression *expr, unsigned long long *value)
+{
+ bool result; /* Etat à retourner */
+
+ result = (expr->value_type == LVT_UNSIGNED_INTEGER);
+
+ if (result)
+ *value = expr->value.u_integer;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
+* value = valeur portée portée par l'expression. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression de chaîne. *
+* *
+* Retour : true si l'expression est de type entier, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_literal_expression_get_string_value(const GScanLiteralExpression *expr, const sized_string_t **value)
+{
+ bool result; /* Etat à retourner */
+
+ result = (expr->value_type == LVT_STRING);
+
+ if (result)
+ *value = &expr->value.string;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
+* value = valeur portée portée par l'expression. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression rationnelle. *
+* *
+* Retour : true si l'expression est de type entier, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_literal_expression_get_regex_value(const GScanLiteralExpression *expr, const regex_t **value)
+{
+ bool result; /* Etat à retourner */
+
+ result = (expr->value_type == LVT_REG_EXPR);
+
+ if (result)
+ *value = &expr->value.preg;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression *expr, const GScanLiteralExpression *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+ int cmp; /* Bilan intermédiaire */
+
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_LITERAL_EXPRESSION);
+ if (!result) goto done;
+
+ if (expr->value_type != other->value_type)
+ {
+ *status = compare_rich_integer_values_unsigned(expr->value_type, other->value_type, op);
+ goto done;
+ }
+
+ switch (expr->value_type)
+ {
+ case LVT_BOOLEAN:
+ switch (op)
+ {
+ case RCO_EQ:
+ *status = (expr->value.boolean == other->value.boolean);
+ result = true;
+ break;
+
+ case RCO_NE:
+ *status = (expr->value.boolean != other->value.boolean);
+ result = true;
+ break;
+
+ default:
+ result = false;
+ break;
+
+ };
+ break;
+
+ case LVT_SIGNED_INTEGER:
+ *status = compare_rich_integer_values_signed(expr->value.s_integer, other->value.s_integer, op);
+ result = true;
+ break;
+
+ case LVT_UNSIGNED_INTEGER:
+ *status = compare_rich_integer_values_unsigned(expr->value.u_integer, other->value.u_integer, op);
+ result = true;
+ break;
+
+ case LVT_STRING:
+ cmp = szstrcmp(&expr->value.string, &other->value.string);
+ *status = compare_rich_integer_values_signed(cmp, 0, op);
+ result = true;
+ break;
+
+ case LVT_REG_EXPR:
+ cmp = strcmp(expr->value.regex, other->value.regex);
+ *status = compare_rich_integer_values_signed(cmp, 0, op);
+ result = true;
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme booléenne. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_literal_expression_reduce_to_boolean(const GScanLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+
+ switch (expr->value_type)
+ {
+ case LVT_BOOLEAN:
+ *out = G_SCAN_EXPRESSION(expr);
+ g_object_ref(G_OBJECT(expr));
+ result = true;
+ break;
+
+ case LVT_SIGNED_INTEGER:
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.s_integer != 0 });
+ result = true;
+ break;
+
+ case LVT_UNSIGNED_INTEGER:
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.u_integer != 0 });
+ result = true;
+ break;
+
+ case LVT_STRING:
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.string.len > 0 });
+ result = true;
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ 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_literal_expression_count(const GScanLiteralExpression *expr, GScanContext *ctx, size_t *count)
+{
+ bool result; /* Bilan à retourner */
+
+ switch (expr->value_type)
+ {
+ case LVT_STRING:
+ *count = expr->value.string.len;
+ result = true;
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ 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_literal_expression_get_item(const GScanLiteralExpression *expr, size_t index, GScanContext *ctx, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ sized_string_t ch; /* Caractère extrait */
+
+ switch (expr->value_type)
+ {
+ case LVT_STRING:
+
+ result = (index < expr->value.string.len);
+
+ if (result)
+ {
+ ch.data = expr->value.string.data + index;
+ ch.len = 1;
+
+ *out = g_scan_literal_expression_new(LVT_STRING, &ch);
+
+ }
+
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/literal.h b/src/analysis/scan/exprs/literal.h
new file mode 100644
index 0000000..9352baf
--- /dev/null
+++ b/src/analysis/scan/exprs/literal.h
@@ -0,0 +1,90 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal.h - prototypes pour la représentation d'une valeur concrète
+ *
+ * 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_LITERAL_H
+#define _ANALYSIS_SCAN_EXPRS_LITERAL_H
+
+
+#include <regex.h>
+#include <stdbool.h>
+
+
+#include "../expr.h"
+#include "../../../common/szstr.h"
+
+
+
+#define G_TYPE_SCAN_LITERAL_EXPRESSION g_scan_literal_expression_get_type()
+#define G_SCAN_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpression))
+#define G_IS_SCAN_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_LITERAL_EXPRESSION))
+#define G_SCAN_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpressionClass))
+#define G_IS_SCAN_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_LITERAL_EXPRESSION))
+#define G_SCAN_LITERAL_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpressionClass))
+
+
+/* Expression portant une valeur concrète (instance) */
+typedef struct _GScanLiteralExpression GScanLiteralExpression;
+
+/* Expression portant une valeur concrète (classe) */
+typedef struct _GScanLiteralExpressionClass GScanLiteralExpressionClass;
+
+
+/* Types naturel équivalant à l'expression */
+typedef enum _LiteralValueType
+{
+ LVT_BOOLEAN, /* Valeur booléenne */
+ LVT_SIGNED_INTEGER, /* Nombre entier 64 bits #1 */
+ LVT_UNSIGNED_INTEGER, /* Nombre entier 64 bits #2 */
+ LVT_STRING, /* Chaîne de caractères */
+ LVT_REG_EXPR, /* Expression rationnelle */
+
+} LiteralValueType;
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+GType g_scan_literal_expression_get_type(void);
+
+/* Organise un appel de fonction avec ses arguments. */
+GScanExpression *g_scan_literal_expression_new(LiteralValueType, ...);
+
+/* Indique le type de valeur portée par une expression. */
+LiteralValueType g_scan_literal_expression_get_value_type(const GScanLiteralExpression *);
+
+/* Indique la valeur portée par une expression booléenne. */
+bool g_scan_literal_expression_get_boolean_value(const GScanLiteralExpression *, bool *);
+
+/* Indique la valeur portée par une expression d'entier. */
+bool g_scan_literal_expression_get_signed_integer_value(const GScanLiteralExpression *, long long *);
+
+/* Indique la valeur portée par une expression d'entier. */
+bool g_scan_literal_expression_get_unsigned_integer_value(const GScanLiteralExpression *, unsigned long long *);
+
+/* Indique la valeur portée par une expression de chaîne. */
+bool g_scan_literal_expression_get_string_value(const GScanLiteralExpression *, const sized_string_t **);
+
+/* Indique la valeur portée par une expression rationnelle. */
+bool g_scan_literal_expression_get_regex_value(const GScanLiteralExpression *, const regex_t **);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_LITERAL_H */
diff --git a/src/analysis/scan/exprs/logical-int.h b/src/analysis/scan/exprs/logical-int.h
new file mode 100644
index 0000000..6df55d0
--- /dev/null
+++ b/src/analysis/scan/exprs/logical-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logical-int.h - prototypes internes pour la gestion des opérations booléennes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H
+
+
+#include "logical.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération booléenne avec un ou deux opérandes (instance) */
+struct _GScanLogicalOperation
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ BooleanOperationType type; /* Type d'opération menée */
+
+ GScanExpression *first; /* Expression impactée #1 */
+ GScanExpression *second; /* Expression impactée #2 */
+
+};
+
+/* Opération booléenne avec un ou deux opérandes (classe) */
+struct _GScanLogicalOperationClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'opération booléenne. */
+bool g_scan_logical_operation_create(GScanLogicalOperation *, BooleanOperationType, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H */
diff --git a/src/analysis/scan/exprs/logical.c b/src/analysis/scan/exprs/logical.c
new file mode 100644
index 0000000..3b07843
--- /dev/null
+++ b/src/analysis/scan/exprs/logical.c
@@ -0,0 +1,518 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logical.c - gestion des opérations booléennes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "logical.h"
+
+
+#include <assert.h>
+
+
+#include "logical-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations booléennes. */
+static void g_scan_logical_operation_class_init(GScanLogicalOperationClass *);
+
+/* Initialise une instance d'opération booléenne. */
+static void g_scan_logical_operation_init(GScanLogicalOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_logical_operation_dispose(GScanLogicalOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_logical_operation_finalize(GScanLogicalOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_scan_logical_operation_compare_rich(const GScanLogicalOperation *, const GScanLogicalOperation *, RichCmpOperation, bool *);
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_logical_operation_reduce(const GScanLogicalOperation *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération booléenne sur expression(s). */
+G_DEFINE_TYPE(GScanLogicalOperation, g_scan_logical_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations booléennes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_logical_operation_class_init(GScanLogicalOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_logical_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_logical_operation_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_logical_operation_compare_rich;
+ expr->reduce = (reduce_expr_fc)g_scan_logical_operation_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération booléenne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_logical_operation_init(GScanLogicalOperation *op)
+{
+ op->first = NULL;
+ op->second = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_logical_operation_dispose(GScanLogicalOperation *op)
+{
+ g_clear_object(&op->first);
+ g_clear_object(&op->second);
+
+ G_OBJECT_CLASS(g_scan_logical_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_logical_operation_finalize(GScanLogicalOperation *op)
+{
+ G_OBJECT_CLASS(g_scan_logical_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type d'opération booléenne à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Organise un appel de fonction avec ses arguments. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_logical_operation_new(BooleanOperationType type, GScanExpression *first, GScanExpression *second)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_BOOLEAN_OPERATION, NULL);
+
+ if (!g_scan_logical_operation_create(G_SCAN_LOGICAL_OPERATION(result), type, first, second))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance à initialiser pleinement. *
+* type = type d'opération booléenne à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Met en place une expression d'opération booléenne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_logical_operation_create(GScanLogicalOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(op), SRS_PENDING);
+ if (!result) goto exit;
+
+ op->type = type;
+
+ switch (type)
+ {
+ case BOT_AND:
+ case BOT_OR:
+ op->first = first;
+ g_object_ref(G_OBJECT(op->first));
+
+ op->second = second;
+ g_object_ref(G_OBJECT(op->second));
+
+ result = true;
+ break;
+
+ case BOT_NOT:
+ op->first = first;
+ g_object_ref(G_OBJECT(op->first));
+
+ result = (second == NULL);
+ assert(second == NULL);
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_logical_operation_compare_rich(const GScanLogicalOperation *item, const GScanLogicalOperation *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_BOOLEAN_OPERATION);
+ if (!result) goto done;
+
+ if (item->type != other->type)
+ {
+ *status = compare_rich_integer_values_unsigned(item->type, other->type, op);
+ goto done;
+ }
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first),
+ G_COMPARABLE_ITEM(other->first),
+ op, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+ if (item->second == NULL)
+ {
+ assert(other->second == NULL);
+
+ switch (op)
+ {
+ case RCO_LT:
+ case RCO_NE:
+ case RCO_GT:
+ *status = false;
+ break;
+
+ case RCO_LE:
+ case RCO_EQ:
+ case RCO_GE:
+ *status = true;
+ break;
+
+ }
+
+ }
+
+ else
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second),
+ G_COMPARABLE_ITEM(other->second),
+ op, status);
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_logical_operation_reduce(const GScanLogicalOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_first; /* Expression réduite (gauche) */
+ ScanReductionState state[2]; /* Bilan de sous-réductons */
+ GScanExpression *new_second; /* Expression réduite (droite) */
+ GScanExpression *bool_operands[2]; /* Expressions booléennes */
+ bool values[2]; /* Valeurs des éléments portés */
+ bool valid[2]; /* Validité de ces valeurs */
+
+ /* Réduction des éléments considérés */
+
+ state[0] = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
+
+ if (expr->second != NULL)
+ state[1] = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
+ else
+ {
+ new_second = NULL;
+ state[1] = SRS_REDUCED;
+ }
+
+ /* Récupération des valeurs booléennes */
+
+ if (new_first != NULL)
+ {
+ valid[0] = g_scan_expression_reduce_to_boolean(new_first, ctx, scope, &bool_operands[0]);
+
+ if (valid[0])
+ valid[0] = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(bool_operands[0]),
+ &values[0]);
+ else
+ bool_operands[0] = NULL;
+
+ }
+ else
+ {
+ bool_operands[0] = NULL;
+ valid[0] = false;
+ }
+
+ if (new_second != NULL)
+ {
+ valid[1] = g_scan_expression_reduce_to_boolean(new_second, ctx, scope, &bool_operands[1]);
+
+ if (valid[1])
+ valid[1] = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(bool_operands[1]),
+ &values[1]);
+ else
+ bool_operands[1] = NULL;
+
+ }
+ else
+ {
+ bool_operands[1] = NULL;
+ valid[1] = false;
+ }
+
+ /* Construction d'une réduction locale ? */
+
+ switch (expr->type)
+ {
+ case BOT_AND:
+ if (valid[0] && valid[1])
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { values[0] && values[1] });
+ result = SRS_REDUCED;
+ }
+
+ else if (valid[0] && !values[0])
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false });
+ result = SRS_REDUCED;
+ }
+
+ else if (valid[1] && !values[1])
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false });
+ result = SRS_REDUCED;
+ }
+
+ else
+ {
+ if (state[0] == SRS_UNRESOLVABLE || state[1] == SRS_UNRESOLVABLE)
+ result = SRS_UNRESOLVABLE;
+ else
+ {
+ assert(state[0] == SRS_WAIT_FOR_SCAN || state[1] == SRS_WAIT_FOR_SCAN);
+ result = SRS_WAIT_FOR_SCAN;
+ }
+ }
+
+ break;
+
+ case BOT_OR:
+ if (valid[0] && valid[1])
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { values[0] || values[1] });
+ result = SRS_REDUCED;
+ }
+
+ else if (valid[0] && values[0])
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true });
+ result = SRS_REDUCED;
+ }
+
+ else if (valid[1] && values[1])
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true });
+ result = SRS_REDUCED;
+ }
+
+ else
+ {
+ if (state[0] == SRS_UNRESOLVABLE || state[1] == SRS_UNRESOLVABLE)
+ result = SRS_UNRESOLVABLE;
+ else
+ {
+ assert(state[0] == SRS_WAIT_FOR_SCAN || state[1] == SRS_WAIT_FOR_SCAN);
+ result = SRS_WAIT_FOR_SCAN;
+ }
+ }
+
+ break;
+
+ case BOT_NOT:
+ if (valid[0])
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { !values[0] });
+ result = SRS_REDUCED;
+ }
+
+ else
+ {
+ if (state[0] == SRS_UNRESOLVABLE)
+ result = SRS_UNRESOLVABLE;
+ else
+ {
+ assert(state[0] == SRS_WAIT_FOR_SCAN);
+ result = SRS_WAIT_FOR_SCAN;
+ }
+ }
+
+ break;
+
+ /* Pour GCC... */
+ default:
+ result = SRS_UNRESOLVABLE;
+ break;
+
+ }
+
+ /* Mise à jour de la progression ? */
+
+ if (result == SRS_WAIT_FOR_SCAN)
+ {
+ if (new_first != expr->first || new_second != expr->second)
+ {
+ assert(new_first != NULL);
+ assert(new_second != NULL || expr->second == NULL);
+
+ *out = g_scan_logical_operation_new(expr->type, new_first, new_second);
+
+ }
+
+ }
+
+ /* Sortie propre */
+
+ g_clear_object(&bool_operands[0]);
+ g_clear_object(&bool_operands[1]);
+
+ g_clear_object(&new_first);
+ g_clear_object(&new_second);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/logical.h b/src/analysis/scan/exprs/logical.h
new file mode 100644
index 0000000..e98bf11
--- /dev/null
+++ b/src/analysis/scan/exprs/logical.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * logical.h - prototypes pour la gestion des opérations booléennes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_LOGICAL_H
+#define _ANALYSIS_SCAN_EXPRS_LOGICAL_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_BOOLEAN_OPERATION g_scan_logical_operation_get_type()
+#define G_SCAN_LOGICAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperation))
+#define G_IS_BOOLEAN_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BOOLEAN_OPERATION))
+#define G_SCAN_LOGICAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperationClass))
+#define G_IS_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BOOLEAN_OPERATION))
+#define G_SCAN_LOGICAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperationClass))
+
+
+/* Opération booléenne avec un ou deux opérandes (instance) */
+typedef struct _GScanLogicalOperation GScanLogicalOperation;
+
+/* Opération booléenne avec un ou deux opérandes (classe) */
+typedef struct _GScanLogicalOperationClass GScanLogicalOperationClass;
+
+
+/* Types d'opérations booléennes supportées */
+typedef enum _BooleanOperationType
+{
+ BOT_AND, /* Opérateur binaire "and" */
+ BOT_OR, /* Opérateur binaire "or" */
+ BOT_NOT, /* Opérateur unaire "not" */
+
+} BooleanOperationType;
+
+
+/* Indique le type défini pour une opération booléenne sur expression(s). */
+GType g_scan_logical_operation_get_type(void);
+
+/* Organise un appel de fonction avec ses arguments. */
+GScanExpression *g_scan_logical_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_LOGICAL_H */
diff --git a/src/analysis/scan/exprs/range-int.h b/src/analysis/scan/exprs/range-int.h
new file mode 100644
index 0000000..6257874
--- /dev/null
+++ b/src/analysis/scan/exprs/range-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range-int.h - prototypes internes pour la représentation compacte d'un éventail de valeurs
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_RANGE_INT_H
+#define _ANALYSIS_SCAN_EXPRS_RANGE_INT_H
+
+
+#include "range.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Représentation compacte d'un éventail de valeurs (instance) */
+struct _GScanCompactRange
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GScanExpression *start; /* Point de départ */
+ GScanExpression *end; /* Point d'arrivée */
+
+};
+
+/* Représentation compacte d'un éventail de valeurs (classe) */
+struct _GScanCompactRangeClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une réprésentation d'un éventail de valeurs. */
+bool g_scan_compact_range_create(GScanCompactRange *, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_RANGE_INT_H */
diff --git a/src/analysis/scan/exprs/range.c b/src/analysis/scan/exprs/range.c
new file mode 100644
index 0000000..9716149
--- /dev/null
+++ b/src/analysis/scan/exprs/range.c
@@ -0,0 +1,355 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range.c - représentation compacte d'un éventail de valeurs
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "range.h"
+
+
+#include "literal.h"
+#include "range-int.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des éventail de valeurs. */
+static void g_scan_compact_range_class_init(GScanCompactRangeClass *);
+
+/* Initialise une instance d'éventail de valeurs. */
+static void g_scan_compact_range_init(GScanCompactRange *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_compact_range_dispose(GScanCompactRange *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_compact_range_finalize(GScanCompactRange *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_compact_range_reduce(const GScanCompactRange *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_compact_range_reduce_to_boolean(const GScanCompactRange *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réalise l'intersection entre deux ensembles. */
+static GScanExpression *g_scan_compact_range_intersect(const GScanCompactRange *expr, const GScanExpression *, GScanContext *, GScanScope *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une représentation compacte d'un éventail de valeurs. */
+G_DEFINE_TYPE(GScanCompactRange, g_scan_compact_range, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des éventail de valeurs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_class_init(GScanCompactRangeClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_compact_range_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_compact_range_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->reduce = (reduce_expr_fc)g_scan_compact_range_reduce;
+ expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_compact_range_reduce_to_boolean;
+ expr->intersect = (intersect_scan_expr_fc)g_scan_compact_range_intersect;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance à initialiser. *
+* *
+* Description : Initialise une instance d'éventail de valeurs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_init(GScanCompactRange *range)
+{
+ range->start = NULL;
+ range->end = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_dispose(GScanCompactRange *range)
+{
+ g_clear_object(&range->start);
+ g_clear_object(&range->end);
+
+ G_OBJECT_CLASS(g_scan_compact_range_parent_class)->dispose(G_OBJECT(range));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_finalize(GScanCompactRange *range)
+{
+ G_OBJECT_CLASS(g_scan_compact_range_parent_class)->finalize(G_OBJECT(range));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : start = point de départ de la plage de valeurs. *
+* end = point d'arrivée de la plage de valeurs. *
+* *
+* Description : Organise une réprésentation d'un éventail de valeurs. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_compact_range_new(GScanExpression *start, GScanExpression *end)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_COMPACT_RANGE, NULL);
+
+ if (!g_scan_compact_range_create(G_SCAN_COMPACT_RANGE(result), start, end))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance à initialiser pleinement. *
+* start = point de départ de la plage de valeurs. *
+* end = point d'arrivée de la plage de valeurs. *
+* *
+* Description : Met en place une réprésentation d'un éventail de valeurs. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_compact_range_create(GScanCompactRange *range, GScanExpression *start, GScanExpression *end)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(range), SRS_PENDING);
+ if (!result) goto exit;
+
+ range->start = start;
+ g_object_ref(G_OBJECT(start));
+
+ range->end = end;
+ g_object_ref(G_OBJECT(end));
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_compact_range_reduce(const GScanCompactRange *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_start; /* Nouvelle réduction #1 */
+ GScanExpression *new_end; /* Nouvelle réduction #2 */
+ ScanReductionState state_start; /* Etat synthétisé #1 */
+ ScanReductionState state_end; /* Etat synthétisé #2 */
+
+ new_start = NULL;
+ new_end = NULL;
+
+ state_start = g_scan_expression_reduce(expr->start, ctx, scope, &new_start);
+ if (state_start == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_end = g_scan_expression_reduce(expr->end, ctx, scope, &new_end);
+ if (state_end == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (state_start == SRS_WAIT_FOR_SCAN || state_end == SRS_WAIT_FOR_SCAN)
+ result = SRS_WAIT_FOR_SCAN;
+ else
+ result = SRS_REDUCED;
+
+ if (new_start != expr->start || new_end != expr->end)
+ *out = g_scan_compact_range_new(new_start, new_end);
+
+ exit:
+
+ g_clear_object(&new_start);
+ g_clear_object(&new_end);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme booléenne. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_compact_range_reduce_to_boolean(const GScanCompactRange *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ bool status; /* Bilan d'une comparaison */
+
+ result = G_IS_SCAN_LITERAL_EXPRESSION(expr->start) && G_IS_SCAN_LITERAL_EXPRESSION(expr->end);
+ if (!result) goto exit;
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(expr->start),
+ G_COMPARABLE_ITEM(expr->end),
+ RCO_LE, &status);
+ if (!result) goto exit;
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à filtrer. *
+* other = expression utilisée pour le filtrage. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* *
+* Description : Réalise l'intersection entre deux ensembles. *
+* *
+* Retour : Intersection entre les deux ensembles ou NULL en cas d'échec.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_scan_compact_range_intersect(const GScanCompactRange *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope)
+{
+ GScanExpression *result; /* Instance à retourner */
+
+
+
+
+ result = true; // TODO
+
+
+
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/range.h b/src/analysis/scan/exprs/range.h
new file mode 100644
index 0000000..4b7ad04
--- /dev/null
+++ b/src/analysis/scan/exprs/range.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range.h - prototypes pour la représentation compacte d'un éventail de valeurs
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_SET_H
+#define _ANALYSIS_SCAN_EXPRS_SET_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_COMPACT_RANGE g_scan_compact_range_get_type()
+#define G_SCAN_COMPACT_RANGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRange))
+#define G_IS_SCAN_COMPACT_RANGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_COMPACT_RANGE))
+#define G_SCAN_COMPACT_RANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRangeClass))
+#define G_IS_SCAN_COMPACT_RANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_COMPACT_RANGE))
+#define G_SCAN_COMPACT_RANGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRangeClass))
+
+
+/* Représentation compacte d'un éventail de valeurs (instance) */
+typedef struct _GScanCompactRange GScanCompactRange;
+
+/* Représentation compacte d'un éventail de valeurs (classe) */
+typedef struct _GScanCompactRangeClass GScanCompactRangeClass;
+
+
+/* Indique le type défini pour une représentation compacte d'un éventail de valeurs. */
+GType g_scan_compact_range_get_type(void);
+
+/* Organise une réprésentation d'un éventail de valeurs. */
+GScanExpression *g_scan_compact_range_new(GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SET_H */
diff --git a/src/analysis/scan/exprs/relational-int.h b/src/analysis/scan/exprs/relational-int.h
new file mode 100644
index 0000000..813b89d
--- /dev/null
+++ b/src/analysis/scan/exprs/relational-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relational-int.h - prototypes internes pour la gestion des opérations relationnelles
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H
+
+
+#include "relational.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération relationnelle impliquant deux opérandes (instance) */
+struct _GScanRelationalOperation
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ RichCmpOperation rel_type; /* Type de relation étudiée */
+
+ GScanExpression *left; /* Expression impactée #1 */
+ GScanExpression *right; /* Expression impactée #2 */
+
+};
+
+/* Opération relationnelle impliquant deux opérandes (classe) */
+struct _GScanRelationalOperationClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une opération relationnelle entre expressions. */
+bool g_scan_relational_operation_create(GScanRelationalOperation *, RichCmpOperation, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H */
diff --git a/src/analysis/scan/exprs/relational.c b/src/analysis/scan/exprs/relational.c
new file mode 100644
index 0000000..74a972b
--- /dev/null
+++ b/src/analysis/scan/exprs/relational.c
@@ -0,0 +1,411 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relational.c - gestion des opérations relationnelles
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "relational.h"
+
+
+#include <assert.h>
+
+
+#include "relational-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations de relations. */
+static void g_scan_relational_operation_class_init(GScanRelationalOperationClass *);
+
+/* Initialise une instance d'opération de relation. */
+static void g_scan_relational_operation_init(GScanRelationalOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_relational_operation_dispose(GScanRelationalOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_relational_operation_finalize(GScanRelationalOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_scan_relational_operation_compare_rich(const GScanRelationalOperation *, const GScanRelationalOperation *, RichCmpOperation, bool *);
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_relational_operation_reduce(const GScanRelationalOperation *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+G_DEFINE_TYPE(GScanRelationalOperation, g_scan_relational_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations de relations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_relational_operation_class_init(GScanRelationalOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_relational_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_relational_operation_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_relational_operation_compare_rich;
+ expr->reduce = (reduce_expr_fc)g_scan_relational_operation_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération de relation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_relational_operation_init(GScanRelationalOperation *op)
+{
+ op->left = NULL;
+ op->right = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_relational_operation_dispose(GScanRelationalOperation *op)
+{
+ g_clear_object(&op->left);
+ g_clear_object(&op->right);
+
+ G_OBJECT_CLASS(g_scan_relational_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_relational_operation_finalize(GScanRelationalOperation *op)
+{
+ G_OBJECT_CLASS(g_scan_relational_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type d'opération booléenne à représenter. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Organise une opération relationnelle entre expressions. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_RELATIONAL_OPERATION, NULL);
+
+ if (!g_scan_relational_operation_create(G_SCAN_RELATIONAL_OPERATION(result), type, left, right))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser pleinement. *
+* type = type d'opération booléenne à représenter. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Met en place une opération relationnelle entre expressions. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_relational_operation_create(GScanRelationalOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(op), SRS_PENDING);
+ if (!result) goto exit;
+
+ op->rel_type = type;
+
+ op->left = left;
+ g_object_ref(G_OBJECT(op->left));
+
+ op->right = right;
+ g_object_ref(G_OBJECT(op->right));
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_relational_operation_compare_rich(const GScanRelationalOperation *item, const GScanRelationalOperation *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_RELATIONAL_OPERATION);
+ if (!result) goto done;
+
+ if (item->rel_type != other->rel_type)
+ {
+ *status = compare_rich_integer_values_unsigned(item->rel_type, other->rel_type, op);
+ goto done;
+ }
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left),
+ G_COMPARABLE_ITEM(other->left),
+ op, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
+ G_COMPARABLE_ITEM(other->right),
+ op, status);
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_relational_operation_reduce(const GScanRelationalOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_left; /* Expression réduite (gauche) */
+ GScanExpression *new_right; /* Expression réduite (droite) */
+ ScanReductionState state_left; /* Etat synthétisé #1 */
+ ScanReductionState state_right; /* Etat synthétisé #2 */
+ LiteralValueType vtype_left; /* Type de valeur portée #1 */
+ LiteralValueType vtype_right; /* Type de valeur portée #2 */
+ GScanExpression *casted; /* Nouvelle forme en booléen */
+ bool status; /* Bilan d'une comparaison */
+ bool valid; /* Validité de ce bilan obtenu */
+
+ /* Réduction des éléments considérés */
+
+ new_left = NULL;
+ new_right = NULL;
+
+ state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (state_left == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (state_right == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Transtypage vers des booléens imposé ? */
+
+ if (expr->rel_type == RCO_EQ || expr->rel_type == RCO_NE)
+ {
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left))
+ {
+ vtype_left = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(new_left));
+
+ if (vtype_left == LVT_BOOLEAN)
+ {
+ if (g_scan_expression_reduce_to_boolean(new_right, ctx, scope, &casted))
+ {
+ g_object_unref(G_OBJECT(new_right));
+ new_right = casted;
+ }
+ }
+
+ }
+
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_right))
+ {
+ vtype_right = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(new_right));
+
+ if (vtype_right == LVT_BOOLEAN)
+ {
+ if (g_scan_expression_reduce_to_boolean(new_left, ctx, scope, &casted))
+ {
+ g_object_unref(G_OBJECT(new_left));
+ new_left = casted;
+ }
+ }
+
+ }
+
+ }
+
+ /* Construction d'une réduction locale ? */
+
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
+ {
+ valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(new_left),
+ G_COMPARABLE_ITEM(new_right),
+ expr->rel_type, &status);
+
+ if (valid)
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { status });
+ result = SRS_REDUCED;
+ }
+ else
+ result = SRS_UNRESOLVABLE;
+
+ }
+
+ /* Mise à jour de la progression ? */
+
+ else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
+ {
+ if (new_left != expr->left || new_right != expr->right)
+ *out = g_scan_relational_operation_new(expr->rel_type, new_left, new_right);
+
+ result = SRS_WAIT_FOR_SCAN;
+
+ }
+
+ /* Cas des situations où les expressions ne sont pas exploitables (!) */
+ else
+ {
+ assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+ result = SRS_UNRESOLVABLE;
+
+ }
+
+ /* Sortie propre */
+
+ exit:
+
+ g_clear_object(&new_left);
+ g_clear_object(&new_right);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/relational.h b/src/analysis/scan/exprs/relational.h
new file mode 100644
index 0000000..10d58a6
--- /dev/null
+++ b/src/analysis/scan/exprs/relational.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relational.h - prototypes pour la gestion des opérations relationnelles
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_RELATIONAL_H
+#define _ANALYSIS_SCAN_EXPRS_RELATIONAL_H
+
+
+#include "../expr.h"
+#include "../../../glibext/comparison.h"
+
+
+
+#define G_TYPE_SCAN_RELATIONAL_OPERATION g_scan_relational_operation_get_type()
+#define G_SCAN_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperation))
+#define G_IS_SCAN_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_RELATIONAL_OPERATION))
+#define G_SCAN_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperationClass))
+#define G_IS_SCAN_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_RELATIONAL_OPERATION))
+#define G_SCAN_RELATIONAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperationClass))
+
+
+/* Opération relationnelle impliquant deux opérandes (instance) */
+typedef struct _GScanRelationalOperation GScanRelationalOperation;
+
+/* Opération relationnelle impliquant deux opérandes (classe) */
+typedef struct _GScanRelationalOperationClass GScanRelationalOperationClass;
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+GType g_scan_relational_operation_get_type(void);
+
+/* Organise une opération relationnelle entre expressions. */
+GScanExpression *g_scan_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_RELATIONAL_H */
diff --git a/src/analysis/scan/exprs/set-int.h b/src/analysis/scan/exprs/set-int.h
new file mode 100644
index 0000000..10ca8d0
--- /dev/null
+++ b/src/analysis/scan/exprs/set-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * set-int.h - prototypes internes pour la base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_SET_INT_H
+#define _ANALYSIS_SCAN_EXPRS_SET_INT_H
+
+
+#include "set.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (instance) */
+struct _GScanGenericSet
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GScanExpression **items; /* Liste d'éléments embarqués */
+ size_t count; /* Quantité de ces éléments */
+
+};
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (classe) */
+struct _GScanGenericSetClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un ensemble d'éléments homogènes ou hétérogènes. */
+bool g_scan_generic_set_create(GScanGenericSet *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SET_INT_H */
diff --git a/src/analysis/scan/exprs/set.c b/src/analysis/scan/exprs/set.c
new file mode 100644
index 0000000..438e7e3
--- /dev/null
+++ b/src/analysis/scan/exprs/set.c
@@ -0,0 +1,407 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * set.c - base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "set.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "literal.h"
+#include "set-int.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des bases d'ensembles d'éléments. */
+static void g_scan_generic_set_class_init(GScanGenericSetClass *);
+
+/* Initialise une instance de base d'ensemble d'éléments. */
+static void g_scan_generic_set_init(GScanGenericSet *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_generic_set_dispose(GScanGenericSet *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_generic_set_finalize(GScanGenericSet *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_generic_set_reduce(const GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_generic_set_reduce_to_boolean(const GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Dénombre les éléments portés par une expression. */
+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, GScanContext *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une base d'ensembles d'éléments homogènes ou hétérogènes. */
+G_DEFINE_TYPE(GScanGenericSet, g_scan_generic_set, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des bases d'ensembles d'éléments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_generic_set_class_init(GScanGenericSetClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_generic_set_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_generic_set_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->reduce = (reduce_expr_fc)g_scan_generic_set_reduce;
+ expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_generic_set_reduce_to_boolean;
+ expr->count = (count_scan_expr_fc)g_scan_generic_set_count_items;
+ expr->get = (get_scan_expr_fc)g_scan_generic_set_get_item;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : set = instance à initialiser. *
+* *
+* Description : Initialise une instance de base d'ensemble d'éléments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_generic_set_init(GScanGenericSet *set)
+{
+ set->items = NULL;
+ set->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : set = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_generic_set_dispose(GScanGenericSet *set)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < set->count; i++)
+ g_clear_object(&set->items[i]);
+
+ G_OBJECT_CLASS(g_scan_generic_set_parent_class)->dispose(G_OBJECT(set));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : set = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_generic_set_finalize(GScanGenericSet *set)
+{
+ if (set->items != NULL)
+ free(set->items);
+
+ G_OBJECT_CLASS(g_scan_generic_set_parent_class)->finalize(G_OBJECT(set));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Constitue un ensemble d'éléments homogènes ou hétérogènes. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_generic_set_new(void)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_GENERIC_SET, NULL);
+
+ if (!g_scan_generic_set_create(G_SCAN_GENERIC_SET(result)))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : set = instance à initialiser pleinement. *
+* *
+* Description : Met en place un ensemble d'éléments homogènes ou hétérogènes.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_generic_set_create(GScanGenericSet *set)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(set), SRS_PENDING);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : set = ensemble à compléter. *
+* item = nouvel élément à intégrer. *
+* *
+* Description : Ajoute un nouvel élément à un ensemble. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_generic_set_add_item(GScanGenericSet *set, GScanExpression *item)
+{
+ set->items = realloc(set->items, ++set->count * sizeof(GScanExpression *));
+
+ set->items[set->count - 1] = item;
+ g_object_ref(G_OBJECT(item));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_generic_set_reduce(const GScanGenericSet *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ GScanExpression *item; /* Elément en cours d'analyse */
+ GScanExpression *new; /* Nouvelle réduction obtenue */
+ ScanReductionState state; /* Etat synthétisé d'un élément*/
+ size_t k; /* Boucle de parcours #2 */
+
+ result = SRS_REDUCED;
+
+ for (i = 0; i < expr->count; i++)
+ {
+ item = expr->items[i];
+
+ state = g_scan_expression_reduce(item, ctx, scope, &new);
+ if (state == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ g_clear_object(out);
+ break;
+ }
+
+ if (state == SRS_WAIT_FOR_SCAN)
+ result = SRS_WAIT_FOR_SCAN;
+
+ if (new != item)
+ {
+ if (*out == NULL)
+ {
+ *out = g_scan_generic_set_new();
+
+ for (k = 0; k < i; k++)
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), expr->items[k]);
+
+ }
+
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), new);
+
+ }
+
+ else
+ {
+ if (*out != NULL)
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), item);
+ }
+
+ g_object_unref(G_OBJECT(new));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme booléenne. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_generic_set_reduce_to_boolean(const GScanGenericSet *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->count > 0 });
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* 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_generic_set_count_items(const GScanGenericSet *expr, GScanContext *ctx, size_t *count)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ *count = expr->count;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* index = indice de l'élément à transférer. *
+* 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_generic_set_get_item(const GScanGenericSet *expr, size_t index, GScanContext *ctx, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+
+ result = (index < expr->count);
+
+ if (result)
+ *out = expr->items[index];
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/set.h b/src/analysis/scan/exprs/set.h
new file mode 100644
index 0000000..c9fb3b3
--- /dev/null
+++ b/src/analysis/scan/exprs/set.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * set.h - prototypes pour la base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_SET_H
+#define _ANALYSIS_SCAN_EXPRS_SET_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_GENERIC_SET g_scan_generic_set_get_type()
+#define G_SCAN_GENERIC_SET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_GENERIC_SET, GScanGenericSet))
+#define G_IS_SCAN_GENERIC_SET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_GENERIC_SET))
+#define G_SCAN_GENERIC_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_GENERIC_SET, GScanGenericSetClass))
+#define G_IS_SCAN_GENERIC_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_GENERIC_SET))
+#define G_SCAN_GENERIC_SET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_GENERIC_SET, GScanGenericSetClass))
+
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (instance) */
+typedef struct _GScanGenericSet GScanGenericSet;
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (classe) */
+typedef struct _GScanGenericSetClass GScanGenericSetClass;
+
+
+/* Indique le type défini pour une base d'ensembles d'éléments homogènes ou hétérogènes. */
+GType g_scan_generic_set_get_type(void);
+
+/* Constitue un ensemble d'éléments homogènes ou hétérogènes. */
+GScanExpression *g_scan_generic_set_new(void);
+
+/* Ajoute un nouvel élément à un ensemble. */
+void g_scan_generic_set_add_item(GScanGenericSet *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SET_H */
diff --git a/src/analysis/scan/exprs/setcounter-int.h b/src/analysis/scan/exprs/setcounter-int.h
new file mode 100644
index 0000000..c9e3da5
--- /dev/null
+++ b/src/analysis/scan/exprs/setcounter-int.h
@@ -0,0 +1,69 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * setcounter-int.h - prototypes internes pour le décompte global de correspondances locales
+ *
+ * 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_SETCOUNTER_INT_H
+#define _ANALYSIS_SCAN_EXPRS_SETCOUNTER_INT_H
+
+
+#include "setcounter.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Décompte global de correspondances locales (instance) */
+struct _GScanSetMatchCounter
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ union
+ {
+ const GSearchPattern **patterns; /* Motifs associés */
+ GSearchPattern **ref_patterns; /* Motifs associés */
+ };
+ size_t count; /* Nombre de ces motifs */
+ bool shared; /* Définition de propriété */
+
+ ScanSetCounterType type; /* Type de décompte */
+ size_t number; /* Eventuel volume associé */
+
+};
+
+/* Décompte global de correspondances locales (classe) */
+struct _GScanSetMatchCounterClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un décompte de motifs avec correspondances. */
+bool g_scan_set_match_counter_create_shared(GScanSetMatchCounter *, const GSearchPattern ** const, size_t);
+
+/* Met en place un décompte de motifs avec correspondances. */
+bool g_scan_set_match_counter_create_and_ref(GScanSetMatchCounter *, GSearchPattern ** const, size_t);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SETCOUNTER_INT_H */
diff --git a/src/analysis/scan/exprs/setcounter.c b/src/analysis/scan/exprs/setcounter.c
new file mode 100644
index 0000000..bed315e
--- /dev/null
+++ b/src/analysis/scan/exprs/setcounter.c
@@ -0,0 +1,477 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * setcounter.c - décompte global de correspondances locales
+ *
+ * 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 "setcounter.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include "setcounter-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INSTANCIATION D'UNE FORME DE CONDITION --------------------- */
+
+
+/* Initialise la classe des opérations booléennes. */
+static void g_scan_set_match_counter_class_init(GScanSetMatchCounterClass *);
+
+/* Initialise une instance d'opération booléenne. */
+static void g_scan_set_match_counter_init(GScanSetMatchCounter *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_set_match_counter_dispose(GScanSetMatchCounter *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_set_match_counter_finalize(GScanSetMatchCounter *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_set_match_counter_reduce(const GScanSetMatchCounter *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INSTANCIATION D'UNE FORME DE CONDITION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */
+G_DEFINE_TYPE(GScanSetMatchCounter, g_scan_set_match_counter, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations booléennes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_set_match_counter_class_init(GScanSetMatchCounterClass *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_match_counter_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_set_match_counter_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->reduce = (reduce_expr_fc)g_scan_set_match_counter_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération booléenne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_set_match_counter_init(GScanSetMatchCounter *counter)
+{
+ counter->patterns = NULL;
+ counter->count = 0;
+ counter->shared = true;
+
+ counter->type = SSCT_NONE;
+ counter->number = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_set_match_counter_dispose(GScanSetMatchCounter *counter)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (!counter->shared)
+ for (i = 0; i < counter->count; i++)
+ g_clear_object(&counter->ref_patterns[i]);
+
+ G_OBJECT_CLASS(g_scan_set_match_counter_parent_class)->dispose(G_OBJECT(counter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_set_match_counter_finalize(GScanSetMatchCounter *counter)
+{
+ if (counter->patterns != NULL)
+ free(counter->patterns);
+
+ G_OBJECT_CLASS(g_scan_set_match_counter_parent_class)->finalize(G_OBJECT(counter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : patterns = motifs à impliquer. *
+* count = quantité de ces motifs. *
+* *
+* Description : Constitue un décompte de motifs avec correspondances. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_set_match_counter_new_shared(const GSearchPattern ** const patterns, size_t count)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_SET_MATCH_COUNTER, NULL);
+
+ if (!g_scan_set_match_counter_create_shared(G_SCAN_SET_MATCH_COUNTER(result), patterns, count))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : counter = instance à initialiser pleinement. *
+* patterns = motifs à impliquer. *
+* count = quantité de ces motifs. *
+* *
+* Description : Met en place un décompte de motifs avec correspondances. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_set_match_counter_create_shared(GScanSetMatchCounter *counter, const GSearchPattern ** const patterns, size_t count)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(counter), SRS_WAIT_FOR_SCAN);
+ if (!result) goto exit;
+
+ counter->patterns = malloc(count * sizeof(GSearchPattern *));
+ counter->count = count;
+
+ memcpy(counter->patterns, patterns, count * sizeof(GSearchPattern *));
+
+ counter->shared = true;
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : patterns = motifs à impliquer. *
+* count = quantité de ces motifs. *
+* *
+* Description : Constitue un décompte de motifs avec correspondances. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_set_match_counter_new(GSearchPattern ** const patterns, size_t count)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_SET_MATCH_COUNTER, NULL);
+
+ if (!g_scan_set_match_counter_create_and_ref(G_SCAN_SET_MATCH_COUNTER(result), patterns, count))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : counter = instance à initialiser pleinement. *
+* patterns = motifs à impliquer. *
+* count = quantité de ces motifs. *
+* *
+* Description : Met en place un décompte de motifs avec correspondances. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_set_match_counter_create_and_ref(GScanSetMatchCounter *counter, GSearchPattern ** const patterns, size_t count)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(counter), SRS_WAIT_FOR_SCAN);
+ if (!result) goto exit;
+
+ counter->patterns = malloc(count * sizeof(GSearchPattern *));
+ counter->count = count;
+
+ memcpy(counter->patterns, patterns, count * sizeof(GSearchPattern *));
+
+ for (i = 0; i < count; i++)
+ g_object_ref(G_OBJECT(patterns[i]));
+
+ counter->shared = false;
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : counter = décompte à compléter. *
+* patterns = motifs à impliquer. *
+* count = quantité de ces motifs. *
+* *
+* Description : Ajoute de nouveaux motifs à un ensemble à décompter. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_set_match_counter_add_extra_shared_patterns(GScanSetMatchCounter *counter, const GSearchPattern ** const patterns, size_t count)
+{
+ size_t first; /* Premier emplacement libre */
+
+ assert(counter->shared);
+
+ first = counter->count;
+
+ counter->count += count;
+ counter->patterns = realloc(counter->patterns, counter->count * sizeof(GSearchPattern *));
+
+ memcpy(counter->patterns + first, patterns, count * sizeof(GSearchPattern *));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : counter = décompte à compléter. *
+* patterns = motifs à impliquer. *
+* count = quantité de ces motifs. *
+* *
+* Description : Ajoute de nouveaux motifs à un ensemble à décompter. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_set_match_counter_add_and_ref_extra_patterns(GScanSetMatchCounter *counter, GSearchPattern ** const patterns, size_t count)
+{
+ size_t first; /* Premier emplacement libre */
+ size_t i; /* Boucle de parcours */
+
+ assert(!counter->shared);
+
+ first = counter->count;
+
+ counter->count += count;
+ counter->patterns = realloc(counter->patterns, counter->count * sizeof(GSearchPattern *));
+
+ memcpy(counter->patterns + first, patterns, count * sizeof(GSearchPattern *));
+
+ for (i = 0; i < count; i++)
+ g_object_ref(G_OBJECT(patterns[i]));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : counter = décompte à configurer. *
+* type = type de décompte à considérer. *
+* number = volume minimal de motifs avec correspondances. *
+* *
+* Description : Précise le volume de motifs avec correspondances à retrouver.*
+* *
+* Retour : Bilan de validité des arguments fournis. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_set_match_counter_define_expected_matches(GScanSetMatchCounter *counter, ScanSetCounterType type, size_t *number)
+{
+ bool result; /* Bilan à retourner */
+
+ counter->type = type;
+
+ if (type == SSCT_NUMBER)
+ {
+ counter->number = *number;
+ result = (counter->number <= counter->count);
+ }
+ else
+ result = true;
+
+ 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_match_counter_reduce(const GScanSetMatchCounter *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ size_t matched; /* Qté de motifs avec résultats*/
+ size_t i; /* Boucle de parcours */
+ GScanMatches *matches; /* Série de correspondances */
+ size_t count; /* Quantité de correspondances */
+ bool status; /* Bilan d'évaluation finale */
+
+ if (g_scan_context_is_scan_done(ctx))
+ {
+ matched = 0;
+
+ for (i = 0; i < expr->count; i++)
+ {
+ matches = g_scan_context_get_full_matches(ctx, expr->patterns[i]);
+
+ if (matches != NULL)
+ {
+ count = g_scan_matches_count(matches);
+
+ if (count > 0)
+ matched++;
+
+ g_object_unref(G_OBJECT(matches));
+
+ }
+
+ }
+
+ switch (expr->type)
+ {
+ case SSCT_NONE:
+ status = (matched == 0);
+ break;
+
+ case SSCT_ANY:
+ status = (matched >= 1);
+ break;
+
+ case SSCT_ALL:
+ status = (matched == expr->count);
+ break;
+
+ case SSCT_NUMBER:
+ status = (matched >= expr->number);
+ break;
+
+ }
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+
+ result = SRS_REDUCED;
+
+ }
+ else
+ result = SRS_WAIT_FOR_SCAN;
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/setcounter.h b/src/analysis/scan/exprs/setcounter.h
new file mode 100644
index 0000000..28c92b4
--- /dev/null
+++ b/src/analysis/scan/exprs/setcounter.h
@@ -0,0 +1,81 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * setcounter.h - prototypes pour le décompte global de correspondances locales
+ *
+ * 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_SETCOUNTER_H
+#define _ANALYSIS_SCAN_EXPRS_SETCOUNTER_H
+
+
+#include <glib-object.h>
+
+
+#include "../expr.h"
+#include "../pattern.h"
+
+
+
+#define G_TYPE_SCAN_SET_MATCH_COUNTER g_scan_set_match_counter_get_type()
+#define G_SCAN_SET_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SET_MATCH_COUNTER, GScanSetMatchCounter))
+#define G_IS_SCAN_SET_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SET_MATCH_COUNTER))
+#define G_SCAN_SET_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SET_MATCH_COUNTER, GScanSetMatchCounterClass))
+#define G_IS_SCAN_SET_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SET_MATCH_COUNTER))
+#define G_SCAN_SET_MATCH_COUNTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SET_MATCH_COUNTER, GScanSetMatchCounterClass))
+
+
+/* Décompte global de correspondances locales (instance) */
+typedef struct _GScanSetMatchCounter GScanSetMatchCounter;
+
+/* Décompte global de correspondances locales (classe) */
+typedef struct _GScanSetMatchCounterClass GScanSetMatchCounterClass;
+
+
+/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */
+GType g_scan_set_match_counter_get_type(void);
+
+/* Met en place un décompte de correspondances obtenues. */
+GScanExpression *g_scan_set_match_counter_new_shared(const GSearchPattern ** const, size_t);
+
+/* Met en place un décompte de correspondances obtenues. */
+GScanExpression *g_scan_set_match_counter_new(GSearchPattern ** const, size_t);
+
+/* Ajoute de nouveaux motifs à un ensemble à décompter. */
+void g_scan_set_match_counter_add_extra_shared_patterns(GScanSetMatchCounter *, const GSearchPattern ** const, size_t);
+
+/* Ajoute de nouveaux motifs à un ensemble à décompter. */
+void g_scan_set_match_counter_add_and_ref_extra_patterns(GScanSetMatchCounter *, GSearchPattern ** const, size_t);
+
+/* Formes de volume de correspondances */
+typedef enum _ScanSetCounterType
+{
+ SSCT_NONE, /* Aucun motif avec résultats */
+ SSCT_ANY, /* Au moins un motif trouvé */
+ SSCT_ALL, /* Tous les motifs présents */
+ SSCT_NUMBER, /* Au moins n motifs avec rés. */
+
+} ScanSetCounterType;
+
+/* Précise le volume de motifs avec correspondances à retrouver. */
+bool g_scan_set_match_counter_define_expected_matches(GScanSetMatchCounter *, ScanSetCounterType, size_t *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SETCOUNTER_H */
diff --git a/src/analysis/scan/exprs/strop-int.h b/src/analysis/scan/exprs/strop-int.h
new file mode 100644
index 0000000..c2b40cf
--- /dev/null
+++ b/src/analysis/scan/exprs/strop-int.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strop-int.h - prototypes internes pour la gestion des opérations booléennes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_STROP_INT_H
+#define _ANALYSIS_SCAN_EXPRS_STROP_INT_H
+
+
+#include "strop.h"
+
+
+#include "../expr-int.h"
+#include "../../../common/extstr.h"
+
+
+
+/* Opération booléenne avec un ou deux opérandes (instance) */
+struct _GScanStringOperation
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ StringOperationType type; /* Type d'opération menée */
+ bool case_sensitive; /* Respect de la casse ? */
+
+ GScanExpression *left; /* Expression impactée #1 */
+ GScanExpression *right; /* Expression impactée #2 */
+
+};
+
+/* Opération booléenne avec un ou deux opérandes (classe) */
+struct _GScanStringOperationClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'opération traite une chaîne. */
+bool g_scan_string_operation_create(GScanStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_STROP_INT_H */
diff --git a/src/analysis/scan/exprs/strop.c b/src/analysis/scan/exprs/strop.c
new file mode 100644
index 0000000..c188c36
--- /dev/null
+++ b/src/analysis/scan/exprs/strop.c
@@ -0,0 +1,455 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strop.c - gestion des opérations booléennes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "strop.h"
+
+
+#include <assert.h>
+#include <string.h>
+#include <strings.h>
+
+
+#include "strop-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations visant des chaînes. */
+static void g_scan_string_operation_class_init(GScanStringOperationClass *);
+
+/* Initialise une instance d'opération visant une chaîne. */
+static void g_scan_string_operation_init(GScanStringOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_string_operation_dispose(GScanStringOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_string_operation_finalize(GScanStringOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_string_operation_reduce(const GScanStringOperation *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération traitant une chaîne de caractères. */
+G_DEFINE_TYPE(GScanStringOperation, g_scan_string_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations visant des chaînes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_string_operation_class_init(GScanStringOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_string_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_string_operation_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->reduce = (reduce_expr_fc)g_scan_string_operation_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération visant une chaîne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_string_operation_init(GScanStringOperation *op)
+{
+ op->left = NULL;
+ op->right = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_string_operation_dispose(GScanStringOperation *op)
+{
+ g_clear_object(&op->left);
+ g_clear_object(&op->right);
+
+ G_OBJECT_CLASS(g_scan_string_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_string_operation_finalize(GScanStringOperation *op)
+{
+ G_OBJECT_CLASS(g_scan_string_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type d'opération booléenne à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* sensitive = détermine la prise en compte de la casse. *
+* *
+* Description : Organise un appel de fonction avec ses arguments. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_STRING_OPERATION, NULL);
+
+ if (!g_scan_string_operation_create(G_SCAN_STRING_OPERATION(result), type, first, second, sensitive))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser pleinement. *
+* type = type d'opération booléenne à représenter. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
+* sensitive = détermine la prise en compte de la casse. *
+* *
+* Description : Met en place une expression d'opération traite une chaîne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_string_operation_create(GScanStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(op), SRS_PENDING);
+ if (!result) goto exit;
+
+ op->type = type;
+
+ switch (type)
+ {
+ case SOT_CONTAINS:
+ case SOT_STARTSWITH:
+ case SOT_ENDSWITH:
+ op->case_sensitive = sensitive;
+ break;
+
+ case SOT_MATCHES:
+ break;
+
+ case SOT_IEQUALS:
+ assert(!sensitive);
+ op->case_sensitive = false;
+ break;
+
+ }
+
+ op->left = left;
+ g_object_ref(G_OBJECT(op->left));
+
+ op->right = right;
+ g_object_ref(G_OBJECT(op->right));
+
+ exit:
+
+ 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_string_operation_reduce(const GScanStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_left; /* Expression réduite (gauche) */
+ GScanExpression *new_right; /* Expression réduite (droite) */
+ ScanReductionState state_left; /* Etat synthétisé #1 */
+ ScanReductionState state_right; /* Etat synthétisé #2 */
+ GScanLiteralExpression *op_left; /* Opérande gauche final */
+ GScanLiteralExpression *op_right; /* Opérande droite final */
+ const sized_string_t *strings[2]; /* Chaînes en jeu */
+ const void *found; /* Présence d'une bribe ? */
+ bool status; /* Bilan de comparaison #1 */
+ int ret; /* Bilan de comparaison #2 */
+ size_t offset; /* Point de départ d'analyse */
+ const regex_t *preg; /* Expression rationnelle */
+
+ /* Réduction des éléments considérés */
+
+ new_left = NULL;
+ new_right = NULL;
+
+ state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (state_left == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (state_right == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Construction d'une réduction locale ? */
+
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
+ {
+ op_left = G_SCAN_LITERAL_EXPRESSION(new_left);
+ op_right = G_SCAN_LITERAL_EXPRESSION(new_right);
+
+ if (!g_scan_literal_expression_get_string_value(op_left, &strings[0]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ result = SRS_REDUCED;
+
+ switch (expr->type)
+ {
+ case SOT_CONTAINS:
+
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (expr->case_sensitive)
+ found = memmem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len);
+
+ else
+ found = memcasemem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len);
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { found != NULL });
+ break;
+
+ case SOT_STARTSWITH:
+
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (strings[0]->len < strings[1]->len)
+ status = false;
+
+ else
+ {
+ if (expr->case_sensitive)
+ ret = memcmp(strings[0]->data, strings[1]->data, strings[1]->len);
+ else
+ ret = memcasecmp(strings[0]->data, strings[1]->data, strings[1]->len);
+
+ status = (ret == 0);
+
+ }
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+ break;
+
+ case SOT_ENDSWITH:
+
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (strings[0]->len < strings[1]->len)
+ status = false;
+
+ else
+ {
+ offset = strings[0]->len - strings[1]->len;
+
+ if (expr->case_sensitive)
+ ret = memcmp(strings[0]->data + offset, strings[1]->data, strings[1]->len);
+ else
+ ret = memcasecmp(strings[0]->data + offset, strings[1]->data, strings[1]->len);
+
+ status = (ret == 0);
+
+ }
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+ break;
+
+ case SOT_MATCHES:
+
+ if (!g_scan_literal_expression_get_regex_value(op_right, &preg))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ ret = regexec(preg, strings[0]->data, 0, NULL, 0);
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { ret != REG_NOMATCH });
+ break;
+
+ case SOT_IEQUALS:
+
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (strings[0]->len != strings[1]->len)
+ status = false;
+
+ else
+ {
+ ret = memcasecmp(strings[0]->data, strings[1]->data, strings[1]->len);
+ status = (ret == 0);
+ }
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+ break;
+
+ }
+
+ }
+
+ /* Mise à jour de la progression ? */
+
+ else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
+ {
+ if (new_left != expr->left || new_right != expr->right)
+ *out = g_scan_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive);
+
+ result = SRS_WAIT_FOR_SCAN;
+
+ }
+
+ /* Cas des situations où les expressions ne sont pas exploitables (!) */
+ else
+ {
+ assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+ result = SRS_UNRESOLVABLE;
+
+ }
+
+ /* Sortie propre */
+
+ exit:
+
+ g_clear_object(&new_left);
+ g_clear_object(&new_right);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/strop.h b/src/analysis/scan/exprs/strop.h
new file mode 100644
index 0000000..0a32269
--- /dev/null
+++ b/src/analysis/scan/exprs/strop.h
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strop.h - prototypes pour la gestion des opérations booléennes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_STROP_H
+#define _ANALYSIS_SCAN_EXPRS_STROP_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_STRING_OPERATION g_scan_string_operation_get_type()
+#define G_SCAN_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperation))
+#define G_IS_SCAN_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_STRING_OPERATION))
+#define G_SCAN_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperationClass))
+#define G_IS_SCAN_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_STRING_OPERATION))
+#define G_SCAN_STRING_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperationClass))
+
+
+/* Opération booléenne avec un ou deux opérandes (instance) */
+typedef struct _GScanStringOperation GScanStringOperation;
+
+/* Opération booléenne avec un ou deux opérandes (classe) */
+typedef struct _GScanStringOperationClass GScanStringOperationClass;
+
+
+/* Types d'opérations booléennes supportées */
+typedef enum _StringOperationType
+{
+ SOT_CONTAINS, /* Opérateurs "[i]contains" */
+ SOT_STARTSWITH, /* Opérateurs "[i]startswith" */
+ SOT_ENDSWITH, /* Opérateurs "[i]endswith" */
+ SOT_MATCHES, /* Opérateur "matches" */
+ SOT_IEQUALS, /* Opérateur "iequals" */
+
+} StringOperationType;
+
+
+/* Indique le type défini pour une opération traitant une chaîne de caractères. */
+GType g_scan_string_operation_get_type(void);
+
+/* Organise un appel de fonction avec ses arguments. */
+GScanExpression *g_scan_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_STROP_H */