diff options
Diffstat (limited to 'plugins/kaitai/parsers')
| -rw-r--r-- | plugins/kaitai/parsers/attribute-int.h | 3 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/attribute.c | 197 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/attribute.h | 20 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/instance.c | 149 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/instance.h | 3 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/meta-int.h | 3 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/meta.c | 81 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/meta.h | 3 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/struct-int.h | 2 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/struct.c | 114 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/switch.c | 112 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/type-int.h | 3 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/type.c | 58 | ||||
| -rw-r--r-- | plugins/kaitai/parsers/type.h | 3 |
14 files changed, 548 insertions, 203 deletions
diff --git a/plugins/kaitai/parsers/attribute-int.h b/plugins/kaitai/parsers/attribute-int.h index ef64089..7d37af3 100644 --- a/plugins/kaitai/parsers/attribute-int.h +++ b/plugins/kaitai/parsers/attribute-int.h @@ -51,6 +51,9 @@ struct _GKaitaiAttribute /* KAP_FIXED_CONTENT */ sized_string_t fixed_content; /* Données brutes attendues */ + /* KAP_BIT_FIELD_TYPE */ + uint8_t bf_size; /* Nombre de bits visés */ + /* KAP_BASIC_TYPE */ struct { diff --git a/plugins/kaitai/parsers/attribute.c b/plugins/kaitai/parsers/attribute.c index c61fe99..6050bb1 100644 --- a/plugins/kaitai/parsers/attribute.c +++ b/plugins/kaitai/parsers/attribute.c @@ -25,6 +25,7 @@ #include <assert.h> +#include <stdlib.h> #include <string.h> @@ -35,6 +36,7 @@ #include "attribute-int.h" #include "../expression.h" #include "../scope.h" +#include "../records/bits.h" #include "../records/empty.h" #include "../records/item.h" #include "../records/list.h" @@ -56,6 +58,9 @@ static void g_kaitai_attribute_dispose(GKaitaiAttribute *); /* Procède à la libération totale de la mémoire. */ static void g_kaitai_attribute_finalize(GKaitaiAttribute *); +/* Traduit en champ de bits une chaîne de caractères. */ +static bool g_kaitai_attribute_resolve_bit_field(GKaitaiAttribute *, const char *); + /* Traduit en type concret une chaîne de caractères. */ static bool g_kaitai_attribute_resolve_type(GKaitaiAttribute *, const char *); @@ -71,7 +76,7 @@ static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); /* Extrait d'un contenu une série d'octets avec terminaison. */ static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *, const kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); @@ -80,7 +85,7 @@ static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *, const static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttribute *, const kaitai_scope_t *, const GBinContent *, const vmpa2t *, phys_t *, mrange_t *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -243,7 +248,7 @@ GKaitaiAttribute *g_kaitai_attribute_new(GYamlNode *parent) result = g_object_new(G_TYPE_KAITAI_ATTRIBUTE, NULL); - if (!g_kaitai_attribute_create(result, parent, true)) + if (!g_kaitai_attribute_create(result, parent, false /* TODO : REMME ? */)) g_clear_object(&result); return result; @@ -399,7 +404,10 @@ bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool if (value != NULL) { - if (g_kaitai_attribute_resolve_type(attrib, value)) + if (g_kaitai_attribute_resolve_bit_field(attrib, value)) + attrib->payload |= KAP_BIT_FIELD_TYPE; + + else if (g_kaitai_attribute_resolve_type(attrib, value)) attrib->payload |= KAP_BASIC_TYPE; else @@ -701,6 +709,54 @@ bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool * Paramètres : attrib = attribut Kaitai en cours de constitution. * * desc = chaîne de caractère à interpréter en type. * * * +* Description : Traduit en champ de bits une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_attribute_resolve_bit_field(GKaitaiAttribute *attrib, const char *desc) +{ + bool result; /* Bilan à retourner */ + size_t len; /* Taille de la chaîne à lire */ + char *end; /* Prochain caractère à lire */ + unsigned long size; /* Taille du champ de bits */ + + result = false; + + if (desc[0] == 'b') + { + len = strlen(desc); + + size = strtoul(&desc[1], &end, 10); + + if (size > 64) + { + printf("Unsupported size for bit field: %lu\n", size); + goto exit; + } + + result = ((desc + len) == end); + + if (result) + attrib->bf_size = size; + + } + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : attrib = attribut Kaitai en cours de constitution. * +* desc = chaîne de caractère à interpréter en type. * +* * * Description : Traduit en type concret une chaîne de caractères. * * * * Retour : Bilan de l'opération. * @@ -930,7 +986,7 @@ static bool g_kaitai_attribute_check(const GKaitaiAttribute *attrib) } /** - * Si une séquence d'octets finaux est spécifiées, alors l'attribut + * Si une séquence d'octets finaux est spécifiée, alors l'attribut * doit correspondre à un type str[z] (lecture) ou de taille fixée * (validation post-lecture). */ @@ -1018,7 +1074,8 @@ static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *attr * Les travaux de copie ne portent ainsi que sur le présent attribut. */ - result->raw_id = strdup(attrib->raw_id); + if (attrib->raw_id != NULL) + result->raw_id = strdup(attrib->raw_id); if (attrib->orig_id != NULL) result->orig_id = strdup(attrib->orig_id); @@ -1428,6 +1485,50 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon } +/****************************************************************************** +* * +* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. * +* content = contenu binaire à venir lire. * +* epos = tête de lecture avec granularité en bits. * +* size = quantité de bits à prendre en compte. * +* endian = boustime des données à respecter. * +* out = valeur à sauvegarder sous une forme générique.[OUT]* +* * +* Description : Lit la valeur d'un champ de bits Kaitai représenté. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_attribute_read_bit_field_value(const GKaitaiAttribute *attrib, const GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian, resolved_value_t *out) +{ + bool result; /* Bilan à retourner */ + ext_vmpa_t tmpepos; /* Localisation modifiable */ + uint64_t tmp64; /* Valeur de 64 bits lue */ + + result = false; + + if (attrib->payload & KAP_BIT_FIELD_TYPE) + { + copy_evmpa(&tmpepos, epos); + + result = g_binary_content_read_bits(content, &tmpepos, size, endian, &tmp64); + + if (result) + { + out->type = GVT_UNSIGNED_INTEGER; + out->unsigned_integer = tmp64; + } + + } + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* IMPLEMENTATION DES FONCTIONS DE CLASSE */ @@ -1439,7 +1540,7 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon * Paramètres : attrib = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -1450,7 +1551,7 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon * * ******************************************************************************/ -static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ resolved_value_t authorized; /* Validation des traitements */ @@ -1499,7 +1600,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s /* Zone de travail restreinte */ g_binary_content_compute_end_pos(content, &tmp); - diff = compute_vmpa_diff(pos, &tmp); + diff = compute_vmpa_diff(&epos->base, &tmp); + + if (epos->consumed_extra_bits > 0 && diff > 0) + diff--; if (attrib->payload & KAP_SIZED) { @@ -1537,8 +1641,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (!result) goto exit; - init_mrange(&work_range, pos, diff); - work_area = g_restricted_content_new_ro(content, &work_range); + align_evmpa_on_byte(epos); + + init_mrange(&work_range, &epos->base, diff); + work_area = g_restricted_content_new(content, &work_range); has_empty_size = (diff == 0); @@ -1555,13 +1661,18 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s assert(false); else if (attrib->payload & KAP_SIZED_EOS) + { + align_evmpa_on_byte(epos); result = true; + } else if (attrib->payload & KAP_FIXED_CONTENT) { if (diff >= attrib->fixed_content.len) { - copy_vmpa(&tmp, pos); + align_evmpa_on_byte(epos); + + copy_vmpa(&tmp, &epos->base); data = g_binary_content_get_raw_access(work_area, &tmp, attrib->fixed_content.len); assert(data != NULL); @@ -1575,8 +1686,26 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s } + else if (attrib->payload & KAP_BIT_FIELD_TYPE) + { + if (attrib->has_endian) + endian = attrib->endian; + else + endian = g_kaitai_meta_get_endian(locals->meta); + + *record = g_record_bit_field_new(attrib, work_area, epos, attrib->bf_size, endian); + + result = (*record != NULL); + + if (result) + advance_evmpa_bits(epos, attrib->bf_size); + + } + else if (attrib->payload & KAP_BASIC_TYPE) { + align_evmpa_on_byte(epos); + switch (attrib->basic) { case BTP_CHAR: @@ -1584,7 +1713,8 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (attrib->is_string) { if ((attrib->payload & KAP_SIZED) == 0) - result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals, work_area, pos, record); + result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals, + work_area, &epos->base, record); } else { @@ -1627,7 +1757,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (user_type != NULL) { result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(user_type), - locals, work_area, pos, record); + locals, work_area, epos, record); if (result) /** @@ -1647,7 +1777,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s } else if (attrib->payload & KAP_DYNAMIC_TYPE) - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, pos, record); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, epos, record); else if (attrib->payload & KAP_SIZED) { @@ -1660,6 +1790,11 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (result && *record == NULL) { /** + * A ce stade, la granularité des travaux est l'octet. + */ + assert(epos->consumed_extra_bits == 0); + + /** * On choisit de laisser la création de correspondances nulles. * * Cela permet de disposer de la présence de champs valides, même vides @@ -1668,12 +1803,13 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s /* if (diff > 0) */ { - result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content, pos, &diff, &range); + result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content, + &epos->base, &diff, &range); if (result) { if (has_empty_size) - *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, pos)); + *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, &epos->base)); else { @@ -1685,7 +1821,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s *record = G_MATCH_RECORD(g_record_item_new(attrib, work_area, &range, endian)); if (*record != NULL) - advance_vmpa(pos, diff); + advance_vmpa(&epos->base, diff); else result = false; @@ -1701,13 +1837,16 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (attrib->payload & KAP_SIZED) { - cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), pos); + /* Réalignement éventuel suite aux lectures dans la zone périmétrée... */ + align_evmpa_on_byte(epos); + + cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), &epos->base); /* Pour GCC... */ max_size = get_mrange_length(&work_range); if (cur_diff < max_size) - advance_vmpa(pos, max_size - cur_diff); + advance_vmpa(&epos->base, max_size - cur_diff); assert(work_area != content); g_object_unref(G_OBJECT(work_area)); @@ -1932,7 +2071,7 @@ static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttri * Paramètres : attrib = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -1943,7 +2082,7 @@ static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttri * * ******************************************************************************/ -static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ resolved_value_t authorized; /* Validation des traitements */ @@ -1957,7 +2096,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc resolved_value_t loop; /* Poursuite des lectures ? */ if (attrib->repetition == KAR_NO_REPETITION) - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, record); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, record); else { @@ -1975,7 +2114,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc } - list = g_record_list_new(attrib, content, pos); + list = g_record_list_new(attrib, content, &epos->base); switch (attrib->repetition) { @@ -1984,17 +2123,17 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc result = true; g_binary_content_compute_end_pos(content, &end); - diff = compute_vmpa_diff(pos, &end); + diff = compute_vmpa_diff(&epos->base, &end); while (diff > 0) { - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child); if (!result) break; g_record_list_add_record(list, child); remember_last_record(locals, child); - diff = compute_vmpa_diff(pos, &end); + diff = compute_vmpa_diff(&epos->base, &end); } @@ -2025,7 +2164,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc for (i = 0; i < count; i++) { - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child); if (!result) break; g_record_list_add_record(list, child); @@ -2039,7 +2178,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc do { - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child); if (!result) break; g_record_list_add_record(list, child); diff --git a/plugins/kaitai/parsers/attribute.h b/plugins/kaitai/parsers/attribute.h index 38b78d7..9b43936 100644 --- a/plugins/kaitai/parsers/attribute.h +++ b/plugins/kaitai/parsers/attribute.h @@ -56,18 +56,19 @@ typedef struct _GKaitaiAttributeClass GKaitaiAttributeClass; /* Type de charge associée à un attribut */ typedef enum _KaitaiAttributePayload { - KAP_UNINITIALIZED = (0 << 0), /* Type non initialisé */ + KAP_UNINITIALIZED = (0 << 0), /* Type non initialisé */ - KAP_FIXED_CONTENT = (1 << 0), /* Contenu brut attendu */ - KAP_BASIC_TYPE = (1 << 1), /* Type prédéfini */ - KAP_USER_TYPE = (1 << 2), /* Type personnalisé */ - KAP_DYNAMIC_TYPE = (1 << 3), /* Type dynmatique */ - KAP_SIZED = (1 << 4), /* Bourrage dimensionné */ - KAP_SIZED_EOS = (1 << 5), /* Bourrage final */ + KAP_FIXED_CONTENT = (1 << 0), /* Contenu brut attendu */ + KAP_BIT_FIELD_TYPE = (1 << 1), /* Champ d'un ou plusieurs bits*/ + KAP_BASIC_TYPE = (1 << 2), /* Type prédéfini */ + KAP_USER_TYPE = (1 << 3), /* Type personnalisé */ + KAP_DYNAMIC_TYPE = (1 << 4), /* Type dynmatique */ + KAP_SIZED = (1 << 5), /* Bourrage dimensionné */ + KAP_SIZED_EOS = (1 << 6), /* Bourrage final */ } KaitaiAttributePayload; -/* Types de base reconnus par Kaitai */ +/* Types de base reconnus par Kaitai */ /* TODO : REMME ? (car non utilisé) */ typedef enum _KaitaiBasicType { KBT_U1, /* Octet non signé */ @@ -149,6 +150,9 @@ bool g_kaitai_attribute_handle_signed_integer(const GKaitaiAttribute *); /* Lit la valeur d'un élément Kaitai entier représenté. */ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *, const GBinContent *, const mrange_t *, SourceEndian, resolved_value_t *); +/* Lit la valeur d'un champ de bits Kaitai représenté. */ +bool g_kaitai_attribute_read_bit_field_value(const GKaitaiAttribute *, const GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian, resolved_value_t *); + #endif /* _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_H */ diff --git a/plugins/kaitai/parsers/instance.c b/plugins/kaitai/parsers/instance.c index 63db224..d62c1f6 100644 --- a/plugins/kaitai/parsers/instance.c +++ b/plugins/kaitai/parsers/instance.c @@ -34,7 +34,7 @@ #include "instance-int.h" #include "../expression.h" -#include "../records/value.h" +#include "../records/delayed.h" @@ -59,7 +59,7 @@ static void g_kaitai_instance_finalize(GKaitaiInstance *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -349,74 +349,30 @@ const char *g_kaitai_instance_get_name(const GKaitaiInstance *inst) * * * Paramètres : inst = lecteur d'instance Kaitai à consulter. * * locals = variables locales pour les résolutions de types. * -* value = valeur à sauvegarder sous une forme générique. [OUT]* +* content = contenu binaire lié à la correspondance. * * * -* Description : Détermine la valeur d'un élément Kaitai entier calculé. * +* Description : Détermine la valeur effective d'un élément Kaitai dynamique. * * * -* Retour : Bilan de l'opération. * +* Retour : valeur à sauvegarder sous une forme générique. * * * * Remarques : - * * * ******************************************************************************/ -bool g_kaitai_instance_compute_value(const GKaitaiInstance *inst, const kaitai_scope_t *locals, resolved_value_t *value) +GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content) { - bool result; /* Bilan à retourner */ - - if (inst->value == NULL) - result = false; - - else - result = resolve_kaitai_expression_as_any(locals, - inst->value, - strlen(inst->value), - value); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : inst = structure Kaitai en cours de parcours. * -* locals = variables locales pour les résolutions de types. * -* content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * -* record = noeud d'arborescence d'éléments rencontrés. [OUT] * -* * -* Description : Parcourt un contenu binaire selon des spécifications Kaitai. * -* * -* Retour : Bilan de l'opératon : true pour continuer, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) -{ - bool result; /* Bilan à retourner */ + GMatchRecord *result; /* Enregistrement à retourner */ GBinContent *work_area; /* Aire de travail */ GKaitaiStream *stream; /* Flux de données pour Kaitai */ - resolved_value_t offset; /* Position à adopter */ + bool status; /* Bilan intermédiaire */ vmpa2t forced_pos; /* Tete de lecture constituée */ + resolved_value_t offset; /* Position à adopter */ GKaitaiParserClass *class; /* Classe parente à solliciter */ + ext_vmpa_t epos; /* Tête de lecture complète */ - if (inst->value != NULL) - { - *record = G_MATCH_RECORD(g_record_value_new(inst, locals)); + result = NULL; - result = (*record != NULL); - - } - - else + if (inst->value == NULL) { /* Contenu particulier */ @@ -425,8 +381,8 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ else { - result = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream); - if (!result) goto exit; + status = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream); + if (!status) goto exit; work_area = g_kaitai_stream_get_content(stream); @@ -438,8 +394,8 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ g_binary_content_compute_start_pos(work_area, &forced_pos); - result = resolve_kaitai_expression_as_integer(locals, inst->pos, strlen(inst->pos), &offset); - if (!result) goto exit_with_content; + status = resolve_kaitai_expression_as_integer(locals, inst->pos, strlen(inst->pos), &offset); + if (!status) goto exit_with_content; if (offset.type == GVT_UNSIGNED_INTEGER) advance_vmpa(&forced_pos, offset.unsigned_integer); @@ -450,7 +406,7 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ if (offset.signed_integer < 0) { - result = false; + status = false; goto exit_with_content; } @@ -462,7 +418,9 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ class = G_KAITAI_PARSER_CLASS(g_kaitai_instance_parent_class); - result = class->parse(G_KAITAI_PARSER(inst), locals, work_area, &forced_pos, record); + init_evmpa_from_vmpa(&epos, &forced_pos); + + class->parse(G_KAITAI_PARSER(inst), locals, work_area, &epos, &result); exit_with_content: @@ -476,3 +434,70 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ return result; } + + +/****************************************************************************** +* * +* Paramètres : inst = lecteur d'instance Kaitai à consulter. * +* locals = variables locales pour les résolutions de types. * +* value = valeur à sauvegarder sous une forme générique. [OUT]* +* * +* Description : Détermine la valeur d'un élément Kaitai entier calculé. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_instance_compute_value(const GKaitaiInstance *inst, const kaitai_scope_t *locals, resolved_value_t *value) +{ + bool result; /* Bilan à retourner */ + + if (inst->value == NULL) + result = false; + + else + result = resolve_kaitai_expression_as_any(locals, + inst->value, + strlen(inst->value), + value); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : inst = structure Kaitai en cours de parcours. * +* locals = variables locales pour les résolutions de types. * +* content = données binaires à analyser et traduire. * +* epos = tête de lecture courante. [OUT] * +* record = noeud d'arborescence d'éléments rencontrés. [OUT] * +* * +* Description : Parcourt un contenu binaire selon des spécifications Kaitai. * +* * +* Retour : Bilan de l'opératon : true pour continuer, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) +{ + bool result; /* Bilan à retourner */ + + *record = G_MATCH_RECORD(g_record_delayed_new(inst, locals, inst->value == NULL ? content : NULL)); + + result = (*record != NULL); + + return result; + +} diff --git a/plugins/kaitai/parsers/instance.h b/plugins/kaitai/parsers/instance.h index a9aee9a..4594137 100644 --- a/plugins/kaitai/parsers/instance.h +++ b/plugins/kaitai/parsers/instance.h @@ -60,6 +60,9 @@ GKaitaiInstance *g_kaitai_instance_new(GYamlNode *); /* Indique le nom attribué à une instance Kaitai. */ const char *g_kaitai_instance_get_name(const GKaitaiInstance *); +/* Détermine la valeur effective d'un élément Kaitai dynamique. */ +GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *, const kaitai_scope_t *, GBinContent *); + /* Détermine la valeur d'un élément Kaitai entier calculé. */ bool g_kaitai_instance_compute_value(const GKaitaiInstance *, const kaitai_scope_t *, resolved_value_t *); diff --git a/plugins/kaitai/parsers/meta-int.h b/plugins/kaitai/parsers/meta-int.h index 7d847ef..5fe9174 100644 --- a/plugins/kaitai/parsers/meta-int.h +++ b/plugins/kaitai/parsers/meta-int.h @@ -39,6 +39,9 @@ struct _GKaitaiMeta SourceEndian endian; /* Boutisme par défaut */ + char **dependencies; /* Définitions à importer */ + size_t dep_count; /* Nombre de ces définitions */ + }; /* Description globale d'une définition Kaitai (classe) */ diff --git a/plugins/kaitai/parsers/meta.c b/plugins/kaitai/parsers/meta.c index dc30c73..132eefd 100644 --- a/plugins/kaitai/parsers/meta.c +++ b/plugins/kaitai/parsers/meta.c @@ -97,6 +97,9 @@ static void g_kaitai_meta_init(GKaitaiMeta *meta) meta->endian = SRE_LITTLE; + meta->dependencies = NULL; + meta->dep_count = 0; + } @@ -133,12 +136,20 @@ static void g_kaitai_meta_dispose(GKaitaiMeta *meta) static void g_kaitai_meta_finalize(GKaitaiMeta *meta) { + size_t i; /* Boucle de parcours */ + if (meta->id != NULL) free(meta->id); if (meta->title != NULL) free(meta->title); + for (i = 0; i < meta->dep_count; i++) + free(meta->dependencies[i]); + + if (meta->dependencies != NULL) + free(meta->dependencies); + G_OBJECT_CLASS(g_kaitai_meta_parent_class)->finalize(G_OBJECT(meta)); } @@ -188,6 +199,9 @@ bool g_kaitai_meta_create(GKaitaiMeta *meta, GYamlNode *parent) bool result; /* Bilan à retourner */ GYamlNode *node; /* Noeud particulier présent */ const char *value; /* Valeur Yaml particulière */ + GYamlNode **nodes; /* Eventuels noeuds trouvés */ + size_t count; /* Quantité de ces noeuds */ + size_t i; /* Boucle de parcours */ result = true; @@ -245,6 +259,45 @@ bool g_kaitai_meta_create(GKaitaiMeta *meta, GYamlNode *parent) } + /* Imports */ + + node = g_yaml_node_find_first_by_path(parent, "/meta/imports/"); + + if (node != NULL) + { + result = G_IS_YAML_COLLEC(node); + + if (result) + { + nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(node), &count); + + for (i = 0; i < count; i++) + { + if (!G_IS_YAML_PAIR(nodes[i])) + break; + + value = g_yaml_pair_get_key(G_YAML_PAIR(nodes[i])); + + meta->dependencies = realloc(meta->dependencies, ++meta->dep_count * sizeof(char *)); + + meta->dependencies[meta->dep_count - 1] = strdup(value); + + g_object_unref(G_OBJECT(nodes[i])); + + } + + result = (i == count); + + for (; i < count; i++) + g_object_unref(G_OBJECT(nodes[i])); + + if (nodes != NULL) + free(nodes); + + } + + } + return result; } @@ -279,7 +332,7 @@ const char *g_kaitai_meta_get_id(const GKaitaiMeta *meta) * * * Description : Fournit la désignation humaine d'une définiton Kaitai. * * * -* Retour : Intitulé de définition OU NULL. * +* Retour : Intitulé de définition ou NULL. * * * * Remarques : - * * * @@ -317,3 +370,29 @@ SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *meta) return result; } + + +/****************************************************************************** +* * +* Paramètres : meta = description globale à consulter. * +* count = quantité de définitions à importer. [OUT] * +* * +* Description : Indique la liste des définitions à importer. * +* * +* Retour : Liste de désignations de définitions ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *meta, size_t *count) +{ + const char * const *result; /* Liste à retourner */ + + result = (const char * const *)meta->dependencies; + + *count = meta->dep_count; + + return result; + +} diff --git a/plugins/kaitai/parsers/meta.h b/plugins/kaitai/parsers/meta.h index 3797823..b8b685d 100644 --- a/plugins/kaitai/parsers/meta.h +++ b/plugins/kaitai/parsers/meta.h @@ -63,6 +63,9 @@ const char *g_kaitai_meta_get_title(const GKaitaiMeta *); /* Indique le boustime observé par défaut par une définiton. */ SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *); +/* Indique la liste des définitions à importer. */ +const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *, size_t *); + #endif /* _PLUGINS_KAITAI_PARSERS_META_H */ diff --git a/plugins/kaitai/parsers/struct-int.h b/plugins/kaitai/parsers/struct-int.h index f34be32..6eb6e53 100644 --- a/plugins/kaitai/parsers/struct-int.h +++ b/plugins/kaitai/parsers/struct-int.h @@ -37,6 +37,8 @@ struct _GKaitaiStruct { GKaitaiParser parent; /* A laisser en premier */ + char *filename; /* Eventuelle source de données*/ + GKaitaiMeta *meta; /* Description globale */ GKaitaiAttribute **seq_items; /* Sous-attributs présents */ diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c index 128a788..d447cf3 100644 --- a/plugins/kaitai/parsers/struct.c +++ b/plugins/kaitai/parsers/struct.c @@ -33,6 +33,7 @@ #include "struct-int.h" +#include "../import.h" #include "../parser.h" #include "../records/empty.h" #include "../records/group.h" @@ -54,13 +55,16 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *); /* Procède à la libération totale de la mémoire. */ static void g_kaitai_structure_finalize(GKaitaiStruct *); +/* Charge les éventuelles dépendances de la définition. */ +static bool g_kaitai_structure_load_imports(GKaitaiStruct *); + /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -116,6 +120,8 @@ static void g_kaitai_structure_class_init(GKaitaiStructClass *klass) static void g_kaitai_structure_init(GKaitaiStruct *kstruct) { + kstruct->filename = NULL; + kstruct->meta = NULL; kstruct->seq_items = NULL; @@ -182,6 +188,9 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *kstruct) static void g_kaitai_structure_finalize(GKaitaiStruct *kstruct) { + if (kstruct->filename != NULL) + free(kstruct->filename); + if (kstruct->seq_items != NULL) free(kstruct->seq_items); @@ -305,6 +314,8 @@ bool g_kaitai_structure_create_from_file(GKaitaiStruct *kstruct, const char *fil bool result; /* Bilan à retourner */ GYamlNode *root; /* Noeud racine YAML */ + kstruct->filename = strdup(filename); + root = parse_yaml_from_file(filename); if (root != NULL) @@ -343,6 +354,7 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) GYamlNode **nodes; /* Eventuels noeuds trouvés */ size_t count; /* Quantité de ces noeuds */ size_t i; /* Boucle de parcours */ + size_t first; /* Premier emplacement dispo. */ bool failed; /* Détection d'un échec */ result = false; @@ -352,6 +364,9 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) kstruct->meta = g_kaitai_meta_new(parent); assert(kstruct->meta != NULL); + result = g_kaitai_structure_load_imports(kstruct); + if (!result) goto bad_loading; + /* Séquence */ collec = g_yaml_node_find_first_by_path(parent, "/seq/"); @@ -406,13 +421,15 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) if (count > 0) { - kstruct->types = calloc(count, sizeof(GKaitaiType *)); - kstruct->types_count = count; + first = kstruct->types_count; + + kstruct->types_count += count; + kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *)); for (i = 0; i < count; i++) { - kstruct->types[i] = g_kaitai_type_new(nodes[i]); - if (kstruct->types[i] == NULL) break; + kstruct->types[first + i] = g_kaitai_type_new(nodes[i]); + if (kstruct->types[first + i] == NULL) break; g_object_unref(G_OBJECT(nodes[i])); @@ -529,6 +546,49 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) /****************************************************************************** * * +* Paramètres : kstruct = lecteur de définition à initialiser pleinement. * +* * +* Description : Charge les éventuelles dépendances de la définition. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_structure_load_imports(GKaitaiStruct *kstruct) +{ + bool result; /* Bilan d'opération à renvoyer*/ + const char * const *dependencies; /* Liste d'imports requis */ + size_t count; /* Quantité de ces imports */ + size_t i; /* Boucle de parcours */ + GKaitaiType *imported; /* Structure importée */ + + result = true; + + dependencies = g_kaitai_meta_get_dependencies(kstruct->meta, &count); + + for (i = 0; i < count; i++) + { + imported = import_kaitai_definition(dependencies[i], kstruct->filename); + if (imported == NULL) break; + + kstruct->types_count++; + kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *)); + + kstruct->types[kstruct->types_count - 1] = imported; + + } + + result = (i == count); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : kstruct = structure Kaitai à consulter. * * * * Description : Fournit la description globale d'une définition Kaitai. * @@ -624,6 +684,9 @@ GKaitaiType *g_kaitai_structure_find_sub_type(const GKaitaiStruct *kstruct, cons break; } + result = g_kaitai_structure_find_sub_type(G_KAITAI_STRUCT(kstruct->types[i]), name); + if (result != NULL) break; + } return result; @@ -649,13 +712,15 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont GMatchRecord *result; /* Arborescence à retourner */ vmpa2t pos; /* Tête de lecture */ kaitai_scope_t locals; /* Variables locales */ - bool status; /* Bilan de l'analyse */ + ext_vmpa_t epos; /* Tête de lecture complète */ g_binary_content_compute_start_pos(content, &pos); init_record_scope(&locals, kstruct->meta); - status = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &pos, &result); + init_evmpa_from_vmpa(&epos, &pos); + + g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &epos, &result); return result; @@ -673,7 +738,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont * Paramètres : kstruct = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -684,7 +749,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont * * ******************************************************************************/ -static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ GRecordGroup *group; /* Ensemble à constituer */ @@ -697,7 +762,7 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop /* Si le groupe est vide */ if ((kstruct->seq_items_count + kstruct->instances_count) == 0) { - *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, pos)); + *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, &epos->base)); if (locals->root == NULL) locals->root = *record; @@ -716,10 +781,18 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop old = locals->parent; locals->parent = *record; - for (i = 0; i < kstruct->seq_items_count; i++) + /** + * Les instances sont à charger avant les éléments fixes car + * des références au premières peuvent être attendues dans ces derniers. + * + * Les évolutions de la tête de lecture n'ont en revanche normalement + * pas d'incidence sur le chargement des éléments fixes. + */ + + for (i = 0; i < kstruct->instances_count; i++) { - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]), - locals, content, pos, &child); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]), + locals, content, epos, &child); if (!result) goto exit; if (child != NULL) @@ -730,10 +803,16 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop } - for (i = 0; i < kstruct->instances_count; i++) + /** + * Seconde phase. + */ + + locals->parent = *record; + + for (i = 0; i < kstruct->seq_items_count; i++) { - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]), - locals, content, pos, &child); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]), + locals, content, epos, &child); if (!result) goto exit; if (child != NULL) @@ -748,6 +827,9 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop locals->parent = old; + if (!result) + g_clear_object(record); + } return result; diff --git a/plugins/kaitai/parsers/switch.c b/plugins/kaitai/parsers/switch.c index c823f27..6cfc96b 100644 --- a/plugins/kaitai/parsers/switch.c +++ b/plugins/kaitai/parsers/switch.c @@ -83,7 +83,7 @@ static void g_kaitai_switch_finalize(GKaitaiSwitch *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -285,7 +285,7 @@ static const char *is_suitable_switch_case_for_integer(const switch_case_t *swca { if (value->type == GVT_UNSIGNED_INTEGER) { - unsigned_conv = strtoull(swcase->value, NULL, 10); + unsigned_conv = strtoull(swcase->value, NULL, 0); valid = (errno != ERANGE && errno != EINVAL); @@ -295,7 +295,7 @@ static const char *is_suitable_switch_case_for_integer(const switch_case_t *swca } else { - signed_conv = strtoll(swcase->value, NULL, 10); + signed_conv = strtoll(swcase->value, NULL, 0); valid = (errno != ERANGE && errno != EINVAL); @@ -569,7 +569,7 @@ bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAt * Paramètres : kswitch = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -580,127 +580,65 @@ bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAt * * ******************************************************************************/ -static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ - GMatchRecord *reference; /* Correspondance à utiliser */ - GKaitaiParser *creator; /* Lecteur d'origine */ - KaitaiAttributePayload payload; /* Type de charge supportée */ - BaseType basic; /* Type de base reconnu */ - bool is_string; /* Type lié à une chaîne ? */ -#ifndef NDEBUG - bool status; /* Bilan d'une consultation */ -#endif const char *final_type; /* Type à utiliser au final */ resolved_value_t value; /* Valeur de cible entière */ + bool status; /* Bilan intermédiaire */ size_t i; /* Boucle de parcours */ GKaitaiAttribute *attrib; /* Lecteur approprié */ - result = false; - - /* Détermination de la forme de comparaison */ - - reference = g_match_record_find_by_name(locals->parent, - kswitch->target, strlen(kswitch->target), - DIRECT_SEARCH_DEEP_LEVEL); - - if (reference == NULL) - goto exit; - - creator = g_match_record_get_creator(reference); - - if (creator == NULL) - goto exit_with_ref; - - if (!G_IS_KAITAI_ATTRIBUTE(creator)) - goto exit_with_creator; - - payload = g_kaitai_attribute_get_payload(G_KAITAI_ATTRIBUTE(creator)); - - if ((payload & KAP_BASIC_TYPE) == 0) - goto exit_with_creator; - -#ifndef NDEBUG - status = g_kaitai_attribute_get_basic_type(G_KAITAI_ATTRIBUTE(creator), &basic, &is_string); - assert(status); -#else - g_kaitai_attribute_get_basic_type(G_KAITAI_ATTRIBUTE(creator), &basic, &is_string); -#endif - - /* Détermination du type visé */ + result = true; final_type = NULL; - if (is_string) - { - result = resolve_kaitai_expression_as_bytes(locals, - kswitch->target, - strlen(kswitch->target), - &value); - if (!result) goto exit_with_creator; + /* Tenative n°1 : version "entier" */ + + status = resolve_kaitai_expression_as_integer(locals, kswitch->target, strlen(kswitch->target), &value); + if (status) for (i = 0; i < kswitch->count; i++) { - final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value); + final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value); if (final_type != NULL) - break; + goto next_step; } - } - - else - { - if (basic == BTP_UCHAR || basic == BTP_USHORT || basic == BTP_UINT || basic == BTP_ULONG_LONG) - { - result = resolve_kaitai_expression_as_integer(locals, - kswitch->target, - strlen(kswitch->target), - &value); - if (!result) goto exit_with_creator; + status = resolve_kaitai_expression_as_bytes(locals, kswitch->target, strlen(kswitch->target), &value); - for (i = 0; i < kswitch->count; i++) - { - final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value); + /* Tenative n°1 : version "chaîne" */ - if (final_type != NULL) - break; + if (status) + for (i = 0; i < kswitch->count; i++) + { + final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value); - } + if (final_type != NULL) + goto next_step; } - else - printf("other type: %u\n", basic); - - } - if (final_type == NULL && kswitch->defcase != NULL) final_type = kswitch->defcase->type; + next_step: + /* Mise en place d'un attribut et analyse */ if (final_type != NULL) { attrib = g_kaitai_attribute_dup_for_user_type(kswitch->generic, final_type); - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib), locals, content, pos, record); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib), locals, content, epos, record); g_object_unref(G_OBJECT(attrib)); } - exit_with_creator: - - g_object_unref(G_OBJECT(creator)); - - exit_with_ref: - - g_object_unref(G_OBJECT(reference)); - - exit: - + return true; return result; } diff --git a/plugins/kaitai/parsers/type-int.h b/plugins/kaitai/parsers/type-int.h index 4a4d939..535ce57 100644 --- a/plugins/kaitai/parsers/type-int.h +++ b/plugins/kaitai/parsers/type-int.h @@ -50,6 +50,9 @@ struct _GKaitaiTypeClass /* Met en place un lecteur de type pour Kaitai. */ bool g_kaitai_type_create(GKaitaiType *, GYamlNode *); +/* Met en place un lecteur de type externe pour Kaitai. */ +bool g_kaitai_type_create_as_import(GKaitaiType *, const char *, const char *); + #endif /* PLUGINS_KAITAI_PARSERS_TYPE_INT_H */ diff --git a/plugins/kaitai/parsers/type.c b/plugins/kaitai/parsers/type.c index 30d0373..81efbeb 100644 --- a/plugins/kaitai/parsers/type.c +++ b/plugins/kaitai/parsers/type.c @@ -215,6 +215,64 @@ bool g_kaitai_type_create(GKaitaiType *type, GYamlNode *parent) /****************************************************************************** * * +* Paramètres : name = nom à attribuer au futur type. * +* filename = chemin vers une définition Kaitai à charger. * +* * +* Description : Construit un lecteur de type externe pour Kaitai. * +* * +* Retour : Instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GKaitaiType *g_kaitai_type_new_as_import(const char *name, const char *filename) +{ + GKaitaiType *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_KAITAI_TYPE, NULL); + + if (!g_kaitai_type_create_as_import(result, name, filename)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = lecteur de type Kaitai à initialiser pleinement. * +* name = nom à attribuer au futur type. * +* filename = chemin vers une définition Kaitai à charger. * +* * +* Description : Met en place un lecteur de type externe pour Kaitai. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_type_create_as_import(GKaitaiType *type, const char *name, const char *filename) +{ + bool result; /* Bilan à retourner */ + + /* Extraction du nom */ + + type->name = strdup(name); + + /* Extraction des bases du type */ + + result = g_kaitai_structure_create_from_file(G_KAITAI_STRUCT(type), filename); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : type = définition de type particulier à consulter. * * * * Description : Indique le nom de scène du type représenté. * diff --git a/plugins/kaitai/parsers/type.h b/plugins/kaitai/parsers/type.h index 0656c64..d19ab90 100644 --- a/plugins/kaitai/parsers/type.h +++ b/plugins/kaitai/parsers/type.h @@ -54,6 +54,9 @@ GType g_kaitai_type_get_type(void); /* Construit un lecteur de type pour Kaitai. */ GKaitaiType *g_kaitai_type_new(GYamlNode *); +/* Construit un lecteur de type externe pour Kaitai. */ +GKaitaiType *g_kaitai_type_new_as_import(const char *, const char *); + /* Indique le nom de scène du type représenté. */ const char *g_kaitai_type_get_name(const GKaitaiType *); |
