summaryrefslogtreecommitdiff
path: root/plugins/kaitai/parsers/struct.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/kaitai/parsers/struct.c')
-rw-r--r--plugins/kaitai/parsers/struct.c114
1 files changed, 98 insertions, 16 deletions
diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c
index 128a788..d447cf3 100644
--- a/plugins/kaitai/parsers/struct.c
+++ b/plugins/kaitai/parsers/struct.c
@@ -33,6 +33,7 @@
#include "struct-int.h"
+#include "../import.h"
#include "../parser.h"
#include "../records/empty.h"
#include "../records/group.h"
@@ -54,13 +55,16 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *);
/* Procède à la libération totale de la mémoire. */
static void g_kaitai_structure_finalize(GKaitaiStruct *);
+/* Charge les éventuelles dépendances de la définition. */
+static bool g_kaitai_structure_load_imports(GKaitaiStruct *);
+
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
/* Parcourt un contenu binaire selon des spécifications Kaitai. */
-static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **);
+static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **);
@@ -116,6 +120,8 @@ static void g_kaitai_structure_class_init(GKaitaiStructClass *klass)
static void g_kaitai_structure_init(GKaitaiStruct *kstruct)
{
+ kstruct->filename = NULL;
+
kstruct->meta = NULL;
kstruct->seq_items = NULL;
@@ -182,6 +188,9 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *kstruct)
static void g_kaitai_structure_finalize(GKaitaiStruct *kstruct)
{
+ if (kstruct->filename != NULL)
+ free(kstruct->filename);
+
if (kstruct->seq_items != NULL)
free(kstruct->seq_items);
@@ -305,6 +314,8 @@ bool g_kaitai_structure_create_from_file(GKaitaiStruct *kstruct, const char *fil
bool result; /* Bilan à retourner */
GYamlNode *root; /* Noeud racine YAML */
+ kstruct->filename = strdup(filename);
+
root = parse_yaml_from_file(filename);
if (root != NULL)
@@ -343,6 +354,7 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
GYamlNode **nodes; /* Eventuels noeuds trouvés */
size_t count; /* Quantité de ces noeuds */
size_t i; /* Boucle de parcours */
+ size_t first; /* Premier emplacement dispo. */
bool failed; /* Détection d'un échec */
result = false;
@@ -352,6 +364,9 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
kstruct->meta = g_kaitai_meta_new(parent);
assert(kstruct->meta != NULL);
+ result = g_kaitai_structure_load_imports(kstruct);
+ if (!result) goto bad_loading;
+
/* Séquence */
collec = g_yaml_node_find_first_by_path(parent, "/seq/");
@@ -406,13 +421,15 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
if (count > 0)
{
- kstruct->types = calloc(count, sizeof(GKaitaiType *));
- kstruct->types_count = count;
+ first = kstruct->types_count;
+
+ kstruct->types_count += count;
+ kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *));
for (i = 0; i < count; i++)
{
- kstruct->types[i] = g_kaitai_type_new(nodes[i]);
- if (kstruct->types[i] == NULL) break;
+ kstruct->types[first + i] = g_kaitai_type_new(nodes[i]);
+ if (kstruct->types[first + i] == NULL) break;
g_object_unref(G_OBJECT(nodes[i]));
@@ -529,6 +546,49 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent)
/******************************************************************************
* *
+* Paramètres : kstruct = lecteur de définition à initialiser pleinement. *
+* *
+* Description : Charge les éventuelles dépendances de la définition. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_structure_load_imports(GKaitaiStruct *kstruct)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ const char * const *dependencies; /* Liste d'imports requis */
+ size_t count; /* Quantité de ces imports */
+ size_t i; /* Boucle de parcours */
+ GKaitaiType *imported; /* Structure importée */
+
+ result = true;
+
+ dependencies = g_kaitai_meta_get_dependencies(kstruct->meta, &count);
+
+ for (i = 0; i < count; i++)
+ {
+ imported = import_kaitai_definition(dependencies[i], kstruct->filename);
+ if (imported == NULL) break;
+
+ kstruct->types_count++;
+ kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *));
+
+ kstruct->types[kstruct->types_count - 1] = imported;
+
+ }
+
+ result = (i == count);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : kstruct = structure Kaitai à consulter. *
* *
* Description : Fournit la description globale d'une définition Kaitai. *
@@ -624,6 +684,9 @@ GKaitaiType *g_kaitai_structure_find_sub_type(const GKaitaiStruct *kstruct, cons
break;
}
+ result = g_kaitai_structure_find_sub_type(G_KAITAI_STRUCT(kstruct->types[i]), name);
+ if (result != NULL) break;
+
}
return result;
@@ -649,13 +712,15 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont
GMatchRecord *result; /* Arborescence à retourner */
vmpa2t pos; /* Tête de lecture */
kaitai_scope_t locals; /* Variables locales */
- bool status; /* Bilan de l'analyse */
+ ext_vmpa_t epos; /* Tête de lecture complète */
g_binary_content_compute_start_pos(content, &pos);
init_record_scope(&locals, kstruct->meta);
- status = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &pos, &result);
+ init_evmpa_from_vmpa(&epos, &pos);
+
+ g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &epos, &result);
return result;
@@ -673,7 +738,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont
* Paramètres : kstruct = structure Kaitai en cours de parcours. *
* locals = variables locales pour les résolutions de types. *
* content = données binaires à analyser et traduire. *
-* pos = tête de lecture courante. [OUT] *
+* epos = tête de lecture courante. [OUT] *
* record = noeud d'arborescence d'éléments rencontrés. [OUT] *
* *
* Description : Parcourt un contenu binaire selon des spécifications Kaitai. *
@@ -684,7 +749,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont
* *
******************************************************************************/
-static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record)
+static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record)
{
bool result; /* Bilan à retourner */
GRecordGroup *group; /* Ensemble à constituer */
@@ -697,7 +762,7 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
/* Si le groupe est vide */
if ((kstruct->seq_items_count + kstruct->instances_count) == 0)
{
- *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, pos));
+ *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, &epos->base));
if (locals->root == NULL)
locals->root = *record;
@@ -716,10 +781,18 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
old = locals->parent;
locals->parent = *record;
- for (i = 0; i < kstruct->seq_items_count; i++)
+ /**
+ * Les instances sont à charger avant les éléments fixes car
+ * des références au premières peuvent être attendues dans ces derniers.
+ *
+ * Les évolutions de la tête de lecture n'ont en revanche normalement
+ * pas d'incidence sur le chargement des éléments fixes.
+ */
+
+ for (i = 0; i < kstruct->instances_count; i++)
{
- result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]),
- locals, content, pos, &child);
+ result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]),
+ locals, content, epos, &child);
if (!result) goto exit;
if (child != NULL)
@@ -730,10 +803,16 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
}
- for (i = 0; i < kstruct->instances_count; i++)
+ /**
+ * Seconde phase.
+ */
+
+ locals->parent = *record;
+
+ for (i = 0; i < kstruct->seq_items_count; i++)
{
- result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]),
- locals, content, pos, &child);
+ result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]),
+ locals, content, epos, &child);
if (!result) goto exit;
if (child != NULL)
@@ -748,6 +827,9 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop
locals->parent = old;
+ if (!result)
+ g_clear_object(record);
+
}
return result;