diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analysis/scan/exprs/Makefile.am | 2 | ||||
-rw-r--r-- | src/analysis/scan/exprs/call.c | 2 | ||||
-rw-r--r-- | src/analysis/scan/exprs/extract-int.h | 57 | ||||
-rw-r--r-- | src/analysis/scan/exprs/extract.c | 396 | ||||
-rw-r--r-- | src/analysis/scan/exprs/extract.h | 56 | ||||
-rw-r--r-- | src/analysis/scan/grammar.y | 139 | ||||
-rw-r--r-- | src/analysis/scan/item-int.h | 5 | ||||
-rw-r--r-- | src/analysis/scan/item.c | 33 | ||||
-rw-r--r-- | src/analysis/scan/item.h | 3 | ||||
-rw-r--r-- | src/analysis/scan/space.c | 1 |
10 files changed, 629 insertions, 65 deletions
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am index a0b2f3d..37f4133 100644 --- a/src/analysis/scan/exprs/Makefile.am +++ b/src/analysis/scan/exprs/Makefile.am @@ -11,6 +11,8 @@ libanalysisscanexprs_la_SOURCES = \ call.h call.c \ counter-int.h \ counter.h counter.c \ + extract-int.h \ + extract.h extract.c \ handler-int.h \ handler.h handler.c \ intersect-int.h \ diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c index 74e0cba..e335933 100644 --- a/src/analysis/scan/exprs/call.c +++ b/src/analysis/scan/exprs/call.c @@ -271,9 +271,9 @@ static ScanReductionState g_scan_pending_call_reduce(const GScanPendingCall *exp 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 */ + GScanExpression *new_next; /* Nouvelle version du suivant */ access = G_SCAN_NAMED_ACCESS(expr); diff --git a/src/analysis/scan/exprs/extract-int.h b/src/analysis/scan/exprs/extract-int.h new file mode 100644 index 0000000..562e537 --- /dev/null +++ b/src/analysis/scan/exprs/extract-int.h @@ -0,0 +1,57 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * extract-int.h - prototypes internes pour l'organisation d'une extraction d'un élément d'une série interne + * + * Copyright (C) 2023 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H +#define _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H + + +#include "extract.h" + + +#include "access-int.h" + + + +/* Extraction d'un élément donné au sein d'une série interne (instance) */ +struct _GScanPendingExtraction +{ + GScanNamedAccess parent; /* A laisser en premier */ + + GScanExpression *index; /* Arguments d'appel fournis */ + +}; + +/* Extraction d'un élément donné au sein d'une série interne (classe) */ +struct _GScanPendingExtractionClass +{ + GScanNamedAccessClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une expression d'extraction d'élément interne. */ +bool g_scan_pending_extraction_create(GScanPendingExtraction *, const sized_string_t *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H */ diff --git a/src/analysis/scan/exprs/extract.c b/src/analysis/scan/exprs/extract.c new file mode 100644 index 0000000..b140ed9 --- /dev/null +++ b/src/analysis/scan/exprs/extract.c @@ -0,0 +1,396 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * extract.c - organisation d'une extraction d'un élément d'une série interne + * + * Copyright (C) 2023 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "extract.h" + + +#include <assert.h> +#include <string.h> + + +#include "extract-int.h" +#include "../../../core/global.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des extractions d'éléments internes. */ +static void g_scan_pending_extraction_class_init(GScanPendingExtractionClass *); + +/* Initialise une instance d'extraction d'élément interne. */ +static void g_scan_pending_extraction_init(GScanPendingExtraction *); + +/* Supprime toutes les références externes. */ +static void g_scan_pending_extraction_dispose(GScanPendingExtraction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_pending_extraction_finalize(GScanPendingExtraction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Réduit une expression à une forme plus simple. */ +static ScanReductionState g_scan_pending_extraction_reduce(const GScanPendingExtraction *, GScanContext *, GScanScope *, GScanExpression **); + +/* Reproduit un accès en place dans une nouvelle instance. */ +static void g_scan_pending_extraction_copy(GScanPendingExtraction *, const GScanPendingExtraction *); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une extraction d'élément de série interne. */ +G_DEFINE_TYPE(GScanPendingExtraction, g_scan_pending_extraction, G_TYPE_SCAN_NAMED_ACCESS); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des extractions d'éléments internes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_class_init(GScanPendingExtractionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + GScanNamedAccessClass *access; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pending_extraction_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_pending_extraction_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)NULL; + expr->reduce = (reduce_expr_fc)g_scan_pending_extraction_reduce; + + access = G_SCAN_NAMED_ACCESS_CLASS(klass); + + access->copy = (copy_scan_access_fc)g_scan_pending_extraction_copy; + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance à initialiser. * +* * +* Description : Initialise une instance d'extraction d'élément interne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_init(GScanPendingExtraction *extract) +{ + extract->index = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_dispose(GScanPendingExtraction *extract) +{ + g_clear_object(&extract->index); + + G_OBJECT_CLASS(g_scan_pending_extraction_parent_class)->dispose(G_OBJECT(extract)); + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_finalize(GScanPendingExtraction *extract) +{ + G_OBJECT_CLASS(g_scan_pending_extraction_parent_class)->finalize(G_OBJECT(extract)); + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de l'objet d'appel à identifier. * +* index = indice de l'élément à extraire. * +* * +* Description : Organise l'extraction d'un élément d'une série interne. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_scan_pending_extraction_new(const sized_string_t *target, GScanExpression *index) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_PENDING_EXTRACTION, NULL); + + if (!g_scan_pending_extraction_create(G_SCAN_PENDING_EXTRACTION(result), target, index)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance à initialiser pleinement. * +* target = désignation de l'objet d'appel à identifier. * +* index = indice de l'élément à extraire. * +* * +* Description : Met en place une expression d'extraction d'élément interne. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_pending_extraction_create(GScanPendingExtraction *extract, const sized_string_t *target, GScanExpression *index) +{ + bool result; /* Bilan à retourner */ + + result = g_scan_named_access_create(G_SCAN_NAMED_ACCESS(extract), target); + if (!result) goto exit; + + extract->index = index; + g_object_ref(G_OBJECT(index)); + + exit: + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static ScanReductionState g_scan_pending_extraction_reduce(const GScanPendingExtraction *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + ScanReductionState result; /* Etat synthétisé à retourner */ + GScanNamedAccess *access; /* Autre vision de l'expression*/ + GScanRegisteredItem *resolved; /* Cible concrète obtenue */ + GScanExpression *new; /* Nouvelle réduction obtenue */ + GObject *final; /* Expression ou élément ? */ + GScanExpression *new_next; /* Nouvelle version du suivant */ + + access = G_SCAN_NAMED_ACCESS(expr); + + resolved = _g_scan_named_access_prepare_reduction(access, ctx, scope); + + if (resolved == NULL) + result = SRS_UNRESOLVABLE; + + else + { + /* Actualisation nécessaire des arguments ? */ + + result = g_scan_expression_reduce(expr->index, ctx, scope, &new); + + /* Suite des traitements */ + + if (result == SRS_WAIT_FOR_SCAN) + { + /** + * Si changement il y a eu... + */ + if (new != expr->index) + { + *out = g_scan_pending_extraction_new(NULL, new); + + /** + * Fonctionnement équivalent de : + * g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(*out), resolved); + */ + G_SCAN_NAMED_ACCESS(*out)->resolved = resolved; + g_object_ref(G_OBJECT(resolved)); + + if (G_SCAN_NAMED_ACCESS(expr)->next != NULL) + g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS(*out), G_SCAN_NAMED_ACCESS(expr)->next); + + } + + } + + else if (result == SRS_REDUCED) + { + final = g_scan_registered_item_extract_at(resolved, new, ctx, scope); + + if (final != NULL) + { + /** + * Si le produit de l'appel à la fonction est une expression d'évaluation + * classique, alors ce produit constitue la réduction finale de la chaîne. + * + * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne. + */ + if (!G_IS_SCAN_REGISTERED_ITEM(final)) + { + if (access->next != NULL) + result = SRS_UNRESOLVABLE; + + else + { + *out = G_SCAN_EXPRESSION(final); + g_object_ref(G_OBJECT(final)); + + result = SRS_REDUCED; + + } + + } + else + { + if (access->next != NULL) + { + new_next = g_scan_named_access_duplicate(access->next, G_SCAN_REGISTERED_ITEM(final)); + + result = g_scan_expression_reduce(new_next, ctx, scope, out); + + g_object_unref(G_OBJECT(new_next)); + + } + + /** + * Le cas ci-après est typique de l'extension Kaitai : field[n] + * renvoie vers une instance GScanRegisteredItem (GKaitaiBrowser). + * + * Il n'y a donc pas d'expression en jeu, et l'élément est le dernier + * de la liste. + */ + else + { + if (g_scan_registered_item_reduce(G_SCAN_REGISTERED_ITEM(final), ctx, scope, out)) + result = SRS_REDUCED; + else + result = SRS_UNRESOLVABLE; + + } + + } + + } + + else + result = SRS_UNRESOLVABLE; + + g_clear_object(&final); + + } + + /* Libération locale des arguments reconstruits */ + + g_clear_object(&new); + + g_object_unref(G_OBJECT(resolved)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * +* * +* Description : Reproduit un accès en place dans une nouvelle instance. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_copy(GScanPendingExtraction *dest, const GScanPendingExtraction *src) +{ + GScanNamedAccessClass *class; /* Classe parente à solliciter */ + + class = G_SCAN_NAMED_ACCESS_CLASS(g_scan_pending_extraction_parent_class); + + class->copy(G_SCAN_NAMED_ACCESS(dest), G_SCAN_NAMED_ACCESS(src)); + + dest->index = src->index; + g_object_ref(G_OBJECT(src->index)); + +} diff --git a/src/analysis/scan/exprs/extract.h b/src/analysis/scan/exprs/extract.h new file mode 100644 index 0000000..8ed1cfa --- /dev/null +++ b/src/analysis/scan/exprs/extract.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * extract.h - prototypes pour l'organisation d'une extraction d'un élément d'une série interne + * + * Copyright (C) 2023 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_EXTRACT_H +#define _ANALYSIS_SCAN_EXPRS_EXTRACT_H + + +#include "../expr.h" +#include "../../../common/szstr.h" + + + +#define G_TYPE_SCAN_PENDING_EXTRACTION g_scan_pending_extraction_get_type() +#define G_SCAN_PENDING_EXTRACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtraction)) +#define G_IS_SCAN_PENDING_EXTRACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PENDING_EXTRACTION)) +#define G_SCAN_PENDING_EXTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtractionClass)) +#define G_IS_SCAN_PENDING_EXTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PENDING_EXTRACTION)) +#define G_SCAN_PENDING_EXTRACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtractionClass)) + + +/* Extraction d'un élément donné au sein d'une série interne (instance) */ +typedef struct _GScanPendingExtraction GScanPendingExtraction; + +/* Extraction d'un élément donné au sein d'une série interne (classe) */ +typedef struct _GScanPendingExtractionClass GScanPendingExtractionClass; + + +/* Indique le type défini pour une extraction d'élément de série interne. */ +GType g_scan_pending_extraction_get_type(void); + +/* Organise l'extraction d'un élément d'une série interne. */ +GScanExpression *g_scan_pending_extraction_new(const sized_string_t *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_EXTRACT_H */ diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y index c63dda7..2863e21 100644 --- a/src/analysis/scan/grammar.y +++ b/src/analysis/scan/grammar.y @@ -31,6 +31,7 @@ typedef void *yyscan_t; #include "exprs/arithmetic.h" #include "exprs/call.h" #include "exprs/counter.h" +#include "exprs/extract.h" #include "exprs/handler.h" #include "exprs/intersect.h" #include "exprs/item.h" @@ -274,7 +275,8 @@ YY_DECL; %type <expr> cexpression _cexpression %type <expr> literal -%type <expr> item_chain +%type <expr> chain_items +%type <expr> chain_item %type <args_list> call_args %type <expr> logical_expr %type <expr> relational_expr @@ -285,9 +287,9 @@ YY_DECL; %type <expr> pattern_set_items %type <expr> set %type <expr> set_items -%type <expr> set_access %type <expr> intersection %type <expr> pattern_handler +%type <expr> _pattern_handler @@ -942,14 +944,13 @@ YY_DECL; cexpression : _cexpression { $$ = $1; if ($$ == NULL) { printf("ERROR !!!\n"); YYERROR; } } _cexpression : literal { $$ = $1; } - | item_chain { $$ = $1; } + | chain_items { $$ = $1; } | logical_expr { $$ = $1; } | relational_expr { $$ = $1; } | string_op { $$ = $1; } | arithm_expr { $$ = $1; } | set_match_counter { $$ = $1; } | set { $$ = $1; } - | set_access { $$ = $1; } | intersection { $$ = $1; } | pattern_handler { $$ = $1; } | "(" cexpression ")" { $$ = $2; } @@ -993,42 +994,48 @@ YY_DECL; { $$ = g_scan_literal_expression_new(LVT_STRING, &$1); } + | STRING "[" cexpression "]" + { + GScanExpression *__src; + __src = g_scan_literal_expression_new(LVT_STRING, &$1); + $$ = g_scan_set_item_new(__src, $3); + g_object_unref(G_OBJECT(__src)); + g_object_unref(G_OBJECT($3)); + } ; - item_chain : NAME { $$ = g_scan_named_access_new(&$1); } - | NAME "(" ")" { $$ = g_scan_pending_call_new(&$1, NULL, 0); } - | NAME "(" call_args ")" + + chain_items : chain_item { - size_t __i; - $$ = g_scan_pending_call_new(&$1, $3.args, $3.count); - for (__i = 0; __i < $3.count; __i++) - g_object_unref(G_OBJECT($3.args[__i])); - free($3.args); + $$ = $1; } - | item_chain "." NAME + | chain_items "." chain_item { - GScanExpression *__next; - __next = g_scan_named_access_new(&$3); - g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next)); + g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS($3)); $$ = $1; } - | item_chain "." NAME "(" ")" + ; + + chain_item : NAME + { + $$ = g_scan_named_access_new(&$1); + } + | NAME "(" ")" { - GScanExpression *__next; - __next = g_scan_pending_call_new(&$3, NULL, 0); - g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next)); - $$ = $1; + $$ = g_scan_pending_call_new(&$1, NULL, 0); } - | item_chain "." NAME "(" call_args ")" + | NAME "(" call_args ")" { - GScanExpression *__next; size_t __i; - __next = g_scan_pending_call_new(&$3, $5.args, $5.count); - for (__i = 0; __i < $5.count; __i++) - g_object_unref(G_OBJECT($5.args[__i])); - free($5.args); - g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next)); - $$ = $1; + $$ = g_scan_pending_call_new(&$1, $3.args, $3.count); + for (__i = 0; __i < $3.count; __i++) + g_object_unref(G_OBJECT($3.args[__i])); + free($3.args); + } + | NAME "[" cexpression "]" + { + $$ = g_scan_pending_extraction_new(&$1, $3); + g_object_unref(G_OBJECT($3)); } ; @@ -1307,46 +1314,39 @@ relational_expr : cexpression "<" cexpression { $$ = g_scan_relational_operatio ; - set : "(" ")" - { - $$ = g_scan_generic_set_new(); - } - | "(" cexpression "," ")" - { - $$ = g_scan_generic_set_new(); - g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $2); - g_object_unref(G_OBJECT($2)); - } - | "(" set_items ")" - { - $$ = $2; - } - ; - - set_items : cexpression "," cexpression - { - $$ = g_scan_generic_set_new(); - g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $1); - g_object_unref(G_OBJECT($1)); - g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3); - g_object_unref(G_OBJECT($3)); - } - | set_items "," cexpression - { - $$ = $1; - g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3); - g_object_unref(G_OBJECT($3)); - } - ; + set : "(" ")" + { + $$ = g_scan_generic_set_new(); + } + | "(" cexpression "," ")" + { + $$ = g_scan_generic_set_new(); + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $2); + g_object_unref(G_OBJECT($2)); + } + | "(" set_items ")" + { + $$ = $2; + } + ; - set_access : cexpression "[" cexpression "]" + set_items : cexpression "," cexpression { - $$ = g_scan_set_item_new($1, $3); + $$ = g_scan_generic_set_new(); + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $1); g_object_unref(G_OBJECT($1)); + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3); + g_object_unref(G_OBJECT($3)); + } + | set_items "," cexpression + { + $$ = $1; + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3); g_object_unref(G_OBJECT($3)); } ; + intersection : cexpression "in" cexpression { $$ = g_scan_sets_intersection_new($1, $3); @@ -1355,7 +1355,20 @@ relational_expr : cexpression "<" cexpression { $$ = g_scan_relational_operatio } ; - pattern_handler : BYTES_ID + + pattern_handler : _pattern_handler + { + $$ = $1; + } + | pattern_handler "[" cexpression "]" + { + $$ = g_scan_set_item_new($1, $3); + g_object_unref(G_OBJECT($1)); + g_object_unref(G_OBJECT($3)); + } + ; + + _pattern_handler : BYTES_ID { GSearchPattern *__pat; __pat = g_scan_rule_get_local_variable(*built_rule, $1.data); diff --git a/src/analysis/scan/item-int.h b/src/analysis/scan/item-int.h index 76431c9..a04b861 100644 --- a/src/analysis/scan/item-int.h +++ b/src/analysis/scan/item-int.h @@ -44,6 +44,9 @@ typedef bool (* reduce_registered_item_fc) (GScanRegisteredItem *, GScanContext /* Effectue un appel à une fonction enregistrée. */ typedef bool (* run_registered_item_call_fc) (GScanRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); +/* Effectue une extraction d'élément à partir d'une série. */ +typedef GObject * (* extract_registered_item_at) (GScanRegisteredItem *, GScanExpression *, GScanContext *, GScanScope *); + /* Expression d'évaluation généraliste (instance) */ struct _GScanRegisteredItem @@ -58,9 +61,11 @@ struct _GScanRegisteredItemClass GObjectClass parent; /* A laisser en premier */ get_registered_item_name_fc get_name; /* Obtention du nom associé */ + resolve_registered_item_fc resolve; /* Opération de résolution */ reduce_registered_item_fc reduce; /* Opération de réduction */ run_registered_item_call_fc run_call; /* Appel à une fonction connue */ + extract_registered_item_at extract; /* Extraction d'un élément */ }; diff --git a/src/analysis/scan/item.c b/src/analysis/scan/item.c index 930a334..509ad28 100644 --- a/src/analysis/scan/item.c +++ b/src/analysis/scan/item.c @@ -290,3 +290,36 @@ bool g_scan_registered_item_run_call(GScanRegisteredItem *item, GScanExpression return result; } + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* index = indice de l'élément à cibler. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* * +* Description : Effectue une extraction d'élément à partir d'une série. * +* * +* Retour : Elément de série obtenu ou NULL si erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GObject *g_scan_registered_item_extract_at(GScanRegisteredItem *item, GScanExpression *index, GScanContext *ctx, GScanScope *scope) +{ + GObject *result; /* Elément récupéré à renvoyer */ + GScanRegisteredItemClass *class; /* Classe à activer */ + + class = G_SCAN_REGISTERED_ITEM_GET_CLASS(item); + + if (class->extract == NULL) + result = NULL; + + else + result = class->extract(item, index, ctx, scope); + + return result; + +} diff --git a/src/analysis/scan/item.h b/src/analysis/scan/item.h index 904064e..a6c56c3 100644 --- a/src/analysis/scan/item.h +++ b/src/analysis/scan/item.h @@ -64,6 +64,9 @@ bool g_scan_registered_item_reduce(GScanRegisteredItem *, GScanContext *, GScanS /* Effectue un appel à une fonction enregistrée. */ bool g_scan_registered_item_run_call(GScanRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); +/* Effectue une extraction d'élément à partir d'une série. */ +GObject *g_scan_registered_item_extract_at(GScanRegisteredItem *, GScanExpression *, GScanContext *, GScanScope *); + #endif /* _ANALYSIS_SCAN_ITEM_H */ diff --git a/src/analysis/scan/space.c b/src/analysis/scan/space.c index e4d5049..909b96d 100644 --- a/src/analysis/scan/space.c +++ b/src/analysis/scan/space.c @@ -24,7 +24,6 @@ #include "space.h" -#include <assert.h> #include <string.h> |