summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2023-10-09 22:49:59 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2023-10-09 22:49:59 (GMT)
commit7c6fe94c90d320813d0d78a9dbef707696f31505 (patch)
tree912b5c51469c02e6ef680c0c60739787ccff4891 /plugins
parentcb05b99a8c451ff80d88f988e2654c794b0f3750 (diff)
Support some last missing features from Kaitai: bit fields, instance search order and stream EOF.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/kaitai/grammar.y53
-rw-r--r--plugins/kaitai/import.c2
-rw-r--r--plugins/kaitai/import.h2
-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.c206
-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/struct.c45
-rw-r--r--plugins/kaitai/parsers/switch.c112
-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/record.c4
-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/browser.c14
-rw-r--r--plugins/kaitai/tokens.l2
29 files changed, 1357 insertions, 352 deletions
diff --git a/plugins/kaitai/grammar.y b/plugins/kaitai/grammar.y
index 2f2b820..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);
diff --git a/plugins/kaitai/import.c b/plugins/kaitai/import.c
index f645eae..88cd03a 100644
--- a/plugins/kaitai/import.c
+++ b/plugins/kaitai/import.c
@@ -170,7 +170,7 @@ static GKaitaiStruct *load_relative_kaitai_definition(const char *target, const
* *
******************************************************************************/
-GKaitaiStruct *load_relative_kaitai_definition(const char *target, const char *reference)
+GKaitaiStruct *load_kaitai_definition(const char *target, const char *reference)
{
GKaitaiStruct *result; /* Structure chargée à renvoyer*/
diff --git a/plugins/kaitai/import.h b/plugins/kaitai/import.h
index 12fde07..66a0f5a 100644
--- a/plugins/kaitai/import.h
+++ b/plugins/kaitai/import.h
@@ -34,7 +34,7 @@
GKaitaiType *import_kaitai_definition(const char *, const char *);
/* Met en place un interpréteur pour une définition désignée. */
-GKaitaiStruct *load_relative_kaitai_definition(const char *, const char *);
+GKaitaiStruct *load_kaitai_definition(const char *, const char *);
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 58d8dd1..d0505d8 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 **);
@@ -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).
*/
@@ -1429,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 */
@@ -1440,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. *
@@ -1451,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 */
@@ -1483,6 +1583,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
result = false;
*record = NULL;
+ printf("\n");
+ printf("------------parsing %s -( payload: %x - ut=%d )-----------\n",
+ attrib->raw_id, attrib->payload, attrib->payload & KAP_USER_TYPE);
+
/* Lecture soumise à condition ? */
if (attrib->condition != NULL)
@@ -1492,6 +1596,8 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
strlen(attrib->condition),
&authorized);
+ printf("condition '%s': res=%d auth=%d\n", attrib->condition, result, authorized.status);
+
if (!result || !authorized.status)
goto exit;
@@ -1500,7 +1606,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)
{
@@ -1538,7 +1647,9 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
if (!result)
goto exit;
- init_mrange(&work_range, pos, diff);
+ 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);
@@ -1553,16 +1664,24 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
/* Etablissement d'une zone de correspondance */
if (attrib->payload == KAP_UNINITIALIZED)
- assert(false);
+ {
+ printf("attrib: '%s'\n", attrib->raw_id);
+ //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);
@@ -1576,8 +1695,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:
@@ -1585,7 +1722,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
{
@@ -1625,10 +1763,13 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
{
user_type = find_sub_type(locals, attrib->named_type);
+ printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> find '%s' => %p\n",
+ attrib->named_type, user_type);
+
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)
/**
@@ -1648,7 +1789,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)
{
@@ -1661,6 +1802,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
@@ -1669,12 +1815,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
{
@@ -1686,7 +1833,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;
@@ -1702,13 +1849,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));
@@ -1717,6 +1867,8 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s
exit:
+ printf(" ===[[ %s / %p ]]=== >> %d\n", attrib->raw_id, attrib, result);
+
return result;
}
@@ -1933,7 +2085,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. *
@@ -1944,7 +2096,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 */
@@ -1958,7 +2110,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
{
@@ -1976,7 +2128,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)
{
@@ -1985,17 +2137,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);
}
@@ -2026,7 +2178,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);
@@ -2040,7 +2192,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/struct.c b/plugins/kaitai/parsers/struct.c
index f23a264..62dc25a 100644
--- a/plugins/kaitai/parsers/struct.c
+++ b/plugins/kaitai/parsers/struct.c
@@ -64,7 +64,7 @@ static bool g_kaitai_structure_load_imports(GKaitaiStruct *);
/* 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 **);
@@ -712,13 +712,17 @@ 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);
+
+ printf("FINAL STATUS :: %d\n", result != NULL);
return result;
@@ -736,7 +740,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. *
@@ -747,7 +751,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 */
@@ -760,7 +764,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;
@@ -779,10 +783,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)
@@ -793,10 +805,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)
@@ -811,6 +829,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/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/record.c b/plugins/kaitai/record.c
index db573ed..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));
}
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/browser.c b/plugins/kaitai/rost/browser.c
index 075c5ff..159915b 100644
--- a/plugins/kaitai/rost/browser.c
+++ b/plugins/kaitai/rost/browser.c
@@ -32,9 +32,10 @@
#include "browser-int.h"
+#include "../records/bits.h"
+#include "../records/delayed.h"
#include "../records/item.h"
#include "../records/list.h"
-#include "../records/value.h"
@@ -354,11 +355,14 @@ static bool g_kaitai_browser_reduce(GKaitaiBrowser *item, GScanContext *ctx, GSc
else
{
- if (G_IS_RECORD_ITEM(item->record))
- result = g_record_item_get_value(G_RECORD_ITEM(item->record), &value);
+ 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_VALUE(item->record))
- result = g_record_value_compute_and_aggregate_value(G_RECORD_VALUE(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;
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; }