summaryrefslogtreecommitdiff
path: root/plugins/kaitai
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/kaitai')
-rw-r--r--plugins/kaitai/Makefile.am5
-rw-r--r--plugins/kaitai/core.c4
-rw-r--r--plugins/kaitai/grammar.y73
-rw-r--r--plugins/kaitai/import.c300
-rw-r--r--plugins/kaitai/import.h41
-rw-r--r--plugins/kaitai/parser-int.h2
-rw-r--r--plugins/kaitai/parser.c15
-rw-r--r--plugins/kaitai/parser.h2
-rw-r--r--plugins/kaitai/parsers/attribute-int.h3
-rw-r--r--plugins/kaitai/parsers/attribute.c197
-rw-r--r--plugins/kaitai/parsers/attribute.h20
-rw-r--r--plugins/kaitai/parsers/instance.c149
-rw-r--r--plugins/kaitai/parsers/instance.h3
-rw-r--r--plugins/kaitai/parsers/meta-int.h3
-rw-r--r--plugins/kaitai/parsers/meta.c81
-rw-r--r--plugins/kaitai/parsers/meta.h3
-rw-r--r--plugins/kaitai/parsers/struct-int.h2
-rw-r--r--plugins/kaitai/parsers/struct.c114
-rw-r--r--plugins/kaitai/parsers/switch.c112
-rw-r--r--plugins/kaitai/parsers/type-int.h3
-rw-r--r--plugins/kaitai/parsers/type.c58
-rw-r--r--plugins/kaitai/parsers/type.h3
-rw-r--r--plugins/kaitai/python/Makefile.am5
-rw-r--r--plugins/kaitai/python/module.c3
-rw-r--r--plugins/kaitai/python/parsers/attribute.c11
-rw-r--r--plugins/kaitai/python/parsers/meta.c52
-rw-r--r--plugins/kaitai/python/records/Makefile.am5
-rw-r--r--plugins/kaitai/python/records/bits.c318
-rw-r--r--plugins/kaitai/python/records/bits.h45
-rw-r--r--plugins/kaitai/python/records/delayed.c (renamed from plugins/kaitai/python/records/value.c)94
-rw-r--r--plugins/kaitai/python/records/delayed.h (renamed from plugins/kaitai/python/records/value.h)16
-rw-r--r--plugins/kaitai/python/records/module.c6
-rw-r--r--plugins/kaitai/python/rost/Makefile.am14
-rw-r--r--plugins/kaitai/python/rost/module.c115
-rw-r--r--plugins/kaitai/python/rost/module.h41
-rw-r--r--plugins/kaitai/python/rost/trigger.c236
-rw-r--r--plugins/kaitai/python/rost/trigger.h45
-rw-r--r--plugins/kaitai/record.c18
-rw-r--r--plugins/kaitai/records/Makefile.am8
-rw-r--r--plugins/kaitai/records/bits-int.h59
-rw-r--r--plugins/kaitai/records/bits.c283
-rw-r--r--plugins/kaitai/records/bits.h62
-rw-r--r--plugins/kaitai/records/delayed-int.h (renamed from plugins/kaitai/records/value-int.h)19
-rw-r--r--plugins/kaitai/records/delayed.c (renamed from plugins/kaitai/records/value.c)128
-rw-r--r--plugins/kaitai/records/delayed.h (renamed from plugins/kaitai/records/value.h)32
-rw-r--r--plugins/kaitai/rost/Makefile.am18
-rw-r--r--plugins/kaitai/rost/browser-int.h58
-rw-r--r--plugins/kaitai/rost/browser.c478
-rw-r--r--plugins/kaitai/rost/browser.h58
-rw-r--r--plugins/kaitai/rost/core.c66
-rw-r--r--plugins/kaitai/rost/core.h37
-rw-r--r--plugins/kaitai/rost/space-int.h55
-rw-r--r--plugins/kaitai/rost/space.c254
-rw-r--r--plugins/kaitai/rost/space.h59
-rw-r--r--plugins/kaitai/rost/trigger-int.h59
-rw-r--r--plugins/kaitai/rost/trigger.c320
-rw-r--r--plugins/kaitai/rost/trigger.h61
-rw-r--r--plugins/kaitai/scope.c2
-rw-r--r--plugins/kaitai/tokens.l2
59 files changed, 3967 insertions, 368 deletions
diff --git a/plugins/kaitai/Makefile.am b/plugins/kaitai/Makefile.am
index cbc0f25..9a4e112 100644
--- a/plugins/kaitai/Makefile.am
+++ b/plugins/kaitai/Makefile.am
@@ -54,6 +54,7 @@ libkaitai_la_SOURCES = \
array.h array.c \
core.h core.c \
expression.h \
+ import.h import.c \
parser-int.h \
parser.h parser.c \
record-int.h \
@@ -67,6 +68,7 @@ libkaitai_la_SOURCES = \
libkaitai_la_LIBADD = \
parsers/libkaitaiparsers.la \
records/libkaitairecords.la \
+ rost/libkaitairost.la \
$(PYTHON3_LIBADD)
libkaitai_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
@@ -88,5 +90,4 @@ CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h
EXTRA_DIST = tokens.h
-# misc
-SUBDIRS = parsers records $(PYTHON3_SUBDIRS)
+SUBDIRS = parsers records rost $(PYTHON3_SUBDIRS)
diff --git a/plugins/kaitai/core.c b/plugins/kaitai/core.c
index 7483fbc..c41d96d 100644
--- a/plugins/kaitai/core.c
+++ b/plugins/kaitai/core.c
@@ -30,6 +30,8 @@
#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
+#include "rost/core.h"
+
#ifdef INCLUDE_PYTHON3_BINDINGS
@@ -62,7 +64,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
- result = true;
+ result = add_kaitai_support_to_rost();
#ifdef INCLUDE_PYTHON3_BINDINGS
diff --git a/plugins/kaitai/grammar.y b/plugins/kaitai/grammar.y
index 9e31113..9745dc8 100644
--- a/plugins/kaitai/grammar.y
+++ b/plugins/kaitai/grammar.y
@@ -31,9 +31,10 @@ typedef void *yyscan_t;
#include "expression.h"
#include "record.h"
+#include "records/bits.h"
+#include "records/delayed.h"
#include "records/item.h"
#include "records/list.h"
-#include "records/value.h"
}
@@ -580,7 +581,9 @@ YY_DECL;
%token ROOT "_root"
%token PARENT "_parent"
%token LAST "_"
+%token IO "_io"
%token METH_IO "._io"
+%token IO_EOF ".eof"
%token TRUE_CONST "true"
%token FALSE_CONST "false"
@@ -622,6 +625,7 @@ YY_DECL;
%type <value> field
%type <value> enumeration
%type <value> stream
+%type <value> stream_meths
@@ -714,6 +718,7 @@ YY_DECL;
| field { $$ = $1; }
| enumeration { $$ = $1; }
| stream { $$ = $1; }
+ | stream_meths { $$ = $1; }
| arithmetic_expr { $$ = $1; }
| relational_expr { $$ = $1; }
| logical_expr { $$ = $1; }
@@ -1487,7 +1492,35 @@ YY_DECL;
}
- stream : any_expr "._io"
+ stream : "_io"
+ {
+ GBinContent *__content;
+ mrange_t __range;
+ vmpa2t __next;
+
+ if (locals->last == NULL)
+ {
+ __content = g_match_record_get_content(locals->root);
+
+ g_binary_content_compute_start_pos(__content, &__next);
+
+ }
+ else
+ {
+ __content = g_match_record_get_content(locals->last);
+
+ g_match_record_get_range(locals->last, &__range);
+ compute_mrange_end_addr(&__range, &__next);
+
+ }
+
+ $$.stream = g_kaitai_stream_new(__content, &__next);
+ $$.type = GVT_STREAM;
+
+ g_object_unref(G_OBJECT(__content));
+
+ }
+ | any_expr "._io"
{
GBinContent *__content;
mrange_t __range;
@@ -1508,6 +1541,15 @@ YY_DECL;
}
;
+ stream_meths : stream ".eof"
+ {
+ $$.status = g_kaitai_stream_has_reached_eof($1.stream);;
+ $$.type = GVT_BOOLEAN;
+
+ EXIT_RESOLVED_VALUE($1);
+
+ }
+ ;
%%
@@ -1656,8 +1698,11 @@ static bool reduce_resolved_kaitai_expression(resolved_value_t *in_out)
while (result && in_out->type == GVT_RECORD)
{
- if (G_IS_RECORD_VALUE(in_out->record))
- result = g_record_value_compute_value(G_RECORD_VALUE(in_out->record), &deeper);
+ if (G_IS_RECORD_BIT_FIELD(in_out->record))
+ result = g_record_bit_field_get_value(G_RECORD_BIT_FIELD(in_out->record), &deeper);
+
+ else if (G_IS_RECORD_DELAYED(in_out->record))
+ result = g_record_delayed_compute_value(G_RECORD_DELAYED(in_out->record), &deeper);
else if (G_IS_RECORD_ITEM(in_out->record))
result = g_record_item_get_value(G_RECORD_ITEM(in_out->record), &deeper);
@@ -1734,6 +1779,26 @@ bool resolve_kaitai_expression_as_boolean(const kaitai_scope_t *locals, const ch
if (result)
result = reduce_resolved_kaitai_expression(out);
+ if (result)
+ {
+ if (out->type == GVT_UNSIGNED_INTEGER)
+ {
+ out->status = (out->unsigned_integer != 0);
+ out->type = GVT_BOOLEAN;
+ }
+ else if (out->type == GVT_SIGNED_INTEGER)
+ {
+ out->status = (out->signed_integer != 0);
+ out->type = GVT_BOOLEAN;
+ }
+ else if (out->type == GVT_FLOAT)
+ {
+ out->status = (out->floating_number != 0);
+ out->type = GVT_BOOLEAN;
+ }
+
+ }
+
if (result && out->type != GVT_BOOLEAN)
{
EXIT_RESOLVED_VALUE(*out);
diff --git a/plugins/kaitai/import.c b/plugins/kaitai/import.c
new file mode 100644
index 0000000..0412ff7
--- /dev/null
+++ b/plugins/kaitai/import.c
@@ -0,0 +1,300 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * import.c - localisation de fichiers de définitions externes
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "import.h"
+
+
+#include <libgen.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <common/environment.h>
+#include <core/logs.h>
+
+
+
+/* Charge un type Kaitai à partir d'une définition voisine. */
+static GKaitaiType *import_relative_kaitai_definition(const char *, const char *);
+
+/* Charge un type Kaitai depuis un emplacement de $KSPATH. */
+static GKaitaiType *import_kaitai_definition_from_env(const char *);
+
+/* Charge un interpréteur pour une définition voisine. */
+static GKaitaiStruct *load_relative_kaitai_definition(const char *, const char *);
+
+/* Charge un interpréteur depuis un emplacement de $KSPATH. */
+static GKaitaiStruct *load_kaitai_definition_from_env(const char *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* reference = éventuel fichier pour les positions relatives. *
+* *
+* Description : Charge un type Kaitai à partir d'une définition voisine. *
+* *
+* Retour : Type valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GKaitaiType *import_relative_kaitai_definition(const char *target, const char *reference)
+{
+ GKaitaiType *result; /* Structure chargée à renvoyer*/
+ char *tmp; /* Zone de travail temporaire */
+ char *base; /* Base de recherche */
+ char *filename; /* Nom de fichier à tester */
+ int ret; /* Bilan d'une construction */
+
+ result = NULL;
+
+ tmp = strdup(reference);
+ base = dirname(tmp);
+
+ ret = asprintf(&filename, "%s%c%s.ksy", base, G_DIR_SEPARATOR, target);
+ if (ret == -1) goto build_error;
+
+ result = g_kaitai_type_new_as_import(target, filename);
+
+ free(filename);
+
+ build_error:
+
+ free(tmp);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* *
+* Description : Charge un type Kaitai depuis un emplacement de $KSPATH. *
+* *
+* Retour : Type valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GKaitaiType *import_kaitai_definition_from_env(const char *target)
+{
+ GKaitaiType *result; /* Structure chargée à renvoyer*/
+ char *paths; /* Emplacements de greffons */
+ char *save; /* Sauvegarde pour ré-entrance */
+ char *path; /* Chemin à fouiller */
+ char *filename; /* Nom de fichier à tester */
+ int ret; /* Bilan d'une construction */
+
+ result = NULL;
+
+ paths = get_env_var("KSPATH");
+
+ save = NULL; /* gcc... */
+
+ for (path = strtok_r(paths, ":", &save);
+ path != NULL;
+ path = strtok_r(NULL, ":", &save))
+ {
+ ret = asprintf(&filename, "%s%c%s.ksy", path, G_DIR_SEPARATOR, target);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ continue;
+ }
+
+ result = g_kaitai_type_new_as_import(target, filename);
+
+ if (result != NULL)
+ log_variadic_message(LMT_PROCESS, _("Found a required Kaitai definition to import: %s"), filename);
+
+ free(filename);
+
+ }
+
+ free(paths);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* reference = éventuel fichier pour les positions relatives. *
+* *
+* Description : Met en place un type Kaitai pour une définition désignée. *
+* *
+* Retour : Type valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiType *import_kaitai_definition(const char *target, const char *reference)
+{
+ GKaitaiType *result; /* Structure chargée à renvoyer*/
+
+ result = NULL;
+
+ if (reference != NULL)
+ result = import_relative_kaitai_definition(target, reference);
+
+ if (result == NULL)
+ result = import_kaitai_definition_from_env(target);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* reference = éventuel fichier pour les positions relatives. *
+* *
+* Description : Charge un interpréteur pour une définition voisine. *
+* *
+* Retour : Interprétateur valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GKaitaiStruct *load_relative_kaitai_definition(const char *target, const char *reference)
+{
+ GKaitaiStruct *result; /* Structure chargée à renvoyer*/
+ char *tmp; /* Zone de travail temporaire */
+ char *base; /* Base de recherche */
+ char *filename; /* Nom de fichier à tester */
+ int ret; /* Bilan d'une construction */
+
+ result = NULL;
+
+ tmp = strdup(reference);
+ base = dirname(tmp);
+
+ ret = asprintf(&filename, "%s%c%s.ksy", base, G_DIR_SEPARATOR, target);
+ if (ret == -1) goto build_error;
+
+ result = g_kaitai_structure_new_from_file(filename);
+
+ free(filename);
+
+ build_error:
+
+ free(tmp);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* *
+* Description : Charge un interpréteur depuis un emplacement de $KSPATH. *
+* *
+* Retour : Interprétateur valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GKaitaiStruct *load_kaitai_definition_from_env(const char *target)
+{
+ GKaitaiStruct *result; /* Structure chargée à renvoyer*/
+ char *paths; /* Emplacements de greffons */
+ char *save; /* Sauvegarde pour ré-entrance */
+ char *path; /* Chemin à fouiller */
+ char *filename; /* Nom de fichier à tester */
+ int ret; /* Bilan d'une construction */
+
+ result = NULL;
+
+ paths = get_env_var("KSPATH");
+
+ save = NULL; /* gcc... */
+
+ for (path = strtok_r(paths, ":", &save);
+ path != NULL;
+ path = strtok_r(NULL, ":", &save))
+ {
+ ret = asprintf(&filename, "%s%c%s.ksy", path, G_DIR_SEPARATOR, target);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ continue;
+ }
+
+ result = g_kaitai_structure_new_from_file(filename);
+
+ if (result != NULL)
+ log_variadic_message(LMT_PROCESS, _("Found a required Kaitai definition: %s"), filename);
+
+ free(filename);
+
+ }
+
+ free(paths);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de la définition à retrouver. *
+* reference = éventuel fichier pour les positions relatives. *
+* *
+* Description : Met en place un interpréteur pour une définition désignée. *
+* *
+* Retour : Interprétateur valide en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiStruct *load_kaitai_definition(const char *target, const char *reference)
+{
+ GKaitaiStruct *result; /* Structure chargée à renvoyer*/
+
+ result = NULL;
+
+ if (reference != NULL)
+ result = load_relative_kaitai_definition(target, reference);
+
+ if (result == NULL)
+ result = load_kaitai_definition_from_env(target);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/import.h b/plugins/kaitai/import.h
new file mode 100644
index 0000000..66a0f5a
--- /dev/null
+++ b/plugins/kaitai/import.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * import.h - prototypes pour la localisation de fichiers de définitions externes
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_IMPORT_H
+#define _PLUGINS_KAITAI_IMPORT_H
+
+
+#include "parsers/struct.h"
+#include "parsers/type.h"
+
+
+
+/* Met en place un type Kaitai pour une définition désignée. */
+GKaitaiType *import_kaitai_definition(const char *, const char *);
+
+/* Met en place un interpréteur pour une définition désignée. */
+GKaitaiStruct *load_kaitai_definition(const char *, const char *);
+
+
+
+#endif /* _PLUGINS_KAITAI_IMPORT_H */
diff --git a/plugins/kaitai/parser-int.h b/plugins/kaitai/parser-int.h
index 4ddb0f9..8bac523 100644
--- a/plugins/kaitai/parser-int.h
+++ b/plugins/kaitai/parser-int.h
@@ -30,7 +30,7 @@
/* Parcourt un contenu binaire selon des spécifications Kaitai. */
-typedef bool (* parse_kaitai_fc) (GKaitaiParser *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+typedef bool (* parse_kaitai_fc) (GKaitaiParser *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
diff --git a/plugins/kaitai/parser.c b/plugins/kaitai/parser.c
index 77c15b3..cfe1aa1 100644
--- a/plugins/kaitai/parser.c
+++ b/plugins/kaitai/parser.c
@@ -24,6 +24,9 @@
#include "parser.h"
+#include <assert.h>
+
+
#include "parser-int.h"
@@ -131,7 +134,7 @@ static void g_kaitai_parser_finalize(GKaitaiParser *parser)
* Paramètres : parser = structure Kaitai en cours de parcours. *
* locals = variables locales pour les résolutions de types. *
* content = données binaires à analyser et traduire. *
-* pos = tête de lecture courante. [OUT] *
+* epos = tête de lecture courante. [OUT] *
* record = noeud d'arborescence d'éléments rencontrés. [OUT] *
* *
* Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
@@ -142,18 +145,22 @@ static void g_kaitai_parser_finalize(GKaitaiParser *parser)
* *
******************************************************************************/
-bool g_kaitai_parser_parse_content(GKaitaiParser *parser, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+bool g_kaitai_parser_parse_content(GKaitaiParser *parser, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
{
bool result; /* Bilan à retourner */
GKaitaiParserClass *class; /* Classe de l'instance */
+ *record = NULL;
+
class = G_KAITAI_PARSER_GET_CLASS(parser);
- result = class->parse(parser, locals, content, pos, record);
+ result = class->parse(parser, locals, content, epos, record);
- if (result)
+ if (result && *record != NULL)
remember_last_record(locals, *record);
+ assert((!result && *record == NULL) || result);
+
return result;
}
diff --git a/plugins/kaitai/parser.h b/plugins/kaitai/parser.h
index 4c17087..64d759d 100644
--- a/plugins/kaitai/parser.h
+++ b/plugins/kaitai/parser.h
@@ -56,7 +56,7 @@ typedef struct _GKaitaiParserClass GKaitaiParserClass;
GType g_kaitai_parser_get_type(void);
/* Parcourt un contenu binaire selon des spécifications Kaitai. */
-bool g_kaitai_parser_parse_content(GKaitaiParser *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+bool g_kaitai_parser_parse_content(GKaitaiParser *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
diff --git a/plugins/kaitai/parsers/attribute-int.h b/plugins/kaitai/parsers/attribute-int.h
index ef64089..7d37af3 100644
--- a/plugins/kaitai/parsers/attribute-int.h
+++ b/plugins/kaitai/parsers/attribute-int.h
@@ -51,6 +51,9 @@ struct _GKaitaiAttribute
/* KAP_FIXED_CONTENT */
sized_string_t fixed_content; /* Données brutes attendues */
+ /* KAP_BIT_FIELD_TYPE */
+ uint8_t bf_size; /* Nombre de bits visés */
+
/* KAP_BASIC_TYPE */
struct
{
diff --git a/plugins/kaitai/parsers/attribute.c b/plugins/kaitai/parsers/attribute.c
index c61fe99..6050bb1 100644
--- a/plugins/kaitai/parsers/attribute.c
+++ b/plugins/kaitai/parsers/attribute.c
@@ -25,6 +25,7 @@
#include <assert.h>
+#include <stdlib.h>
#include <string.h>
@@ -35,6 +36,7 @@
#include "attribute-int.h"
#include "../expression.h"
#include "../scope.h"
+#include "../records/bits.h"
#include "../records/empty.h"
#include "../records/item.h"
#include "../records/list.h"
@@ -56,6 +58,9 @@ static void g_kaitai_attribute_dispose(GKaitaiAttribute *);
/* Procède à la libération totale de la mémoire. */
static void g_kaitai_attribute_finalize(GKaitaiAttribute *);
+/* Traduit en champ de bits une chaîne de caractères. */
+static bool g_kaitai_attribute_resolve_bit_field(GKaitaiAttribute *, const char *);
+
/* Traduit en type concret une chaîne de caractères. */
static bool g_kaitai_attribute_resolve_type(GKaitaiAttribute *, const char *);
@@ -71,7 +76,7 @@ static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *);
/* Parcourt un contenu binaire selon des spécifications Kaitai. */
-static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
/* Extrait d'un contenu une série d'octets avec terminaison. */
static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *, const kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
@@ -80,7 +85,7 @@ static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *, const
static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttribute *, const kaitai_scope_t *, const GBinContent *, const vmpa2t *, phys_t *, mrange_t *);
/* Parcourt un contenu binaire selon des spécifications Kaitai. */
-static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
@@ -243,7 +248,7 @@ GKaitaiAttribute *g_kaitai_attribute_new(GYamlNode *parent)
result = g_object_new(G_TYPE_KAITAI_ATTRIBUTE, NULL);
- if (!g_kaitai_attribute_create(result, parent, true))
+ if (!g_kaitai_attribute_create(result, parent, false /* TODO : REMME ? */))
g_clear_object(&result);
return result;
@@ -399,7 +404,10 @@ bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool
if (value != NULL)
{
- if (g_kaitai_attribute_resolve_type(attrib, value))
+ if (g_kaitai_attribute_resolve_bit_field(attrib, value))
+ attrib->payload |= KAP_BIT_FIELD_TYPE;
+
+ else if (g_kaitai_attribute_resolve_type(attrib, value))
attrib->payload |= KAP_BASIC_TYPE;
else
@@ -701,6 +709,54 @@ bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool
* Paramètres : attrib = attribut Kaitai en cours de constitution. *
* desc = chaîne de caractère à interpréter en type. *
* *
+* Description : Traduit en champ de bits une chaîne de caractères. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_attribute_resolve_bit_field(GKaitaiAttribute *attrib, const char *desc)
+{
+ bool result; /* Bilan à retourner */
+ size_t len; /* Taille de la chaîne à lire */
+ char *end; /* Prochain caractère à lire */
+ unsigned long size; /* Taille du champ de bits */
+
+ result = false;
+
+ if (desc[0] == 'b')
+ {
+ len = strlen(desc);
+
+ size = strtoul(&desc[1], &end, 10);
+
+ if (size > 64)
+ {
+ printf("Unsupported size for bit field: %lu\n", size);
+ goto exit;
+ }
+
+ result = ((desc + len) == end);
+
+ if (result)
+ attrib->bf_size = size;
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = attribut Kaitai en cours de constitution. *
+* desc = chaîne de caractère à interpréter en type. *
+* *
* Description : Traduit en type concret une chaîne de caractères. *
* *
* Retour : Bilan de l'opération. *
@@ -930,7 +986,7 @@ static bool g_kaitai_attribute_check(const GKaitaiAttribute *attrib)
}
/**
- * Si une séquence d'octets finaux est spécifiées, alors l'attribut
+ * Si une séquence d'octets finaux est spécifiée, alors l'attribut
* doit correspondre à un type str[z] (lecture) ou de taille fixée
* (validation post-lecture).
*/
@@ -1018,7 +1074,8 @@ static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *attr
* Les travaux de copie ne portent ainsi que sur le présent attribut.
*/
- result->raw_id = strdup(attrib->raw_id);
+ if (attrib->raw_id != NULL)
+ result->raw_id = strdup(attrib->raw_id);
if (attrib->orig_id != NULL)
result->orig_id = strdup(attrib->orig_id);
@@ -1428,6 +1485,50 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon
}
+/******************************************************************************
+* *
+* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. *
+* content = contenu binaire à venir lire. *
+* epos = tête de lecture avec granularité en bits. *
+* size = quantité de bits à prendre en compte. *
+* endian = boustime des données à respecter. *
+* out = valeur à sauvegarder sous une forme générique.[OUT]*
+* *
+* Description : Lit la valeur d'un champ de bits Kaitai représenté. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_attribute_read_bit_field_value(const GKaitaiAttribute *attrib, const GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian, resolved_value_t *out)
+{
+ bool result; /* Bilan à retourner */
+ ext_vmpa_t tmpepos; /* Localisation modifiable */
+ uint64_t tmp64; /* Valeur de 64 bits lue */
+
+ result = false;
+
+ if (attrib->payload & KAP_BIT_FIELD_TYPE)
+ {
+ copy_evmpa(&tmpepos, epos);
+
+ result = g_binary_content_read_bits(content, &tmpepos, size, endian, &tmp64);
+
+ if (result)
+ {
+ out->type = GVT_UNSIGNED_INTEGER;
+ out->unsigned_integer = tmp64;
+ }
+
+ }
+
+ return result;
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
@@ -1439,7 +1540,7 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon
* Paramètres : attrib = structure Kaitai en cours de parcours. *
* locals = variables locales pour les résolutions de types. *
* content = données binaires à analyser et traduire. *
-* pos = tête de lecture courante. [OUT] *
+* epos = tête de lecture courante. [OUT] *
* record = noeud d'arborescence d'éléments rencontrés. [OUT] *
* *
* Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
@@ -1450,7 +1551,7 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon
* *
******************************************************************************/
-static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
{
bool result; /* Bilan à retourner */
resolved_value_t authorized; /* Validation des traitements */
@@ -1499,7 +1600,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
/* Zone de travail restreinte */
g_binary_content_compute_end_pos(content, &tmp);
- diff = compute_vmpa_diff(pos, &tmp);
+ diff = compute_vmpa_diff(&epos->base, &tmp);
+
+ if (epos->consumed_extra_bits > 0 && diff > 0)
+ diff--;
if (attrib->payload & KAP_SIZED)
{
@@ -1537,8 +1641,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
if (!result)
goto exit;
- init_mrange(&work_range, pos, diff);
- work_area = g_restricted_content_new_ro(content, &work_range);
+ align_evmpa_on_byte(epos);
+
+ init_mrange(&work_range, &epos->base, diff);
+ work_area = g_restricted_content_new(content, &work_range);
has_empty_size = (diff == 0);
@@ -1555,13 +1661,18 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
assert(false);
else if (attrib->payload & KAP_SIZED_EOS)
+ {
+ align_evmpa_on_byte(epos);
result = true;
+ }
else if (attrib->payload & KAP_FIXED_CONTENT)
{
if (diff >= attrib->fixed_content.len)
{
- copy_vmpa(&tmp, pos);
+ align_evmpa_on_byte(epos);
+
+ copy_vmpa(&tmp, &epos->base);
data = g_binary_content_get_raw_access(work_area, &tmp, attrib->fixed_content.len);
assert(data != NULL);
@@ -1575,8 +1686,26 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
}
+ else if (attrib->payload & KAP_BIT_FIELD_TYPE)
+ {
+ if (attrib->has_endian)
+ endian = attrib->endian;
+ else
+ endian = g_kaitai_meta_get_endian(locals->meta);
+
+ *record = g_record_bit_field_new(attrib, work_area, epos, attrib->bf_size, endian);
+
+ result = (*record != NULL);
+
+ if (result)
+ advance_evmpa_bits(epos, attrib->bf_size);
+
+ }
+
else if (attrib->payload & KAP_BASIC_TYPE)
{
+ align_evmpa_on_byte(epos);
+
switch (attrib->basic)
{
case BTP_CHAR:
@@ -1584,7 +1713,8 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
if (attrib->is_string)
{
if ((attrib->payload & KAP_SIZED) == 0)
- result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals, work_area, pos, record);
+ result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals,
+ work_area, &epos->base, record);
}
else
{
@@ -1627,7 +1757,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
if (user_type != NULL)
{
result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(user_type),
- locals, work_area, pos, record);
+ locals, work_area, epos, record);
if (result)
/**
@@ -1647,7 +1777,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
}
else if (attrib->payload & KAP_DYNAMIC_TYPE)
- result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, pos, record);
+ result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, epos, record);
else if (attrib->payload & KAP_SIZED)
{
@@ -1660,6 +1790,11 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
if (result && *record == NULL)
{
/**
+ * A ce stade, la granularité des travaux est l'octet.
+ */
+ assert(epos->consumed_extra_bits == 0);
+
+ /**
* On choisit de laisser la création de correspondances nulles.
*
* Cela permet de disposer de la présence de champs valides, même vides
@@ -1668,12 +1803,13 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
/* if (diff > 0) */
{
- result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content, pos, &diff, &range);
+ result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content,
+ &epos->base, &diff, &range);
if (result)
{
if (has_empty_size)
- *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, pos));
+ *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, &epos->base));
else
{
@@ -1685,7 +1821,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
*record = G_MATCH_RECORD(g_record_item_new(attrib, work_area, &range, endian));
if (*record != NULL)
- advance_vmpa(pos, diff);
+ advance_vmpa(&epos->base, diff);
else
result = false;
@@ -1701,13 +1837,16 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
if (attrib->payload & KAP_SIZED)
{
- cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), pos);
+ /* Réalignement éventuel suite aux lectures dans la zone périmétrée... */
+ align_evmpa_on_byte(epos);
+
+ cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), &epos->base);
/* Pour GCC... */
max_size = get_mrange_length(&work_range);
if (cur_diff < max_size)
- advance_vmpa(pos, max_size - cur_diff);
+ advance_vmpa(&epos->base, max_size - cur_diff);
assert(work_area != content);
g_object_unref(G_OBJECT(work_area));
@@ -1932,7 +2071,7 @@ static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttri
* Paramètres : attrib = structure Kaitai en cours de parcours. *
* locals = variables locales pour les résolutions de types. *
* content = données binaires à analyser et traduire. *
-* pos = tête de lecture courante. [OUT] *
+* epos = tête de lecture courante. [OUT] *
* record = noeud d'arborescence d'éléments rencontrés. [OUT] *
* *
* Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
@@ -1943,7 +2082,7 @@ static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttri
* *
******************************************************************************/
-static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
{
bool result; /* Bilan à retourner */
resolved_value_t authorized; /* Validation des traitements */
@@ -1957,7 +2096,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc
resolved_value_t loop; /* Poursuite des lectures ? */
if (attrib->repetition == KAR_NO_REPETITION)
- result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, record);
+ result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, record);
else
{
@@ -1975,7 +2114,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc
}
- list = g_record_list_new(attrib, content, pos);
+ list = g_record_list_new(attrib, content, &epos->base);
switch (attrib->repetition)
{
@@ -1984,17 +2123,17 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc
result = true;
g_binary_content_compute_end_pos(content, &end);
- diff = compute_vmpa_diff(pos, &end);
+ diff = compute_vmpa_diff(&epos->base, &end);
while (diff > 0)
{
- result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child);
+ result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child);
if (!result) break;
g_record_list_add_record(list, child);
remember_last_record(locals, child);
- diff = compute_vmpa_diff(pos, &end);
+ diff = compute_vmpa_diff(&epos->base, &end);
}
@@ -2025,7 +2164,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc
for (i = 0; i < count; i++)
{
- result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child);
+ result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child);
if (!result) break;
g_record_list_add_record(list, child);
@@ -2039,7 +2178,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc
do
{
- result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child);
+ result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child);
if (!result) break;
g_record_list_add_record(list, child);
diff --git a/plugins/kaitai/parsers/attribute.h b/plugins/kaitai/parsers/attribute.h
index 38b78d7..9b43936 100644
--- a/plugins/kaitai/parsers/attribute.h
+++ b/plugins/kaitai/parsers/attribute.h
@@ -56,18 +56,19 @@ typedef struct _GKaitaiAttributeClass GKaitaiAttributeClass;
/* Type de charge associée à un attribut */
typedef enum _KaitaiAttributePayload
{
- KAP_UNINITIALIZED = (0 << 0), /* Type non initialisé */
+ KAP_UNINITIALIZED = (0 << 0), /* Type non initialisé */
- KAP_FIXED_CONTENT = (1 << 0), /* Contenu brut attendu */
- KAP_BASIC_TYPE = (1 << 1), /* Type prédéfini */
- KAP_USER_TYPE = (1 << 2), /* Type personnalisé */
- KAP_DYNAMIC_TYPE = (1 << 3), /* Type dynmatique */
- KAP_SIZED = (1 << 4), /* Bourrage dimensionné */
- KAP_SIZED_EOS = (1 << 5), /* Bourrage final */
+ KAP_FIXED_CONTENT = (1 << 0), /* Contenu brut attendu */
+ KAP_BIT_FIELD_TYPE = (1 << 1), /* Champ d'un ou plusieurs bits*/
+ KAP_BASIC_TYPE = (1 << 2), /* Type prédéfini */
+ KAP_USER_TYPE = (1 << 3), /* Type personnalisé */
+ KAP_DYNAMIC_TYPE = (1 << 4), /* Type dynmatique */
+ KAP_SIZED = (1 << 5), /* Bourrage dimensionné */
+ KAP_SIZED_EOS = (1 << 6), /* Bourrage final */
} KaitaiAttributePayload;
-/* Types de base reconnus par Kaitai */
+/* Types de base reconnus par Kaitai */ /* TODO : REMME ? (car non utilisé) */
typedef enum _KaitaiBasicType
{
KBT_U1, /* Octet non signé */
@@ -149,6 +150,9 @@ bool g_kaitai_attribute_handle_signed_integer(const GKaitaiAttribute *);
/* Lit la valeur d'un élément Kaitai entier représenté. */
bool g_kaitai_attribute_read_value(const GKaitaiAttribute *, const GBinContent *, const mrange_t *, SourceEndian, resolved_value_t *);
+/* Lit la valeur d'un champ de bits Kaitai représenté. */
+bool g_kaitai_attribute_read_bit_field_value(const GKaitaiAttribute *, const GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian, resolved_value_t *);
+
#endif /* _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_H */
diff --git a/plugins/kaitai/parsers/instance.c b/plugins/kaitai/parsers/instance.c
index 63db224..d62c1f6 100644
--- a/plugins/kaitai/parsers/instance.c
+++ b/plugins/kaitai/parsers/instance.c
@@ -34,7 +34,7 @@
#include "instance-int.h"
#include "../expression.h"
-#include "../records/value.h"
+#include "../records/delayed.h"
@@ -59,7 +59,7 @@ static void g_kaitai_instance_finalize(GKaitaiInstance *);
/* Parcourt un contenu binaire selon des spécifications Kaitai. */
-static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
@@ -349,74 +349,30 @@ const char *g_kaitai_instance_get_name(const GKaitaiInstance *inst)
* *
* Paramètres : inst = lecteur d'instance Kaitai à consulter. *
* locals = variables locales pour les résolutions de types. *
-* value = valeur à sauvegarder sous une forme générique. [OUT]*
+* content = contenu binaire lié à la correspondance. *
* *
-* Description : Détermine la valeur d'un élément Kaitai entier calculé. *
+* Description : Détermine la valeur effective d'un élément Kaitai dynamique. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : valeur à sauvegarder sous une forme générique. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_kaitai_instance_compute_value(const GKaitaiInstance *inst, const kaitai_scope_t *locals, resolved_value_t *value)
+GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content)
{
- bool result; /* Bilan à retourner */
-
- if (inst->value == NULL)
- result = false;
-
- else
- result = resolve_kaitai_expression_as_any(locals,
- inst->value,
- strlen(inst->value),
- value);
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : inst = structure Kaitai en cours de parcours. *
-* locals = variables locales pour les résolutions de types. *
-* content = données binaires à analyser et traduire. *
-* pos = tête de lecture courante. [OUT] *
-* record = noeud d'arborescence d'éléments rencontrés. [OUT] *
-* *
-* Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
-* *
-* Retour : Bilan de l'opératon : true pour continuer, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
-{
- bool result; /* Bilan à retourner */
+ GMatchRecord *result; /* Enregistrement à retourner */
GBinContent *work_area; /* Aire de travail */
GKaitaiStream *stream; /* Flux de données pour Kaitai */
- resolved_value_t offset; /* Position à adopter */
+ bool status; /* Bilan intermédiaire */
vmpa2t forced_pos; /* Tete de lecture constituée */
+ resolved_value_t offset; /* Position à adopter */
GKaitaiParserClass *class; /* Classe parente à solliciter */
+ ext_vmpa_t epos; /* Tête de lecture complète */
- if (inst->value != NULL)
- {
- *record = G_MATCH_RECORD(g_record_value_new(inst, locals));
+ result = NULL;
- result = (*record != NULL);
-
- }
-
- else
+ if (inst->value == NULL)
{
/* Contenu particulier */
@@ -425,8 +381,8 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_
else
{
- result = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream);
- if (!result) goto exit;
+ status = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream);
+ if (!status) goto exit;
work_area = g_kaitai_stream_get_content(stream);
@@ -438,8 +394,8 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_
g_binary_content_compute_start_pos(work_area, &forced_pos);
- result = resolve_kaitai_expression_as_integer(locals, inst->pos, strlen(inst->pos), &offset);
- if (!result) goto exit_with_content;
+ status = resolve_kaitai_expression_as_integer(locals, inst->pos, strlen(inst->pos), &offset);
+ if (!status) goto exit_with_content;
if (offset.type == GVT_UNSIGNED_INTEGER)
advance_vmpa(&forced_pos, offset.unsigned_integer);
@@ -450,7 +406,7 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_
if (offset.signed_integer < 0)
{
- result = false;
+ status = false;
goto exit_with_content;
}
@@ -462,7 +418,9 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_
class = G_KAITAI_PARSER_CLASS(g_kaitai_instance_parent_class);
- result = class->parse(G_KAITAI_PARSER(inst), locals, work_area, &forced_pos, record);
+ init_evmpa_from_vmpa(&epos, &forced_pos);
+
+ class->parse(G_KAITAI_PARSER(inst), locals, work_area, &epos, &result);
exit_with_content:
@@ -476,3 +434,70 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : inst = lecteur d'instance Kaitai à consulter. *
+* locals = variables locales pour les résolutions de types. *
+* value = valeur à sauvegarder sous une forme générique. [OUT]*
+* *
+* Description : Détermine la valeur d'un élément Kaitai entier calculé. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_instance_compute_value(const GKaitaiInstance *inst, const kaitai_scope_t *locals, resolved_value_t *value)
+{
+ bool result; /* Bilan à retourner */
+
+ if (inst->value == NULL)
+ result = false;
+
+ else
+ result = resolve_kaitai_expression_as_any(locals,
+ inst->value,
+ strlen(inst->value),
+ value);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : inst = structure Kaitai en cours de parcours. *
+* locals = variables locales pour les résolutions de types. *
+* content = données binaires à analyser et traduire. *
+* epos = tête de lecture courante. [OUT] *
+* record = noeud d'arborescence d'éléments rencontrés. [OUT] *
+* *
+* Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
+* *
+* Retour : Bilan de l'opératon : true pour continuer, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
+{
+ bool result; /* Bilan à retourner */
+
+ *record = G_MATCH_RECORD(g_record_delayed_new(inst, locals, inst->value == NULL ? content : NULL));
+
+ result = (*record != NULL);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/parsers/instance.h b/plugins/kaitai/parsers/instance.h
index a9aee9a..4594137 100644
--- a/plugins/kaitai/parsers/instance.h
+++ b/plugins/kaitai/parsers/instance.h
@@ -60,6 +60,9 @@ GKaitaiInstance *g_kaitai_instance_new(GYamlNode *);
/* Indique le nom attribué à une instance Kaitai. */
const char *g_kaitai_instance_get_name(const GKaitaiInstance *);
+/* Détermine la valeur effective d'un élément Kaitai dynamique. */
+GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *, const kaitai_scope_t *, GBinContent *);
+
/* Détermine la valeur d'un élément Kaitai entier calculé. */
bool g_kaitai_instance_compute_value(const GKaitaiInstance *, const kaitai_scope_t *, resolved_value_t *);
diff --git a/plugins/kaitai/parsers/meta-int.h b/plugins/kaitai/parsers/meta-int.h
index 7d847ef..5fe9174 100644
--- a/plugins/kaitai/parsers/meta-int.h
+++ b/plugins/kaitai/parsers/meta-int.h
@@ -39,6 +39,9 @@ struct _GKaitaiMeta
SourceEndian endian; /* Boutisme par défaut */
+ char **dependencies; /* Définitions à importer */
+ size_t dep_count; /* Nombre de ces définitions */
+
};
/* Description globale d'une définition Kaitai (classe) */
diff --git a/plugins/kaitai/parsers/meta.c b/plugins/kaitai/parsers/meta.c
index dc30c73..132eefd 100644
--- a/plugins/kaitai/parsers/meta.c
+++ b/plugins/kaitai/parsers/meta.c
@@ -97,6 +97,9 @@ static void g_kaitai_meta_init(GKaitaiMeta *meta)
meta->endian = SRE_LITTLE;
+ meta->dependencies = NULL;
+ meta->dep_count = 0;
+
}
@@ -133,12 +136,20 @@ static void g_kaitai_meta_dispose(GKaitaiMeta *meta)
static void g_kaitai_meta_finalize(GKaitaiMeta *meta)
{
+ size_t i; /* Boucle de parcours */
+
if (meta->id != NULL)
free(meta->id);
if (meta->title != NULL)
free(meta->title);
+ for (i = 0; i < meta->dep_count; i++)
+ free(meta->dependencies[i]);
+
+ if (meta->dependencies != NULL)
+ free(meta->dependencies);
+
G_OBJECT_CLASS(g_kaitai_meta_parent_class)->finalize(G_OBJECT(meta));
}
@@ -188,6 +199,9 @@ bool g_kaitai_meta_create(GKaitaiMeta *meta, GYamlNode *parent)
bool result; /* Bilan à retourner */
GYamlNode *node; /* Noeud particulier présent */
const char *value; /* Valeur Yaml particulière */
+ GYamlNode **nodes; /* Eventuels noeuds trouvés */
+ size_t count; /* Quantité de ces noeuds */
+ size_t i; /* Boucle de parcours */
result = true;
@@ -245,6 +259,45 @@ bool g_kaitai_meta_create(GKaitaiMeta *meta, GYamlNode *parent)
}
+ /* Imports */
+
+ node = g_yaml_node_find_first_by_path(parent, "/meta/imports/");
+
+ if (node != NULL)
+ {
+ result = G_IS_YAML_COLLEC(node);
+
+ if (result)
+ {
+ nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(node), &count);
+
+ for (i = 0; i < count; i++)
+ {
+ if (!G_IS_YAML_PAIR(nodes[i]))
+ break;
+
+ value = g_yaml_pair_get_key(G_YAML_PAIR(nodes[i]));
+
+ meta->dependencies = realloc(meta->dependencies, ++meta->dep_count * sizeof(char *));
+
+ meta->dependencies[meta->dep_count - 1] = strdup(value);
+
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ }
+
+ result = (i == count);
+
+ for (; i < count; i++)
+ g_object_unref(G_OBJECT(nodes[i]));
+
+ if (nodes != NULL)
+ free(nodes);
+
+ }
+
+ }
+
return result;
}
@@ -279,7 +332,7 @@ const char *g_kaitai_meta_get_id(const GKaitaiMeta *meta)
* *
* Description : Fournit la désignation humaine d'une définiton Kaitai. *
* *
-* Retour : Intitulé de définition OU NULL. *
+* Retour : Intitulé de définition ou NULL. *
* *
* Remarques : - *
* *
@@ -317,3 +370,29 @@ SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *meta)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : meta = description globale à consulter. *
+* count = quantité de définitions à importer. [OUT] *
+* *
+* Description : Indique la liste des définitions à importer. *
+* *
+* Retour : Liste de désignations de définitions ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *meta, size_t *count)
+{
+ const char * const *result; /* Liste à retourner */
+
+ result = (const char * const *)meta->dependencies;
+
+ *count = meta->dep_count;
+
+ return result;
+
+}
diff --git a/plugins/kaitai/parsers/meta.h b/plugins/kaitai/parsers/meta.h
index 3797823..b8b685d 100644
--- a/plugins/kaitai/parsers/meta.h
+++ b/plugins/kaitai/parsers/meta.h
@@ -63,6 +63,9 @@ const char *g_kaitai_meta_get_title(const GKaitaiMeta *);
/* Indique le boustime observé par défaut par une définiton. */
SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *);
+/* Indique la liste des définitions à importer. */
+const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *, size_t *);
+
#endif /* _PLUGINS_KAITAI_PARSERS_META_H */
diff --git a/plugins/kaitai/parsers/struct-int.h b/plugins/kaitai/parsers/struct-int.h
index f34be32..6eb6e53 100644
--- a/plugins/kaitai/parsers/struct-int.h
+++ b/plugins/kaitai/parsers/struct-int.h
@@ -37,6 +37,8 @@ struct _GKaitaiStruct
{
GKaitaiParser parent; /* A laisser en premier */
+ char *filename; /* Eventuelle source de données*/
+
GKaitaiMeta *meta; /* Description globale */
GKaitaiAttribute **seq_items; /* Sous-attributs présents */
diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c
index 128a788..d447cf3 100644
--- a/plugins/kaitai/parsers/struct.c
+++ b/plugins/kaitai/parsers/struct.c
@@ -33,6 +33,7 @@
#include "struct-int.h"
+#include "../import.h"
#include "../parser.h"
#include "../records/empty.h"
#include "../records/group.h"
@@ -54,13 +55,16 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *);
/* Procède à la libération totale de la mémoire. */
static void g_kaitai_structure_finalize(GKaitaiStruct *);
+/* Charge les éventuelles dépendances de la définition. */
+static bool g_kaitai_structure_load_imports(GKaitaiStruct *);
+
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
/* Parcourt un contenu binaire selon des spécifications Kaitai. */
-static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
@@ -116,6 +120,8 @@ static void g_kaitai_structure_class_init(GKaitaiStructClass *klass)
static void g_kaitai_structure_init(GKaitaiStruct *kstruct)
{
+ kstruct->filename = NULL;
+
kstruct->meta = NULL;
kstruct->seq_items = NULL;
@@ -182,6 +188,9 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *kstruct)
static void g_kaitai_structure_finalize(GKaitaiStruct *kstruct)
{
+ if (kstruct->filename != NULL)
+ free(kstruct->filename);
+
if (kstruct->seq_items != NULL)
free(kstruct->seq_items);
@@ -305,6 +314,8 @@ bool g_kaitai_structure_create_from_file(GKaitaiStruct *kstruct, const char *fil
bool result; /* Bilan à retourner */
GYamlNode *root; /* Noeud racine YAML */
+ kstruct->filename = strdup(filename);
+
root = parse_yaml_from_file(filename);
if (root != NULL)
@@ -343,6 +354,7 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
GYamlNode **nodes; /* Eventuels noeuds trouvés */
size_t count; /* Quantité de ces noeuds */
size_t i; /* Boucle de parcours */
+ size_t first; /* Premier emplacement dispo. */
bool failed; /* Détection d'un échec */
result = false;
@@ -352,6 +364,9 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
kstruct->meta = g_kaitai_meta_new(parent);
assert(kstruct->meta != NULL);
+ result = g_kaitai_structure_load_imports(kstruct);
+ if (!result) goto bad_loading;
+
/* Séquence */
collec = g_yaml_node_find_first_by_path(parent, "/seq/");
@@ -406,13 +421,15 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
if (count > 0)
{
- kstruct->types = calloc(count, sizeof(GKaitaiType *));
- kstruct->types_count = count;
+ first = kstruct->types_count;
+
+ kstruct->types_count += count;
+ kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *));
for (i = 0; i < count; i++)
{
- kstruct->types[i] = g_kaitai_type_new(nodes[i]);
- if (kstruct->types[i] == NULL) break;
+ kstruct->types[first + i] = g_kaitai_type_new(nodes[i]);
+ if (kstruct->types[first + i] == NULL) break;
g_object_unref(G_OBJECT(nodes[i]));
@@ -529,6 +546,49 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
/******************************************************************************
* *
+* Paramètres : kstruct = lecteur de définition à initialiser pleinement. *
+* *
+* Description : Charge les éventuelles dépendances de la définition. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_structure_load_imports(GKaitaiStruct *kstruct)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ const char * const *dependencies; /* Liste d'imports requis */
+ size_t count; /* Quantité de ces imports */
+ size_t i; /* Boucle de parcours */
+ GKaitaiType *imported; /* Structure importée */
+
+ result = true;
+
+ dependencies = g_kaitai_meta_get_dependencies(kstruct->meta, &count);
+
+ for (i = 0; i < count; i++)
+ {
+ imported = import_kaitai_definition(dependencies[i], kstruct->filename);
+ if (imported == NULL) break;
+
+ kstruct->types_count++;
+ kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *));
+
+ kstruct->types[kstruct->types_count - 1] = imported;
+
+ }
+
+ result = (i == count);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : kstruct = structure Kaitai à consulter. *
* *
* Description : Fournit la description globale d'une définition Kaitai. *
@@ -624,6 +684,9 @@ GKaitaiType *g_kaitai_structure_find_sub_type(const GKaitaiStruct *kstruct, cons
break;
}
+ result = g_kaitai_structure_find_sub_type(G_KAITAI_STRUCT(kstruct->types[i]), name);
+ if (result != NULL) break;
+
}
return result;
@@ -649,13 +712,15 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont
GMatchRecord *result; /* Arborescence à retourner */
vmpa2t pos; /* Tête de lecture */
kaitai_scope_t locals; /* Variables locales */
- bool status; /* Bilan de l'analyse */
+ ext_vmpa_t epos; /* Tête de lecture complète */
g_binary_content_compute_start_pos(content, &pos);
init_record_scope(&locals, kstruct->meta);
- status = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &pos, &result);
+ init_evmpa_from_vmpa(&epos, &pos);
+
+ g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &epos, &result);
return result;
@@ -673,7 +738,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont
* Paramètres : kstruct = structure Kaitai en cours de parcours. *
* locals = variables locales pour les résolutions de types. *
* content = données binaires à analyser et traduire. *
-* pos = tête de lecture courante. [OUT] *
+* epos = tête de lecture courante. [OUT] *
* record = noeud d'arborescence d'éléments rencontrés. [OUT] *
* *
* Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
@@ -684,7 +749,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont
* *
******************************************************************************/
-static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
{
bool result; /* Bilan à retourner */
GRecordGroup *group; /* Ensemble à constituer */
@@ -697,7 +762,7 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
/* Si le groupe est vide */
if ((kstruct->seq_items_count + kstruct->instances_count) == 0)
{
- *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, pos));
+ *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, &epos->base));
if (locals->root == NULL)
locals->root = *record;
@@ -716,10 +781,18 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
old = locals->parent;
locals->parent = *record;
- for (i = 0; i < kstruct->seq_items_count; i++)
+ /**
+ * Les instances sont à charger avant les éléments fixes car
+ * des références au premières peuvent être attendues dans ces derniers.
+ *
+ * Les évolutions de la tête de lecture n'ont en revanche normalement
+ * pas d'incidence sur le chargement des éléments fixes.
+ */
+
+ for (i = 0; i < kstruct->instances_count; i++)
{
- result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]),
- locals, content, pos, &child);
+ result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]),
+ locals, content, epos, &child);
if (!result) goto exit;
if (child != NULL)
@@ -730,10 +803,16 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
}
- for (i = 0; i < kstruct->instances_count; i++)
+ /**
+ * Seconde phase.
+ */
+
+ locals->parent = *record;
+
+ for (i = 0; i < kstruct->seq_items_count; i++)
{
- result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]),
- locals, content, pos, &child);
+ result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]),
+ locals, content, epos, &child);
if (!result) goto exit;
if (child != NULL)
@@ -748,6 +827,9 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
locals->parent = old;
+ if (!result)
+ g_clear_object(record);
+
}
return result;
diff --git a/plugins/kaitai/parsers/switch.c b/plugins/kaitai/parsers/switch.c
index c823f27..6cfc96b 100644
--- a/plugins/kaitai/parsers/switch.c
+++ b/plugins/kaitai/parsers/switch.c
@@ -83,7 +83,7 @@ static void g_kaitai_switch_finalize(GKaitaiSwitch *);
/* Parcourt un contenu binaire selon des spécifications Kaitai. */
-static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
@@ -285,7 +285,7 @@ static const char *is_suitable_switch_case_for_integer(const switch_case_t *swca
{
if (value->type == GVT_UNSIGNED_INTEGER)
{
- unsigned_conv = strtoull(swcase->value, NULL, 10);
+ unsigned_conv = strtoull(swcase->value, NULL, 0);
valid = (errno != ERANGE && errno != EINVAL);
@@ -295,7 +295,7 @@ static const char *is_suitable_switch_case_for_integer(const switch_case_t *swca
}
else
{
- signed_conv = strtoll(swcase->value, NULL, 10);
+ signed_conv = strtoll(swcase->value, NULL, 0);
valid = (errno != ERANGE && errno != EINVAL);
@@ -569,7 +569,7 @@ bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAt
* Paramètres : kswitch = structure Kaitai en cours de parcours. *
* locals = variables locales pour les résolutions de types. *
* content = données binaires à analyser et traduire. *
-* pos = tête de lecture courante. [OUT] *
+* epos = tête de lecture courante. [OUT] *
* record = noeud d'arborescence d'éléments rencontrés. [OUT] *
* *
* Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
@@ -580,127 +580,65 @@ bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAt
* *
******************************************************************************/
-static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
{
bool result; /* Bilan à retourner */
- GMatchRecord *reference; /* Correspondance à utiliser */
- GKaitaiParser *creator; /* Lecteur d'origine */
- KaitaiAttributePayload payload; /* Type de charge supportée */
- BaseType basic; /* Type de base reconnu */
- bool is_string; /* Type lié à une chaîne ? */
-#ifndef NDEBUG
- bool status; /* Bilan d'une consultation */
-#endif
const char *final_type; /* Type à utiliser au final */
resolved_value_t value; /* Valeur de cible entière */
+ bool status; /* Bilan intermédiaire */
size_t i; /* Boucle de parcours */
GKaitaiAttribute *attrib; /* Lecteur approprié */
- result = false;
-
- /* Détermination de la forme de comparaison */
-
- reference = g_match_record_find_by_name(locals->parent,
- kswitch->target, strlen(kswitch->target),
- DIRECT_SEARCH_DEEP_LEVEL);
-
- if (reference == NULL)
- goto exit;
-
- creator = g_match_record_get_creator(reference);
-
- if (creator == NULL)
- goto exit_with_ref;
-
- if (!G_IS_KAITAI_ATTRIBUTE(creator))
- goto exit_with_creator;
-
- payload = g_kaitai_attribute_get_payload(G_KAITAI_ATTRIBUTE(creator));
-
- if ((payload & KAP_BASIC_TYPE) == 0)
- goto exit_with_creator;
-
-#ifndef NDEBUG
- status = g_kaitai_attribute_get_basic_type(G_KAITAI_ATTRIBUTE(creator), &basic, &is_string);
- assert(status);
-#else
- g_kaitai_attribute_get_basic_type(G_KAITAI_ATTRIBUTE(creator), &basic, &is_string);
-#endif
-
- /* Détermination du type visé */
+ result = true;
final_type = NULL;
- if (is_string)
- {
- result = resolve_kaitai_expression_as_bytes(locals,
- kswitch->target,
- strlen(kswitch->target),
- &value);
- if (!result) goto exit_with_creator;
+ /* Tenative n°1 : version "entier" */
+
+ status = resolve_kaitai_expression_as_integer(locals, kswitch->target, strlen(kswitch->target), &value);
+ if (status)
for (i = 0; i < kswitch->count; i++)
{
- final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value);
+ final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value);
if (final_type != NULL)
- break;
+ goto next_step;
}
- }
-
- else
- {
- if (basic == BTP_UCHAR || basic == BTP_USHORT || basic == BTP_UINT || basic == BTP_ULONG_LONG)
- {
- result = resolve_kaitai_expression_as_integer(locals,
- kswitch->target,
- strlen(kswitch->target),
- &value);
- if (!result) goto exit_with_creator;
+ status = resolve_kaitai_expression_as_bytes(locals, kswitch->target, strlen(kswitch->target), &value);
- for (i = 0; i < kswitch->count; i++)
- {
- final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value);
+ /* Tenative n°1 : version "chaîne" */
- if (final_type != NULL)
- break;
+ if (status)
+ for (i = 0; i < kswitch->count; i++)
+ {
+ final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value);
- }
+ if (final_type != NULL)
+ goto next_step;
}
- else
- printf("other type: %u\n", basic);
-
- }
-
if (final_type == NULL && kswitch->defcase != NULL)
final_type = kswitch->defcase->type;
+ next_step:
+
/* Mise en place d'un attribut et analyse */
if (final_type != NULL)
{
attrib = g_kaitai_attribute_dup_for_user_type(kswitch->generic, final_type);
- result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib), locals, content, pos, record);
+ result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib), locals, content, epos, record);
g_object_unref(G_OBJECT(attrib));
}
- exit_with_creator:
-
- g_object_unref(G_OBJECT(creator));
-
- exit_with_ref:
-
- g_object_unref(G_OBJECT(reference));
-
- exit:
-
+ return true;
return result;
}
diff --git a/plugins/kaitai/parsers/type-int.h b/plugins/kaitai/parsers/type-int.h
index 4a4d939..535ce57 100644
--- a/plugins/kaitai/parsers/type-int.h
+++ b/plugins/kaitai/parsers/type-int.h
@@ -50,6 +50,9 @@ struct _GKaitaiTypeClass
/* Met en place un lecteur de type pour Kaitai. */
bool g_kaitai_type_create(GKaitaiType *, GYamlNode *);
+/* Met en place un lecteur de type externe pour Kaitai. */
+bool g_kaitai_type_create_as_import(GKaitaiType *, const char *, const char *);
+
#endif /* PLUGINS_KAITAI_PARSERS_TYPE_INT_H */
diff --git a/plugins/kaitai/parsers/type.c b/plugins/kaitai/parsers/type.c
index 30d0373..81efbeb 100644
--- a/plugins/kaitai/parsers/type.c
+++ b/plugins/kaitai/parsers/type.c
@@ -215,6 +215,64 @@ bool g_kaitai_type_create(GKaitaiType *type, GYamlNode *parent)
/******************************************************************************
* *
+* Paramètres : name = nom à attribuer au futur type. *
+* filename = chemin vers une définition Kaitai à charger. *
+* *
+* Description : Construit un lecteur de type externe pour Kaitai. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiType *g_kaitai_type_new_as_import(const char *name, const char *filename)
+{
+ GKaitaiType *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_TYPE, NULL);
+
+ if (!g_kaitai_type_create_as_import(result, name, filename))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = lecteur de type Kaitai à initialiser pleinement. *
+* name = nom à attribuer au futur type. *
+* filename = chemin vers une définition Kaitai à charger. *
+* *
+* Description : Met en place un lecteur de type externe pour Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_type_create_as_import(GKaitaiType *type, const char *name, const char *filename)
+{
+ bool result; /* Bilan à retourner */
+
+ /* Extraction du nom */
+
+ type->name = strdup(name);
+
+ /* Extraction des bases du type */
+
+ result = g_kaitai_structure_create_from_file(G_KAITAI_STRUCT(type), filename);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : type = définition de type particulier à consulter. *
* *
* Description : Indique le nom de scène du type représenté. *
diff --git a/plugins/kaitai/parsers/type.h b/plugins/kaitai/parsers/type.h
index 0656c64..d19ab90 100644
--- a/plugins/kaitai/parsers/type.h
+++ b/plugins/kaitai/parsers/type.h
@@ -54,6 +54,9 @@ GType g_kaitai_type_get_type(void);
/* Construit un lecteur de type pour Kaitai. */
GKaitaiType *g_kaitai_type_new(GYamlNode *);
+/* Construit un lecteur de type externe pour Kaitai. */
+GKaitaiType *g_kaitai_type_new_as_import(const char *, const char *);
+
/* Indique le nom de scène du type représenté. */
const char *g_kaitai_type_get_name(const GKaitaiType *);
diff --git a/plugins/kaitai/python/Makefile.am b/plugins/kaitai/python/Makefile.am
index ab40744..f222a66 100644
--- a/plugins/kaitai/python/Makefile.am
+++ b/plugins/kaitai/python/Makefile.am
@@ -11,7 +11,8 @@ libkaitaipython_la_SOURCES = \
libkaitaipython_la_LIBADD = \
parsers/libkaitaipythonparsers.la \
- records/libkaitaipythonrecords.la
+ records/libkaitaipythonrecords.la \
+ rost/libkaitaipythonrost.la
libkaitaipython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
@@ -22,4 +23,4 @@ devdir = $(includedir)/chrysalide-$(subdir)
dev_HEADERS = $(libkaitaipython_la_SOURCES:%c=)
-SUBDIRS = parsers records
+SUBDIRS = parsers records rost
diff --git a/plugins/kaitai/python/module.c b/plugins/kaitai/python/module.c
index fa1f9c2..07fb962 100644
--- a/plugins/kaitai/python/module.c
+++ b/plugins/kaitai/python/module.c
@@ -39,6 +39,7 @@
#include "stream.h"
#include "parsers/module.h"
#include "records/module.h"
+#include "rost/module.h"
@@ -89,6 +90,7 @@ bool add_kaitai_module_to_python_module(void)
if (result) result = add_kaitai_parsers_module();
if (result) result = add_kaitai_records_module();
+ if (result) result = add_kaitai_rost_module();
if (!result)
Py_XDECREF(module);
@@ -124,6 +126,7 @@ bool populate_kaitai_module(void)
if (result) result = populate_kaitai_parsers_module();
if (result) result = populate_kaitai_records_module();
+ if (result) result = populate_kaitai_rost_module();
assert(result);
diff --git a/plugins/kaitai/python/parsers/attribute.c b/plugins/kaitai/python/parsers/attribute.c
index c8ea314..c2f3db6 100644
--- a/plugins/kaitai/python/parsers/attribute.c
+++ b/plugins/kaitai/python/parsers/attribute.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * attribute.h - équivalent Python du fichier "plugins/kaitai/parsers/attribute.h"
+ * attribute.c - équivalent Python du fichier "plugins/kaitai/parsers/attribute.c"
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -149,9 +149,14 @@ static PyObject *py_kaitai_attribute_get_raw_id(PyObject *self, void *closure)
attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self));
value = g_kaitai_attribute_get_raw_id(attrib);
- assert(value != NULL);
- result = PyUnicode_FromString(value);
+ if (value == NULL)
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ else
+ result = PyUnicode_FromString(value);
return result;
diff --git a/plugins/kaitai/python/parsers/meta.c b/plugins/kaitai/python/parsers/meta.c
index 3432640..0bd7bf9 100644
--- a/plugins/kaitai/python/parsers/meta.c
+++ b/plugins/kaitai/python/parsers/meta.c
@@ -50,6 +50,9 @@ static PyObject *py_kaitai_meta_get_id(PyObject *, void *);
/* Fournit la désignation humaine d'une définiton Kaitai. */
static PyObject *py_kaitai_meta_get_title(PyObject *, void *);
+/* Indique la liste des définitions à importer. */
+static PyObject *py_kaitai_meta_get_dependencies(PyObject *, void *);
+
/******************************************************************************
@@ -162,7 +165,7 @@ static PyObject *py_kaitai_meta_get_id(PyObject *self, void *closure)
* *
* Description : Fournit la désignation humaine d'une définiton Kaitai. *
* *
-* Retour : Intitulé de définition OU None. *
+* Retour : Intitulé de définition ou None. *
* *
* Remarques : - *
* *
@@ -206,7 +209,7 @@ static PyObject *py_kaitai_meta_get_title(PyObject *self, void *closure)
* *
* Description : Fournit la désignation humaine d'une définiton Kaitai. *
* *
-* Retour : Intitulé de définition OU None. *
+* Retour : Intitulé de définition ou None. *
* *
* Remarques : - *
* *
@@ -238,6 +241,50 @@ static PyObject *py_kaitai_meta_get_endian(PyObject *self, void *closure)
/******************************************************************************
* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique la liste des définitions à importer. *
+* *
+* Retour : Liste de désignations de définitions, vide ou non. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_kaitai_meta_get_dependencies(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GKaitaiMeta *meta; /* Version native de l'objet */
+ const char * const *dependencies; /* Liste d'imports requis */
+ size_t count; /* Quantité de ces imports */
+ size_t i; /* Boucle de parcours */
+
+#define KAITAI_META_DEPENDENCIES_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ dependencies, py_kaitai_meta, \
+ "Tuple of all definitions to import for the current" \
+ " definition.\n" \
+ "\n" \
+ "The result may be an empty string list." \
+)
+
+ meta = G_KAITAI_META(pygobject_get(self));
+
+ dependencies = g_kaitai_meta_get_dependencies(meta, &count);
+
+ result = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ PyTuple_SetItem(result, i, PyUnicode_FromString(dependencies[i]));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : - *
* *
* Description : Fournit un accès à une définition de type à diffuser. *
@@ -258,6 +305,7 @@ PyTypeObject *get_python_kaitai_meta_type(void)
KAITAI_META_ID_ATTRIB,
KAITAI_META_TITLE_ATTRIB,
KAITAI_META_ENDIAN_ATTRIB,
+ KAITAI_META_DEPENDENCIES_ATTRIB,
{ NULL }
};
diff --git a/plugins/kaitai/python/records/Makefile.am b/plugins/kaitai/python/records/Makefile.am
index 1413228..3a3c672 100644
--- a/plugins/kaitai/python/records/Makefile.am
+++ b/plugins/kaitai/python/records/Makefile.am
@@ -2,12 +2,13 @@
noinst_LTLIBRARIES = libkaitaipythonrecords.la
libkaitaipythonrecords_la_SOURCES = \
+ bits.h bits.c \
+ delayed.h delayed.c \
empty.h empty.c \
group.h group.c \
item.h item.c \
list.h list.c \
- module.h module.c \
- value.h value.c
+ module.h module.c
libkaitaipythonrecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
diff --git a/plugins/kaitai/python/records/bits.c b/plugins/kaitai/python/records/bits.c
new file mode 100644
index 0000000..f94148b
--- /dev/null
+++ b/plugins/kaitai/python/records/bits.c
@@ -0,0 +1,318 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.h - équivalent Python du fichier "plugins/kaitai/parsers/bits.h"
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "bits.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/arch/vmpa.h>
+
+
+#include "../record.h"
+#include "../parsers/attribute.h"
+#include "../../records/bits-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(record_bit_field, G_TYPE_RECORD_BIT_FIELD);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_record_bit_field_init(PyObject *, PyObject *, PyObject *);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+static PyObject *py_record_bit_field_get_value(PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_record_bit_field_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+#if 0
+ GKaitaiAttribute *attrib; /* Attribut défini créateur */
+ GBinContent *content; /* Contenu binaire analysé */
+ mrange_t range; /* Espace couvert */
+ SourceEndian endian; /* Boutisme à observer */
+ int ret; /* Bilan de lecture des args. */
+ GRecordBitField *field; /* Création GLib à transmettre */
+#endif
+
+#define RECORD_BIT_FIELD_DOC \
+ "The RecordItem class remembers a match between a described attribute and" \
+ " its concret value read from parsed binary data." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " RecordItem(content, range, endian, attrib)" \
+ "\n" \
+ "Where the *attrib* arguments refers to a" \
+ " pychrysalide.plugins.kaitai.parsers.KaitaiAttribute instance as the" \
+ " creator of the newly created object, *content* points to a" \
+ " pychrysalide.analysis.BinContent instance, *range* is a" \
+ " pychrysalide.arch.mrange object, *endian* states with a" \
+ " pychrysalide.analysis.BinContent.SourceEndian hint the endianness used" \
+ " to read integer values."
+
+ /* Récupération des paramètres */
+
+#if 0 /* FIXME */
+
+ ret = PyArg_ParseTuple(args, "O&O&O&",
+ convert_to_kaitai_attribute, &attrib,
+ convert_to_binary_content, &content,
+ convert_any_to_mrange, &range,
+ convert_to_binary_content, &endian);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ field = G_RECORD_BIT_FIELD(pygobject_get(self));
+
+ if (!g_record_bit_field_create(field, attrib, content, &range, endian))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create record bit field."));
+ return -1;
+ }
+
+ return 0;
+
+#endif
+
+ PyErr_SetString(PyExc_ValueError, _("Unable to create record bit field at the moment."));
+ return -1;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Lit la valeur d'un élément Kaitai entier représenté. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_record_bit_field_get_value(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GRecordBitField *field; /* Version native de l'élément */
+ resolved_value_t resolved; /* Valeur sous forme générique */
+ bool status; /* Bilan d'opération */
+
+#define RECORD_BIT_FIELD_VALUE_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ value, py_record_bit_field, \
+ "Carried value (as integer), or None in case of error." \
+)
+
+ result = NULL;
+
+ field = G_RECORD_BIT_FIELD(pygobject_get(self));
+
+ status = g_record_bit_field_get_value(field, &resolved);
+
+ if (status)
+ switch (resolved.type)
+ {
+ case GVT_UNSIGNED_INTEGER:
+ result = PyLong_FromUnsignedLongLong(resolved.unsigned_integer);
+ break;
+
+ default:
+ assert(false);
+ result = Py_None;
+ Py_INCREF(result);
+ break;
+
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_record_bit_field_type(void)
+{
+ static PyMethodDef py_record_bit_field_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_record_bit_field_getseters[] = {
+ RECORD_BIT_FIELD_VALUE_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_record_bit_field_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.records.RecordBitField",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = RECORD_BIT_FIELD_DOC,
+
+ .tp_methods = py_record_bit_field_methods,
+ .tp_getset = py_record_bit_field_getseters,
+
+ .tp_init = py_record_bit_field_init,
+ .tp_new = py_record_bit_field_new,
+
+ };
+
+ return &py_record_bit_field_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.....RecordBitField. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_record_bit_field_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'RecordItem' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_record_bit_field_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.records");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_match_record_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_RECORD_BIT_FIELD, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en correspondance attribut/binaire. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_record_bit_field(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_record_bit_field_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record bit field");
+ break;
+
+ case 1:
+ *((GRecordBitField **)dst) = G_RECORD_BIT_FIELD(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/records/bits.h b/plugins/kaitai/python/records/bits.h
new file mode 100644
index 0000000..6c833bb
--- /dev/null
+++ b/plugins/kaitai/python/records/bits.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/bits.h"
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_BITS_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_BITS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_record_bit_field_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordBitField'. */
+bool ensure_python_record_bit_field_is_registered(void);
+
+/* Tente de convertir en correspondance attribut/binaire. */
+int convert_to_record_bit_field(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_BITS_H */
diff --git a/plugins/kaitai/python/records/value.c b/plugins/kaitai/python/records/delayed.c
index bd4ad74..32e3db1 100644
--- a/plugins/kaitai/python/records/value.c
+++ b/plugins/kaitai/python/records/delayed.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * value.c - équivalent Python du fichier "plugins/kaitai/parsers/value.c"
+ * delayed.c - équivalent Python du fichier "plugins/kaitai/parsers/delayed.c"
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -22,7 +22,7 @@
*/
-#include "value.h"
+#include "delayed.h"
#include <assert.h>
@@ -40,17 +40,17 @@
#include "../record.h"
#include "../scope.h"
#include "../parsers/instance.h"
-#include "../../records/value-int.h"
+#include "../../records/delayed-int.h"
-CREATE_DYN_CONSTRUCTOR(record_value, G_TYPE_RECORD_VALUE);
+CREATE_DYN_CONSTRUCTOR(record_delayed, G_TYPE_RECORD_DELAYED);
/* Initialise une instance sur la base du dérivé de GObject. */
-static int py_record_value_init(PyObject *, PyObject *, PyObject *);
+static int py_record_delayed_init(PyObject *, PyObject *, PyObject *);
/* Lit la valeur d'un élément Kaitai entier représenté. */
-static PyObject *py_record_value_get_value(PyObject *, void *);
+static PyObject *py_record_delayed_get_value(PyObject *, void *);
@@ -68,31 +68,37 @@ static PyObject *py_record_value_get_value(PyObject *, void *);
* *
******************************************************************************/
-static int py_record_value_init(PyObject *self, PyObject *args, PyObject *kwds)
+static int py_record_delayed_init(PyObject *self, PyObject *args, PyObject *kwds)
{
GKaitaiInstance *inst; /* Instance définie créatrice */
kaitai_scope_t *locals; /* Environnement local */
+ GBinContent *content; /* Contenu binaire analysé */
int ret; /* Bilan de lecture des args. */
- GRecordValue *value; /* Création GLib à transmettre */
+ GRecordDelayed *delayed; /* Création GLib à transmettre */
-#define RECORD_VALUE_DOC \
- "The RecordValue class stores a link to an instance used to compute a" \
+#define RECORD_DELAYED_DOC \
+ "The RecordDelayed class stores a link to an instance used to compute a" \
" given value." \
"\n" \
"Instances can be created using the following constructor:\n" \
"\n" \
- " RecordValue(inst, locals)" \
+ " RecordDelayed(inst, locals, content)" \
"\n" \
"Where the *inst* arguments refers to a" \
" pychrysalide.plugins.kaitai.parsers.KaitaiInstance instance as the" \
" creator of the newly created object, *locals* points to a" \
- " pychrysalide.plugins.kaitai.KaitaiScope structure used as current scope."
+ " pychrysalide.plugins.kaitai.KaitaiScope structure used as current scope." \
+ " The *content* argument is a pychrysalide.analysis.BinContent instance if" \
+ " the delayed instance does not define a direct value."
/* Récupération des paramètres */
- ret = PyArg_ParseTuple(args, "O&O&",
+ content = NULL;
+
+ ret = PyArg_ParseTuple(args, "O&O&|O&",
convert_to_kaitai_instance, &inst,
- convert_to_kaitai_scope, &locals);
+ convert_to_kaitai_scope, &locals,
+ convert_to_binary_content_or_none, &content);
if (!ret) return -1;
/* Initialisation d'un objet GLib */
@@ -102,11 +108,11 @@ static int py_record_value_init(PyObject *self, PyObject *args, PyObject *kwds)
/* Eléments de base */
- value = G_RECORD_VALUE(pygobject_get(self));
+ delayed = G_RECORD_DELAYED(pygobject_get(self));
- if (!g_record_value_create(value, inst, locals))
+ if (!g_record_delayed_create(delayed, inst, locals, content))
{
- PyErr_SetString(PyExc_ValueError, _("Unable to create record value."));
+ PyErr_SetString(PyExc_ValueError, _("Unable to create record delayed."));
return -1;
}
@@ -128,24 +134,24 @@ static int py_record_value_init(PyObject *self, PyObject *args, PyObject *kwds)
* *
******************************************************************************/
-static PyObject *py_record_value_get_value(PyObject *self, void *closure)
+static PyObject *py_record_delayed_get_value(PyObject *self, void *closure)
{
PyObject *result; /* Valeur à retourner */
- GRecordValue *value; /* Version native de l'élément */
+ GRecordDelayed *delayed; /* Version native de l'élément */
resolved_value_t resolved; /* Valeur sous forme générique */
bool status; /* Bilan d'opération */
-#define RECORD_VALUE_VALUE_ATTRIB PYTHON_GET_DEF_FULL \
+#define RECORD_DELAYED_VALUE_ATTRIB PYTHON_GET_DEF_FULL \
( \
- value, py_record_value, \
+ value, py_record_delayed, \
"Carried value (as integer, bytes), or None in case of error." \
)
result = NULL;
- value = G_RECORD_VALUE(pygobject_get(self));
+ delayed = G_RECORD_DELAYED(pygobject_get(self));
- status = g_record_value_compute_and_aggregate_value(value, &resolved);
+ status = g_record_delayed_compute_and_aggregate_value(delayed, &resolved);
if (status)
switch (resolved.type)
@@ -216,37 +222,37 @@ static PyObject *py_record_value_get_value(PyObject *self, void *closure)
* *
******************************************************************************/
-PyTypeObject *get_python_record_value_type(void)
+PyTypeObject *get_python_record_delayed_type(void)
{
- static PyMethodDef py_record_value_methods[] = {
+ static PyMethodDef py_record_delayed_methods[] = {
{ NULL }
};
- static PyGetSetDef py_record_value_getseters[] = {
- RECORD_VALUE_VALUE_ATTRIB,
+ static PyGetSetDef py_record_delayed_getseters[] = {
+ RECORD_DELAYED_VALUE_ATTRIB,
{ NULL }
};
- static PyTypeObject py_record_value_type = {
+ static PyTypeObject py_record_delayed_type = {
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "pychrysalide.plugins.kaitai.records.RecordValue",
+ .tp_name = "pychrysalide.plugins.kaitai.records.RecordDelayed",
.tp_basicsize = sizeof(PyGObject),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_doc = RECORD_VALUE_DOC,
+ .tp_doc = RECORD_DELAYED_DOC,
- .tp_methods = py_record_value_methods,
- .tp_getset = py_record_value_getseters,
+ .tp_methods = py_record_delayed_methods,
+ .tp_getset = py_record_delayed_getseters,
- .tp_init = py_record_value_init,
- .tp_new = py_record_value_new,
+ .tp_init = py_record_delayed_init,
+ .tp_new = py_record_delayed_new,
};
- return &py_record_value_type;
+ return &py_record_delayed_type;
}
@@ -255,7 +261,7 @@ PyTypeObject *get_python_record_value_type(void)
* *
* Paramètres : - *
* *
-* Description : Prend en charge l'objet 'pychrysalide...records.RecordValue. *
+* Description : Prend en charge l'objet 'pychrysalide..records.RecordDelayed.*
* *
* Retour : Bilan de l'opération. *
* *
@@ -263,13 +269,13 @@ PyTypeObject *get_python_record_value_type(void)
* *
******************************************************************************/
-bool ensure_python_record_value_is_registered(void)
+bool ensure_python_record_delayed_is_registered(void)
{
- PyTypeObject *type; /* Type Python 'RecordValue' */
+ PyTypeObject *type; /* Type Python 'RecordDelayed' */
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
- type = get_python_record_value_type();
+ type = get_python_record_delayed_type();
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
{
@@ -280,7 +286,7 @@ bool ensure_python_record_value_is_registered(void)
if (!ensure_python_match_record_is_registered())
return false;
- if (!register_class_for_pygobject(dict, G_TYPE_RECORD_VALUE, type))
+ if (!register_class_for_pygobject(dict, G_TYPE_RECORD_DELAYED, type))
return false;
}
@@ -303,11 +309,11 @@ bool ensure_python_record_value_is_registered(void)
* *
******************************************************************************/
-int convert_to_record_value(PyObject *arg, void *dst)
+int convert_to_record_delayed(PyObject *arg, void *dst)
{
int result; /* Bilan à retourner */
- result = PyObject_IsInstance(arg, (PyObject *)get_python_record_value_type());
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_record_delayed_type());
switch (result)
{
@@ -317,11 +323,11 @@ int convert_to_record_value(PyObject *arg, void *dst)
break;
case 0:
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record value");
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record delayed");
break;
case 1:
- *((GRecordValue **)dst) = G_RECORD_VALUE(pygobject_get(arg));
+ *((GRecordDelayed **)dst) = G_RECORD_DELAYED(pygobject_get(arg));
break;
default:
diff --git a/plugins/kaitai/python/records/value.h b/plugins/kaitai/python/records/delayed.h
index 16cadcb..ba2d23a 100644
--- a/plugins/kaitai/python/records/value.h
+++ b/plugins/kaitai/python/records/delayed.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * value.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/value.h"
+ * delayed.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/delayed.h"
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -22,8 +22,8 @@
*/
-#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H
-#define _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H
+#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H
+#define _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H
#include <Python.h>
@@ -32,14 +32,14 @@
/* Fournit un accès à une définition de type à diffuser. */
-PyTypeObject *get_python_record_value_type(void);
+PyTypeObject *get_python_record_delayed_type(void);
-/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordValue'. */
-bool ensure_python_record_value_is_registered(void);
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordDelayed'. */
+bool ensure_python_record_delayed_is_registered(void);
/* Tente de convertir en valeur calculée. */
-int convert_to_record_value(PyObject *, void *);
+int convert_to_record_delayed(PyObject *, void *);
-#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H */
+#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H */
diff --git a/plugins/kaitai/python/records/module.c b/plugins/kaitai/python/records/module.c
index ea33c31..af97434 100644
--- a/plugins/kaitai/python/records/module.c
+++ b/plugins/kaitai/python/records/module.c
@@ -32,11 +32,12 @@
#include <plugins/pychrysalide/helpers.h>
+#include "bits.h"
+#include "delayed.h"
#include "empty.h"
#include "group.h"
#include "item.h"
#include "list.h"
-#include "value.h"
@@ -109,11 +110,12 @@ bool populate_kaitai_records_module(void)
result = true;
+ if (result) result = ensure_python_record_bit_field_is_registered();
+ if (result) result = ensure_python_record_delayed_is_registered();
if (result) result = ensure_python_record_empty_is_registered();
if (result) result = ensure_python_record_group_is_registered();
if (result) result = ensure_python_record_item_is_registered();
if (result) result = ensure_python_record_list_is_registered();
- if (result) result = ensure_python_record_value_is_registered();
assert(result);
diff --git a/plugins/kaitai/python/rost/Makefile.am b/plugins/kaitai/python/rost/Makefile.am
new file mode 100644
index 0000000..cae0419
--- /dev/null
+++ b/plugins/kaitai/python/rost/Makefile.am
@@ -0,0 +1,14 @@
+
+noinst_LTLIBRARIES = libkaitaipythonrost.la
+
+libkaitaipythonrost_la_SOURCES = \
+ module.h module.c \
+ trigger.h trigger.c
+
+libkaitaipythonrost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaipythonrost_la_SOURCES:%c=)
diff --git a/plugins/kaitai/python/rost/module.c b/plugins/kaitai/python/rost/module.c
new file mode 100644
index 0000000..66a5a82
--- /dev/null
+++ b/plugins/kaitai/python/rost/module.c
@@ -0,0 +1,115 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire rost en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "trigger.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Ajoute le module 'plugins.kaitai.rost' au module Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_kaitai_rost_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_PLUGINS_KAITAI_ROST_DOC \
+ "This module creates some glue to extend the ROST features" \
+ " using Kaitai definitions for analyzing and filtering" \
+ " contents."
+
+ static PyModuleDef py_chrysalide_kaitai_rost_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.plugins.kaitai.rost",
+ .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_ROST_DOC,
+
+ .m_size = -1,
+
+ };
+
+ result = false;
+
+ super = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+ module = build_python_module(super, &py_chrysalide_kaitai_rost_module);
+
+ result = (module != NULL);
+
+ assert(result);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'plugins.kaitai.rost'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_kaitai_rost_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_kaitai_trigger_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/rost/module.h b/plugins/kaitai/python/rost/module.h
new file mode 100644
index 0000000..8415c2e
--- /dev/null
+++ b/plugins/kaitai/python/rost/module.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire rost en tant que module
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H
+#define _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.kaitai.rost' au module Python. */
+bool add_kaitai_rost_module(void);
+
+/* Intègre les objets du module 'plugins.kaitai.rost'. */
+bool populate_kaitai_rost_module(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H */
diff --git a/plugins/kaitai/python/rost/trigger.c b/plugins/kaitai/python/rost/trigger.c
new file mode 100644
index 0000000..180ef6e
--- /dev/null
+++ b/plugins/kaitai/python/rost/trigger.c
@@ -0,0 +1,236 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.c - équivalent Python du fichier "plugins/kaitai/rost/trigger.c"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "trigger.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/scan/item.h>
+
+
+#include "../parsers/struct.h"
+#include "../../parsers/struct.h"
+#include "../../rost/trigger-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_trigger, G_TYPE_KAITAI_TRIGGER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_trigger_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_kaitai_trigger_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GKaitaiStruct *kstruct; /* Définition Kaitai en place */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiTrigger *trigger; /* Création GLib à transmettre */
+
+#define KAITAI_TRIGGER_DOC \
+ "The KaitaiTrigger object store an access to a loaded Kaitai definition" \
+ " creates as many as required instances from it when ROST filters contents" \
+ " with the help of the Kaitai module.\n" \
+ "\n" \
+ "Instances can be created using following constructor:\n" \
+ "\n" \
+ " KaitaiTrigger(kstruct)" \
+ "\n" \
+ "Where *kstruct* is a pychrysalide.plugins.kaitai.parsers.KaitaiStruct" \
+ " instance loaded with a valid Kaitai definition."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_kaitai_structure, &kstruct);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ trigger = G_KAITAI_TRIGGER(pygobject_get(self));
+
+ if (!g_kaitai_trigger_create(trigger, kstruct))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai stream."));
+ return -1;
+
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_trigger_type(void)
+{
+ static PyMethodDef py_kaitai_trigger_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_trigger_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_trigger_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.rost.KaitaiTrigger",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = KAITAI_TRIGGER_DOC,
+
+ .tp_methods = py_kaitai_trigger_methods,
+ .tp_getset = py_kaitai_trigger_getseters,
+
+ .tp_init = py_kaitai_trigger_init,
+ .tp_new = py_kaitai_trigger_new,
+
+ };
+
+ return &py_kaitai_trigger_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....rost.KaitaiTrigger. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_trigger_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'RecordEmpty' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_trigger_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.rost");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_registered_item_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_TRIGGER, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en accès à une définition Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_trigger(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_trigger_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai trigger");
+ break;
+
+ case 1:
+ *((GKaitaiTrigger **)dst) = G_KAITAI_TRIGGER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/rost/trigger.h b/plugins/kaitai/python/rost/trigger.h
new file mode 100644
index 0000000..44776f7
--- /dev/null
+++ b/plugins/kaitai/python/rost/trigger.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/rost/trigger.h"
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H
+#define _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_trigger_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.rost.KaitaiTrigger'. */
+bool ensure_python_kaitai_trigger_is_registered(void);
+
+/* Tente de convertir en accès à une définition Kaitai. */
+int convert_to_kaitai_trigger(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H */
diff --git a/plugins/kaitai/record.c b/plugins/kaitai/record.c
index 5717b17..de1e80d 100644
--- a/plugins/kaitai/record.c
+++ b/plugins/kaitai/record.c
@@ -115,6 +115,10 @@ static void g_match_record_init(GMatchRecord *record)
static void g_match_record_dispose(GMatchRecord *record)
{
+ g_clear_object(&record->creator);
+
+ g_clear_object(&record->content);
+
G_OBJECT_CLASS(g_match_record_parent_class)->dispose(G_OBJECT(record));
}
@@ -331,12 +335,16 @@ static GMatchRecord *_g_match_record_find_by_name(GMatchRecord *record, const ch
{
label = g_kaitai_attribute_get_label(G_KAITAI_ATTRIBUTE(record->creator));
- label_len = strlen(label);
-
- if (label_len == len && strncmp(label, name, len) == 0)
+ if (label != NULL)
{
- result = record;
- g_object_ref(G_OBJECT(result));
+ label_len = strlen(label);
+
+ if (label_len == len && strncmp(label, name, len) == 0)
+ {
+ result = record;
+ g_object_ref(G_OBJECT(result));
+ }
+
}
}
diff --git a/plugins/kaitai/records/Makefile.am b/plugins/kaitai/records/Makefile.am
index c11e823..3884bfb 100644
--- a/plugins/kaitai/records/Makefile.am
+++ b/plugins/kaitai/records/Makefile.am
@@ -2,6 +2,10 @@
noinst_LTLIBRARIES = libkaitairecords.la
libkaitairecords_la_SOURCES = \
+ bits-int.h \
+ bits.h bits.c \
+ delayed-int.h \
+ delayed.h delayed.c \
empty-int.h \
empty.h empty.c \
group-int.h \
@@ -9,9 +13,7 @@ libkaitairecords_la_SOURCES = \
item-int.h \
item.h item.c \
list-int.h \
- list.h list.c \
- value-int.h \
- value.h value.c
+ list.h list.c
libkaitairecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
diff --git a/plugins/kaitai/records/bits-int.h b/plugins/kaitai/records/bits-int.h
new file mode 100644
index 0000000..7b03911
--- /dev/null
+++ b/plugins/kaitai/records/bits-int.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits-int.h - prototypes internes pour la conservation d'un champ de bits entre attribut et 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_RECORDS_BITS_INT_H
+#define _PLUGINS_KAITAI_RECORDS_BITS_INT_H
+
+
+#include "bits.h"
+
+
+#include "../record-int.h"
+
+
+
+/* Correspondance de bits établie entre un attribut et du binaire (instance) */
+struct _GRecordBitField
+{
+ GMatchRecord parent; /* A laisser en premier */
+
+ ext_vmpa_t epos; /* Point de départ */
+ uint8_t size; /* Quantité de bits concernés */
+ SourceEndian endian; /* Boutisme des données imposé */
+
+};
+
+/* Correspondance de bits établie entre un attribut et du binaire (classe) */
+struct _GRecordBitFieldClass
+{
+ GMatchRecordClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une correspondance entre attribut et binaire. */
+bool g_record_bit_field_create(GRecordBitField *, GKaitaiAttribute *, GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_BITS_INT_H */
diff --git a/plugins/kaitai/records/bits.c b/plugins/kaitai/records/bits.c
new file mode 100644
index 0000000..d224112
--- /dev/null
+++ b/plugins/kaitai/records/bits.c
@@ -0,0 +1,283 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.c - conservation d'un champ de bits entre attribut et 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "bits.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include "bits-int.h"
+
+
+
+/* -------------------- DEFINITION D'UNE CORRESPONDANCE UNITAIRE -------------------- */
+
+
+/* Initialise la classe des correspondances attribut/binaire. */
+static void g_record_bit_field_class_init(GRecordBitFieldClass *);
+
+/* Initialise une correspondance entre attribut et binaire. */
+static void g_record_bit_field_init(GRecordBitField *);
+
+/* Supprime toutes les références externes. */
+static void g_record_bit_field_dispose(GRecordBitField *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_record_bit_field_finalize(GRecordBitField *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Calcule ou fournit la zone couverte par une correspondance. */
+static void g_record_bit_field_get_range(const GRecordBitField *, mrange_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UNE CORRESPONDANCE UNITAIRE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une correspondance entre un attribut et du binaire. */
+G_DEFINE_TYPE(GRecordBitField, g_record_bit_field, G_TYPE_MATCH_RECORD);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des correspondances attribut/binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_bit_field_class_init(GRecordBitFieldClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GMatchRecordClass *record; /* Version parente de la classe*/
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_record_bit_field_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_record_bit_field_finalize;
+
+ record = G_MATCH_RECORD_CLASS(klass);
+
+ record->get_range = (get_record_range_fc)g_record_bit_field_get_range;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = instance à initialiser. *
+* *
+* Description : Initialise une correspondance entre attribut et binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_bit_field_init(GRecordBitField *field)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_bit_field_dispose(GRecordBitField *field)
+{
+ G_OBJECT_CLASS(g_record_bit_field_parent_class)->dispose(G_OBJECT(field));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_bit_field_finalize(GRecordBitField *field)
+{
+ G_OBJECT_CLASS(g_record_bit_field_parent_class)->finalize(G_OBJECT(field));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : attrib = analyseur à l'origine de la correspondance. *
+* content = contenu binaire lié à la correspondance. *
+* epos = tête de lecture avec granularité en bits. *
+* size = quantité de bits à prendre en compte. *
+* endian = boustime des données à respecter. *
+* *
+* Description : Crée une nouvelle correspondance entre attribut et binaire. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GMatchRecord *g_record_bit_field_new(GKaitaiAttribute *attrib, GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian)
+{
+ GMatchRecord *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_RECORD_BIT_FIELD, NULL);
+
+ if (!g_record_bit_field_create(G_RECORD_BIT_FIELD(result), attrib, content, epos, size, endian))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = correspondance à initialiser pleinement. *
+* attrib = analyseur à l'origine de la correspondance. *
+* content = contenu binaire lié à la correspondance. *
+* epos = tête de lecture avec granularité en bits. *
+* size = quantité de bits à prendre en compte. *
+* endian = boustime des données à respecter. *
+* *
+* Description : Met en place une correspondance entre attribut et binaire. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_record_bit_field_create(GRecordBitField *field, GKaitaiAttribute *attrib, GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_match_record_create(G_MATCH_RECORD(field), G_KAITAI_PARSER(attrib), content);
+
+ if (result)
+ {
+ copy_evmpa(&field->epos, epos);
+ field->size = size;
+ field->endian = endian;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = correspondance à consulter. *
+* out = valeur à sauvegarder sous une forme générique. [OUT] *
+* *
+* Description : Lit la valeur d'un élément Kaitai entier représenté. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_record_bit_field_get_value(const GRecordBitField *field, resolved_value_t *out)
+{
+ bool result; /* Bilan à retourner */
+ GKaitaiParser *parser; /* Attribut associé à l'élément*/
+
+ parser = g_match_record_get_creator(G_MATCH_RECORD(field));
+ assert(G_IS_KAITAI_ATTRIBUTE(parser));
+
+ result = g_kaitai_attribute_read_bit_field_value(G_KAITAI_ATTRIBUTE(parser),
+ G_MATCH_RECORD(field)->content,
+ &field->epos, field->size,
+ field->endian, out);
+
+ g_object_unref(G_OBJECT(parser));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : record = correspondance à consulter. *
+* range = zone de couverture déterminée. [OUT] *
+* *
+* Description : Calcule ou fournit la zone couverte par une correspondance. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_record_bit_field_get_range(const GRecordBitField *record, mrange_t *range)
+{
+ phys_t len; /* Taille en octets */
+
+ len = record->size / 8;
+
+ if (record->size % 8 > 0)
+ len ++;
+
+ init_mrange(range, &record->epos.base, len);
+
+}
diff --git a/plugins/kaitai/records/bits.h b/plugins/kaitai/records/bits.h
new file mode 100644
index 0000000..923e8e3
--- /dev/null
+++ b/plugins/kaitai/records/bits.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.h - prototypes pour la conservation d'un champ de bits entre attribut et 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_RECORDS_BITS_H
+#define _PLUGINS_KAITAI_RECORDS_BITS_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+#include "../parsers/attribute.h"
+
+
+
+#define G_TYPE_RECORD_BIT_FIELD g_record_bit_field_get_type()
+#define G_RECORD_BIT_FIELD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_BIT_FIELD, GRecordBitField))
+#define G_IS_RECORD_BIT_FIELD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_BIT_FIELD))
+#define G_RECORD_BIT_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_BIT_FIELD, GRecordBitFieldClass))
+#define G_IS_RECORD_BIT_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_BIT_FIELD))
+#define G_RECORD_BIT_FIELD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_BIT_FIELD, GRecordBitFieldClass))
+
+
+/* Correspondance de bits établie entre un attribut et du binaire (instance) */
+typedef struct _GRecordBitField GRecordBitField;
+
+/* Correspondance de bits établie entre un attribut et du binaire (classe) */
+typedef struct _GRecordBitFieldClass GRecordBitFieldClass;
+
+
+/* Indique le type défini pour une correspondance entre un attribut et du binaire. */
+GType g_record_bit_field_get_type(void);
+
+/* Crée une nouvelle correspondance entre attribut et binaire. */
+GMatchRecord *g_record_bit_field_new(GKaitaiAttribute *, GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian);
+
+/* Lit la valeur d'un élément Kaitai entier représenté. */
+bool g_record_bit_field_get_value(const GRecordBitField *, resolved_value_t *);
+
+
+
+#endif /* _PLUGINS_KAITAI_RECORDS_BITS_H */
diff --git a/plugins/kaitai/records/value-int.h b/plugins/kaitai/records/delayed-int.h
index 6a84a7f..9275500 100644
--- a/plugins/kaitai/records/value-int.h
+++ b/plugins/kaitai/records/delayed-int.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * value-int.h - prototypes internes pour la conservation d'une instance virtuelle
+ * delayed-int.h - prototypes internes pour la conservation d'une instance virtuelle
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -21,11 +21,11 @@
*/
-#ifndef _PLUGINS_KAITAI_RECORDS_VALUE_INT_H
-#define _PLUGINS_KAITAI_RECORDS_VALUE_INT_H
+#ifndef _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H
+#define _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H
-#include "value.h"
+#include "delayed.h"
#include "../record-int.h"
@@ -33,16 +33,19 @@
/* Valeur calculée selon des correspondances parallèles (instance) */
-struct _GRecordValue
+struct _GRecordDelayed
{
GMatchRecord parent; /* A laisser en premier */
kaitai_scope_t locals; /* Sauvegarde de contexte */
+ bool has_value; /* Port d'une valeur directe ? */
+ GMatchRecord *real_record; /* Enregistrement effectif */
+
};
/* Valeur calculée selon des correspondances parallèles (classe) */
-struct _GRecordValueClass
+struct _GRecordDelayedClass
{
GMatchRecordClass parent; /* A laisser en premier */
@@ -50,8 +53,8 @@ struct _GRecordValueClass
/* Met en place une valeur calculée selon des correspondances. */
-bool g_record_value_create(GRecordValue *, GKaitaiInstance *, const kaitai_scope_t *);
+bool g_record_delayed_create(GRecordDelayed *, GKaitaiInstance *, const kaitai_scope_t *, GBinContent *);
-#endif /* _PLUGINS_KAITAI_RECORDS_VALUE_INT_H */
+#endif /* _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H */
diff --git a/plugins/kaitai/records/value.c b/plugins/kaitai/records/delayed.c
index cafe5c3..8c1395c 100644
--- a/plugins/kaitai/records/value.c
+++ b/plugins/kaitai/records/delayed.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * value.c - conservation d'une correspondance entre attribut et binaire
+ * delayed.c - conservation d'une correspondance entre attribut et binaire
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -21,7 +21,7 @@
*/
-#include "value.h"
+#include "delayed.h"
#include <assert.h>
@@ -29,7 +29,8 @@
#include <string.h>
-#include "value-int.h"
+#include "delayed-int.h"
+#include "item.h"
#include "../parsers/attribute.h"
@@ -38,16 +39,16 @@
/* Initialise la classe des valeurs purement calculées. */
-static void g_record_value_class_init(GRecordValueClass *);
+static void g_record_delayed_class_init(GRecordDelayedClass *);
/* Initialise une correspondance entre attribut et binaire. */
-static void g_record_value_init(GRecordValue *);
+static void g_record_delayed_init(GRecordDelayed *);
/* Supprime toutes les références externes. */
-static void g_record_value_dispose(GRecordValue *);
+static void g_record_delayed_dispose(GRecordDelayed *);
/* Procède à la libération totale de la mémoire. */
-static void g_record_value_finalize(GRecordValue *);
+static void g_record_delayed_finalize(GRecordDelayed *);
@@ -55,7 +56,7 @@ static void g_record_value_finalize(GRecordValue *);
/* Calcule ou fournit la zone couverte par une correspondance. */
-static void g_record_value_get_range(const GRecordValue *, mrange_t *);
+static void g_record_delayed_get_range(const GRecordDelayed *, mrange_t *);
@@ -65,7 +66,7 @@ static void g_record_value_get_range(const GRecordValue *, mrange_t *);
/* Indique le type défini pour une valeur calculée selon des correspondances établies. */
-G_DEFINE_TYPE(GRecordValue, g_record_value, G_TYPE_MATCH_RECORD);
+G_DEFINE_TYPE(GRecordDelayed, g_record_delayed, G_TYPE_MATCH_RECORD);
/******************************************************************************
@@ -80,26 +81,26 @@ G_DEFINE_TYPE(GRecordValue, g_record_value, G_TYPE_MATCH_RECORD);
* *
******************************************************************************/
-static void g_record_value_class_init(GRecordValueClass *klass)
+static void g_record_delayed_class_init(GRecordDelayedClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GMatchRecordClass *record; /* Version parente de la classe*/
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_record_value_dispose;
- object->finalize = (GObjectFinalizeFunc)g_record_value_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_record_delayed_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_record_delayed_finalize;
record = G_MATCH_RECORD_CLASS(klass);
- record->get_range = (get_record_range_fc)g_record_value_get_range;
+ record->get_range = (get_record_range_fc)g_record_delayed_get_range;
}
/******************************************************************************
* *
-* Paramètres : value = instance à initialiser. *
+* Paramètres : delayed = instance à initialiser. *
* *
* Description : Initialise une correspondance entre attribut et binaire. *
* *
@@ -109,16 +110,18 @@ static void g_record_value_class_init(GRecordValueClass *klass)
* *
******************************************************************************/
-static void g_record_value_init(GRecordValue *value)
+static void g_record_delayed_init(GRecordDelayed *delayed)
{
- init_record_scope(&value->locals, NULL);
+ init_record_scope(&delayed->locals, NULL);
+
+ delayed->real_record = NULL;
}
/******************************************************************************
* *
-* Paramètres : value = instance d'objet GLib à traiter. *
+* Paramètres : delayed = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -128,18 +131,18 @@ static void g_record_value_init(GRecordValue *value)
* *
******************************************************************************/
-static void g_record_value_dispose(GRecordValue *value)
+static void g_record_delayed_dispose(GRecordDelayed *delayed)
{
- reset_record_scope(&value->locals);
+ reset_record_scope(&delayed->locals);
- G_OBJECT_CLASS(g_record_value_parent_class)->dispose(G_OBJECT(value));
+ G_OBJECT_CLASS(g_record_delayed_parent_class)->dispose(G_OBJECT(delayed));
}
/******************************************************************************
* *
-* Paramètres : value = instance d'objet GLib à traiter. *
+* Paramètres : delayed = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -149,17 +152,18 @@ static void g_record_value_dispose(GRecordValue *value)
* *
******************************************************************************/
-static void g_record_value_finalize(GRecordValue *value)
+static void g_record_delayed_finalize(GRecordDelayed *delayed)
{
- G_OBJECT_CLASS(g_record_value_parent_class)->finalize(G_OBJECT(value));
+ G_OBJECT_CLASS(g_record_delayed_parent_class)->finalize(G_OBJECT(delayed));
}
/******************************************************************************
* *
-* Paramètres : inst = analyseur à l'origine de la correspondance. *
-* locals = correspondances courantes pour résolutions. *
+* Paramètres : inst = analyseur à l'origine de la correspondance. *
+* locals = correspondances courantes pour résolutions. *
+* content = contenu binaire lié à la correspondance. *
* *
* Description : Crée une nouvelle valeur calculée à partir d'une instance. *
* *
@@ -169,13 +173,13 @@ static void g_record_value_finalize(GRecordValue *value)
* *
******************************************************************************/
-GRecordValue *g_record_value_new(GKaitaiInstance *inst, const kaitai_scope_t *locals)
+GRecordDelayed *g_record_delayed_new(GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content)
{
- GRecordValue *result; /* Structure à retourner */
+ GRecordDelayed *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_RECORD_VALUE, NULL);
+ result = g_object_new(G_TYPE_RECORD_DELAYED, NULL);
- if (!g_record_value_create(result, inst, locals))
+ if (!g_record_delayed_create(result, inst, locals, content))
g_clear_object(&result);
return result;
@@ -185,9 +189,10 @@ GRecordValue *g_record_value_new(GKaitaiInstance *inst, const kaitai_scope_t *lo
/******************************************************************************
* *
-* Paramètres : value = correspondance à initialiser pleinement. *
-* inst = analyseur à l'origine de la correspondance. *
-* locals = correspondances courantes pour résolutions. *
+* Paramètres : delayed = correspondance à initialiser pleinement. *
+* inst = analyseur à l'origine de la correspondance. *
+* locals = correspondances courantes pour résolutions. *
+* content = contenu binaire lié à la correspondance. *
* *
* Description : Met en place une valeur calculée à partir d'une instance. *
* *
@@ -197,14 +202,14 @@ GRecordValue *g_record_value_new(GKaitaiInstance *inst, const kaitai_scope_t *lo
* *
******************************************************************************/
-bool g_record_value_create(GRecordValue *value, GKaitaiInstance *inst, const kaitai_scope_t *locals)
+bool g_record_delayed_create(GRecordDelayed *delayed, GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content)
{
bool result; /* Bilan à retourner */
- result = g_match_record_create(G_MATCH_RECORD(value), G_KAITAI_PARSER(inst), NULL);
+ result = g_match_record_create(G_MATCH_RECORD(delayed), G_KAITAI_PARSER(inst), content);
if (result)
- copy_record_scope(&value->locals, locals);
+ copy_record_scope(&delayed->locals, locals);
return result;
@@ -213,8 +218,8 @@ bool g_record_value_create(GRecordValue *value, GKaitaiInstance *inst, const kai
/******************************************************************************
* *
-* Paramètres : value = correspondance à consulter. *
-* value = valeur à sauvegarder sous une forme générique. [OUT] *
+* Paramètres : delayed = correspondance à consulter. *
+* out = valeur à sauvegarder sous forme générique. [OUT] *
* *
* Description : Détermine la valeur d'un élément Kaitai calculé. *
* *
@@ -224,17 +229,36 @@ bool g_record_value_create(GRecordValue *value, GKaitaiInstance *inst, const kai
* *
******************************************************************************/
-bool g_record_value_compute_value(const GRecordValue *value, resolved_value_t *out)
+bool g_record_delayed_compute_value(GRecordDelayed *delayed, resolved_value_t *out)
{
bool result; /* Bilan à retourner */
GKaitaiParser *parser; /* Instance liée à l'élément */
- parser = g_match_record_get_creator(G_MATCH_RECORD(value));
+ parser = g_match_record_get_creator(G_MATCH_RECORD(delayed));
assert(G_IS_KAITAI_ATTRIBUTE(parser));
- result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser),
- &value->locals,
- out);
+ if (G_MATCH_RECORD(delayed)->content == NULL)
+ result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser),
+ &delayed->locals,
+ out);
+
+ else
+ {
+ if (delayed->real_record == NULL)
+ delayed->real_record = g_kaitai_instance_compute_real_record(G_KAITAI_INSTANCE(parser),
+ &delayed->locals,
+ G_MATCH_RECORD(delayed)->content);
+
+ if (delayed->real_record == NULL)
+ result = false;
+
+ else
+ {
+ assert(G_IS_RECORD_ITEM(delayed->real_record));
+ result = g_record_item_get_value(G_RECORD_ITEM(delayed->real_record), out);
+ }
+
+ }
g_object_unref(G_OBJECT(parser));
@@ -245,8 +269,8 @@ bool g_record_value_compute_value(const GRecordValue *value, resolved_value_t *o
/******************************************************************************
* *
-* Paramètres : value = correspondance à consulter. *
-* value = valeur à sauvegarder sous une forme générique. [OUT] *
+* Paramètres : delayed = correspondance à consulter. *
+* out = valeur à sauvegarder sous forme générique. [OUT] *
* *
* Description : Détermine et ajuste la valeur d'un élément Kaitai calculé. *
* *
@@ -256,20 +280,12 @@ bool g_record_value_compute_value(const GRecordValue *value, resolved_value_t *o
* *
******************************************************************************/
-bool g_record_value_compute_and_aggregate_value(const GRecordValue *value, resolved_value_t *out)
+bool g_record_delayed_compute_and_aggregate_value(GRecordDelayed *delayed, resolved_value_t *out)
{
bool result; /* Bilan à retourner */
- GKaitaiParser *parser; /* Instance liée à l'élément */
sized_string_t converted; /* Conversion finale ? */
- parser = g_match_record_get_creator(G_MATCH_RECORD(value));
- assert(G_IS_KAITAI_ATTRIBUTE(parser));
-
- result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser),
- &value->locals,
- out);
-
- g_object_unref(G_OBJECT(parser));
+ result = g_record_delayed_compute_value(delayed, out);
if (result)
{
@@ -318,7 +334,7 @@ bool g_record_value_compute_and_aggregate_value(const GRecordValue *value, resol
/******************************************************************************
* *
-* Paramètres : value = correspondance à consulter. *
+* Paramètres : delayed = correspondance à consulter. *
* range = zone de couverture déterminée. [OUT] *
* *
* Description : Calcule ou fournit la zone couverte par une correspondance. *
@@ -329,7 +345,7 @@ bool g_record_value_compute_and_aggregate_value(const GRecordValue *value, resol
* *
******************************************************************************/
-static void g_record_value_get_range(const GRecordValue *value, mrange_t *range)
+static void g_record_delayed_get_range(const GRecordDelayed *delayed, mrange_t *range)
{
copy_mrange(range, UNUSED_MRANGE_PTR);
diff --git a/plugins/kaitai/records/value.h b/plugins/kaitai/records/delayed.h
index 8ee9cdd..e88bb6c 100644
--- a/plugins/kaitai/records/value.h
+++ b/plugins/kaitai/records/delayed.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * value.h - prototypes pour la conservation d'une correspondance entre attribut et binaire
+ * delayed.h - prototypes pour la conservation d'une correspondance entre attribut et binaire
*
* Copyright (C) 2019 Cyrille Bagard
*
@@ -21,8 +21,8 @@
*/
-#ifndef _PLUGINS_KAITAI_RECORDS_VALUE_H
-#define _PLUGINS_KAITAI_RECORDS_VALUE_H
+#ifndef _PLUGINS_KAITAI_RECORDS_DELAYED_H
+#define _PLUGINS_KAITAI_RECORDS_DELAYED_H
#include <glib-object.h>
@@ -33,33 +33,33 @@
-#define G_TYPE_RECORD_VALUE g_record_value_get_type()
-#define G_RECORD_VALUE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_VALUE, GRecordValue))
-#define G_IS_RECORD_VALUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_VALUE))
-#define G_RECORD_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_VALUE, GRecordValueClass))
-#define G_IS_RECORD_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_VALUE))
-#define G_RECORD_VALUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_VALUE, GRecordValueClass))
+#define G_TYPE_RECORD_DELAYED g_record_delayed_get_type()
+#define G_RECORD_DELAYED(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_DELAYED, GRecordDelayed))
+#define G_IS_RECORD_DELAYED(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_DELAYED))
+#define G_RECORD_DELAYED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_DELAYED, GRecordDelayedClass))
+#define G_IS_RECORD_DELAYED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_DELAYED))
+#define G_RECORD_DELAYED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_DELAYED, GRecordDelayedClass))
/* Valeur calculée selon des correspondances parallèles (instance) */
-typedef struct _GRecordValue GRecordValue;
+typedef struct _GRecordDelayed GRecordDelayed;
/* Valeur calculée selon des correspondances parallèles (classe) */
-typedef struct _GRecordValueClass GRecordValueClass;
+typedef struct _GRecordDelayedClass GRecordDelayedClass;
/* Indique le type défini pour une valeur calculée selon des correspondances établies. */
-GType g_record_value_get_type(void);
+GType g_record_delayed_get_type(void);
/* Crée une nouvelle valeur calculée à partir d'une instance. */
-GRecordValue *g_record_value_new(GKaitaiInstance *, const kaitai_scope_t *);
+GRecordDelayed *g_record_delayed_new(GKaitaiInstance *, const kaitai_scope_t *, GBinContent *);
/* Détermine la valeur d'un élément Kaitai entier calculé. */
-bool g_record_value_compute_value(const GRecordValue *, resolved_value_t *);
+bool g_record_delayed_compute_value(GRecordDelayed *, resolved_value_t *);
/* Détermine et ajuste la valeur d'un élément Kaitai calculé. */
-bool g_record_value_compute_and_aggregate_value(const GRecordValue *, resolved_value_t *);
+bool g_record_delayed_compute_and_aggregate_value(GRecordDelayed *, resolved_value_t *);
-#endif /* _PLUGINS_KAITAI_RECORDS_VALUE_H */
+#endif /* _PLUGINS_KAITAI_RECORDS_DELAYED_H */
diff --git a/plugins/kaitai/rost/Makefile.am b/plugins/kaitai/rost/Makefile.am
new file mode 100644
index 0000000..c7ea84a
--- /dev/null
+++ b/plugins/kaitai/rost/Makefile.am
@@ -0,0 +1,18 @@
+
+noinst_LTLIBRARIES = libkaitairost.la
+
+libkaitairost_la_SOURCES = \
+ browser-int.h \
+ browser.h browser.c \
+ core.h core.c \
+ space-int.h \
+ space.h space.c \
+ trigger-int.h \
+ trigger.h trigger.c
+
+libkaitairost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitairost_la_SOURCES:%c=)
diff --git a/plugins/kaitai/rost/browser-int.h b/plugins/kaitai/rost/browser-int.h
new file mode 100644
index 0000000..4b49680
--- /dev/null
+++ b/plugins/kaitai/rost/browser-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * browser-int.h - prototypes internes pour le parcours des résultats d'analyse Kaitai pour ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_ROST_BROWSER_INT_H
+#define PLUGINS_KAITAI_ROST_BROWSER_INT_H
+
+
+#include <analysis/scan/item-int.h>
+
+
+#include "browser.h"
+
+
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (instance) */
+struct _GKaitaiBrowser
+{
+ GScanRegisteredItem parent; /* A laisser en premier */
+
+ char *path; /* Chamin vers l'enregistrement*/
+ GMatchRecord *record; /* Correspondance à parcourir */
+
+};
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (classe) */
+struct _GKaitaiBrowserClass
+{
+ GScanRegisteredItemClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un nouveau parcours de correspondances Kaitai. */
+bool g_kaitai_browser_create(GKaitaiBrowser *, const char *, GMatchRecord *);
+
+
+
+#endif /* PLUGINS_KAITAI_ROST_BROWSER_INT_H */
diff --git a/plugins/kaitai/rost/browser.c b/plugins/kaitai/rost/browser.c
new file mode 100644
index 0000000..159915b
--- /dev/null
+++ b/plugins/kaitai/rost/browser.c
@@ -0,0 +1,478 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * browser.c - accès à des définitions Kaitai depuis ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "browser.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include <analysis/scan/exprs/literal.h>
+
+
+#include "browser-int.h"
+#include "../records/bits.h"
+#include "../records/delayed.h"
+#include "../records/item.h"
+#include "../records/list.h"
+
+
+
+/* ---------------------- PARCOURS DE CORRESPONDANCES ETABLIES ---------------------- */
+
+
+/* Initialise la classe des parcours de correspondances Kaitai. */
+static void g_kaitai_browser_class_init(GKaitaiBrowserClass *);
+
+/* Initialise un parcours de correspondances Kaitai. */
+static void g_kaitai_browser_init(GKaitaiBrowser *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_browser_dispose(GKaitaiBrowser *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_browser_finalize(GKaitaiBrowser *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_kaitai_browser_get_name(const GKaitaiBrowser *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool g_kaitai_browser_resolve(GKaitaiBrowser *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_kaitai_browser_reduce(GKaitaiBrowser *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Effectue une extraction d'élément à partir d'une série. */
+static GObject *g_kaitai_browser_extract_at(GKaitaiBrowser *, const GScanExpression *, GScanContext *, GScanScope *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* PARCOURS DE CORRESPONDANCES ETABLIES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un parcours de correspondances Kaitai pour ROST. */
+G_DEFINE_TYPE(GKaitaiBrowser, g_kaitai_browser, G_TYPE_SCAN_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des parcours de correspondances Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_class_init(GKaitaiBrowserClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_browser_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_browser_finalize;
+
+ registered = G_SCAN_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_kaitai_browser_get_name;
+ registered->resolve = (resolve_registered_item_fc)g_kaitai_browser_resolve;
+ registered->reduce = (reduce_registered_item_fc)g_kaitai_browser_reduce;
+ registered->extract = (extract_registered_item_at)g_kaitai_browser_extract_at;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = instance à initialiser. *
+* *
+* Description : Initialise un parcours de correspondances Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_init(GKaitaiBrowser *browser)
+{
+ browser->path = NULL;
+ browser->record = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_dispose(GKaitaiBrowser *browser)
+{
+ g_clear_object(&browser->record);
+
+ G_OBJECT_CLASS(g_kaitai_browser_parent_class)->dispose(G_OBJECT(browser));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_finalize(GKaitaiBrowser *browser)
+{
+ if (browser->path != NULL)
+ free(browser->path);
+
+ G_OBJECT_CLASS(g_kaitai_browser_parent_class)->finalize(G_OBJECT(browser));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : path = chemin vers l'enregistrement fourni. *
+* record = correspondance racine à considérer. *
+* *
+* Description : Crée un nouveau parcours de correspondances Kaitai. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiBrowser *g_kaitai_browser_new(const char *path, GMatchRecord *record)
+{
+ GKaitaiBrowser *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_BROWSER, NULL);
+
+ if (!g_kaitai_browser_create(result, path, record))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = encadrement d'un parcours de correspondances. *
+* path = chemin vers l'enregistrement fourni. *
+* record = correspondance racine à considérer. *
+* *
+* Description : Met en place un nouveau parcours de correspondances Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_browser_create(GKaitaiBrowser *browser, const char *path, GMatchRecord *record)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (path != NULL)
+ browser->path = strdup(path);
+
+ browser->record = record;
+ g_object_ref(G_OBJECT(browser->record));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_kaitai_browser_get_name(const GKaitaiBrowser *item)
+{
+ char *result; /* Désignation à retourner */
+ int ret; /* Statut de construction */
+
+ if (item->path == NULL)
+ result = strdup("kaitai://");
+
+ else
+ {
+ ret = asprintf(&result, "kaitai://%s", item->path);
+ assert(ret > 0);
+
+ if (ret <= 0)
+ result = strdup("kaitai://???");
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT]*
+* *
+* Description : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_browser_resolve(GKaitaiBrowser *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ GMatchRecord *found; /* Correspondance trouvée */
+ char *path;
+ int ret; /* Statut de construction */
+
+ found = g_match_record_find_by_name(item->record, target, strlen(target), 1);
+ result = (found != NULL);
+
+ if (result)
+ {
+ ret = asprintf(&path, "%s.%s", item->path, target);
+ assert(ret > 0);
+
+ if (ret <= 0)
+ path = strdup("!?");
+
+ *out = G_SCAN_REGISTERED_ITEM(g_kaitai_browser_new(path, found));
+
+ free(path);
+ g_object_unref(G_OBJECT(found));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_browser_reduce(GKaitaiBrowser *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ size_t count; /* Décompte total à considérer */
+ resolved_value_t value; /* Valeur brute à transformer */
+
+ if (G_IS_RECORD_LIST(item->record))
+ {
+ count = g_record_list_count_records(G_RECORD_LIST(item->record));
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ count > 0 });
+
+ result = true;
+
+ }
+
+ else
+ {
+ if (G_IS_RECORD_BIT_FIELD(item->record))
+ result = g_record_bit_field_get_value(G_RECORD_BIT_FIELD(item->record), &value);
+
+ else if (G_IS_RECORD_DELAYED(item->record))
+ result = g_record_delayed_compute_and_aggregate_value(G_RECORD_DELAYED(item->record), &value);
+
+ else if (G_IS_RECORD_ITEM(item->record))
+ result = g_record_item_get_value(G_RECORD_ITEM(item->record), &value);
+
+ else
+ result = false;
+
+ if (result)
+ {
+ switch (value.type)
+ {
+ case GVT_UNSIGNED_INTEGER:
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &value.unsigned_integer);
+ break;
+
+ case GVT_SIGNED_INTEGER:
+ *out = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &value.signed_integer);
+ break;
+
+ case GVT_FLOAT:
+ /* TODO */
+ break;
+
+ case GVT_BOOLEAN:
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &value.status);
+ break;
+
+ case GVT_BYTES:
+ *out = g_scan_literal_expression_new(LVT_STRING, &value.bytes);
+ break;
+
+ default:
+ break;
+
+ }
+
+ EXIT_RESOLVED_VALUE(value);
+
+ }
+
+ }
+
+ 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 : - *
+* *
+******************************************************************************/
+
+static GObject *g_kaitai_browser_extract_at(GKaitaiBrowser *item, const GScanExpression *index, GScanContext *ctx, GScanScope *scope)
+{
+ GObject *result; /* Elément récupéré à renvoyer */
+ GScanLiteralExpression *literal; /* Accès direct à l'indice */
+ LiteralValueType vtype; /* Type de valeur portée */
+ unsigned long long at; /* Valeur concrète du point */
+ bool status; /* Bilan d'obtention d'indice */
+ GRecordList *list; /* Accès direct à la liste */
+ size_t count; /* Décompte total à considérer */
+ GMatchRecord *found; /* Correspondance trouvée */
+ char *path;
+ int ret; /* Statut de construction */
+
+ result = NULL;
+
+ /* Validations préliminaires */
+
+ if (!G_IS_RECORD_LIST(item->record)) goto exit;
+ if (!G_IS_SCAN_LITERAL_EXPRESSION(index)) goto exit;
+
+ literal = G_SCAN_LITERAL_EXPRESSION(index);
+
+ vtype = g_scan_literal_expression_get_value_type(literal);
+ if (vtype != LVT_UNSIGNED_INTEGER) goto exit;
+
+ status = g_scan_literal_expression_get_unsigned_integer_value(literal, &at);
+ if (!status) goto exit;
+
+ list = G_RECORD_LIST(item->record);
+
+ count = g_record_list_count_records(list);
+ if (at >= count) goto exit;
+
+ /* Récupération de l'élément visé */
+
+ found = g_record_list_get_record(list, at);
+ if (found == NULL) goto exit;
+
+ ret = asprintf(&path, "%s[%llu]", item->path, at);
+ assert(ret > 0);
+
+ if (ret <= 0)
+ path = strdup("!?");
+
+ result = G_OBJECT(g_kaitai_browser_new(path, found));
+
+ free(path);
+ g_object_unref(G_OBJECT(found));
+
+ exit:
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/browser.h b/plugins/kaitai/rost/browser.h
new file mode 100644
index 0000000..89b9f6f
--- /dev/null
+++ b/plugins/kaitai/rost/browser.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * browser.h - prototypes pour le parcours des résultats d'analyse Kaitai pour ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_ROST_BROWSER_H
+#define PLUGINS_KAITAI_ROST_BROWSER_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+
+
+
+#define G_TYPE_KAITAI_BROWSER g_kaitai_browser_get_type()
+#define G_KAITAI_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_BROWSER, GKaitaiBrowser))
+#define G_IS_KAITAI_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_BROWSER))
+#define G_KAITAI_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_BROWSER, GKaitaiBrowserClass))
+#define G_IS_KAITAI_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_BROWSER))
+#define G_KAITAI_BROWSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_BROWSER, GKaitaiBrowserClass))
+
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (instance) */
+typedef struct _GKaitaiBrowser GKaitaiBrowser;
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (classe) */
+typedef struct _GKaitaiBrowserClass GKaitaiBrowserClass;
+
+
+/* Indique le type défini pour un parcours de correspondances Kaitai pour ROST. */
+GType g_kaitai_browser_get_type(void);
+
+/* Crée un nouveau parcours de correspondances Kaitai. */
+GKaitaiBrowser *g_kaitai_browser_new(const char *, GMatchRecord *);
+
+
+
+#endif /* PLUGINS_KAITAI_ROST_BROWSER_H */
diff --git a/plugins/kaitai/rost/core.c b/plugins/kaitai/rost/core.c
new file mode 100644
index 0000000..8271389
--- /dev/null
+++ b/plugins/kaitai/rost/core.c
@@ -0,0 +1,66 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - mise à disposition d'un support Kaitai pour ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <core/global.h>
+
+
+#include "space.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre un support de Kaitai pour ROST. *
+* *
+* Retour : Bilan du chargement mené. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_kaitai_support_to_rost(void)
+{
+ bool result; /* Bilan à retourner */
+ GScanNamespace *root_ns; /* Espace de noms ROST racine */
+ GScanNamespace *kaitai_ns; /* Espace de noms pour Kaitai */
+
+ result = true;
+
+ root_ns = get_rost_root_namespace();
+
+ kaitai_ns = g_kaitai_namespace_new();
+
+ result = g_scan_namespace_register_item(root_ns, G_SCAN_REGISTERED_ITEM(kaitai_ns));
+
+ g_object_unref(G_OBJECT(kaitai_ns));
+
+ g_object_unref(G_OBJECT(root_ns));
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/core.h b/plugins/kaitai/rost/core.h
new file mode 100644
index 0000000..6f810eb
--- /dev/null
+++ b/plugins/kaitai/rost/core.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour la mise à disposition d'un support Kaitai pour ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_ROST_CORE_H
+#define _PLUGINS_KAITAI_ROST_CORE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Intègre un support de Kaitai pour ROST. */
+bool add_kaitai_support_to_rost(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_CORE_H */
diff --git a/plugins/kaitai/rost/space-int.h b/plugins/kaitai/rost/space-int.h
new file mode 100644
index 0000000..47ec707
--- /dev/null
+++ b/plugins/kaitai/rost/space-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space-int.h - prototypes internes pour la définition d'un espace de noms pour les fonctions de scan
+ *
+ * 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 _PLUGINS_KAITAI_ROST_SPACE_INT_H
+#define _PLUGINS_KAITAI_ROST_SPACE_INT_H
+
+
+#include "space.h"
+
+
+#include <analysis/scan/space-int.h>
+
+
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (instance) */
+struct _GKaitaiNamespace
+{
+ GScanNamespace parent; /* A laisser en premier */
+
+};
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (classe) */
+struct _GKaitaiNamespaceClass
+{
+ GScanNamespaceClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un nouvel espace de noms pour scan. */
+bool g_kaitai_namespace_create(GKaitaiNamespace *);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_SPACE_INT_H */
diff --git a/plugins/kaitai/rost/space.c b/plugins/kaitai/rost/space.c
new file mode 100644
index 0000000..ee922d2
--- /dev/null
+++ b/plugins/kaitai/rost/space.c
@@ -0,0 +1,254 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.c - définition d'un espace de noms pour les fonctions de scan
+ *
+ * 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/>.
+ */
+
+
+#include "space.h"
+
+
+#include <string.h>
+
+
+#include "trigger.h"
+#include "space-int.h"
+#include "../import.h"
+
+
+
+/* ------------------------- SOCLE POUR LES ESPACES DE NOMS ------------------------- */
+
+
+/* Initialise la classe des espaces de noms dynamiques Kaitai. */
+static void g_kaitai_namespace_class_init(GKaitaiNamespaceClass *);
+
+/* Initialise une instance d'espace de noms dynamiques Kaitai. */
+static void g_kaitai_namespace_init(GKaitaiNamespace *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_namespace_dispose(GKaitaiNamespace *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_namespace_finalize(GKaitaiNamespace *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Lance une résolution d'élément à solliciter. */
+static bool g_kaitai_namespace_resolve(GKaitaiNamespace *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* SOCLE POUR LES ESPACES DE NOMS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une définition d'espace de noms dynamique Kaitai. */
+G_DEFINE_TYPE(GKaitaiNamespace, g_kaitai_namespace, G_TYPE_SCAN_NAMESPACE);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des espaces de noms dynamiques Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_class_init(GKaitaiNamespaceClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_namespace_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_namespace_finalize;
+
+ registered = G_SCAN_REGISTERED_ITEM_CLASS(klass);
+
+ registered->resolve = (resolve_registered_item_fc)g_kaitai_namespace_resolve;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance à initialiser. *
+* *
+* Description : Initialise une instance d'espace de noms dynamiques Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_init(GKaitaiNamespace *space)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_dispose(GKaitaiNamespace *space)
+{
+ G_OBJECT_CLASS(g_kaitai_namespace_parent_class)->dispose(G_OBJECT(space));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_finalize(GKaitaiNamespace *space)
+{
+ G_OBJECT_CLASS(g_kaitai_namespace_parent_class)->finalize(G_OBJECT(space));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un nouvel espace de noms dynamique pour Kaitai. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanNamespace *g_kaitai_namespace_new(void)
+{
+ GScanNamespace *result; /* Instance à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_NAMESPACE, NULL);
+
+ if (!g_kaitai_namespace_create(G_KAITAI_NAMESPACE(result)))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'espace de noms à initialiser. *
+* name = désignation du futur espace de noms. *
+* *
+* Description : Met en place un nouvel espace de noms pour scan. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_namespace_create(GKaitaiNamespace *space)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_namespace_create(G_SCAN_NAMESPACE(space), "kaitai");
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT]*
+* *
+* Description : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_namespace_resolve(GKaitaiNamespace *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ GScanRegisteredItemClass *parent; /* Version de classe parente */
+ GKaitaiStruct *kstruct; /* Lecteur de définition */
+
+ parent = G_SCAN_REGISTERED_ITEM_CLASS(g_kaitai_namespace_parent_class);
+
+ result = parent->resolve(G_SCAN_REGISTERED_ITEM(item), target, ctx, scope, out);
+
+ if (!result)
+ {
+ kstruct = load_kaitai_definition(target, NULL);
+
+ if (kstruct != NULL)
+ {
+ *out = g_kaitai_trigger_new(kstruct);
+ result = true;
+
+ g_object_unref(G_OBJECT(kstruct));
+
+ }
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/space.h b/plugins/kaitai/rost/space.h
new file mode 100644
index 0000000..5dcea5e
--- /dev/null
+++ b/plugins/kaitai/rost/space.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.h - prototypes pour la définition d'un espace de noms pour les fonctions de scan
+ *
+ * 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 _PLUGINS_KAITAI_ROST_SPACE_H
+#define _PLUGINS_KAITAI_ROST_SPACE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/scan/space.h>
+
+
+
+#define G_TYPE_KAITAI_NAMESPACE g_kaitai_namespace_get_type()
+#define G_KAITAI_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespace))
+#define G_IS_KAITAI_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_NAMESPACE))
+#define G_KAITAI_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespaceClass))
+#define G_IS_KAITAI_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_NAMESPACE))
+#define G_KAITAI_NAMESPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespaceClass))
+
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (instance) */
+typedef struct _GKaitaiNamespace GKaitaiNamespace;
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (classe) */
+typedef struct _GKaitaiNamespaceClass GKaitaiNamespaceClass;
+
+
+/* Indique le type défini pour une définition d'espace de noms dynamique Kaitai. */
+GType g_kaitai_namespace_get_type(void);
+
+/* Construit un nouvel espace de noms dynamique pour Kaitai. */
+GScanNamespace *g_kaitai_namespace_new(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_SPACE_H */
diff --git a/plugins/kaitai/rost/trigger-int.h b/plugins/kaitai/rost/trigger-int.h
new file mode 100644
index 0000000..6830cd7
--- /dev/null
+++ b/plugins/kaitai/rost/trigger-int.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger-int.h - prototypes internes pour l'accès à des définitions Kaitai depuis ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_ROST_TRIGGER_INT_H
+#define _PLUGINS_KAITAI_ROST_TRIGGER_INT_H
+
+
+#include <analysis/scan/item-int.h>
+
+
+#include "trigger.h"
+
+
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (instance) */
+struct _GKaitaiTrigger
+{
+ GScanRegisteredItem parent; /* A laisser en premier */
+
+ char *name; /* Désignation arbitraire */
+
+ GKaitaiStruct *kstruct; /* Définition à décliner */
+
+};
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (classe) */
+struct _GKaitaiTriggerClass
+{
+ GScanRegisteredItemClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un accès à une définition Kaitai pour ROST. */
+bool g_kaitai_trigger_create(GKaitaiTrigger *, GKaitaiStruct *);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_TRIGGER_INT_H */
diff --git a/plugins/kaitai/rost/trigger.c b/plugins/kaitai/rost/trigger.c
new file mode 100644
index 0000000..6bb6e5d
--- /dev/null
+++ b/plugins/kaitai/rost/trigger.c
@@ -0,0 +1,320 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.c - accès à des définitions Kaitai depuis ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "trigger.h"
+
+
+#include <string.h>
+
+
+#include "browser.h"
+#include "trigger-int.h"
+
+
+
+/* ---------------------- ACCES ET DECLENCHEMENT D'UNE ANALYSE ---------------------- */
+
+
+/* Initialise la classe des accès aux définitions Kaitai. */
+static void g_kaitai_trigger_class_init(GKaitaiTriggerClass *);
+
+/* Initialise un accès à une définition Kaitai. */
+static void g_kaitai_trigger_init(GKaitaiTrigger *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_trigger_dispose(GKaitaiTrigger *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_trigger_finalize(GKaitaiTrigger *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_kaitai_trigger_get_name(const GKaitaiTrigger *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool g_kaitai_trigger_resolve(GKaitaiTrigger *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ACCES ET DECLENCHEMENT D'UNE ANALYSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un accès à une définition Kaitai pour ROST. */
+G_DEFINE_TYPE(GKaitaiTrigger, g_kaitai_trigger, G_TYPE_SCAN_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des accès aux définitions Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_class_init(GKaitaiTriggerClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_trigger_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_trigger_finalize;
+
+ registered = G_SCAN_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_kaitai_trigger_get_name;
+ registered->resolve = (resolve_registered_item_fc)g_kaitai_trigger_resolve;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = instance à initialiser. *
+* *
+* Description : Initialise un accès à une définition Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_init(GKaitaiTrigger *trigger)
+{
+ trigger->name = NULL;
+
+ trigger->kstruct = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_dispose(GKaitaiTrigger *trigger)
+{
+ g_clear_object(&trigger->kstruct);
+
+ G_OBJECT_CLASS(g_kaitai_trigger_parent_class)->dispose(G_OBJECT(trigger));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_finalize(GKaitaiTrigger *trigger)
+{
+ if (trigger->name != NULL)
+ free(trigger->name);
+
+ G_OBJECT_CLASS(g_kaitai_trigger_parent_class)->finalize(G_OBJECT(trigger));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = définition Kaitai à manipuler avec du contenu. *
+* *
+* Description : Crée un nouvel accès à une définition Kaitai à instancier. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanRegisteredItem *g_kaitai_trigger_new(GKaitaiStruct *kstruct)
+{
+ GScanRegisteredItem *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_TRIGGER, NULL);
+
+ if (!g_kaitai_trigger_create(G_KAITAI_TRIGGER(result), kstruct))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = lien vers une définition Kaitai à instancier. *
+* kstruct = définition Kaitai à manipuler avec du contenu. *
+* *
+* Description : Met en place un accès à une définition Kaitai pour ROST. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_trigger_create(GKaitaiTrigger *trigger, GKaitaiStruct *kstruct)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ trigger->kstruct = kstruct;
+ g_object_ref(G_OBJECT(trigger->kstruct));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_kaitai_trigger_get_name(const GKaitaiTrigger *trigger)
+{
+ char *result; /* Désignation à retourner */
+ GKaitaiMeta *meta; /* Eventuelles métadonnées */
+ const char *id; /* Identifiant de définition */
+
+ if (trigger->name != NULL)
+ result = strdup(trigger->name);
+
+ else
+ {
+ result = NULL;
+
+ meta = g_kaitai_structure_get_meta(trigger->kstruct);
+ if (meta == NULL) goto done;
+
+ id = g_kaitai_meta_get_id(meta);
+ if (id == NULL) goto done;
+
+ result = strdup(id);
+
+ g_object_unref(G_OBJECT(meta));
+
+ done:
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT]*
+* *
+* Description : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_trigger_resolve(GKaitaiTrigger *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ GKaitaiBrowser *browser; /* Navigateur pour résultats */
+ GBinContent *content; /* Contenu binaire à analyser */
+ GMatchRecord *record; /* Premier niveau de résultats */
+
+ browser = g_object_get_data(G_OBJECT(item), "kaitai_browser");
+
+ if (browser == NULL)
+ {
+ content = g_scan_context_get_content(ctx);
+
+ record = g_kaitai_structure_parse(item->kstruct, content);
+
+ g_object_unref(G_OBJECT(content));
+
+ if (record != NULL)
+ {
+ browser = g_kaitai_browser_new(NULL, record);
+
+ g_object_set_data_full(G_OBJECT(item), "kaitai_browser", browser, g_object_unref);
+
+ }
+
+ }
+
+ if (browser == NULL)
+ result = false;
+
+ else
+ result = g_scan_registered_item_resolve(G_SCAN_REGISTERED_ITEM(browser), target, ctx, scope, out);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/trigger.h b/plugins/kaitai/rost/trigger.h
new file mode 100644
index 0000000..f55e998
--- /dev/null
+++ b/plugins/kaitai/rost/trigger.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.h - prototypes pour l'accès à des définitions Kaitai depuis ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_ROST_TRIGGER_H
+#define PLUGINS_KAITAI_ROST_TRIGGER_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/scan/item.h>
+
+
+#include "../parsers/struct.h"
+
+
+
+#define G_TYPE_KAITAI_TRIGGER g_kaitai_trigger_get_type()
+#define G_KAITAI_TRIGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_TRIGGER, GKaitaiTrigger))
+#define G_IS_KAITAI_TRIGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_TRIGGER))
+#define G_KAITAI_TRIGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_TRIGGER, GKaitaiTriggerClass))
+#define G_IS_KAITAI_TRIGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_TRIGGER))
+#define G_KAITAI_TRIGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_TRIGGER, GKaitaiTriggerClass))
+
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (instance) */
+typedef struct _GKaitaiTrigger GKaitaiTrigger;
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (classe) */
+typedef struct _GKaitaiTriggerClass GKaitaiTriggerClass;
+
+
+/* Indique le type défini pour un accès à une définition Kaitai pour ROST. */
+GType g_kaitai_trigger_get_type(void);
+
+/* Crée un nouvel accès à une définition Kaitai à instancier. */
+GScanRegisteredItem *g_kaitai_trigger_new(GKaitaiStruct *);
+
+
+
+#endif /* PLUGINS_KAITAI_ROST_TRIGGER_H */
diff --git a/plugins/kaitai/scope.c b/plugins/kaitai/scope.c
index 6d1d47a..fad8890 100644
--- a/plugins/kaitai/scope.c
+++ b/plugins/kaitai/scope.c
@@ -231,7 +231,7 @@ GKaitaiType *find_sub_type(const kaitai_scope_t *locals, const char *name)
size_t i; /* Boucle de parcours */
GKaitaiParser *parser; /* Lecteur d'origine */
- GMatchRecord *list[] = { locals->root, locals->parent, locals->last };
+ GMatchRecord *list[] = { locals->last, locals->parent, locals->root };
result = NULL;
diff --git a/plugins/kaitai/tokens.l b/plugins/kaitai/tokens.l
index 3ddf40d..8c93299 100644
--- a/plugins/kaitai/tokens.l
+++ b/plugins/kaitai/tokens.l
@@ -91,7 +91,9 @@
"_root" { return ROOT; }
"_parent" { return PARENT; }
"_" { return LAST; }
+"_io" { return IO; }
"._io" { return METH_IO; }
+".eof" { return IO_EOF; }
"true" { return TRUE_CONST; }
"false" { return FALSE_CONST; }