summaryrefslogtreecommitdiff
path: root/src/analysis/scan/exprs
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2023-08-06 16:54:57 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2023-08-06 16:54:57 (GMT)
commit4fcc35a52ccb025b6d803d85e017931cd2452960 (patch)
treee95920f16c273e41f9cae1ea2f02571c221a514e /src/analysis/scan/exprs
parent74d062d4ec55d7ac3914bbf64b8b6c5ab52227df (diff)
Extend the ROST grammar with a first batch of new features.
Diffstat (limited to 'src/analysis/scan/exprs')
-rw-r--r--src/analysis/scan/exprs/Makefile.am20
-rw-r--r--src/analysis/scan/exprs/access-int.h17
-rw-r--r--src/analysis/scan/exprs/access.c269
-rw-r--r--src/analysis/scan/exprs/access.h27
-rw-r--r--src/analysis/scan/exprs/arithmetic-int.h (renamed from src/analysis/scan/exprs/arithmop-int.h)18
-rw-r--r--src/analysis/scan/exprs/arithmetic.c638
-rw-r--r--src/analysis/scan/exprs/arithmetic.h (renamed from src/analysis/scan/exprs/arithmop.h)30
-rw-r--r--src/analysis/scan/exprs/call-int.h12
-rw-r--r--src/analysis/scan/exprs/call.c280
-rw-r--r--src/analysis/scan/exprs/call.h22
-rw-r--r--src/analysis/scan/exprs/counter-int.h57
-rw-r--r--src/analysis/scan/exprs/counter.c248
-rw-r--r--src/analysis/scan/exprs/counter.h59
-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/literal-int.h16
-rw-r--r--src/analysis/scan/exprs/literal.c363
-rw-r--r--src/analysis/scan/exprs/literal.h49
-rw-r--r--src/analysis/scan/exprs/logical-int.h (renamed from src/analysis/scan/exprs/boolop-int.h)18
-rw-r--r--src/analysis/scan/exprs/logical.c (renamed from src/analysis/scan/exprs/boolop.c)257
-rw-r--r--src/analysis/scan/exprs/logical.h (renamed from src/analysis/scan/exprs/boolop.h)26
-rw-r--r--src/analysis/scan/exprs/range-int.h58
-rw-r--r--src/analysis/scan/exprs/range.c352
-rw-r--r--src/analysis/scan/exprs/range.h55
-rw-r--r--src/analysis/scan/exprs/relational-int.h (renamed from src/analysis/scan/exprs/relop-int.h)18
-rw-r--r--src/analysis/scan/exprs/relational.c (renamed from src/analysis/scan/exprs/relop.c)200
-rw-r--r--src/analysis/scan/exprs/relational.h56
-rw-r--r--src/analysis/scan/exprs/relop.h56
-rw-r--r--src/analysis/scan/exprs/set-int.h54
-rw-r--r--src/analysis/scan/exprs/set.c (renamed from src/analysis/scan/exprs/arithmop.c)355
-rw-r--r--src/analysis/scan/exprs/set.h58
-rw-r--r--src/analysis/scan/exprs/strop-int.h8
-rw-r--r--src/analysis/scan/exprs/strop.c207
-rw-r--r--src/analysis/scan/exprs/strop.h22
35 files changed, 3242 insertions, 1086 deletions
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am
index efe25fc..1266a63 100644
--- a/src/analysis/scan/exprs/Makefile.am
+++ b/src/analysis/scan/exprs/Makefile.am
@@ -5,16 +5,24 @@ noinst_LTLIBRARIES = libanalysisscanexprs.la
libanalysisscanexprs_la_SOURCES = \
access-int.h \
access.h access.c \
- arithmop-int.h \
- arithmop.h arithmop.c \
- boolop-int.h \
- boolop.h boolop.c \
+ arithmetic-int.h \
+ arithmetic.h arithmetic.c \
call-int.h \
call.h call.c \
+ counter-int.h \
+ counter.h counter.c \
+ intersect-int.h \
+ intersect.h intersect.c \
literal-int.h \
literal.h literal.c \
- relop-int.h \
- relop.h relop.c \
+ logical-int.h \
+ logical.h logical.c \
+ range-int.h \
+ range.h range.c \
+ relational-int.h \
+ relational.h relational.c \
+ set-int.h \
+ set.h set.c \
strop-int.h \
strop.h strop.c
diff --git a/src/analysis/scan/exprs/access-int.h b/src/analysis/scan/exprs/access-int.h
index 2212b48..725051c 100644
--- a/src/analysis/scan/exprs/access-int.h
+++ b/src/analysis/scan/exprs/access-int.h
@@ -32,8 +32,11 @@
+/* Reproduit un accès en place dans une nouvelle instance. */
+typedef void (* copy_scan_access_fc) (GScanNamedAccess *, const GScanNamedAccess *);
+
/* Accès à un élément d'expression sous-jacent (instance) */
-struct _GNamedAccess
+struct _GScanNamedAccess
{
GScanExpression parent; /* A laisser en premier */
@@ -46,23 +49,25 @@ struct _GNamedAccess
char *target; /* Cible dans l'espace */
- struct _GNamedAccess *next; /* Evnetuel prochain élément */
+ struct _GScanNamedAccess *next; /* Evnetuel prochain élément */
};
/* Accès à un élément d'expression sous-jacent (classe) */
-struct _GNamedAccessClass
+struct _GScanNamedAccessClass
{
GScanExpressionClass parent; /* A laisser en premier */
+ copy_scan_access_fc copy; /* Reproduction d'accès */
+
};
/* Met en place une expression d'accès. */
-bool g_named_access_create(GNamedAccess *, const sized_string_t *);
+bool g_scan_named_access_create(GScanNamedAccess *, const sized_string_t *);
-/* Réduit une expression à une forme plus simple. */
-bool _g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
+/* Prépare une réduction en menant une résolution locale. */
+GRegisteredItem *_g_scan_named_access_prepare_reduction(GScanNamedAccess *, GScanContext *, GScanScope *);
diff --git a/src/analysis/scan/exprs/access.c b/src/analysis/scan/exprs/access.c
index ad66f60..1c3a880 100644
--- a/src/analysis/scan/exprs/access.c
+++ b/src/analysis/scan/exprs/access.c
@@ -30,6 +30,7 @@
#include "access-int.h"
+#include "literal.h"
#include "../../../core/global.h"
@@ -38,27 +39,27 @@
/* Initialise la classe des appels de fonction avec arguments. */
-static void g_named_access_class_init(GNamedAccessClass *);
+static void g_scan_named_access_class_init(GScanNamedAccessClass *);
/* Initialise une instance d'appel de fonction avec arguments. */
-static void g_named_access_init(GNamedAccess *);
+static void g_scan_named_access_init(GScanNamedAccess *);
/* Supprime toutes les références externes. */
-static void g_named_access_dispose(GNamedAccess *);
+static void g_scan_named_access_dispose(GScanNamedAccess *);
/* Procède à la libération totale de la mémoire. */
-static void g_named_access_finalize(GNamedAccess *);
+static void g_scan_named_access_finalize(GScanNamedAccess *);
+/* Reproduit un accès en place dans une nouvelle instance. */
+static void g_scan_named_access_copy(GScanNamedAccess *, const GScanNamedAccess *);
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_named_access_copy(GNamedAccess *, const GNamedAccess *);
/* Réduit une expression à une forme plus simple. */
-static bool g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_named_access_reduce(GScanNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
@@ -68,7 +69,7 @@ static bool g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *,
/* Indique le type défini pour un appel de fonction enregistrée. */
-G_DEFINE_TYPE(GNamedAccess, g_named_access, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanNamedAccess, g_scan_named_access, G_TYPE_SCAN_EXPRESSION);
/******************************************************************************
@@ -83,21 +84,22 @@ G_DEFINE_TYPE(GNamedAccess, g_named_access, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_named_access_class_init(GNamedAccessClass *klass)
+static void g_scan_named_access_class_init(GScanNamedAccessClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GScanExpressionClass *expr; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_named_access_dispose;
- object->finalize = (GObjectFinalizeFunc)g_named_access_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_named_access_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_named_access_finalize;
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)NULL;
- expr->copy = (copy_expr_fc)g_named_access_copy;
- expr->reduce = (reduce_expr_fc)g_named_access_reduce;
+ expr->reduce = (reduce_expr_fc)g_scan_named_access_reduce;
+
+ klass->copy = g_scan_named_access_copy;
}
@@ -114,7 +116,7 @@ static void g_named_access_class_init(GNamedAccessClass *klass)
* *
******************************************************************************/
-static void g_named_access_init(GNamedAccess *access)
+static void g_scan_named_access_init(GScanNamedAccess *access)
{
access->any = NULL;
access->target = NULL;
@@ -136,13 +138,13 @@ static void g_named_access_init(GNamedAccess *access)
* *
******************************************************************************/
-static void g_named_access_dispose(GNamedAccess *access)
+static void g_scan_named_access_dispose(GScanNamedAccess *access)
{
g_clear_object(&access->any);
g_clear_object(&access->next);
- G_OBJECT_CLASS(g_named_access_parent_class)->dispose(G_OBJECT(access));
+ G_OBJECT_CLASS(g_scan_named_access_parent_class)->dispose(G_OBJECT(access));
}
@@ -159,12 +161,12 @@ static void g_named_access_dispose(GNamedAccess *access)
* *
******************************************************************************/
-static void g_named_access_finalize(GNamedAccess *access)
+static void g_scan_named_access_finalize(GScanNamedAccess *access)
{
if (access->target != NULL)
free(access->target);
- G_OBJECT_CLASS(g_named_access_parent_class)->finalize(G_OBJECT(access));
+ G_OBJECT_CLASS(g_scan_named_access_parent_class)->finalize(G_OBJECT(access));
}
@@ -181,13 +183,13 @@ static void g_named_access_finalize(GNamedAccess *access)
* *
******************************************************************************/
-GScanExpression *g_named_access_new(const sized_string_t *target)
+GScanExpression *g_scan_named_access_new(const sized_string_t *target)
{
GScanExpression *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_NAMED_ACCESS, NULL);
+ result = g_object_new(G_TYPE_SCAN_NAMED_ACCESS, NULL);
- if (!g_named_access_create(G_NAMED_ACCESS(result), target))
+ if (!g_scan_named_access_create(G_SCAN_NAMED_ACCESS(result), target))
g_clear_object(&result);
return result;
@@ -208,16 +210,14 @@ GScanExpression *g_named_access_new(const sized_string_t *target)
* *
******************************************************************************/
-bool g_named_access_create(GNamedAccess *access, const sized_string_t *target)
+bool g_scan_named_access_create(GScanNamedAccess *access, const sized_string_t *target)
{
bool result; /* Bilan à retourner */
- result = g_scan_expression_create(G_SCAN_EXPRESSION(access), EVT_PENDING);
- if (!result) goto exit;
-
- access->target = strndup(target->data, target->len);
+ result = true;
- exit:
+ if (target != NULL)
+ access->target = strndup(target->data, target->len);
return result;
@@ -226,10 +226,10 @@ bool g_named_access_create(GNamedAccess *access, const sized_string_t *target)
/******************************************************************************
* *
-* Paramètres : access = expression d'appel à actualiser. *
-* base = zone de recherche pour la résolution à venir. *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
* *
-* Description : Définit une base de recherche pour la cible d'accès. *
+* Description : Reproduit un accès en place dans une nouvelle instance. *
* *
* Retour : - *
* *
@@ -237,55 +237,74 @@ bool g_named_access_create(GNamedAccess *access, const sized_string_t *target)
* *
******************************************************************************/
-void g_named_access_set_base(GNamedAccess *access, GRegisteredItem *base)
+static void g_scan_named_access_copy(GScanNamedAccess *dest, const GScanNamedAccess *src)
{
- g_clear_object(&access->base);
+ /**
+ * Les champs suivants sont voués à être remplacés ou supprimés.
+ *
+ * On évite donc une instanciation inutile.
+ */
- access->base = base;
- g_object_ref(G_OBJECT(base));
+ /*
+ if (src->any != NULL)
+ {
+ dest->any = src->any;
+ g_object_ref(src->any);
+ }
+ */
+
+ if (src->target != NULL)
+ dest->target = strdup(src->target);
+
+ if (src->next != NULL)
+ {
+ dest->next = src->next;
+ g_object_ref(src->next);
+ }
}
/******************************************************************************
* *
-* Paramètres : access = expression d'appel à compléter. *
-* next = expression d'appel suivante dans la chaîne. *
+* Paramètres : accès = expression d'accès à copier. *
+* resolved = nouvelle base à imposer. *
* *
-* Description : Complète la chaine d'accès à des expressions. *
+* Description : Reproduit un accès en place dans une nouvelle instance. *
* *
-* Retour : - *
+* Retour : Nouvelle instance d'expression d'accès. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_named_access_attach_next(GNamedAccess *access, GNamedAccess *next)
+GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *access, GRegisteredItem *resolved)
{
- if (access->next != NULL)
- g_named_access_attach_next(access->next, next);
+ GScanExpression *result; /* Instance copiée à retourner */
+ GType type; /* Type d'objet à copier */
+ GScanNamedAccessClass *class; /* Classe à activer */
- else
- {
- access->next = next;
- g_object_ref(G_OBJECT(next));
- }
+ type = G_TYPE_FROM_INSTANCE(access);
-}
+ result = g_object_new(type, NULL);
+ class = G_SCAN_NAMED_ACCESS_GET_CLASS(access);
+ class->copy(G_SCAN_NAMED_ACCESS(result), access);
-/* ---------------------------------------------------------------------------------- */
-/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
-/* ---------------------------------------------------------------------------------- */
+ g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(result), resolved);
+
+ return result;
+
+}
/******************************************************************************
* *
-* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
-* src = expression source à copier. *
+* Paramètres : access = expression d'appel à actualiser. *
+* base = zone de recherche pour la résolution à venir. *
* *
-* Description : Reproduit une expression en place dans une nouvelle instance.*
+* Description : Définit une base de recherche pour la cible d'accès. *
* *
* Retour : - *
* *
@@ -293,27 +312,47 @@ void g_named_access_attach_next(GNamedAccess *access, GNamedAccess *next)
* *
******************************************************************************/
-static void g_named_access_copy(GNamedAccess *dest, const GNamedAccess *src)
+void g_scan_named_access_set_base(GScanNamedAccess *access, GRegisteredItem *base)
{
- GScanExpressionClass *class; /* Classe parente à solliciter */
+ g_clear_object(&access->base);
- class = G_SCAN_EXPRESSION_CLASS(g_named_access_parent_class);
+ access->base = base;
+ g_object_ref(G_OBJECT(base));
- class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+}
- if (src->any != NULL)
+
+/******************************************************************************
+* *
+* Paramètres : access = expression d'appel à compléter. *
+* next = expression d'appel suivante dans la chaîne. *
+* *
+* Description : Complète la chaine d'accès à des expressions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_named_access_attach_next(GScanNamedAccess *access, GScanNamedAccess *next)
+{
+ if (access->next != NULL)
+ g_scan_named_access_attach_next(access->next, next);
+
+ else
{
- dest->any = src->any;
- g_object_ref(src->any);
+ access->next = next;
+ g_object_ref(G_OBJECT(next));
}
- if (src->target != NULL)
- dest->target = strdup(src->target);
+}
- if (src->next != NULL)
- dest->next = G_NAMED_ACCESS(g_scan_expression_duplicate(G_SCAN_EXPRESSION(src->next)));
-}
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
@@ -321,24 +360,21 @@ static void g_named_access_copy(GNamedAccess *dest, const GNamedAccess *src)
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
* scope = portée courante des variables locales. *
-* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
-* Description : Réduit une expression à une forme plus simple. *
+* Description : Prépare une réduction en menant une résolution locale. *
* *
-* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* Retour : Elément résolu avec les moyens du bord ou NULL si échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+GRegisteredItem *_g_scan_named_access_prepare_reduction(GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope)
{
- bool result; /* Bilan à retourner */
+ GRegisteredItem *result; /* Etat synthétisé à retourner */
GRegisteredItem *base; /* Base de recherche courante */
- GRegisteredItem *resolved; /* Cible concrète obtenue */
- GNamedAccess *new; /* Copie mise en place */
- result = true;
+ result = NULL;
if (expr->target != NULL)
{
@@ -350,24 +386,7 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s
else
base = G_REGISTERED_ITEM(get_rost_root_namespace());
- result = g_registered_item_resolve(base, expr->target, ctx, scope, &resolved);
-
- g_object_unref(G_OBJECT(base));
-
- if (result && resolved != NULL)
- {
- new = G_NAMED_ACCESS(g_scan_expression_duplicate(G_SCAN_EXPRESSION(expr)));
-
- g_clear_object(&new->base);
-
- free(new->target);
- new->target = NULL;
-
- new->resolved = resolved;
-
- *out = G_SCAN_EXPRESSION(new);
-
- }
+ g_registered_item_resolve(base, expr->target, ctx, scope, &result);
}
@@ -379,8 +398,8 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s
{
assert(expr->resolved != NULL);
- *out = G_SCAN_EXPRESSION(expr);
- g_object_ref(G_OBJECT(*out));
+ result = expr->resolved;
+ g_object_ref(G_OBJECT(result));
}
@@ -404,25 +423,18 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s
* *
******************************************************************************/
-static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_named_access_reduce(GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
- GNamedAccess *new; /* Eventuel étage suivant */
- GScanExpression *final; /* Expression d'évaluation */
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GRegisteredItem *resolved; /* Cible concrète obtenue */
GScanExpression *new_next; /* Nouvelle version du suivant */
+ bool status; /* Bilan d'une autre règle */
- result = _g_named_access_reduce(expr, ctx, scope, out);
+ resolved = _g_scan_named_access_prepare_reduction(expr, ctx, scope);
- if (result && *out != NULL)
+ if (resolved != NULL)
{
- assert(G_IS_NAMED_ACCESS(*out));
-
- new = G_NAMED_ACCESS(*out);
- *out = NULL;
-
- assert(new->target == NULL);
- assert(G_IS_NAMED_ACCESS(new));
- assert(G_IS_REGISTERED_ITEM(new->resolved));
+ result = SRS_PENDING;
/**
* Si l'élément résolu se trouve en fin de chaîne, alors cet élément
@@ -430,15 +442,11 @@ static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanSc
* Le produit de cette réduction finale bénéficie d'une promotion et
* représente à lui seul la réduction produite pour la chaîne.
*/
- if (new->next == NULL)
+ if (expr->next == NULL)
{
- result = g_registered_item_reduce(new->resolved, ctx, scope, &final);
+ status = g_registered_item_reduce(resolved, ctx, scope, out);
- if (result && final != NULL)
- {
- g_clear_object(out);
- *out = final;
- }
+ result = (status ? SRS_REDUCED : SRS_UNRESOLVABLE);
}
@@ -448,21 +456,34 @@ static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanSc
*/
else
{
- new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next));
- assert(G_IS_NAMED_ACCESS(new_next));
-
- g_named_access_set_base(G_NAMED_ACCESS(new_next), new->resolved);
-
- g_clear_object(out);
+ new_next = g_scan_named_access_duplicate(expr->next, resolved);
result = g_scan_expression_reduce(new_next, ctx, scope, out);
- if (result && *out == NULL)
- *out = new_next;
+ g_object_unref(G_OBJECT(new_next));
}
- g_object_unref(G_OBJECT(new));
+ g_object_unref(G_OBJECT(resolved));
+
+ }
+
+ /**
+ * Si le nom fournit le correspond à aucun élément de la grammaire,
+ * des recherches sont menées ailleurs.
+ */
+ else
+ {
+ result = SRS_UNRESOLVABLE;
+
+ if (g_scan_context_has_rule_for_name(ctx, expr->target))
+ {
+ status = g_scan_context_has_match_for_rule(ctx, expr->target);
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+ result = SRS_REDUCED;
+
+ }
}
diff --git a/src/analysis/scan/exprs/access.h b/src/analysis/scan/exprs/access.h
index a04adc7..7c007a9 100644
--- a/src/analysis/scan/exprs/access.h
+++ b/src/analysis/scan/exprs/access.h
@@ -31,32 +31,35 @@
-#define G_TYPE_NAMED_ACCESS g_named_access_get_type()
-#define G_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_NAMED_ACCESS, GNamedAccess))
-#define G_IS_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_NAMED_ACCESS))
-#define G_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_NAMED_ACCESS, GNamedAccessClass))
-#define G_IS_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_NAMED_ACCESS))
-#define G_NAMED_ACCESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_NAMED_ACCESS, GNamedAccessClass))
+#define G_TYPE_SCAN_NAMED_ACCESS g_scan_named_access_get_type()
+#define G_SCAN_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccess))
+#define G_IS_SCAN_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_NAMED_ACCESS))
+#define G_SCAN_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccessClass))
+#define G_IS_SCAN_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_NAMED_ACCESS))
+#define G_SCAN_NAMED_ACCESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccessClass))
/* Accès à un élément d'expression sous-jacent (instance) */
-typedef struct _GNamedAccess GNamedAccess;
+typedef struct _GScanNamedAccess GScanNamedAccess;
/* Accès à un élément d'expression sous-jacent (classe) */
-typedef struct _GNamedAccessClass GNamedAccessClass;
+typedef struct _GScanNamedAccessClass GScanNamedAccessClass;
/* Indique le type défini pour un appel de fonction enregistrée. */
-GType g_named_access_get_type(void);
+GType g_scan_named_access_get_type(void);
/* Organise un accès à un élément d'expression sous-jacent. */
-GScanExpression *g_named_access_new(const sized_string_t *);
+GScanExpression *g_scan_named_access_new(const sized_string_t *);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *, GRegisteredItem *);
/* Définit une base de recherche pour la cible d'accès. */
-void g_named_access_set_base(GNamedAccess *, GRegisteredItem *);
+void g_scan_named_access_set_base(GScanNamedAccess *, GRegisteredItem *);
/* Complète la chaine d'accès à des expressions. */
-void g_named_access_attach_next(GNamedAccess *, GNamedAccess *);
+void g_scan_named_access_attach_next(GScanNamedAccess *, GScanNamedAccess *);
diff --git a/src/analysis/scan/exprs/arithmop-int.h b/src/analysis/scan/exprs/arithmetic-int.h
index 031de84..c5010b0 100644
--- a/src/analysis/scan/exprs/arithmop-int.h
+++ b/src/analysis/scan/exprs/arithmetic-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * arithmop-int.h - prototypes internes pour la gestion des opérations arithmétiques
+ * arithmetic-int.h - prototypes internes pour la gestion des opérations arithmétiques
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,11 +21,11 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H
-#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H
+#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H
+#define _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H
-#include "arithmop.h"
+#include "arithmetic.h"
#include "../expr-int.h"
@@ -33,7 +33,7 @@
/* Opération arithmétique impliquant deux opérandes (instance) */
-struct _GArithmOperation
+struct _GScanArithmeticOperation
{
GScanExpression parent; /* A laisser en premier */
@@ -45,7 +45,7 @@ struct _GArithmOperation
};
/* Opération arithmétique impliquant deux opérandes (classe) */
-struct _GArithmOperationClass
+struct _GScanArithmeticOperationClass
{
GScanExpressionClass parent; /* A laisser en premier */
@@ -53,8 +53,8 @@ struct _GArithmOperationClass
/* Met en place une opération arithmétique entre expressions. */
-bool g_arithmetic_operation_create(GArithmOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
+bool g_scan_arithmetic_operation_create(GScanArithmeticOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
-#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H */
diff --git a/src/analysis/scan/exprs/arithmetic.c b/src/analysis/scan/exprs/arithmetic.c
new file mode 100644
index 0000000..0c01d2a
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmetic.c
@@ -0,0 +1,638 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmetic.c - gestion des opérations arithmétiques
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "arithmetic.h"
+
+
+#include <assert.h>
+
+
+#include "arithmetic-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations arithmétiques. */
+static void g_scan_arithmetic_operation_class_init(GScanArithmeticOperationClass *);
+
+/* Initialise une instance d'opération arithmétique. */
+static void g_scan_arithmetic_operation_init(GScanArithmeticOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_arithmetic_operation_dispose(GScanArithmeticOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_arithmetic_operation_finalize(GScanArithmeticOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_scan_arithmetic_operation_compare_rich(const GScanArithmeticOperation *, const GScanArithmeticOperation *, RichCmpOperation, bool *);
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_arithmetic_operation_reduce(GScanArithmeticOperation *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+G_DEFINE_TYPE(GScanArithmeticOperation, g_scan_arithmetic_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations arithmétiques. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_class_init(GScanArithmeticOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_arithmetic_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_arithmetic_operation_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_arithmetic_operation_compare_rich;
+ expr->reduce = (reduce_expr_fc)g_scan_arithmetic_operation_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération arithmétique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_init(GScanArithmeticOperation *op)
+{
+ op->left = NULL;
+ op->right = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_dispose(GScanArithmeticOperation *op)
+{
+ g_clear_object(&op->left);
+ g_clear_object(&op->right);
+
+ G_OBJECT_CLASS(g_scan_arithmetic_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_finalize(GScanArithmeticOperation *op)
+{
+ G_OBJECT_CLASS(g_scan_arithmetic_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operator = type d'opération arithmétique à représenter. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Organise une opération arithmétique entre expressions. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_ARITHMETIC_OPERATION, NULL);
+
+ if (!g_scan_arithmetic_operation_create(G_SCAN_ARITHMETIC_OPERATION(result), operator, left, right))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser pleinement. *
+* operator = type d'opération booléenne à représenter. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Met en place une opération arithmétique entre expressions. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_arithmetic_operation_create(GScanArithmeticOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ op->operator = operator;
+
+ op->left = left;
+ g_object_ref(G_OBJECT(op->left));
+
+ op->right = right;
+ g_object_ref(G_OBJECT(op->right));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_arithmetic_operation_compare_rich(const GScanArithmeticOperation *item, const GScanArithmeticOperation *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_ARITHMETIC_OPERATION);
+ if (!result) goto done;
+
+ if (item->operator != other->operator)
+ {
+ result = compare_rich_integer_values_unsigned(item->operator, other->operator, op);
+ goto done;
+ }
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left),
+ G_COMPARABLE_ITEM(other->left),
+ op, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
+ G_COMPARABLE_ITEM(other->right),
+ op, status);
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_arithmetic_operation_reduce(GScanArithmeticOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_left; /* Expression réduite (gauche) */
+ GScanExpression *new_right; /* Expression réduite (droite) */
+ ScanReductionState state_left; /* Etat synthétisé #1 */
+ ScanReductionState state_right; /* Etat synthétisé #2 */
+ GScanLiteralExpression *op_left; /* Opérande gauche final */
+ GScanLiteralExpression *op_right; /* Opérande droite final */
+ LiteralValueType vtype_left; /* Type de valeur portée #1 */
+ LiteralValueType vtype_right; /* Type de valeur portée #2 */
+ long long val_1_s; /* Première valeur à traiter */
+ unsigned long long val_1_u; /* Première valeur à traiter */
+ long long val_2_s; /* Seconde valeur à traiter */
+ unsigned long long val_2_u; /* Seconde valeur à traiter */
+ LiteralValueType state_final; /* Nature de la valeur finale */
+ long long reduced_s; /* Valeur réduite finale */
+ unsigned long long reduced_u; /* Valeur réduite finale */
+
+ /* Réduction des éléments considérés */
+
+ new_left = NULL;
+ new_right = NULL;
+
+ state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (state_left == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (state_right == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Construction d'une réduction locale ? */
+
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
+ {
+ /* Récupération de l'opérande de gauche */
+
+ op_left = G_SCAN_LITERAL_EXPRESSION(new_left);
+ vtype_left = g_scan_literal_expression_get_value_type(op_left);
+
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_signed_integer_value(op_left, &val_1_s))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else if (vtype_left == LVT_UNSIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_unsigned_integer_value(op_left, &val_1_u))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Récupération de l'opérande de droite */
+
+ op_right = G_SCAN_LITERAL_EXPRESSION(new_right);
+ vtype_right = g_scan_literal_expression_get_value_type(op_right);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_signed_integer_value(op_right, &val_2_s))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else if (vtype_right == LVT_UNSIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_unsigned_integer_value(op_right, &val_2_u))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Partie des calculs */
+
+ result = SRS_REDUCED;
+
+ switch (expr->operator)
+ {
+ case AEO_PLUS:
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s + val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ if ((long long)val_2_u > val_1_s)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s + (long long)val_2_u;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s + (long long)val_2_u;
+ }
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ if ((long long)val_1_u > val_2_s)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = (long long)val_1_u + val_2_s;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = (long long)val_1_u + val_2_s;
+ }
+
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u + val_2_u;
+
+ }
+ }
+ break;
+
+ case AEO_MINUS:
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ if (val_2_s < val_1_s)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s - val_2_s;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s - val_2_s;
+ }
+
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s - (long long)val_2_u;
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = (long long)val_1_u - val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ if (val_1_u > val_2_u)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u - val_2_u;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_u - val_2_u;
+ }
+
+ }
+ }
+ break;
+
+ case AEO_MUL:
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s * val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s * (long long)val_2_u;
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = (long long)val_1_u * val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u * val_2_u;
+
+ }
+ }
+ break;
+
+ case AEO_DIV:
+ if ((vtype_right == LVT_SIGNED_INTEGER && val_2_s == 0)
+ || (vtype_right == LVT_UNSIGNED_INTEGER && val_2_u == 0))
+ {
+ result = SRS_UNRESOLVABLE;
+ break;
+ }
+
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s / val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s / (long long)val_2_u;
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = (long long)val_1_u / val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u / val_2_u;
+
+ }
+ }
+ break;
+
+ case AEO_MOD:
+ result = SRS_UNRESOLVABLE;
+ /* FIXME
+ result = (val_2 != 0);
+ if (result)
+ reduced = val_1 % val_2;
+ */
+ break;
+
+ }
+
+ if (result == SRS_REDUCED)
+ {
+ if (state_final == LVT_SIGNED_INTEGER)
+ *out = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &reduced_s);
+ else
+ {
+ assert(state_final == LVT_UNSIGNED_INTEGER);
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &reduced_u);
+ }
+
+ }
+
+ }
+
+ /* Mise à jour de la progression ? */
+
+ else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
+ {
+ if (new_left != expr->left || new_right != expr->right)
+ *out = g_scan_arithmetic_operation_new(expr->operator, new_left, new_right);
+
+ result = SRS_WAIT_FOR_SCAN;
+
+ }
+
+ /* Cas des situations où les expressions ne sont pas exploitables (!) */
+ else
+ {
+ assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+ result = SRS_UNRESOLVABLE;
+
+ }
+
+ /* Sortie propre */
+
+ exit:
+
+ g_clear_object(&new_left);
+ g_clear_object(&new_right);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/arithmop.h b/src/analysis/scan/exprs/arithmetic.h
index dcc8bf8..8a1e844 100644
--- a/src/analysis/scan/exprs/arithmop.h
+++ b/src/analysis/scan/exprs/arithmetic.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * arithmop.h - prototypes pour la gestion des opérations arithmétiques
+ * arithmetic.h - prototypes pour la gestion des opérations arithmétiques
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,27 +21,27 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMOP_H
-#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_H
+#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H
+#define _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H
#include "../expr.h"
-#define G_TYPE_ARITHMETIC_OPERATION g_arithmetic_operation_get_type()
-#define G_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperation))
-#define G_IS_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARITHMETIC_OPERATION))
-#define G_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass))
-#define G_IS_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARITHMETIC_OPERATION))
-#define G_ARITHMETIC_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass))
+#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 _GArithmOperation GArithmOperation;
+typedef struct _GScanArithmeticOperation GScanArithmeticOperation;
/* Opération arithmétique impliquant deux opérandes (classe) */
-typedef struct _GArithmOperationClass GArithmOperationClass;
+typedef struct _GScanArithmeticOperationClass GScanArithmeticOperationClass;
/* Type d'opération arithmétique */
@@ -57,11 +57,11 @@ typedef enum _ArithmeticExpressionOperator
/* Indique le type défini pour une opération arithmétique entre expressions. */
-GType g_arithmetic_operation_get_type(void);
+GType g_scan_arithmetic_operation_get_type(void);
/* Organise une opération arithmétique entre expressions. */
-GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
+GScanExpression *g_scan_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
-#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H */
diff --git a/src/analysis/scan/exprs/call-int.h b/src/analysis/scan/exprs/call-int.h
index 631a25b..9646b95 100644
--- a/src/analysis/scan/exprs/call-int.h
+++ b/src/analysis/scan/exprs/call-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* call-int.h - prototypes internes pour l'organisation d'un appel à un élément de scan enregistré
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -33,9 +33,9 @@
/* Exécution d'une fonction auxiliaire d'analyse (instance) */
-struct _GPendingCall
+struct _GScanPendingCall
{
- GNamedAccess parent; /* A laisser en premier */
+ GScanNamedAccess parent; /* A laisser en premier */
GScanExpression **args; /* Arguments d'appel fournis */
size_t count; /* Quantité de ces arguments */
@@ -43,15 +43,15 @@ struct _GPendingCall
};
/* Exécution d'une fonction auxiliaire d'analyse (classe) */
-struct _GPendingCallClass
+struct _GScanPendingCallClass
{
- GNamedAccessClass parent; /* A laisser en premier */
+ GScanNamedAccessClass parent; /* A laisser en premier */
};
/* Met en place une expression d'appel. */
-bool g_pending_call_create(GPendingCall *, const sized_string_t *, GScanExpression **, size_t);
+bool g_scan_pending_call_create(GScanPendingCall *, const sized_string_t *, GScanExpression **, size_t);
diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c
index dde627c..2fd1ff1 100644
--- a/src/analysis/scan/exprs/call.c
+++ b/src/analysis/scan/exprs/call.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* call.c - organisation d'un appel à un élément de scan enregistré
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -38,27 +38,27 @@
/* Initialise la classe des appels de fonction avec arguments. */
-static void g_pending_call_class_init(GPendingCallClass *);
+static void g_scan_pending_call_class_init(GScanPendingCallClass *);
/* Initialise une instance d'appel de fonction avec arguments. */
-static void g_pending_call_init(GPendingCall *);
+static void g_scan_pending_call_init(GScanPendingCall *);
/* Supprime toutes les références externes. */
-static void g_pending_call_dispose(GPendingCall *);
+static void g_scan_pending_call_dispose(GScanPendingCall *);
/* Procède à la libération totale de la mémoire. */
-static void g_pending_call_finalize(GPendingCall *);
+static void g_scan_pending_call_finalize(GScanPendingCall *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_pending_call_copy(GPendingCall *, const GPendingCall *);
-
/* Réduit une expression à une forme plus simple. */
-static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_pending_call_reduce(GScanPendingCall *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+static void g_scan_pending_call_copy(GScanPendingCall *, const GScanPendingCall *);
@@ -68,7 +68,7 @@ static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *,
/* Indique le type défini pour un appel de fonction enregistrée. */
-G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS);
+G_DEFINE_TYPE(GScanPendingCall, g_scan_pending_call, G_TYPE_SCAN_NAMED_ACCESS);
/******************************************************************************
@@ -83,21 +83,25 @@ G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS);
* *
******************************************************************************/
-static void g_pending_call_class_init(GPendingCallClass *klass)
+static void g_scan_pending_call_class_init(GScanPendingCallClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GScanExpressionClass *expr; /* Version de classe parente */
+ GScanNamedAccessClass *access; /* Autre version de la classe */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_pending_call_dispose;
- object->finalize = (GObjectFinalizeFunc)g_pending_call_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pending_call_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_pending_call_finalize;
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)NULL;
- expr->copy = (copy_expr_fc)g_pending_call_copy;
- expr->reduce = (reduce_expr_fc)g_pending_call_reduce;
+ expr->reduce = (reduce_expr_fc)g_scan_pending_call_reduce;
+
+ access = G_SCAN_NAMED_ACCESS_CLASS(klass);
+
+ access->copy = (copy_scan_access_fc)g_scan_pending_call_copy;
}
@@ -114,7 +118,7 @@ static void g_pending_call_class_init(GPendingCallClass *klass)
* *
******************************************************************************/
-static void g_pending_call_init(GPendingCall *call)
+static void g_scan_pending_call_init(GScanPendingCall *call)
{
call->args = NULL;
call->count = 0;
@@ -134,14 +138,14 @@ static void g_pending_call_init(GPendingCall *call)
* *
******************************************************************************/
-static void g_pending_call_dispose(GPendingCall *call)
+static void g_scan_pending_call_dispose(GScanPendingCall *call)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < call->count; i++)
g_clear_object(&call->args[i]);
- G_OBJECT_CLASS(g_pending_call_parent_class)->dispose(G_OBJECT(call));
+ G_OBJECT_CLASS(g_scan_pending_call_parent_class)->dispose(G_OBJECT(call));
}
@@ -158,12 +162,12 @@ static void g_pending_call_dispose(GPendingCall *call)
* *
******************************************************************************/
-static void g_pending_call_finalize(GPendingCall *call)
+static void g_scan_pending_call_finalize(GScanPendingCall *call)
{
if (call->args != NULL)
free(call->args);
- G_OBJECT_CLASS(g_pending_call_parent_class)->finalize(G_OBJECT(call));
+ G_OBJECT_CLASS(g_scan_pending_call_parent_class)->finalize(G_OBJECT(call));
}
@@ -182,13 +186,13 @@ static void g_pending_call_finalize(GPendingCall *call)
* *
******************************************************************************/
-GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpression **args, size_t count)
+GScanExpression *g_scan_pending_call_new(const sized_string_t *target, GScanExpression **args, size_t count)
{
GScanExpression *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_PENDING_CALL, NULL);
+ result = g_object_new(G_TYPE_SCAN_PENDING_CALL, NULL);
- if (!g_pending_call_create(G_PENDING_CALL(result), target, args, count))
+ if (!g_scan_pending_call_create(G_SCAN_PENDING_CALL(result), target, args, count))
g_clear_object(&result);
return result;
@@ -211,12 +215,12 @@ GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpressio
* *
******************************************************************************/
-bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count)
+bool g_scan_pending_call_create(GScanPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
- result = g_named_access_create(G_NAMED_ACCESS(call), target);
+ result = g_scan_named_access_create(G_SCAN_NAMED_ACCESS(call), target);
if (!result) goto exit;
call->args = malloc(count * sizeof(GScanExpression *));
@@ -243,37 +247,6 @@ bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GSc
/******************************************************************************
* *
-* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
-* src = expression source à copier. *
-* *
-* Description : Reproduit une expression en place dans une nouvelle instance.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_pending_call_copy(GPendingCall *dest, const GPendingCall *src)
-{
- GScanExpressionClass *class; /* Classe parente à solliciter */
- size_t i; /* Boucle de parcours */
-
- class = G_SCAN_EXPRESSION_CLASS(g_pending_call_parent_class);
-
- class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
- dest->args = malloc(src->count * sizeof(GScanExpression *));
- dest->count = src->count;
-
- for (i = 0; i < src->count; i++)
- dest->args[i] = g_scan_expression_duplicate(src->args[i]);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
* scope = portée courante des variables locales. *
@@ -287,89 +260,196 @@ static void g_pending_call_copy(GPendingCall *dest, const GPendingCall *src)
* *
******************************************************************************/
-static bool g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_pending_call_reduce(GScanPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
- GNamedAccess *new; /* Eventuel étage suivant */
- GPendingCall *new_call; /* Version en appel */
- size_t i; /* Boucle de parcours */
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanNamedAccess *access; /* Autre vision de l'expression*/
+ GRegisteredItem *resolved; /* Cible concrète obtenue */
+ size_t i; /* Boucle de parcours #1 */
GScanExpression *arg; /* Argument réduit à échanger */
- GObject *final; /* Expression ou élément ? */
+ GScanExpression *new; /* Nouvelle réduction obtenue */
+ ScanReductionState state; /* Etat synthétisé d'un élément*/
+ size_t k; /* Boucle de parcours #2 */
+ GScanExpression **new_args; /* Nouvelle séquence d'args. */
GScanExpression *new_next; /* Nouvelle version du suivant */
+ GObject *final; /* Expression ou élément ? */
+ bool valid; /* Validité de l'élément */
- result = _g_named_access_reduce(G_NAMED_ACCESS(expr), ctx, scope, out);
+ access = G_SCAN_NAMED_ACCESS(expr);
- if (result && *out != NULL)
- {
- assert(G_IS_NAMED_ACCESS(*out));
+ resolved = _g_scan_named_access_prepare_reduction(access, ctx, scope);
+
+ if (resolved == NULL)
+ result = SRS_UNRESOLVABLE;
- new = G_NAMED_ACCESS(*out);
- *out = NULL;
+ else
+ {
+ result = SRS_PENDING;
- assert(new->target == NULL);
- assert(G_IS_PENDING_CALL(new));
- assert(G_IS_REGISTERED_ITEM(new->resolved));
+ /* Actualisation nécessaire des arguments ? */
- new_call = G_PENDING_CALL(new);
+ new_args = NULL;
- for (i = 0; i < new_call->count; i++)
+ for (i = 0; i < expr->count; i++)
{
- result = g_scan_expression_reduce(new_call->args[i], ctx, scope, &arg);
- if (!result) goto exit;
+ arg = expr->args[i];
- if (arg != NULL)
+ state = g_scan_expression_reduce(arg, ctx, scope, &new);
+ if (state == SRS_UNRESOLVABLE)
{
- g_object_unref(G_OBJECT(new_call->args[i]));
- new_call->args[i] = arg;
+ result = SRS_UNRESOLVABLE;
+ break;
}
+ if (state == SRS_WAIT_FOR_SCAN)
+ result = SRS_WAIT_FOR_SCAN;
+
+ if (new != arg)
+ {
+ if (new_args == NULL)
+ {
+ new_args = calloc(expr->count, sizeof(GScanExpression *));
+
+ for (k = 0; k < i; k++)
+ {
+ new_args[k] = expr->args[i];
+ g_object_ref(G_OBJECT(new_args[k]));
+ }
+
+ }
+
+ new_args[i] = new;
+
+ }
+
+ else
+ {
+ if (new_args != NULL)
+ new_args[i] = new;
+ }
}
- result = g_registered_item_run_call(new->resolved,
- new_call->args,
- new_call->count,
- ctx, scope, &final);
+ /* Suite des traitements */
- if (result && final != NULL)
+ if (result == SRS_WAIT_FOR_SCAN)
{
/**
- * Si le produit de l'appel à la fonction est une expression d'évaluation
- * classique, alors ce produit constitue la réduction finale de la chaîne.
- *
- * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne.
+ * Si changement il y a eu...
*/
- if (!G_IS_REGISTERED_ITEM(final))
+ if (new_args != NULL)
{
- assert(new->next == NULL);
- *out = G_SCAN_EXPRESSION(final);
+ *out = g_scan_pending_call_new(NULL, new_args, expr->count);
+
+ /**
+ * Fonctionnement équivalent de :
+ * g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(*out), resolved);
+ */
+ G_SCAN_NAMED_ACCESS(*out)->resolved = resolved;
+ g_object_ref(G_OBJECT(resolved));
+
+ if (G_SCAN_NAMED_ACCESS(expr)->next != NULL)
+ g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS(*out), G_SCAN_NAMED_ACCESS(expr)->next);
+
}
+
+ }
+
+ else if (result == SRS_PENDING)
+ {
+ if (new_args == NULL)
+ valid = g_registered_item_run_call(resolved,
+ expr->args,
+ expr->count,
+ ctx, scope, &final);
else
- {
- assert(new->next != NULL);
+ valid = g_registered_item_run_call(resolved,
+ new_args,
+ expr->count,
+ ctx, scope, &final);
- new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next));
- assert(G_IS_NAMED_ACCESS(new_next));
+ if (valid && final != NULL)
+ {
+ /**
+ * Si le produit de l'appel à la fonction est une expression d'évaluation
+ * classique, alors ce produit constitue la réduction finale de la chaîne.
+ *
+ * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne.
+ */
+ if (!G_IS_REGISTERED_ITEM(final))
+ {
+ assert(access->next == NULL);
- g_named_access_set_base(G_NAMED_ACCESS(new_next), G_REGISTERED_ITEM(final));
+ *out = G_SCAN_EXPRESSION(final);
- result = g_scan_expression_reduce(new_next, ctx, scope, out);
+ result = SRS_REDUCED;
- if (result && *out == NULL)
- *out = new_next;
+ }
else
+ {
+ assert(access->next != NULL);
+
+ new_next = g_scan_named_access_duplicate(access->next, resolved);
+
+ result = g_scan_expression_reduce(new_next, ctx, scope, out);
+
g_object_unref(G_OBJECT(new_next));
+ }
+
}
+ else
+ result = SRS_UNRESOLVABLE;
+
}
- exit:
+ /* Libération locale des arguments reconstruits */
- g_object_unref(G_OBJECT(new));
+ if (new_args != NULL)
+ {
+ for (i = 0; i < expr->count; i++)
+ g_clear_object(&new_args[i]);
+ }
+
+ g_object_unref(G_OBJECT(resolved));
}
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
+* *
+* Description : Reproduit un accès en place dans une nouvelle instance. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_call_copy(GScanPendingCall *dest, const GScanPendingCall *src)
+{
+ GScanNamedAccessClass *class; /* Classe parente à solliciter */
+ size_t i; /* Boucle de parcours */
+
+ class = G_SCAN_NAMED_ACCESS_CLASS(g_scan_pending_call_parent_class);
+
+ class->copy(G_SCAN_NAMED_ACCESS(dest), G_SCAN_NAMED_ACCESS(src));
+
+ dest->args = malloc(src->count * sizeof(GScanExpression *));
+ dest->count = src->count;
+
+ for (i = 0; i < src->count; i++)
+ {
+ dest->args[i] = src->args[i];
+ g_object_ref(G_OBJECT(src->args[i]));
+ }
+
+}
diff --git a/src/analysis/scan/exprs/call.h b/src/analysis/scan/exprs/call.h
index c344036..c4d8964 100644
--- a/src/analysis/scan/exprs/call.h
+++ b/src/analysis/scan/exprs/call.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* call.h - prototypes pour l'organisation d'un appel à un élément de scan enregistré
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -30,26 +30,26 @@
-#define G_TYPE_PENDING_CALL g_pending_call_get_type()
-#define G_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PENDING_CALL, GPendingCall))
-#define G_IS_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PENDING_CALL))
-#define G_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PENDING_CALL, GPendingCallClass))
-#define G_IS_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PENDING_CALL))
-#define G_PENDING_CALL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PENDING_CALL, GPendingCallClass))
+#define G_TYPE_SCAN_PENDING_CALL g_scan_pending_call_get_type()
+#define G_SCAN_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PENDING_CALL, GScanPendingCall))
+#define G_IS_SCAN_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PENDING_CALL))
+#define G_SCAN_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PENDING_CALL, GScanPendingCallClass))
+#define G_IS_SCAN_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PENDING_CALL))
+#define G_SCAN_PENDING_CALL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PENDING_CALL, GScanPendingCallClass))
/* Exécution d'une fonction auxiliaire d'analyse (instance) */
-typedef struct _GPendingCall GPendingCall;
+typedef struct _GScanPendingCall GScanPendingCall;
/* Exécution d'une fonction auxiliaire d'analyse (classe) */
-typedef struct _GPendingCallClass GPendingCallClass;
+typedef struct _GScanPendingCallClass GScanPendingCallClass;
/* Indique le type défini pour un appel de fonction enregistrée. */
-GType g_pending_call_get_type(void);
+GType g_scan_pending_call_get_type(void);
/* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_pending_call_new(const sized_string_t *, GScanExpression **, size_t);
+GScanExpression *g_scan_pending_call_new(const sized_string_t *, GScanExpression **, size_t);
diff --git a/src/analysis/scan/exprs/counter-int.h b/src/analysis/scan/exprs/counter-int.h
new file mode 100644
index 0000000..8c5e56b
--- /dev/null
+++ b/src/analysis/scan/exprs/counter-int.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter-int.h - prototypes internes pour le décompte de correspondances identifiées dans du contenu binaire
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_COUNTER_INT_H
+#define _ANALYSIS_SCAN_EXPRS_COUNTER_INT_H
+
+
+#include "counter.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Décompte des identifications de motifs (instance) */
+struct _GScanMatchCounter
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GSearchPattern *pattern; /* Motif associé */
+
+};
+
+/* Décompte des identifications de motifs (classe) */
+struct _GScanMatchCounterClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un compteur de correspondances. */
+bool g_scan_match_counter_create(GScanMatchCounter *, GSearchPattern *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_COUNTER_INT_H */
diff --git a/src/analysis/scan/exprs/counter.c b/src/analysis/scan/exprs/counter.c
new file mode 100644
index 0000000..290fd02
--- /dev/null
+++ b/src/analysis/scan/exprs/counter.c
@@ -0,0 +1,248 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter.c - décompte de correspondances identifiées dans du contenu binaire
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "counter.h"
+
+
+#include "counter-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INSTANCIATION D'UNE FORME DE CONDITION --------------------- */
+
+
+/* Initialise la classe des opérations booléennes. */
+static void g_scan_match_counter_class_init(GScanMatchCounterClass *);
+
+/* Initialise une instance d'opération booléenne. */
+static void g_scan_match_counter_init(GScanMatchCounter *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_match_counter_dispose(GScanMatchCounter *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_match_counter_finalize(GScanMatchCounter *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_match_counter_reduce(GScanMatchCounter *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INSTANCIATION D'UNE FORME DE CONDITION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */
+G_DEFINE_TYPE(GScanMatchCounter, g_scan_match_counter, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations booléennes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_counter_class_init(GScanMatchCounterClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_match_counter_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_match_counter_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->reduce = (reduce_expr_fc)g_scan_match_counter_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération booléenne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_counter_init(GScanMatchCounter *counter)
+{
+ counter->pattern = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_counter_dispose(GScanMatchCounter *counter)
+{
+ g_clear_object(&counter->pattern);
+
+ G_OBJECT_CLASS(g_scan_match_counter_parent_class)->dispose(G_OBJECT(counter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_counter_finalize(GScanMatchCounter *counter)
+{
+ G_OBJECT_CLASS(g_scan_match_counter_parent_class)->finalize(G_OBJECT(counter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = motif à impliquer. *
+* *
+* Description : Met en place un décompte de correspondances obtenues. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_match_counter_new(GSearchPattern *pattern)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_MATCH_COUNTER, NULL);
+
+ if (!g_scan_match_counter_create(G_SCAN_MATCH_COUNTER(result), pattern))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : counter = instance à initialiser pleinement. *
+* pattern = motif à impliquer. *
+* *
+* Description : Met en place un compteur de correspondances. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_match_counter_create(GScanMatchCounter *counter, GSearchPattern *pattern)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ counter->pattern = pattern;
+ g_object_ref(G_OBJECT(pattern));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_match_counter_reduce(GScanMatchCounter *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ size_t count; /* Quantité de correspondances */
+ const GScanMatch **matches; /* Correspondances établies */
+
+
+ matches = g_scan_context_get_full_matches(ctx, expr->pattern, &count);
+
+
+ printf("matches: %zu\n", count);
+
+
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ count });
+ result = true;
+
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/counter.h b/src/analysis/scan/exprs/counter.h
new file mode 100644
index 0000000..c90953e
--- /dev/null
+++ b/src/analysis/scan/exprs/counter.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter.h - prototypes pour le décompte de correspondances identifiées dans du contenu binaire
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_COUNTER_H
+#define _ANALYSIS_SCAN_EXPRS_COUNTER_H
+
+
+#include <glib-object.h>
+
+
+#include "../expr.h"
+#include "../pattern.h"
+
+
+
+#define G_TYPE_SCAN_MATCH_COUNTER g_scan_match_counter_get_type()
+#define G_SCAN_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounter))
+#define G_IS_SCAN_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MATCH_COUNTER))
+#define G_SCAN_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounterClass))
+#define G_IS_SCAN_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MATCH_COUNTER))
+#define G_SCAN_MATCH_COUNTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounterClass))
+
+
+/* Décompte des identifications de motifs (instance) */
+typedef struct _GScanMatchCounter GScanMatchCounter;
+
+/* Décompte des identifications de motifs (classe) */
+typedef struct _GScanMatchCounterClass GScanMatchCounterClass;
+
+
+/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */
+GType g_scan_match_counter_get_type(void);
+
+/* Met en place un décompte de correspondances obtenues. */
+GScanExpression *g_scan_match_counter_new(GSearchPattern *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_COUNTER_H */
diff --git a/src/analysis/scan/exprs/intersect-int.h b/src/analysis/scan/exprs/intersect-int.h
new file mode 100644
index 0000000..83e4251
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect-int.h - prototypes internes pour l'intersection d'ensembles aux types indentiques
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H
+#define _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H
+
+
+#include "intersect.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération d'intersection entre deux ensembles (instance) */
+struct _GScanSetsIntersection
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GScanExpression *first; /* Expression impactée #1 */
+ GScanExpression *second; /* Expression impactée #2 */
+
+};
+
+/* Opération d'intersection entre deux ensembles (classe) */
+struct _GScanSetsIntersectionClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'opération booléenne. */
+bool g_scan_sets_intersection_create(GScanSetsIntersection *, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H */
diff --git a/src/analysis/scan/exprs/intersect.c b/src/analysis/scan/exprs/intersect.c
new file mode 100644
index 0000000..f0660e0
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect.c
@@ -0,0 +1,290 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect.c - intersection d'ensembles aux types indentiques
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "intersect.h"
+
+
+#include <assert.h>
+
+
+#include "intersect-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des intersections entre deux ensembles. */
+static void g_scan_sets_intersection_class_init(GScanSetsIntersectionClass *);
+
+/* Initialise une instance d'intersection entre deux ensembles. */
+static void g_scan_sets_intersection_init(GScanSetsIntersection *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_sets_intersection_dispose(GScanSetsIntersection *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_sets_intersection_finalize(GScanSetsIntersection *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_sets_intersection_reduce(GScanSetsIntersection *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une intersection entre deux ensembles. */
+G_DEFINE_TYPE(GScanSetsIntersection, g_scan_sets_intersection, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des intersections entre deux ensembles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_class_init(GScanSetsIntersectionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sets_intersection_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_sets_intersection_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->reduce = (reduce_expr_fc)g_scan_sets_intersection_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'intersection entre deux ensembles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_init(GScanSetsIntersection *inter)
+{
+ inter->first = NULL;
+ inter->second = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inter = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_dispose(GScanSetsIntersection *inter)
+{
+ g_clear_object(&inter->first);
+ g_clear_object(&inter->second);
+
+ G_OBJECT_CLASS(g_scan_sets_intersection_parent_class)->dispose(G_OBJECT(inter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inter = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_finalize(GScanSetsIntersection *inter)
+{
+ G_OBJECT_CLASS(g_scan_sets_intersection_parent_class)->finalize(G_OBJECT(inter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type d'opération booléenne à représenter. *
+* first = premier élément concerné. *
+* second = second élément concerné. *
+* *
+* Description : Organise une intersection entre deux ensembles. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_sets_intersection_new(GScanExpression *first, GScanExpression *second)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_SETS_INTERSECTION, NULL);
+
+ if (!g_scan_sets_intersection_create(G_SCAN_SETS_INTERSECTION(result), first, second))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inter = instance à initialiser pleinement. *
+* first = premier élément concerné. *
+* second = second élément concerné. *
+* *
+* Description : Met en place une expression d'opération booléenne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_sets_intersection_create(GScanSetsIntersection *inter, GScanExpression *first, GScanExpression *second)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ inter->first = first;
+ g_object_ref(G_OBJECT(first));
+
+ inter->second = second;
+ g_object_ref(G_OBJECT(second));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_sets_intersection_reduce(GScanSetsIntersection *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_first; /* Nouvelle réduction #1 */
+ GScanExpression *new_second; /* Nouvelle réduction #2 */
+ ScanReductionState state_first; /* Etat synthétisé #1 */
+ ScanReductionState state_second; /* Etat synthétisé #2 */
+
+ new_first = NULL;
+ new_second = NULL;
+
+ state_first = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
+ if (state_first == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_second = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
+ if (state_second == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (state_first == SRS_WAIT_FOR_SCAN || state_second == SRS_WAIT_FOR_SCAN)
+ {
+ if (new_first != expr->first || new_second != expr->second)
+ *out = g_scan_sets_intersection_new(new_first, new_second);
+
+ result = SRS_WAIT_FOR_SCAN;
+
+ }
+
+ else
+ {
+ assert(state_first == SRS_REDUCED && state_second == SRS_REDUCED);
+
+ *out = g_scan_expression_intersect(new_first, new_second, ctx, scope);
+
+ result = (*out != NULL ? SRS_REDUCED : SRS_UNRESOLVABLE);
+
+ }
+
+ exit:
+
+ g_clear_object(&new_first);
+ g_clear_object(&new_second);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/intersect.h b/src/analysis/scan/exprs/intersect.h
new file mode 100644
index 0000000..56efdff
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect.h - prototypes pour l'intersection d'ensembles aux types indentiques
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_INTERSECT_H
+#define _ANALYSIS_SCAN_EXPRS_INTERSECT_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_SETS_INTERSECTION g_scan_sets_intersection_get_type()
+#define G_SCAN_SETS_INTERSECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersection))
+#define G_IS_SCAN_SETS_INTERSECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SETS_INTERSECTION))
+#define G_SCAN_SETS_INTERSECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersectionClass))
+#define G_IS_SCAN_SETS_INTERSECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SETS_INTERSECTION))
+#define G_SCAN_SETS_INTERSECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersectionClass))
+
+
+/* Opération d'intersection entre deux ensembles (instance) */
+typedef struct _GScanSetsIntersection GScanSetsIntersection;
+
+/* Opération d'intersection entre deux ensembles (classe) */
+typedef struct _GScanSetsIntersectionClass GScanSetsIntersectionClass;
+
+
+/* Indique le type défini pour une intersection entre deux ensembles. */
+GType g_scan_sets_intersection_get_type(void);
+
+/* Organise une intersection entre deux ensembles. */
+GScanExpression *g_scan_sets_intersection_new(GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_INTERSECT_H */
diff --git a/src/analysis/scan/exprs/literal-int.h b/src/analysis/scan/exprs/literal-int.h
index 875b3de..b0a0ec5 100644
--- a/src/analysis/scan/exprs/literal-int.h
+++ b/src/analysis/scan/exprs/literal-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* literal-int.h - prototypes internes pour la représentation d'une valeur concrète
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,24 +28,22 @@
#include "literal.h"
-#include <stdbool.h>
-
-
#include "../expr-int.h"
/* Expression portant une valeur concrète (instance) */
-struct _GLiteralExpression
+struct _GScanLiteralExpression
{
GScanExpression parent; /* A laisser en premier */
- ExprValueType value_type; /* Type de valeur portée */
+ LiteralValueType value_type; /* Type de valeur portée */
union
{
bool boolean; /* Valeur booléenne */
- unsigned long long integer; /* Valeur entière 64 bits */
+ long long s_integer; /* Valeur entière 64 bits */
+ unsigned long long u_integer; /* Valeur entière 64 bits */
sized_string_t string; /* Chaîne de caractères */
struct
{
@@ -58,7 +56,7 @@ struct _GLiteralExpression
};
/* Expression portant une valeur concrète (classe) */
-struct _GLiteralExpressionClass
+struct _GScanLiteralExpressionClass
{
GScanExpressionClass parent; /* A laisser en premier */
@@ -66,7 +64,7 @@ struct _GLiteralExpressionClass
/* Met en place une expression de valeur concrête. */
-bool g_literal_expression_create(GLiteralExpression *, ExprValueType, ...);
+bool g_scan_literal_expression_create(GScanLiteralExpression *, LiteralValueType, ...);
diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c
index 119b871..e468382 100644
--- a/src/analysis/scan/exprs/literal.c
+++ b/src/analysis/scan/exprs/literal.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* literal.c - représentation d'une valeur concrète
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -37,16 +37,16 @@
/* Initialise la classe des expressions de valeur concrète. */
-static void g_literal_expression_class_init(GLiteralExpressionClass *);
+static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *);
/* Initialise une instance d'expression de valeur concrète. */
-static void g_literal_expression_init(GLiteralExpression *);
+static void g_scan_literal_expression_init(GScanLiteralExpression *);
/* Supprime toutes les références externes. */
-static void g_literal_expression_dispose(GLiteralExpression *);
+static void g_scan_literal_expression_dispose(GScanLiteralExpression *);
/* Procède à la libération totale de la mémoire. */
-static void g_literal_expression_finalize(GLiteralExpression *);
+static void g_scan_literal_expression_finalize(GScanLiteralExpression *);
@@ -54,13 +54,13 @@ static void g_literal_expression_finalize(GLiteralExpression *);
/* Réalise une comparaison entre objets selon un critère précis. */
-static bool g_literal_expression_compare_rich(const GLiteralExpression *, const GLiteralExpression *, RichCmpOperation, bool *);
+static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression *, const GScanLiteralExpression *, RichCmpOperation, bool *);
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_literal_expression_copy(GLiteralExpression *, const GLiteralExpression *);
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **);
-/* Réduit une expression à une forme plus simple. */
-static bool g_literal_expression_reduce(GLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **);
+/* Dénombre les éléments portés par une expression. */
+static bool g_scan_literal_expression_count(const GScanLiteralExpression *, size_t *);
@@ -70,7 +70,7 @@ static bool g_literal_expression_reduce(GLiteralExpression *, GScanContext *, GS
/* Indique le type défini pour un appel de fonction enregistrée. */
-G_DEFINE_TYPE(GLiteralExpression, g_literal_expression, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanLiteralExpression, g_scan_literal_expression, G_TYPE_SCAN_EXPRESSION);
/******************************************************************************
@@ -85,21 +85,21 @@ G_DEFINE_TYPE(GLiteralExpression, g_literal_expression, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_literal_expression_class_init(GLiteralExpressionClass *klass)
+static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GScanExpressionClass *expr; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_literal_expression_dispose;
- object->finalize = (GObjectFinalizeFunc)g_literal_expression_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_literal_expression_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_literal_expression_finalize;
expr = G_SCAN_EXPRESSION_CLASS(klass);
- expr->cmp_rich = (compare_expr_rich_fc)g_literal_expression_compare_rich;
- expr->copy = (copy_expr_fc)g_literal_expression_copy;
- expr->reduce = (reduce_expr_fc)g_literal_expression_reduce;
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_literal_expression_compare_rich;
+ expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_literal_expression_reduce_to_boolean;
+ expr->count = (count_scan_expr_fc)g_scan_literal_expression_count;
}
@@ -116,8 +116,9 @@ static void g_literal_expression_class_init(GLiteralExpressionClass *klass)
* *
******************************************************************************/
-static void g_literal_expression_init(GLiteralExpression *expr)
+static void g_scan_literal_expression_init(GScanLiteralExpression *expr)
{
+ G_SCAN_EXPRESSION(expr)->state = SRS_REDUCED;
}
@@ -134,9 +135,9 @@ static void g_literal_expression_init(GLiteralExpression *expr)
* *
******************************************************************************/
-static void g_literal_expression_dispose(GLiteralExpression *expr)
+static void g_scan_literal_expression_dispose(GScanLiteralExpression *expr)
{
- G_OBJECT_CLASS(g_literal_expression_parent_class)->dispose(G_OBJECT(expr));
+ G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->dispose(G_OBJECT(expr));
}
@@ -153,9 +154,9 @@ static void g_literal_expression_dispose(GLiteralExpression *expr)
* *
******************************************************************************/
-static void g_literal_expression_finalize(GLiteralExpression *expr)
+static void g_scan_literal_expression_finalize(GScanLiteralExpression *expr)
{
- G_OBJECT_CLASS(g_literal_expression_parent_class)->finalize(G_OBJECT(expr));
+ G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->finalize(G_OBJECT(expr));
}
@@ -167,25 +168,25 @@ static void g_literal_expression_finalize(GLiteralExpression *expr)
* *
* Description : Organise un appel de fonction avec ses arguments. *
* *
-* Retour : Fonction mise en place. *
+* Retour : Expression mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-GScanExpression *g_literal_expression_new(ExprValueType vtype, ...)
+GScanExpression *g_scan_literal_expression_new(LiteralValueType vtype, ...)
{
GScanExpression *result; /* Structure à retourner */
va_list ap; /* Liste d'arguements */
void *ptr; /* Vision générique de valeur */
- result = g_object_new(G_TYPE_LITERAL_EXPRESSION, NULL);
+ result = g_object_new(G_TYPE_SCAN_LITERAL_EXPRESSION, NULL);
va_start(ap, vtype);
ptr = va_arg(ap, void *);
- if (!g_literal_expression_create(G_LITERAL_EXPRESSION(result), vtype, ptr))
+ if (!g_scan_literal_expression_create(G_SCAN_LITERAL_EXPRESSION(result), vtype, ptr))
g_clear_object(&result);
va_end(ap);
@@ -209,12 +210,13 @@ GScanExpression *g_literal_expression_new(ExprValueType vtype, ...)
* *
******************************************************************************/
-bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, ...)
+bool g_scan_literal_expression_create(GScanLiteralExpression *expr, LiteralValueType vtype, ...)
{
bool result; /* Bilan à retourner */
va_list ap; /* Liste d'arguements */
const bool *boolean; /* Valeur booléenne */
- const unsigned long long *integer; /* Valeur entière 64 bits */
+ const long long *s_integer; /* Valeur entière 64 bits #1 */
+ const unsigned long long *u_integer; /* Valeur entière 64 bits #2 */
const sized_string_t *string; /* Chaîne de caractères */
const char *raw; /* Chaîne de caractères brute */
size_t len; /* Taille de la chaîne */
@@ -223,89 +225,115 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype,
char *tmp; /* Zone de travail temporaire */
int ret; /* Bilan d'une opération */
- result = g_scan_expression_create(G_SCAN_EXPRESSION(expr), vtype);
+ va_start(ap, vtype);
- if (result)
+ switch (vtype)
{
- va_start(ap, vtype);
+ case LVT_BOOLEAN:
+ boolean = va_arg(ap, const bool *);
+ expr->value.boolean = *boolean;
+ result = true;
+ break;
- switch (vtype)
- {
- case EVT_BOOLEAN:
- boolean = va_arg(ap, const bool *);
- expr->value.boolean = *boolean;
- break;
+ case LVT_SIGNED_INTEGER:
+ s_integer = va_arg(ap, const long long *);
+ expr->value.s_integer = *s_integer;
+ result = true;
+ break;
- case EVT_INTEGER:
- integer = va_arg(ap, const unsigned long long *);
- expr->value.integer = *integer;
- break;
+ case LVT_UNSIGNED_INTEGER:
+ u_integer = va_arg(ap, const unsigned long long *);
+ expr->value.u_integer = *u_integer;
+ result = true;
+ break;
+
+ case LVT_STRING:
+ string = va_arg(ap, const sized_string_t *);
+ szstrdup(&expr->value.string, string);
+ result = true;
+ break;
- case EVT_STRING:
- string = va_arg(ap, const sized_string_t *);
- szstrdup(&expr->value.string, string);
- break;
+ case LVT_REG_EXPR:
+ raw = va_arg(ap, const char *);
+ len = strlen(raw);
- case EVT_REG_EXPR:
- raw = va_arg(ap, const char *);
- len = strlen(raw);
+ result = (len > 2 && raw[0] == '/');
- result = (len > 2 && raw[0] == '/');
+ cflags = REG_EXTENDED | REG_NOSUB;
- cflags = REG_EXTENDED | REG_NOSUB;
+ for (i = 0; i < 2 && result; i++)
+ {
+ result = (len > 2);
- for (i = 0; i < 2 && result; i++)
+ if (raw[len - 1] == 'i')
{
- result = (len > 2);
+ cflags |= REG_ICASE;
+ len -= 1;
+ }
- if (raw[len - 1] == 'i')
- {
- cflags |= REG_ICASE;
- len -= 1;
- }
+ else if (raw[len - 1] == 's')
+ {
+ cflags |= REG_NEWLINE;
+ len -= 1;
+ }
- else if (raw[len - 1] == 's')
- {
- cflags |= REG_NEWLINE;
- len -= 1;
- }
+ else if (raw[len - 1] == '/')
+ break;
- else if (raw[len - 1] == '/')
- break;
+ }
- }
+ if (result)
+ result = (raw[len - 1] == '/');
- if (result)
- result = (raw[len - 1] == '/');
+ if (result)
+ {
+ assert(len > 2);
+
+ tmp = strndup(&raw[1], len - 2);
+ ret = regcomp(&expr->value.preg, tmp, cflags);
+ free(tmp);
+
+ result = (ret == 0);
if (result)
- {
- assert(len > 2);
+ expr->value.regex = strdup(raw);
+
+ }
+
+ break;
- tmp = strndup(&raw[1], len - 2);
- ret = regcomp(&expr->value.preg, tmp, cflags);
- free(tmp);
+ default:
+ result = false;
+ break;
- result = (ret == 0);
+ }
- if (result)
- expr->value.regex = strdup(raw);
+ va_end(ap);
- }
+ expr->value_type = vtype;
- break;
+ return result;
- default:
- result = false;
- break;
+}
- }
- va_end(ap);
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* *
+* Description : Indique le type de valeur portée par une expression. *
+* *
+* Retour : Type de valeur associée à l'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- }
+LiteralValueType g_scan_literal_expression_get_value_type(const GScanLiteralExpression *expr)
+{
+ LiteralValueType result; /* Type à retourner */
- expr->value_type = vtype;
+ result = expr->value_type;
return result;
@@ -314,7 +342,7 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype,
/******************************************************************************
* *
-* Paramètres : item = premier objet à consulter pour une comparaison. *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
* value = valeur portée portée par l'expression. [OUT] *
* *
* Description : Indique la valeur portée par une expression booléenne. *
@@ -325,14 +353,41 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype,
* *
******************************************************************************/
-bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool *value)
+bool g_scan_literal_expression_get_boolean_value(const GScanLiteralExpression *expr, bool *value)
+{
+ bool result; /* Etat à retourner */
+
+ result = (expr->value_type == LVT_BOOLEAN);
+
+ if (result)
+ *value = expr->value.boolean;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
+* value = valeur portée portée par l'expression. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression d'entier. *
+* *
+* Retour : true si l'expression est de type entier, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_literal_expression_get_signed_integer_value(const GScanLiteralExpression *expr, long long *value)
{
bool result; /* Etat à retourner */
- result = (item->value_type == EVT_BOOLEAN);
+ result = (expr->value_type == LVT_SIGNED_INTEGER);
if (result)
- *value = item->value.boolean;
+ *value = expr->value.u_integer;
return result;
@@ -341,7 +396,7 @@ bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool
/******************************************************************************
* *
-* Paramètres : item = premier objet à consulter pour une comparaison. *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
* value = valeur portée portée par l'expression. [OUT] *
* *
* Description : Indique la valeur portée par une expression d'entier. *
@@ -352,14 +407,14 @@ bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool
* *
******************************************************************************/
-bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsigned long long *value)
+bool g_scan_literal_expression_get_unsigned_integer_value(const GScanLiteralExpression *expr, unsigned long long *value)
{
bool result; /* Etat à retourner */
- result = (item->value_type == EVT_INTEGER);
+ result = (expr->value_type == LVT_UNSIGNED_INTEGER);
if (result)
- *value = item->value.integer;
+ *value = expr->value.u_integer;
return result;
@@ -368,7 +423,7 @@ bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsi
/******************************************************************************
* *
-* Paramètres : item = premier objet à consulter pour une comparaison. *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
* value = valeur portée portée par l'expression. [OUT] *
* *
* Description : Indique la valeur portée par une expression de chaîne. *
@@ -379,14 +434,14 @@ bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsi
* *
******************************************************************************/
-bool g_literal_expression_get_string_value(const GLiteralExpression *item, const sized_string_t **value)
+bool g_scan_literal_expression_get_string_value(const GScanLiteralExpression *expr, const sized_string_t **value)
{
bool result; /* Etat à retourner */
- result = (item->value_type == EVT_STRING);
+ result = (expr->value_type == LVT_STRING);
if (result)
- *value = &item->value.string;
+ *value = &expr->value.string;
return result;
@@ -395,7 +450,7 @@ bool g_literal_expression_get_string_value(const GLiteralExpression *item, const
/******************************************************************************
* *
-* Paramètres : item = premier objet à consulter pour une comparaison. *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
* value = valeur portée portée par l'expression. [OUT] *
* *
* Description : Indique la valeur portée par une expression rationnelle. *
@@ -406,14 +461,14 @@ bool g_literal_expression_get_string_value(const GLiteralExpression *item, const
* *
******************************************************************************/
-bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const regex_t **value)
+bool g_scan_literal_expression_get_regex_value(const GScanLiteralExpression *expr, const regex_t **value)
{
bool result; /* Etat à retourner */
- result = (item->value_type == EVT_REG_EXPR);
+ result = (expr->value_type == LVT_REG_EXPR);
if (result)
- *value = &item->value.preg;
+ *value = &expr->value.preg;
return result;
@@ -428,7 +483,7 @@ bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const
/******************************************************************************
* *
-* Paramètres : item = premier objet à consulter pour une comparaison. *
+* Paramètres : expr = premier objet à consulter pour une comparaison. *
* other = second objet à consulter pour une comparaison. *
* op = opération de comparaison à réaliser. *
* status = bilan des opérations de comparaison. [OUT] *
@@ -441,32 +496,32 @@ bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const
* *
******************************************************************************/
-static bool g_literal_expression_compare_rich(const GLiteralExpression *item, const GLiteralExpression *other, RichCmpOperation op, bool *status)
+static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression *expr, const GScanLiteralExpression *other, RichCmpOperation op, bool *status)
{
bool result; /* Etat à retourner */
int cmp; /* Bilan intermédiaire */
- result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_LITERAL_EXPRESSION);
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_LITERAL_EXPRESSION);
if (!result) goto done;
- if (item->value_type != other->value_type)
+ if (expr->value_type != other->value_type)
{
- *status = compare_rich_integer_values(item->value_type, other->value_type, op);
+ *status = compare_rich_integer_values_unsigned(expr->value_type, other->value_type, op);
goto done;
}
- switch (item->value_type)
+ switch (expr->value_type)
{
- case EVT_BOOLEAN:
+ case LVT_BOOLEAN:
switch (op)
{
case RCO_EQ:
- *status = (item->value.boolean == other->value.boolean);
+ *status = (expr->value.boolean == other->value.boolean);
result = true;
break;
case RCO_NE:
- *status = (item->value.boolean != other->value.boolean);
+ *status = (expr->value.boolean != other->value.boolean);
result = true;
break;
@@ -477,20 +532,25 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co
};
break;
- case EVT_INTEGER:
- *status = compare_rich_integer_values(item->value.integer, other->value.integer, op);
+ case LVT_SIGNED_INTEGER:
+ *status = compare_rich_integer_values_signed(expr->value.s_integer, other->value.s_integer, op);
result = true;
break;
- case EVT_STRING:
- cmp = szstrcmp(&item->value.string, &other->value.string);
- *status = compare_rich_integer_values(cmp, 0, op);
+ case LVT_UNSIGNED_INTEGER:
+ *status = compare_rich_integer_values_unsigned(expr->value.u_integer, other->value.u_integer, op);
result = true;
break;
- case EVT_REG_EXPR:
- cmp = strcmp(item->value.regex, other->value.regex);
- *status = compare_rich_integer_values(cmp, 0, op);
+ case LVT_STRING:
+ cmp = szstrcmp(&expr->value.string, &other->value.string);
+ *status = compare_rich_integer_values_signed(cmp, 0, op);
+ result = true;
+ break;
+
+ case LVT_REG_EXPR:
+ cmp = strcmp(expr->value.regex, other->value.regex);
+ *status = compare_rich_integer_values_signed(cmp, 0, op);
result = true;
break;
@@ -509,62 +569,63 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co
/******************************************************************************
* *
-* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
-* src = expression source à copier. *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
-* Description : Reproduit une expression en place dans une nouvelle instance.*
+* Description : Réduit une expression à une forme booléenne. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_literal_expression_copy(GLiteralExpression *dest, const GLiteralExpression *src)
+static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- GScanExpressionClass *class; /* Classe parente à solliciter */
-
- class = G_SCAN_EXPRESSION_CLASS(g_literal_expression_parent_class);
-
- class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
- dest->value_type = src->value_type;
+ bool result; /* Bilan à retourner */
- switch (src->value_type)
+ switch (expr->value_type)
{
- case EVT_BOOLEAN:
- dest->value.boolean = src->value.boolean;
+ case LVT_BOOLEAN:
+ *out = G_SCAN_EXPRESSION(expr);
+ g_object_ref(G_OBJECT(expr));
+ result = true;
break;
- case EVT_INTEGER:
- dest->value.integer = src->value.integer;
+ case LVT_SIGNED_INTEGER:
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.s_integer != 0 });
+ result = true;
break;
- case EVT_STRING:
- szstrdup(&dest->value.string, &src->value.string);
+ case LVT_UNSIGNED_INTEGER:
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.u_integer != 0 });
+ result = true;
break;
- case EVT_REG_EXPR:
- /*ptr = &expr->value.regex*//* FIXME */;
+ case LVT_STRING:
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.string.len > 0 });
+ result = true;
break;
default:
- assert(false);
+ result = false;
break;
}
+ return result;
+
}
/******************************************************************************
* *
* Paramètres : expr = expression à consulter. *
-* ctx = contexte de suivi de l'analyse courante. *
-* scope = portée courante des variables locales. *
-* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* count = quantité d'éléments déterminée. [OUT] *
* *
-* Description : Réduit une expression à une forme plus simple. *
+* Description : Dénombre les éléments portés par une expression. *
* *
* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
@@ -572,14 +633,22 @@ static void g_literal_expression_copy(GLiteralExpression *dest, const GLiteralEx
* *
******************************************************************************/
-static bool g_literal_expression_reduce(GLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static bool g_scan_literal_expression_count(const GScanLiteralExpression *expr, size_t *count)
{
bool result; /* Bilan à retourner */
- result = true;
+ switch (expr->value_type)
+ {
+ case LVT_STRING:
+ *count = expr->value.string.len;
+ result = true;
+ break;
+
+ default:
+ result = false;
+ break;
- *out = G_SCAN_EXPRESSION(expr);
- g_object_ref(G_OBJECT(expr));
+ }
return result;
diff --git a/src/analysis/scan/exprs/literal.h b/src/analysis/scan/exprs/literal.h
index 7120c07..9352baf 100644
--- a/src/analysis/scan/exprs/literal.h
+++ b/src/analysis/scan/exprs/literal.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* literal.h - prototypes pour la représentation d'une valeur concrète
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,6 +26,7 @@
#include <regex.h>
+#include <stdbool.h>
#include "../expr.h"
@@ -33,38 +34,56 @@
-#define G_TYPE_LITERAL_EXPRESSION g_literal_expression_get_type()
-#define G_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpression))
-#define G_IS_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LITERAL_EXPRESSION))
-#define G_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass))
-#define G_IS_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LITERAL_EXPRESSION))
-#define G_LITERAL_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass))
+#define G_TYPE_SCAN_LITERAL_EXPRESSION g_scan_literal_expression_get_type()
+#define G_SCAN_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpression))
+#define G_IS_SCAN_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_LITERAL_EXPRESSION))
+#define G_SCAN_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpressionClass))
+#define G_IS_SCAN_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_LITERAL_EXPRESSION))
+#define G_SCAN_LITERAL_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpressionClass))
/* Expression portant une valeur concrète (instance) */
-typedef struct _GLiteralExpression GLiteralExpression;
+typedef struct _GScanLiteralExpression GScanLiteralExpression;
/* Expression portant une valeur concrète (classe) */
-typedef struct _GLiteralExpressionClass GLiteralExpressionClass;
+typedef struct _GScanLiteralExpressionClass GScanLiteralExpressionClass;
+
+
+/* Types naturel équivalant à l'expression */
+typedef enum _LiteralValueType
+{
+ LVT_BOOLEAN, /* Valeur booléenne */
+ LVT_SIGNED_INTEGER, /* Nombre entier 64 bits #1 */
+ LVT_UNSIGNED_INTEGER, /* Nombre entier 64 bits #2 */
+ LVT_STRING, /* Chaîne de caractères */
+ LVT_REG_EXPR, /* Expression rationnelle */
+
+} LiteralValueType;
/* Indique le type défini pour un appel de fonction enregistrée. */
-GType g_literal_expression_get_type(void);
+GType g_scan_literal_expression_get_type(void);
/* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_literal_expression_new(ExprValueType, ...);
+GScanExpression *g_scan_literal_expression_new(LiteralValueType, ...);
+
+/* Indique le type de valeur portée par une expression. */
+LiteralValueType g_scan_literal_expression_get_value_type(const GScanLiteralExpression *);
/* Indique la valeur portée par une expression booléenne. */
-bool g_literal_expression_get_boolean_value(const GLiteralExpression *, bool *);
+bool g_scan_literal_expression_get_boolean_value(const GScanLiteralExpression *, bool *);
+
+/* Indique la valeur portée par une expression d'entier. */
+bool g_scan_literal_expression_get_signed_integer_value(const GScanLiteralExpression *, long long *);
/* Indique la valeur portée par une expression d'entier. */
-bool g_literal_expression_get_integer_value(const GLiteralExpression *, unsigned long long *);
+bool g_scan_literal_expression_get_unsigned_integer_value(const GScanLiteralExpression *, unsigned long long *);
/* Indique la valeur portée par une expression de chaîne. */
-bool g_literal_expression_get_string_value(const GLiteralExpression *, const sized_string_t **);
+bool g_scan_literal_expression_get_string_value(const GScanLiteralExpression *, const sized_string_t **);
/* Indique la valeur portée par une expression rationnelle. */
-bool g_literal_expression_get_regex_value(const GLiteralExpression *, const regex_t **);
+bool g_scan_literal_expression_get_regex_value(const GScanLiteralExpression *, const regex_t **);
diff --git a/src/analysis/scan/exprs/boolop-int.h b/src/analysis/scan/exprs/logical-int.h
index c381cfe..6df55d0 100644
--- a/src/analysis/scan/exprs/boolop-int.h
+++ b/src/analysis/scan/exprs/logical-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * boolop-int.h - prototypes internes pour la gestion des opérations booléennes
+ * logical-int.h - prototypes internes pour la gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,11 +21,11 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H
-#define _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H
+#ifndef _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H
-#include "boolop.h"
+#include "logical.h"
#include "../expr-int.h"
@@ -33,7 +33,7 @@
/* Opération booléenne avec un ou deux opérandes (instance) */
-struct _GBoolOperation
+struct _GScanLogicalOperation
{
GScanExpression parent; /* A laisser en premier */
@@ -45,7 +45,7 @@ struct _GBoolOperation
};
/* Opération booléenne avec un ou deux opérandes (classe) */
-struct _GBoolOperationClass
+struct _GScanLogicalOperationClass
{
GScanExpressionClass parent; /* A laisser en premier */
@@ -53,8 +53,8 @@ struct _GBoolOperationClass
/* Met en place une expression d'opération booléenne. */
-bool g_boolean_operation_create(GBoolOperation *, BooleanOperationType, GScanExpression *, GScanExpression *);
+bool g_scan_logical_operation_create(GScanLogicalOperation *, BooleanOperationType, GScanExpression *, GScanExpression *);
-#endif /* _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H */
diff --git a/src/analysis/scan/exprs/boolop.c b/src/analysis/scan/exprs/logical.c
index f6a80dd..4c82b1e 100644
--- a/src/analysis/scan/exprs/boolop.c
+++ b/src/analysis/scan/exprs/logical.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * boolop.c - gestion des opérations booléennes
+ * logical.c - gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,13 +21,13 @@
*/
-#include "boolop.h"
+#include "logical.h"
#include <assert.h>
-#include "boolop-int.h"
+#include "logical-int.h"
#include "literal.h"
@@ -36,16 +36,16 @@
/* Initialise la classe des opérations booléennes. */
-static void g_boolean_operation_class_init(GBoolOperationClass *);
+static void g_scan_logical_operation_class_init(GScanLogicalOperationClass *);
/* Initialise une instance d'opération booléenne. */
-static void g_boolean_operation_init(GBoolOperation *);
+static void g_scan_logical_operation_init(GScanLogicalOperation *);
/* Supprime toutes les références externes. */
-static void g_boolean_operation_dispose(GBoolOperation *);
+static void g_scan_logical_operation_dispose(GScanLogicalOperation *);
/* Procède à la libération totale de la mémoire. */
-static void g_boolean_operation_finalize(GBoolOperation *);
+static void g_scan_logical_operation_finalize(GScanLogicalOperation *);
@@ -53,13 +53,10 @@ static void g_boolean_operation_finalize(GBoolOperation *);
/* Réalise une comparaison entre objets selon un critère précis. */
-static bool g_boolean_operation_compare_rich(const GBoolOperation *, const GBoolOperation *, RichCmpOperation, bool *);
-
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_boolean_operation_copy(GBoolOperation *, const GBoolOperation *);
+static bool g_scan_logical_operation_compare_rich(const GScanLogicalOperation *, const GScanLogicalOperation *, RichCmpOperation, bool *);
/* Réduit une expression à une forme plus simple. */
-static bool g_boolean_operation_reduce(GBoolOperation *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_logical_operation_reduce(GScanLogicalOperation *, GScanContext *, GScanScope *, GScanExpression **);
@@ -69,7 +66,7 @@ static bool g_boolean_operation_reduce(GBoolOperation *, GScanContext *, GScanSc
/* Indique le type défini pour une opération booléenne sur expression(s). */
-G_DEFINE_TYPE(GBoolOperation, g_boolean_operation, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanLogicalOperation, g_scan_logical_operation, G_TYPE_SCAN_EXPRESSION);
/******************************************************************************
@@ -84,21 +81,20 @@ G_DEFINE_TYPE(GBoolOperation, g_boolean_operation, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_boolean_operation_class_init(GBoolOperationClass *klass)
+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_boolean_operation_dispose;
- object->finalize = (GObjectFinalizeFunc)g_boolean_operation_finalize;
+ 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_boolean_operation_compare_rich;
- expr->copy = (copy_expr_fc)g_boolean_operation_copy;
- expr->reduce = (reduce_expr_fc)g_boolean_operation_reduce;
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_logical_operation_compare_rich;
+ expr->reduce = (reduce_expr_fc)g_scan_logical_operation_reduce;
}
@@ -115,7 +111,7 @@ static void g_boolean_operation_class_init(GBoolOperationClass *klass)
* *
******************************************************************************/
-static void g_boolean_operation_init(GBoolOperation *op)
+static void g_scan_logical_operation_init(GScanLogicalOperation *op)
{
op->first = NULL;
op->second = NULL;
@@ -135,12 +131,12 @@ static void g_boolean_operation_init(GBoolOperation *op)
* *
******************************************************************************/
-static void g_boolean_operation_dispose(GBoolOperation *op)
+static void g_scan_logical_operation_dispose(GScanLogicalOperation *op)
{
g_clear_object(&op->first);
g_clear_object(&op->second);
- G_OBJECT_CLASS(g_boolean_operation_parent_class)->dispose(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_logical_operation_parent_class)->dispose(G_OBJECT(op));
}
@@ -157,9 +153,9 @@ static void g_boolean_operation_dispose(GBoolOperation *op)
* *
******************************************************************************/
-static void g_boolean_operation_finalize(GBoolOperation *op)
+static void g_scan_logical_operation_finalize(GScanLogicalOperation *op)
{
- G_OBJECT_CLASS(g_boolean_operation_parent_class)->finalize(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_logical_operation_parent_class)->finalize(G_OBJECT(op));
}
@@ -178,13 +174,13 @@ static void g_boolean_operation_finalize(GBoolOperation *op)
* *
******************************************************************************/
-GScanExpression *g_boolean_operation_new(BooleanOperationType type, GScanExpression *first, GScanExpression *second)
+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_boolean_operation_create(G_BOOLEAN_OPERATION(result), type, first, second))
+ if (!g_scan_logical_operation_create(G_SCAN_LOGICAL_OPERATION(result), type, first, second))
g_clear_object(&result);
return result;
@@ -207,21 +203,10 @@ GScanExpression *g_boolean_operation_new(BooleanOperationType type, GScanExpress
* *
******************************************************************************/
-bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second)
+bool g_scan_logical_operation_create(GScanLogicalOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second)
{
bool result; /* Bilan à retourner */
- result = false;
-
- if (g_scan_expression_get_value_type(first) != EVT_BOOLEAN)
- goto exit;
-
- if (g_scan_expression_get_value_type(second) != EVT_BOOLEAN)
- goto exit;
-
- if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN))
- goto exit;
-
op->type = type;
switch (type)
@@ -245,9 +230,11 @@ bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, G
assert(second != NULL);
break;
- }
+ default:
+ result = false;
+ break;
- exit:
+ }
return result;
@@ -275,7 +262,7 @@ bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, G
* *
******************************************************************************/
-static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const GBoolOperation *other, RichCmpOperation op, bool *status)
+static bool g_scan_logical_operation_compare_rich(const GScanLogicalOperation *item, const GScanLogicalOperation *other, RichCmpOperation op, bool *status)
{
bool result; /* Etat à retourner */
@@ -284,7 +271,7 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G
if (item->type != other->type)
{
- *status = compare_rich_integer_values(item->type, other->type, op);
+ *status = compare_rich_integer_values_unsigned(item->type, other->type, op);
goto done;
}
@@ -332,37 +319,6 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G
/******************************************************************************
* *
-* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
-* src = expression source à copier. *
-* *
-* Description : Reproduit une expression en place dans une nouvelle instance.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_boolean_operation_copy(GBoolOperation *dest, const GBoolOperation *src)
-{
- GScanExpressionClass *class; /* Classe parente à solliciter */
-
- class = G_SCAN_EXPRESSION_CLASS(g_boolean_operation_parent_class);
-
- class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
- dest->type = src->type;
-
- dest->first = g_scan_expression_duplicate(src->first);
-
- if (src->second != NULL)
- dest->second = g_scan_expression_duplicate(src->second);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
* scope = portée courante des variables locales. *
@@ -376,100 +332,173 @@ static void g_boolean_operation_copy(GBoolOperation *dest, const GBoolOperation
* *
******************************************************************************/
-static bool g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_logical_operation_reduce(GScanLogicalOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
+ 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 */
- new_first = NULL;
- new_second = NULL;
-
- result = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
- if (!result) goto exit;
+ state[0] = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
- if (expr->second == NULL)
- new_second = NULL;
+ if (expr->second != NULL)
+ state[1] = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
else
{
- result = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
- if (!result) goto exit;
+ new_second = NULL;
+ state[1] = SRS_REDUCED;
}
- /* Construction d'une réduction locale ? */
+ /* Récupération des valeurs booléennes */
- valid[0] = G_IS_LITERAL_EXPRESSION(new_first);
+ 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_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_first), &values[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;
- valid[1] = G_IS_LITERAL_EXPRESSION(new_second);
+ }
+ else
+ {
+ bool_operands[0] = NULL;
+ valid[0] = false;
+ }
- if (valid[1])
- valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_second), &values[1]);
+ 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_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[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_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false });
+ result = SRS_REDUCED;
+ }
else if (valid[1] && !values[1])
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
+ {
+ *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_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[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_literal_expression_new(EVT_BOOLEAN, (bool []) { true });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true });
+ result = SRS_REDUCED;
+ }
else if (valid[1] && values[1])
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true });
+ {
+ *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_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[0] });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { !values[0] });
+ result = SRS_REDUCED;
+ }
+
+ else
+ {
+ if (state[0] == SRS_UNRESOLVABLE)
+ result = SRS_UNRESOLVABLE;
+ else
+ {
+ assert(state[0] == SRS_WAIT_FOR_SCAN);
+ result = SRS_WAIT_FOR_SCAN;
+ }
+ }
+
break;
}
/* Mise à jour de la progression ? */
- if (*out == NULL)
+ if (result == SRS_WAIT_FOR_SCAN)
{
- if ((new_first != NULL && new_first != expr->first) || (new_second != NULL && new_second != expr->second))
+ if (new_first != expr->first || new_second != expr->second)
{
- if (new_first == NULL)
- {
- new_first = expr->first;
- g_object_ref(G_OBJECT(new_first));
- }
+ assert(new_first != NULL);
+ assert(new_second != NULL || expr->second == NULL);
- if (new_second == NULL)
- {
- new_second = expr->second;
- g_object_ref(G_OBJECT(new_second));
- }
-
- *out = g_boolean_operation_new(expr->type, new_first, new_second);
+ *out = g_scan_logical_operation_new(expr->type, new_first, new_second);
}
}
- exit:
+ /* Sortie propre */
+
+ g_clear_object(&bool_operands[0]);
+ g_clear_object(&bool_operands[1]);
g_clear_object(&new_first);
g_clear_object(&new_second);
diff --git a/src/analysis/scan/exprs/boolop.h b/src/analysis/scan/exprs/logical.h
index 4add5a1..e98bf11 100644
--- a/src/analysis/scan/exprs/boolop.h
+++ b/src/analysis/scan/exprs/logical.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * boolop.h - prototypes pour la gestion des opérations booléennes
+ * logical.h - prototypes pour la gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,27 +21,27 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_BOOLOP_H
-#define _ANALYSIS_SCAN_EXPRS_BOOLOP_H
+#ifndef _ANALYSIS_SCAN_EXPRS_LOGICAL_H
+#define _ANALYSIS_SCAN_EXPRS_LOGICAL_H
#include "../expr.h"
-#define G_TYPE_BOOLEAN_OPERATION g_boolean_operation_get_type()
-#define G_BOOLEAN_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperation))
+#define G_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_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass))
+#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_BOOLEAN_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass))
+#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 _GBoolOperation GBoolOperation;
+typedef struct _GScanLogicalOperation GScanLogicalOperation;
/* Opération booléenne avec un ou deux opérandes (classe) */
-typedef struct _GBoolOperationClass GBoolOperationClass;
+typedef struct _GScanLogicalOperationClass GScanLogicalOperationClass;
/* Types d'opérations booléennes supportées */
@@ -55,11 +55,11 @@ typedef enum _BooleanOperationType
/* Indique le type défini pour une opération booléenne sur expression(s). */
-GType g_boolean_operation_get_type(void);
+GType g_scan_logical_operation_get_type(void);
/* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_boolean_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *);
+GScanExpression *g_scan_logical_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *);
-#endif /* _ANALYSIS_SCAN_EXPRS_BOOLOP_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_LOGICAL_H */
diff --git a/src/analysis/scan/exprs/range-int.h b/src/analysis/scan/exprs/range-int.h
new file mode 100644
index 0000000..6257874
--- /dev/null
+++ b/src/analysis/scan/exprs/range-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range-int.h - prototypes internes pour la représentation compacte d'un éventail de valeurs
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_RANGE_INT_H
+#define _ANALYSIS_SCAN_EXPRS_RANGE_INT_H
+
+
+#include "range.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Représentation compacte d'un éventail de valeurs (instance) */
+struct _GScanCompactRange
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GScanExpression *start; /* Point de départ */
+ GScanExpression *end; /* Point d'arrivée */
+
+};
+
+/* Représentation compacte d'un éventail de valeurs (classe) */
+struct _GScanCompactRangeClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une réprésentation d'un éventail de valeurs. */
+bool g_scan_compact_range_create(GScanCompactRange *, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_RANGE_INT_H */
diff --git a/src/analysis/scan/exprs/range.c b/src/analysis/scan/exprs/range.c
new file mode 100644
index 0000000..f97b15e
--- /dev/null
+++ b/src/analysis/scan/exprs/range.c
@@ -0,0 +1,352 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range.c - représentation compacte d'un éventail de valeurs
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "range.h"
+
+
+#include "literal.h"
+#include "range-int.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des éventail de valeurs. */
+static void g_scan_compact_range_class_init(GScanCompactRangeClass *);
+
+/* Initialise une instance d'éventail de valeurs. */
+static void g_scan_compact_range_init(GScanCompactRange *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_compact_range_dispose(GScanCompactRange *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_compact_range_finalize(GScanCompactRange *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_compact_range_reduce(GScanCompactRange *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_compact_range_reduce_to_boolean(GScanCompactRange *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réalise l'intersection entre deux ensembles. */
+static GScanExpression *g_scan_compact_range_intersect(GScanCompactRange *expr, const GScanExpression *, GScanContext *, GScanScope *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une représentation compacte d'un éventail de valeurs. */
+G_DEFINE_TYPE(GScanCompactRange, g_scan_compact_range, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des éventail de valeurs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_class_init(GScanCompactRangeClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_compact_range_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_compact_range_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->reduce = (reduce_expr_fc)g_scan_compact_range_reduce;
+ expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_compact_range_reduce_to_boolean;
+ expr->intersect = (intersect_scan_expr_fc)g_scan_compact_range_intersect;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance à initialiser. *
+* *
+* Description : Initialise une instance d'éventail de valeurs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_init(GScanCompactRange *range)
+{
+ range->start = NULL;
+ range->end = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_dispose(GScanCompactRange *range)
+{
+ g_clear_object(&range->start);
+ g_clear_object(&range->end);
+
+ G_OBJECT_CLASS(g_scan_compact_range_parent_class)->dispose(G_OBJECT(range));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_finalize(GScanCompactRange *range)
+{
+ G_OBJECT_CLASS(g_scan_compact_range_parent_class)->finalize(G_OBJECT(range));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : start = point de départ de la plage de valeurs. *
+* end = point d'arrivée de la plage de valeurs. *
+* *
+* Description : Organise une réprésentation d'un éventail de valeurs. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_compact_range_new(GScanExpression *start, GScanExpression *end)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_COMPACT_RANGE, NULL);
+
+ if (!g_scan_compact_range_create(G_SCAN_COMPACT_RANGE(result), start, end))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance à initialiser pleinement. *
+* start = point de départ de la plage de valeurs. *
+* end = point d'arrivée de la plage de valeurs. *
+* *
+* Description : Met en place une réprésentation d'un éventail de valeurs. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_compact_range_create(GScanCompactRange *range, GScanExpression *start, GScanExpression *end)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ range->start = start;
+ g_object_ref(G_OBJECT(start));
+
+ range->end = end;
+ g_object_ref(G_OBJECT(end));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_compact_range_reduce(GScanCompactRange *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_start; /* Nouvelle réduction #1 */
+ GScanExpression *new_end; /* Nouvelle réduction #2 */
+ ScanReductionState state_start; /* Etat synthétisé #1 */
+ ScanReductionState state_end; /* Etat synthétisé #2 */
+
+ new_start = NULL;
+ new_end = NULL;
+
+ state_start = g_scan_expression_reduce(expr->start, ctx, scope, &new_start);
+ if (state_start == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_end = g_scan_expression_reduce(expr->end, ctx, scope, &new_end);
+ if (state_end == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (state_start == SRS_WAIT_FOR_SCAN || state_end == SRS_WAIT_FOR_SCAN)
+ result = SRS_WAIT_FOR_SCAN;
+ else
+ result = SRS_REDUCED;
+
+ if (new_start != expr->start || new_end != expr->end)
+ *out = g_scan_compact_range_new(new_start, new_end);
+
+ exit:
+
+ g_clear_object(&new_start);
+ g_clear_object(&new_end);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme booléenne. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_compact_range_reduce_to_boolean(GScanCompactRange *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ bool status; /* Bilan d'une comparaison */
+
+ result = G_IS_SCAN_LITERAL_EXPRESSION(expr->start) && G_IS_SCAN_LITERAL_EXPRESSION(expr->end);
+ if (!result) goto exit;
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(expr->start),
+ G_COMPARABLE_ITEM(expr->end),
+ RCO_LE, &status);
+ if (!result) goto exit;
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à filtrer. *
+* other = expression utilisée pour le filtrage. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* *
+* Description : Réalise l'intersection entre deux ensembles. *
+* *
+* Retour : Intersection entre les deux ensembles ou NULL en cas d'échec.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_scan_compact_range_intersect(GScanCompactRange *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope)
+{
+ GScanExpression *result; /* Instance à retourner */
+
+
+
+
+ result = true; // TODO
+
+
+
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/range.h b/src/analysis/scan/exprs/range.h
new file mode 100644
index 0000000..4b7ad04
--- /dev/null
+++ b/src/analysis/scan/exprs/range.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range.h - prototypes pour la représentation compacte d'un éventail de valeurs
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_SET_H
+#define _ANALYSIS_SCAN_EXPRS_SET_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_COMPACT_RANGE g_scan_compact_range_get_type()
+#define G_SCAN_COMPACT_RANGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRange))
+#define G_IS_SCAN_COMPACT_RANGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_COMPACT_RANGE))
+#define G_SCAN_COMPACT_RANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRangeClass))
+#define G_IS_SCAN_COMPACT_RANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_COMPACT_RANGE))
+#define G_SCAN_COMPACT_RANGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRangeClass))
+
+
+/* Représentation compacte d'un éventail de valeurs (instance) */
+typedef struct _GScanCompactRange GScanCompactRange;
+
+/* Représentation compacte d'un éventail de valeurs (classe) */
+typedef struct _GScanCompactRangeClass GScanCompactRangeClass;
+
+
+/* Indique le type défini pour une représentation compacte d'un éventail de valeurs. */
+GType g_scan_compact_range_get_type(void);
+
+/* Organise une réprésentation d'un éventail de valeurs. */
+GScanExpression *g_scan_compact_range_new(GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SET_H */
diff --git a/src/analysis/scan/exprs/relop-int.h b/src/analysis/scan/exprs/relational-int.h
index 3adbcf0..813b89d 100644
--- a/src/analysis/scan/exprs/relop-int.h
+++ b/src/analysis/scan/exprs/relational-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * relop-int.h - prototypes internes pour la gestion des opérations relationnelles
+ * relational-int.h - prototypes internes pour la gestion des opérations relationnelles
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,11 +21,11 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_RELOP_INT_H
-#define _ANALYSIS_SCAN_EXPRS_RELOP_INT_H
+#ifndef _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H
-#include "relop.h"
+#include "relational.h"
#include "../expr-int.h"
@@ -33,7 +33,7 @@
/* Opération relationnelle impliquant deux opérandes (instance) */
-struct _GRelOperation
+struct _GScanRelationalOperation
{
GScanExpression parent; /* A laisser en premier */
@@ -45,7 +45,7 @@ struct _GRelOperation
};
/* Opération relationnelle impliquant deux opérandes (classe) */
-struct _GRelOperationClass
+struct _GScanRelationalOperationClass
{
GScanExpressionClass parent; /* A laisser en premier */
@@ -53,8 +53,8 @@ struct _GRelOperationClass
/* Met en place une opération relationnelle entre expressions. */
-bool g_relational_operation_create(GRelOperation *, RichCmpOperation, GScanExpression *, GScanExpression *);
+bool g_scan_relational_operation_create(GScanRelationalOperation *, RichCmpOperation, GScanExpression *, GScanExpression *);
-#endif /* _ANALYSIS_SCAN_EXPRS_RELOP_INT_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H */
diff --git a/src/analysis/scan/exprs/relop.c b/src/analysis/scan/exprs/relational.c
index 7dc6864..b56b599 100644
--- a/src/analysis/scan/exprs/relop.c
+++ b/src/analysis/scan/exprs/relational.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * relop.c - gestion des opérations relationnelles
+ * relational.c - gestion des opérations relationnelles
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,10 +21,13 @@
*/
-#include "relop.h"
+#include "relational.h"
-#include "relop-int.h"
+#include <assert.h>
+
+
+#include "relational-int.h"
#include "literal.h"
@@ -33,16 +36,16 @@
/* Initialise la classe des opérations de relations. */
-static void g_relational_operation_class_init(GRelOperationClass *);
+static void g_scan_relational_operation_class_init(GScanRelationalOperationClass *);
/* Initialise une instance d'opération de relation. */
-static void g_relational_operation_init(GRelOperation *);
+static void g_scan_relational_operation_init(GScanRelationalOperation *);
/* Supprime toutes les références externes. */
-static void g_relational_operation_dispose(GRelOperation *);
+static void g_scan_relational_operation_dispose(GScanRelationalOperation *);
/* Procède à la libération totale de la mémoire. */
-static void g_relational_operation_finalize(GRelOperation *);
+static void g_scan_relational_operation_finalize(GScanRelationalOperation *);
@@ -50,13 +53,10 @@ static void g_relational_operation_finalize(GRelOperation *);
/* Réalise une comparaison entre objets selon un critère précis. */
-static bool g_relational_operation_compare_rich(const GRelOperation *, const GRelOperation *, RichCmpOperation, bool *);
-
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_relational_operation_copy(GRelOperation *, const GRelOperation *);
+static bool g_scan_relational_operation_compare_rich(const GScanRelationalOperation *, const GScanRelationalOperation *, RichCmpOperation, bool *);
/* Réduit une expression à une forme plus simple. */
-static bool g_relational_operation_reduce(GRelOperation *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_relational_operation_reduce(GScanRelationalOperation *, GScanContext *, GScanScope *, GScanExpression **);
@@ -66,7 +66,7 @@ static bool g_relational_operation_reduce(GRelOperation *, GScanContext *, GScan
/* Indique le type défini pour une opération de relation entre expressions. */
-G_DEFINE_TYPE(GRelOperation, g_relational_operation, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanRelationalOperation, g_scan_relational_operation, G_TYPE_SCAN_EXPRESSION);
/******************************************************************************
@@ -81,21 +81,20 @@ G_DEFINE_TYPE(GRelOperation, g_relational_operation, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_relational_operation_class_init(GRelOperationClass *klass)
+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_relational_operation_dispose;
- object->finalize = (GObjectFinalizeFunc)g_relational_operation_finalize;
+ 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_relational_operation_compare_rich;
- expr->copy = (copy_expr_fc)g_relational_operation_copy;
- expr->reduce = (reduce_expr_fc)g_relational_operation_reduce;
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_relational_operation_compare_rich;
+ expr->reduce = (reduce_expr_fc)g_scan_relational_operation_reduce;
}
@@ -112,7 +111,7 @@ static void g_relational_operation_class_init(GRelOperationClass *klass)
* *
******************************************************************************/
-static void g_relational_operation_init(GRelOperation *op)
+static void g_scan_relational_operation_init(GScanRelationalOperation *op)
{
op->left = NULL;
op->right = NULL;
@@ -132,12 +131,12 @@ static void g_relational_operation_init(GRelOperation *op)
* *
******************************************************************************/
-static void g_relational_operation_dispose(GRelOperation *op)
+static void g_scan_relational_operation_dispose(GScanRelationalOperation *op)
{
g_clear_object(&op->left);
g_clear_object(&op->right);
- G_OBJECT_CLASS(g_relational_operation_parent_class)->dispose(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_relational_operation_parent_class)->dispose(G_OBJECT(op));
}
@@ -154,9 +153,9 @@ static void g_relational_operation_dispose(GRelOperation *op)
* *
******************************************************************************/
-static void g_relational_operation_finalize(GRelOperation *op)
+static void g_scan_relational_operation_finalize(GScanRelationalOperation *op)
{
- G_OBJECT_CLASS(g_relational_operation_parent_class)->finalize(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_relational_operation_parent_class)->finalize(G_OBJECT(op));
}
@@ -175,13 +174,13 @@ static void g_relational_operation_finalize(GRelOperation *op)
* *
******************************************************************************/
-GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right)
+GScanExpression *g_scan_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right)
{
GScanExpression *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_RELATIONAL_OPERATION, NULL);
+ result = g_object_new(G_TYPE_SCAN_RELATIONAL_OPERATION, NULL);
- if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, left, right))
+ if (!g_scan_relational_operation_create(G_SCAN_RELATIONAL_OPERATION(result), type, left, right))
g_clear_object(&result);
return result;
@@ -204,17 +203,11 @@ GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpressi
* *
******************************************************************************/
-bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right)
+bool g_scan_relational_operation_create(GScanRelationalOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right)
{
bool result; /* Bilan à retourner */
- result = false;
-
- if (g_scan_expression_get_value_type(left) != g_scan_expression_get_value_type(left))
- goto exit;
-
- if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN))
- goto exit;
+ result = true;
op->rel_type = type;
@@ -224,10 +217,6 @@ bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GSc
op->right = right;
g_object_ref(G_OBJECT(op->right));
- result = true;
-
- exit:
-
return result;
}
@@ -254,16 +243,16 @@ bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GSc
* *
******************************************************************************/
-static bool g_relational_operation_compare_rich(const GRelOperation *item, const GRelOperation *other, RichCmpOperation op, bool *status)
+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_RELATIONAL_OPERATION);
+ 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(item->rel_type, other->rel_type, op);
+ *status = compare_rich_integer_values_unsigned(item->rel_type, other->rel_type, op);
goto done;
}
@@ -288,35 +277,6 @@ static bool g_relational_operation_compare_rich(const GRelOperation *item, const
/******************************************************************************
* *
-* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
-* src = expression source à copier. *
-* *
-* Description : Reproduit une expression en place dans une nouvelle instance.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_relational_operation_copy(GRelOperation *dest, const GRelOperation *src)
-{
- GScanExpressionClass *class; /* Classe parente à solliciter */
-
- class = G_SCAN_EXPRESSION_CLASS(g_relational_operation_parent_class);
-
- class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
- dest->rel_type = src->rel_type;
-
- dest->left = g_scan_expression_duplicate(src->left);
- dest->right = g_scan_expression_duplicate(src->right);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
* scope = portée courante des variables locales. *
@@ -330,11 +290,16 @@ static void g_relational_operation_copy(GRelOperation *dest, const GRelOperation
* *
******************************************************************************/
-static bool g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_relational_operation_reduce(GScanRelationalOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
+ ScanReductionState result; /* Etat synthétisé à retourner */
GScanExpression *new_left; /* Expression réduite (gauche) */
GScanExpression *new_right; /* Expression réduite (droite) */
+ 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 */
@@ -343,45 +308,96 @@ static bool g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx
new_left = NULL;
new_right = NULL;
- result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
- if (!result) goto exit;
+ state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (state_left == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ 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));
- result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
- if (!result) goto exit;
+ 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_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
{
valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(new_left),
G_COMPARABLE_ITEM(new_right),
expr->rel_type, &status);
if (valid)
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { status });
+ result = SRS_REDUCED;
+ }
+ else
+ result = SRS_UNRESOLVABLE;
}
/* Mise à jour de la progression ? */
- else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
+ else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
{
- if (new_left == NULL)
- {
- new_left = expr->left;
- g_object_ref(G_OBJECT(new_left));
- }
+ if (new_left != expr->left || new_right != expr->right)
+ *out = g_scan_relational_operation_new(expr->rel_type, new_left, new_right);
- if (new_right == NULL)
- {
- new_right = expr->right;
- g_object_ref(G_OBJECT(new_right));
- }
+ result = SRS_WAIT_FOR_SCAN;
- *out = g_relational_operation_new(expr->rel_type, new_left, new_right);
+ }
+
+ /* Cas des situations où les expressions ne sont pas exploitables (!) */
+ else
+ {
+ assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+ result = SRS_UNRESOLVABLE;
}
+ /* Sortie propre */
+
exit:
g_clear_object(&new_left);
diff --git a/src/analysis/scan/exprs/relational.h b/src/analysis/scan/exprs/relational.h
new file mode 100644
index 0000000..10d58a6
--- /dev/null
+++ b/src/analysis/scan/exprs/relational.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relational.h - prototypes pour la gestion des opérations relationnelles
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_RELATIONAL_H
+#define _ANALYSIS_SCAN_EXPRS_RELATIONAL_H
+
+
+#include "../expr.h"
+#include "../../../glibext/comparison.h"
+
+
+
+#define G_TYPE_SCAN_RELATIONAL_OPERATION g_scan_relational_operation_get_type()
+#define G_SCAN_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperation))
+#define G_IS_SCAN_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_RELATIONAL_OPERATION))
+#define G_SCAN_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperationClass))
+#define G_IS_SCAN_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_RELATIONAL_OPERATION))
+#define G_SCAN_RELATIONAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperationClass))
+
+
+/* Opération relationnelle impliquant deux opérandes (instance) */
+typedef struct _GScanRelationalOperation GScanRelationalOperation;
+
+/* Opération relationnelle impliquant deux opérandes (classe) */
+typedef struct _GScanRelationalOperationClass GScanRelationalOperationClass;
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+GType g_scan_relational_operation_get_type(void);
+
+/* Organise une opération relationnelle entre expressions. */
+GScanExpression *g_scan_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_RELATIONAL_H */
diff --git a/src/analysis/scan/exprs/relop.h b/src/analysis/scan/exprs/relop.h
deleted file mode 100644
index ecbc8ef..0000000
--- a/src/analysis/scan/exprs/relop.h
+++ /dev/null
@@ -1,56 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * relop.h - prototypes pour la gestion des opérations relationnelles
- *
- * Copyright (C) 2022 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _ANALYSIS_SCAN_EXPRS_RELOP_H
-#define _ANALYSIS_SCAN_EXPRS_RELOP_H
-
-
-#include "../expr.h"
-#include "../../../glibext/comparison.h"
-
-
-
-#define G_TYPE_RELATIONAL_OPERATION g_relational_operation_get_type()
-#define G_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperation))
-#define G_IS_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RELATIONAL_OPERATION))
-#define G_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass))
-#define G_IS_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RELATIONAL_OPERATION))
-#define G_RELATIONAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass))
-
-
-/* Opération relationnelle impliquant deux opérandes (instance) */
-typedef struct _GRelOperation GRelOperation;
-
-/* Opération relationnelle impliquant deux opérandes (classe) */
-typedef struct _GRelOperationClass GRelOperationClass;
-
-
-/* Indique le type défini pour une opération de relation entre expressions. */
-GType g_relational_operation_get_type(void);
-
-/* Organise une opération relationnelle entre expressions. */
-GScanExpression *g_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *);
-
-
-
-#endif /* _ANALYSIS_SCAN_EXPRS_RELOP_H */
diff --git a/src/analysis/scan/exprs/set-int.h b/src/analysis/scan/exprs/set-int.h
new file mode 100644
index 0000000..ebb4380
--- /dev/null
+++ b/src/analysis/scan/exprs/set-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * set-int.h - prototypes internes pour la base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_SET_INT_H
+#define _ANALYSIS_SCAN_EXPRS_SET_INT_H
+
+
+#include "set.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (instance) */
+struct _GScanGenericSet
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GScanExpression **items; /* Liste d'éléments embarqués */
+ size_t count; /* Quantité de ces éléments */
+
+};
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (classe) */
+struct _GScanGenericSetClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SET_INT_H */
diff --git a/src/analysis/scan/exprs/arithmop.c b/src/analysis/scan/exprs/set.c
index 5f9e3f1..0a93ced 100644
--- a/src/analysis/scan/exprs/arithmop.c
+++ b/src/analysis/scan/exprs/set.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * arithmop.c - gestion des opérations arithmétiques
+ * set.c - base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,42 +21,49 @@
*/
-#include "arithmop.h"
+#include "set.h"
+
+
+#include <assert.h>
+#include <malloc.h>
-#include "arithmop-int.h"
#include "literal.h"
+#include "set-int.h"
/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
-/* Initialise la classe des opérations arithmétiques. */
-static void g_arithmetic_operation_class_init(GArithmOperationClass *);
+/* Initialise la classe des bases d'ensembles d'éléments. */
+static void g_scan_generic_set_class_init(GScanGenericSetClass *);
-/* Initialise une instance d'opération arithmétique. */
-static void g_arithmetic_operation_init(GArithmOperation *);
+/* 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_arithmetic_operation_dispose(GArithmOperation *);
+static void g_scan_generic_set_dispose(GScanGenericSet *);
/* Procède à la libération totale de la mémoire. */
-static void g_arithmetic_operation_finalize(GArithmOperation *);
+static void g_scan_generic_set_finalize(GScanGenericSet *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Réalise une comparaison entre objets selon un critère précis. */
-static bool g_arithmetic_operation_compare_rich(const GArithmOperation *, const GArithmOperation *, RichCmpOperation, bool *);
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_generic_set_reduce(GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **);
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_arithmetic_operation_copy(GArithmOperation *, const GArithmOperation *);
+/* Dénombre les éléments portés par une expression. */
+static bool g_scan_generic_set_count_items(const GScanGenericSet *, size_t *);
-/* Réduit une expression à une forme plus simple. */
-static bool g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, GScanScope *, GScanExpression **);
+/* Fournit un élément donné issu d'un ensemble constitué. */
+static bool g_scan_generic_set_get_item(const GScanGenericSet *, size_t, GScanExpression **);
@@ -65,15 +72,15 @@ static bool g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, GS
/* ---------------------------------------------------------------------------------- */
-/* Indique le type défini pour une opération de relation entre expressions. */
-G_DEFINE_TYPE(GArithmOperation, g_arithmetic_operation, G_TYPE_SCAN_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 opérations arithmétiques. *
+* Description : Initialise la classe des bases d'ensembles d'éléments. *
* *
* Retour : - *
* *
@@ -81,30 +88,31 @@ G_DEFINE_TYPE(GArithmOperation, g_arithmetic_operation, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_arithmetic_operation_class_init(GArithmOperationClass *klass)
+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_arithmetic_operation_dispose;
- object->finalize = (GObjectFinalizeFunc)g_arithmetic_operation_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_generic_set_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_generic_set_finalize;
expr = G_SCAN_EXPRESSION_CLASS(klass);
- expr->cmp_rich = (compare_expr_rich_fc)g_arithmetic_operation_compare_rich;
- expr->copy = (copy_expr_fc)g_arithmetic_operation_copy;
- expr->reduce = (reduce_expr_fc)g_arithmetic_operation_reduce;
+ 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 : op = instance à initialiser. *
+* Paramètres : set = instance à initialiser. *
* *
-* Description : Initialise une instance d'opération arithmétique. *
+* Description : Initialise une instance de base d'ensemble d'éléments. *
* *
* Retour : - *
* *
@@ -112,17 +120,17 @@ static void g_arithmetic_operation_class_init(GArithmOperationClass *klass)
* *
******************************************************************************/
-static void g_arithmetic_operation_init(GArithmOperation *op)
+static void g_scan_generic_set_init(GScanGenericSet *set)
{
- op->left = NULL;
- op->right = NULL;
+ set->items = NULL;
+ set->count = 0;
}
/******************************************************************************
* *
-* Paramètres : op = instance d'objet GLib à traiter. *
+* Paramètres : set = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -132,19 +140,21 @@ static void g_arithmetic_operation_init(GArithmOperation *op)
* *
******************************************************************************/
-static void g_arithmetic_operation_dispose(GArithmOperation *op)
+static void g_scan_generic_set_dispose(GScanGenericSet *set)
{
- g_clear_object(&op->left);
- g_clear_object(&op->right);
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < set->count; i++)
+ g_clear_object(&set->items[i]);
- G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->dispose(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_generic_set_parent_class)->dispose(G_OBJECT(set));
}
/******************************************************************************
* *
-* Paramètres : op = instance d'objet GLib à traiter. *
+* Paramètres : set = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -154,35 +164,33 @@ static void g_arithmetic_operation_dispose(GArithmOperation *op)
* *
******************************************************************************/
-static void g_arithmetic_operation_finalize(GArithmOperation *op)
+static void g_scan_generic_set_finalize(GScanGenericSet *set)
{
- G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->finalize(G_OBJECT(op));
+ if (set->items != NULL)
+ free(set->items);
+
+ G_OBJECT_CLASS(g_scan_generic_set_parent_class)->finalize(G_OBJECT(set));
}
/******************************************************************************
* *
-* Paramètres : operator = type d'opération arithmétique à représenter. *
-* left = premier opérande concerné. *
-* right = éventuel second opérande impliqué ou NULL. *
+* Paramètres : - *
* *
-* Description : Organise une opération arithmétique entre expressions. *
+* Description : Met en place un ensemble d'éléments homogènes ou hétérogènes.*
* *
-* Retour : Fonction mise en place. *
+* Retour : Expression mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+GScanExpression *g_scan_generic_set_new(void)
{
GScanExpression *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_ARITHMETIC_OPERATION, NULL);
-
- if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, left, right))
- g_clear_object(&result);
+ result = g_object_new(G_TYPE_SCAN_GENERIC_SET, NULL);
return result;
@@ -191,52 +199,23 @@ GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operato
/******************************************************************************
* *
-* 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. *
+* Paramètres : set = ensemble à compléter. *
+* item = nouvel élément à intégrer. *
* *
-* Description : Met en place une opération arithmétique entre expressions. *
+* Description : Ajoute un nouvel élément à un ensemble. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+void g_scan_generic_set_add_item(GScanGenericSet *set, GScanExpression *item)
{
- bool result; /* Bilan à retourner */
- ExprValueType vtype; /* Type de valeur portée */
-
- result = false;
-
- vtype = g_scan_expression_get_value_type(left);
+ set->items = realloc(set->items, ++set->count * sizeof(GScanExpression *));
- if (vtype != EVT_INTEGER && vtype != EVT_PENDING)
- goto exit;
-
- vtype = g_scan_expression_get_value_type(right);
-
- if (vtype != EVT_INTEGER && vtype != EVT_PENDING)
- goto exit;
-
- if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_INTEGER))
- goto exit;
-
- op->operator = operator;
-
- op->left = left;
- g_object_ref(G_OBJECT(op->left));
-
- op->right = right;
- g_object_ref(G_OBJECT(op->right));
-
- result = true;
-
- exit:
-
- return result;
+ set->items[set->count - 1] = item;
+ g_object_ref(G_OBJECT(item));
}
@@ -249,45 +228,69 @@ bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOpe
/******************************************************************************
* *
-* 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] *
+* 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éalise une comparaison entre objets selon un critère précis.*
+* Description : Réduit une expression à une forme plus simple. *
* *
-* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, const GArithmOperation *other, RichCmpOperation op, bool *status)
+static ScanReductionState g_scan_generic_set_reduce(GScanGenericSet *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Etat à retourner */
+ 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 = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_ARITHMETIC_OPERATION);
- if (!result) goto done;
+ result = SRS_REDUCED;
- if (item->operator != other->operator)
+ for (i = 0; i < expr->count; i++)
{
- result = compare_rich_integer_values(item->operator, other->operator, op);
- goto done;
- }
+ item = expr->items[i];
- 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;
+ 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;
- 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;
+ 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]);
- result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
- G_COMPARABLE_ITEM(other->right),
- op, status);
+ }
- done:
+ 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;
@@ -296,29 +299,28 @@ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, co
/******************************************************************************
* *
-* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
-* src = expression source à copier. *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
-* Description : Reproduit une expression en place dans une nouvelle instance.*
+* Description : Réduit une expression à une forme booléenne. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOperation *src)
+static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- GScanExpressionClass *class; /* Classe parente à solliciter */
-
- class = G_SCAN_EXPRESSION_CLASS(g_arithmetic_operation_parent_class);
+ bool result; /* Bilan à retourner */
- class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+ result = true;
- dest->operator = src->operator;
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->count > 0 });
- dest->left = g_scan_expression_duplicate(src->left);
- dest->right = g_scan_expression_duplicate(src->right);
+ return result;
}
@@ -326,11 +328,9 @@ static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOpe
/******************************************************************************
* *
* Paramètres : expr = expression à consulter. *
-* ctx = contexte de suivi de l'analyse courante. *
-* scope = portée courante des variables locales. *
-* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* count = quantité d'éléments déterminée. [OUT] *
* *
-* Description : Réduit une expression à une forme plus simple. *
+* Description : Dénombre les éléments portés par une expression. *
* *
* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
@@ -338,98 +338,41 @@ static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOpe
* *
******************************************************************************/
-static bool g_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, size_t *count)
{
bool result; /* Bilan à retourner */
- GScanExpression *new_left; /* Expression réduite (gauche) */
- GScanExpression *new_right; /* Expression réduite (droite) */
- GLiteralExpression *op_left; /* Opérande gauche final */
- GLiteralExpression *op_right; /* Opérande droite final */
- unsigned long long val_1; /* Première valeur à traiter */
- unsigned long long val_2; /* Seconde valeur à traiter */
- unsigned long long reduced; /* Valeur réduite finale */
-
- /* Réduction des éléments considérés */
-
- new_left = NULL;
- new_right = NULL;
-
- result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
- if (!result) goto exit;
-
- result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
- if (!result) goto exit;
-
- /* Construction d'une réduction locale ? */
-
- if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
- {
- op_left = G_LITERAL_EXPRESSION(new_left);
- op_right = G_LITERAL_EXPRESSION(new_right);
-
- result = g_literal_expression_get_integer_value(op_left, &val_1);
- if (!result) goto exit;
-
- result = g_literal_expression_get_integer_value(op_right, &val_2);
- if (!result) goto exit;
-
- switch (expr->operator)
- {
- case AEO_PLUS:
- reduced = val_1 + val_2;
- break;
-
- case AEO_MINUS:
- reduced = val_1 - val_2;
- break;
-
- case AEO_MUL:
- reduced = val_1 * val_2;
- break;
-
- case AEO_DIV:
- result = (val_2 != 0);
- if (result)
- reduced = val_1 / val_2;
- break;
-
- case AEO_MOD:
- result = (val_2 != 0);
- if (result)
- reduced = val_1 % val_2;
- break;
-
- }
- if (result)
- *out = g_literal_expression_new(EVT_INTEGER, &reduced);
+ result = true;
- }
+ *count = expr->count;
- /* Mise à jour de la progression ? */
+ return result;
- else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
- {
- if (new_left == NULL)
- {
- new_left = expr->left;
- g_object_ref(G_OBJECT(new_left));
- }
+}
- if (new_right == NULL)
- {
- new_right = expr->right;
- g_object_ref(G_OBJECT(new_right));
- }
- *out = g_arithmetic_operation_new(expr->operator, new_left, new_right);
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* index = indice de l'élément à transférer. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Fournit un élément donné issu d'un ensemble constitué. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- }
+static bool g_scan_generic_set_get_item(const GScanGenericSet *expr, size_t index, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
- exit:
+ result = (index < expr->count);
- g_clear_object(&new_left);
- g_clear_object(&new_right);
+ if (result)
+ *out = expr->items[index];
return result;
diff --git a/src/analysis/scan/exprs/set.h b/src/analysis/scan/exprs/set.h
new file mode 100644
index 0000000..f857ce9
--- /dev/null
+++ b/src/analysis/scan/exprs/set.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * set.h - prototypes pour la base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_SET_H
+#define _ANALYSIS_SCAN_EXPRS_SET_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_GENERIC_SET g_scan_generic_set_get_type()
+#define G_SCAN_GENERIC_SET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_GENERIC_SET, GScanGenericSet))
+#define G_IS_SCAN_GENERIC_SET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_GENERIC_SET))
+#define G_SCAN_GENERIC_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_GENERIC_SET, GScanGenericSetClass))
+#define G_IS_SCAN_GENERIC_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_GENERIC_SET))
+#define G_SCAN_GENERIC_SET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_GENERIC_SET, GScanGenericSetClass))
+
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (instance) */
+typedef struct _GScanGenericSet GScanGenericSet;
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (classe) */
+typedef struct _GScanGenericSetClass GScanGenericSetClass;
+
+
+/* Indique le type défini pour une base d'ensembles d'éléments homogènes ou hétérogènes. */
+GType g_scan_generic_set_get_type(void);
+
+/* Met en place un ensemble d'éléments homogènes ou hétérogènes. */
+GScanExpression *g_scan_generic_set_new(void);
+
+/* Ajoute un nouvel élément à un ensemble. */
+void g_scan_generic_set_add_item(GScanGenericSet *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SET_H */
diff --git a/src/analysis/scan/exprs/strop-int.h b/src/analysis/scan/exprs/strop-int.h
index 234ae8f..c2b40cf 100644
--- a/src/analysis/scan/exprs/strop-int.h
+++ b/src/analysis/scan/exprs/strop-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* strop-int.h - prototypes internes pour la gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -34,7 +34,7 @@
/* Opération booléenne avec un ou deux opérandes (instance) */
-struct _GStringOperation
+struct _GScanStringOperation
{
GScanExpression parent; /* A laisser en premier */
@@ -47,7 +47,7 @@ struct _GStringOperation
};
/* Opération booléenne avec un ou deux opérandes (classe) */
-struct _GStringOperationClass
+struct _GScanStringOperationClass
{
GScanExpressionClass parent; /* A laisser en premier */
@@ -55,7 +55,7 @@ struct _GStringOperationClass
/* Met en place une expression d'opération traite une chaîne. */
-bool g_string_operation_create(GStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool);
+bool g_scan_string_operation_create(GScanStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool);
diff --git a/src/analysis/scan/exprs/strop.c b/src/analysis/scan/exprs/strop.c
index 145e8da..c7c2878 100644
--- a/src/analysis/scan/exprs/strop.c
+++ b/src/analysis/scan/exprs/strop.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* strop.c - gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -38,27 +38,24 @@
/* Initialise la classe des opérations visant des chaînes. */
-static void g_string_operation_class_init(GStringOperationClass *);
+static void g_scan_string_operation_class_init(GScanStringOperationClass *);
/* Initialise une instance d'opération visant une chaîne. */
-static void g_string_operation_init(GStringOperation *);
+static void g_scan_string_operation_init(GScanStringOperation *);
/* Supprime toutes les références externes. */
-static void g_string_operation_dispose(GStringOperation *);
+static void g_scan_string_operation_dispose(GScanStringOperation *);
/* Procède à la libération totale de la mémoire. */
-static void g_string_operation_finalize(GStringOperation *);
+static void g_scan_string_operation_finalize(GScanStringOperation *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_string_operation_copy(GStringOperation *, const GStringOperation *);
-
/* Réduit une expression à une forme plus simple. */
-static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_string_operation_reduce(GScanStringOperation *, GScanContext *, GScanScope *, GScanExpression **);
@@ -68,7 +65,7 @@ static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanS
/* Indique le type défini pour une opération traitant une chaîne de caractères. */
-G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanStringOperation, g_scan_string_operation, G_TYPE_SCAN_EXPRESSION);
/******************************************************************************
@@ -83,21 +80,20 @@ G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_string_operation_class_init(GStringOperationClass *klass)
+static void g_scan_string_operation_class_init(GScanStringOperationClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GScanExpressionClass *expr; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_string_operation_dispose;
- object->finalize = (GObjectFinalizeFunc)g_string_operation_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_string_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_string_operation_finalize;
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)NULL;
- expr->copy = (copy_expr_fc)g_string_operation_copy;
- expr->reduce = (reduce_expr_fc)g_string_operation_reduce;
+ expr->reduce = (reduce_expr_fc)g_scan_string_operation_reduce;
}
@@ -114,7 +110,7 @@ static void g_string_operation_class_init(GStringOperationClass *klass)
* *
******************************************************************************/
-static void g_string_operation_init(GStringOperation *op)
+static void g_scan_string_operation_init(GScanStringOperation *op)
{
op->left = NULL;
op->right = NULL;
@@ -134,12 +130,12 @@ static void g_string_operation_init(GStringOperation *op)
* *
******************************************************************************/
-static void g_string_operation_dispose(GStringOperation *op)
+static void g_scan_string_operation_dispose(GScanStringOperation *op)
{
g_clear_object(&op->left);
g_clear_object(&op->right);
- G_OBJECT_CLASS(g_string_operation_parent_class)->dispose(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_string_operation_parent_class)->dispose(G_OBJECT(op));
}
@@ -156,9 +152,9 @@ static void g_string_operation_dispose(GStringOperation *op)
* *
******************************************************************************/
-static void g_string_operation_finalize(GStringOperation *op)
+static void g_scan_string_operation_finalize(GScanStringOperation *op)
{
- G_OBJECT_CLASS(g_string_operation_parent_class)->finalize(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_string_operation_parent_class)->finalize(G_OBJECT(op));
}
@@ -178,13 +174,13 @@ static void g_string_operation_finalize(GStringOperation *op)
* *
******************************************************************************/
-GScanExpression *g_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive)
+GScanExpression *g_scan_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive)
{
GScanExpression *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_STRING_OPERATION, NULL);
+ result = g_object_new(G_TYPE_SCAN_STRING_OPERATION, NULL);
- if (!g_string_operation_create(G_STRING_OPERATION(result), type, first, second, sensitive))
+ if (!g_scan_string_operation_create(G_SCAN_STRING_OPERATION(result), type, first, second, sensitive))
g_clear_object(&result);
return result;
@@ -198,7 +194,7 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio
* type = type d'opération booléenne à représenter. *
* left = premier opérande concerné. *
* right = éventuel second opérande impliqué ou NULL. *
-* sensitive = détermine la prise en compte de la casse. *
+* sensitive = détermine la prise en compte de la casse. *
* *
* Description : Met en place une expression d'opération traite une chaîne. *
* *
@@ -208,22 +204,11 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio
* *
******************************************************************************/
-bool g_string_operation_create(GStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive)
+bool g_scan_string_operation_create(GScanStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive)
{
bool result; /* Bilan à retourner */
- ExprValueType vtype; /* Type de valeur portée */
-
- result = false;
-
- vtype = g_scan_expression_get_value_type(left);
-
- if (vtype != EVT_STRING && vtype != EVT_PENDING)
- goto exit;
-
- vtype = g_scan_expression_get_value_type(right);
- if (vtype != EVT_STRING && vtype != EVT_REG_EXPR && vtype != EVT_PENDING)
- goto exit;
+ result = true;
op->type = type;
@@ -251,10 +236,6 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G
op->right = right;
g_object_ref(G_OBJECT(op->right));
- result = true;
-
- exit:
-
return result;
}
@@ -268,36 +249,6 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G
/******************************************************************************
* *
-* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
-* src = expression source à copier. *
-* *
-* Description : Reproduit une expression en place dans une nouvelle instance.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_string_operation_copy(GStringOperation *dest, const GStringOperation *src)
-{
- GScanExpressionClass *class; /* Classe parente à solliciter */
-
- class = G_SCAN_EXPRESSION_CLASS(g_string_operation_parent_class);
-
- class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
- dest->type = src->type;
- dest->case_sensitive = src->case_sensitive;
-
- dest->left = g_scan_expression_duplicate(src->left);
- dest->right = g_scan_expression_duplicate(src->right);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
* scope = portée courante des variables locales. *
@@ -311,47 +262,65 @@ static void g_string_operation_copy(GStringOperation *dest, const GStringOperati
* *
******************************************************************************/
-static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_string_operation_reduce(GScanStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
+ ScanReductionState result; /* Etat synthétisé à retourner */
GScanExpression *new_left; /* Expression réduite (gauche) */
GScanExpression *new_right; /* Expression réduite (droite) */
- GLiteralExpression *op_left; /* Opérande gauche final */
- GLiteralExpression *op_right; /* Opérande droite final */
+ ScanReductionState state_left; /* Etat synthétisé #1 */
+ ScanReductionState state_right; /* Etat synthétisé #2 */
+ GScanLiteralExpression *op_left; /* Opérande gauche final */
+ GScanLiteralExpression *op_right; /* Opérande droite final */
const sized_string_t *strings[2]; /* Chaînes en jeu */
const void *found; /* Présence d'une bribe ? */
bool status; /* Bilan de comparaison #1 */
+ int ret; /* Bilan de comparaison #2 */
size_t offset; /* Point de départ d'analyse */
const regex_t *preg; /* Expression rationnelle */
- int ret; /* Bilan de comparaison #2 */
/* Réduction des éléments considérés */
new_left = NULL;
new_right = NULL;
- result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
- if (!result) goto exit;
+ state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (state_left == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
- result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
- if (!result) goto exit;
+ state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (state_right == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
/* Construction d'une réduction locale ? */
- if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
{
- op_left = G_LITERAL_EXPRESSION(new_left);
- op_right = G_LITERAL_EXPRESSION(new_right);
+ op_left = G_SCAN_LITERAL_EXPRESSION(new_left);
+ op_right = G_SCAN_LITERAL_EXPRESSION(new_right);
+
+ if (!g_scan_literal_expression_get_string_value(op_left, &strings[0]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
- result = g_literal_expression_get_string_value(op_left, &strings[0]);
- if (!result) goto exit;
+ result = SRS_REDUCED;
switch (expr->type)
{
case SOT_CONTAINS:
- result = g_literal_expression_get_string_value(op_right, &strings[1]);
- if (!result) goto exit;
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
if (expr->case_sensitive)
found = memmem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len);
@@ -359,13 +328,16 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
else
found = memcasemem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len);
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { found != NULL });
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { found != NULL });
break;
case SOT_STARTSWITH:
- result = g_literal_expression_get_string_value(op_right, &strings[1]);
- if (!result) goto exit;
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
if (strings[0]->len < strings[1]->len)
status = false;
@@ -381,13 +353,16 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
}
- result = g_literal_expression_new(EVT_BOOLEAN, &status);
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
break;
case SOT_ENDSWITH:
- result = g_literal_expression_get_string_value(op_right, &strings[1]);
- if (!result) goto exit;
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
if (strings[0]->len < strings[1]->len)
status = false;
@@ -405,23 +380,29 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
}
- result = g_literal_expression_new(EVT_BOOLEAN, &status);
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
break;
case SOT_MATCHES:
- result = g_literal_expression_get_regex_value(op_right, &preg);
- if (!result) goto exit;
+ if (!g_scan_literal_expression_get_regex_value(op_right, &preg))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
ret = regexec(preg, strings[0]->data, 0, NULL, 0);
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH });
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { ret != REG_NOMATCH });
break;
case SOT_IEQUALS:
- result = g_literal_expression_get_string_value(op_right, &strings[1]);
- if (!result) goto exit;
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
if (strings[0]->len != strings[1]->len)
status = false;
@@ -432,7 +413,7 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
status = (ret == 0);
}
- result = g_literal_expression_new(EVT_BOOLEAN, &status);
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
break;
}
@@ -441,24 +422,26 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
/* Mise à jour de la progression ? */
- else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
+ else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
{
- if (new_left == NULL)
- {
- new_left = expr->left;
- g_object_ref(G_OBJECT(new_left));
- }
+ if (new_left != expr->left || new_right != expr->right)
+ *out = g_scan_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive);
- if (new_right == NULL)
- {
- new_right = expr->right;
- g_object_ref(G_OBJECT(new_right));
- }
+ result = SRS_WAIT_FOR_SCAN;
- *out = g_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive);
+ }
+
+ /* Cas des situations où les expressions ne sont pas exploitables (!) */
+ else
+ {
+ assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+ result = SRS_UNRESOLVABLE;
}
+ /* Sortie propre */
+
exit:
g_clear_object(&new_left);
diff --git a/src/analysis/scan/exprs/strop.h b/src/analysis/scan/exprs/strop.h
index c7c0813..0a32269 100644
--- a/src/analysis/scan/exprs/strop.h
+++ b/src/analysis/scan/exprs/strop.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* strop.h - prototypes pour la gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -29,19 +29,19 @@
-#define G_TYPE_STRING_OPERATION g_string_operation_get_type()
-#define G_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_STRING_OPERATION, GStringOperation))
-#define G_IS_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_STRING_OPERATION))
-#define G_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STRING_OPERATION, GStringOperationClass))
-#define G_IS_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STRING_OPERATION))
-#define G_STRING_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STRING_OPERATION, GStringOperationClass))
+#define G_TYPE_SCAN_STRING_OPERATION g_scan_string_operation_get_type()
+#define G_SCAN_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperation))
+#define G_IS_SCAN_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_STRING_OPERATION))
+#define G_SCAN_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperationClass))
+#define G_IS_SCAN_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_STRING_OPERATION))
+#define G_SCAN_STRING_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperationClass))
/* Opération booléenne avec un ou deux opérandes (instance) */
-typedef struct _GStringOperation GStringOperation;
+typedef struct _GScanStringOperation GScanStringOperation;
/* Opération booléenne avec un ou deux opérandes (classe) */
-typedef struct _GStringOperationClass GStringOperationClass;
+typedef struct _GScanStringOperationClass GScanStringOperationClass;
/* Types d'opérations booléennes supportées */
@@ -57,10 +57,10 @@ typedef enum _StringOperationType
/* Indique le type défini pour une opération traitant une chaîne de caractères. */
-GType g_string_operation_get_type(void);
+GType g_scan_string_operation_get_type(void);
/* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool);
+GScanExpression *g_scan_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool);